summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFredrik Rinnestam <fredrik@crux.nu>2017-09-19 23:45:19 +0200
committerFredrik Rinnestam <fredrik@crux.nu>2017-09-19 23:45:19 +0200
commit4da22c00669b68456783e483b8527976a3890e25 (patch)
tree5d1811f2558df5c6c48eaf2301215f7cd613f26a
parenta11b0048057f80b7a8a936b8f56be9f2fd121e7e (diff)
downloadpkgutils-4da22c00669b68456783e483b8527976a3890e25.tar.gz
pkgutils-4da22c00669b68456783e483b8527976a3890e25.tar.xz
added sepen's patch for pkgadd config-file
-rw-r--r--pkgadd.cc24
-rw-r--r--pkgadd.cc.orig278
-rw-r--r--pkgadd.h2
3 files changed, 295 insertions, 9 deletions
diff --git a/pkgadd.cc b/pkgadd.cc
index deeb50bc..d76a39f4 100644
--- a/pkgadd.cc
+++ b/pkgadd.cc
@@ -33,6 +33,7 @@ void pkgadd::run(int argc, char** argv)
// Check command line options
//
string o_root;
+ string o_config;
string o_package;
bool o_upgrade = false;
bool o_force = false;
@@ -43,6 +44,10 @@ void pkgadd::run(int argc, char** argv)
assert_argument(argv, argc, i);
o_root = argv[i + 1];
i++;
+ } else if (option == "-c" || option == "--config") {
+ assert_argument(argv, argc, i);
+ o_config = argv[i + 1];
+ i++;
} else if (option == "-u" || option == "--upgrade") {
o_upgrade = true;
} else if (option == "-f" || option == "--force") {
@@ -71,7 +76,7 @@ void pkgadd::run(int argc, char** argv)
db_open(o_root);
pair<string, pkginfo_t> package = pkg_open(o_package);
- vector<rule_t> config_rules = read_config();
+ vector<rule_t> config_rules = read_config(o_config);
bool installed = db_find_pkg(package.first);
if (installed && !o_upgrade)
@@ -120,18 +125,21 @@ void pkgadd::print_help() const
{
cout << "usage: " << utilname << " [options] <file>" << endl
<< "options:" << endl
- << " -u, --upgrade upgrade package with the same name" << endl
- << " -f, --force force install, overwrite conflicting files" << endl
- << " -r, --root <path> specify alternative installation root" << endl
- << " -v, --version print version and exit" << endl
- << " -h, --help print help and exit" << endl;
+ << " -u, --upgrade upgrade package with the same name" << endl
+ << " -f, --force force install, overwrite conflicting files" << endl
+ << " -r, --root <path> specify alternative installation root" << endl
+ << " -c, --config <file> use alternate configuration file" << endl
+ << " -v, --version print version and exit" << endl
+ << " -h, --help print help and exit" << endl;
}
-vector<rule_t> pkgadd::read_config() const
+vector<rule_t> pkgadd::read_config(string file) const
{
vector<rule_t> rules;
unsigned int linecount = 0;
- const string filename = root + PKGADD_CONF;
+ string filename = root + PKGADD_CONF;
+
+ if (!file.empty()) filename = file;
ifstream in(filename.c_str());
if (in) {
diff --git a/pkgadd.cc.orig b/pkgadd.cc.orig
new file mode 100644
index 00000000..deeb50bc
--- /dev/null
+++ b/pkgadd.cc.orig
@@ -0,0 +1,278 @@
+//
+// pkgutils
+//
+// Copyright (c) 2000-2005 Per Liden
+// Copyright (c) 2006-2017 by CRUX team (http://crux.nu)
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+//
+
+#include "pkgadd.h"
+#include <fstream>
+#include <iterator>
+#include <cstdio>
+#include <regex.h>
+#include <unistd.h>
+
+void pkgadd::run(int argc, char** argv)
+{
+ //
+ // Check command line options
+ //
+ string o_root;
+ string o_package;
+ bool o_upgrade = false;
+ bool o_force = false;
+
+ for (int i = 1; i < argc; i++) {
+ string option(argv[i]);
+ if (option == "-r" || option == "--root") {
+ assert_argument(argv, argc, i);
+ o_root = argv[i + 1];
+ i++;
+ } else if (option == "-u" || option == "--upgrade") {
+ o_upgrade = true;
+ } else if (option == "-f" || option == "--force") {
+ o_force = true;
+ } else if (option[0] == '-' || !o_package.empty()) {
+ throw runtime_error("invalid option " + option);
+ } else {
+ o_package = option;
+ }
+ }
+
+ if (o_package.empty())
+ throw runtime_error("option missing");
+
+ //
+ // Check UID
+ //
+ if (getuid())
+ throw runtime_error("only root can install/upgrade packages");
+
+ //
+ // Install/upgrade package
+ //
+ {
+ db_lock lock(o_root, true);
+ db_open(o_root);
+
+ pair<string, pkginfo_t> package = pkg_open(o_package);
+ vector<rule_t> config_rules = read_config();
+
+ bool installed = db_find_pkg(package.first);
+ if (installed && !o_upgrade)
+ throw runtime_error("package " + package.first + " already installed (use -u to upgrade)");
+ else if (!installed && o_upgrade)
+ throw runtime_error("package " + package.first + " not previously installed (skip -u to install)");
+
+ set<string> non_install_files = apply_install_rules(package.first, package.second, config_rules);
+ set<string> conflicting_files = db_find_conflicts(package.first, package.second);
+
+ if (!conflicting_files.empty()) {
+ if (o_force) {
+ set<string> keep_list;
+ if (o_upgrade) // Don't remove files matching the rules in configuration
+ keep_list = make_keep_list(conflicting_files, config_rules);
+ db_rm_files(conflicting_files, keep_list); // Remove unwanted conflicts
+ } else {
+ copy(conflicting_files.begin(), conflicting_files.end(), ostream_iterator<string>(cerr, "\n"));
+ throw runtime_error("listed file(s) already installed (use -f to ignore and overwrite)");
+ }
+ }
+
+ set<string> keep_list;
+
+ if (o_upgrade) {
+ keep_list = make_keep_list(package.second.files, config_rules);
+ db_rm_pkg(package.first, keep_list);
+ }
+
+ db_add_pkg(package.first, package.second);
+ db_commit();
+ try {
+ pkg_install(o_package, keep_list, non_install_files, installed);
+ } catch (runtime_error&) {
+ if (!installed) {
+ db_rm_pkg(package.first);
+ db_commit();
+ throw runtime_error("failed");
+ }
+ }
+ ldconfig();
+ }
+}
+
+void pkgadd::print_help() const
+{
+ cout << "usage: " << utilname << " [options] <file>" << endl
+ << "options:" << endl
+ << " -u, --upgrade upgrade package with the same name" << endl
+ << " -f, --force force install, overwrite conflicting files" << endl
+ << " -r, --root <path> specify alternative installation root" << endl
+ << " -v, --version print version and exit" << endl
+ << " -h, --help print help and exit" << endl;
+}
+
+vector<rule_t> pkgadd::read_config() const
+{
+ vector<rule_t> rules;
+ unsigned int linecount = 0;
+ const string filename = root + PKGADD_CONF;
+ ifstream in(filename.c_str());
+
+ if (in) {
+ while (!in.eof()) {
+ string line;
+ getline(in, line);
+ linecount++;
+ if (!line.empty() && line[0] != '#') {
+ if (line.length() >= PKGADD_CONF_MAXLINE)
+ throw runtime_error(filename + ":" + itos(linecount) + ": line too long, aborting");
+
+ char event[PKGADD_CONF_MAXLINE];
+ char pattern[PKGADD_CONF_MAXLINE];
+ char action[PKGADD_CONF_MAXLINE];
+ char dummy[PKGADD_CONF_MAXLINE];
+ if (sscanf(line.c_str(), "%s %s %s %s", event, pattern, action, dummy) != 3)
+ throw runtime_error(filename + ":" + itos(linecount) + ": wrong number of arguments, aborting");
+
+ if (!strcmp(event, "UPGRADE") || !strcmp(event, "INSTALL")) {
+ rule_t rule;
+ rule.event = strcmp(event, "UPGRADE") ? INSTALL : UPGRADE;
+ rule.pattern = pattern;
+ if (!strcmp(action, "YES")) {
+ rule.action = true;
+ } else if (!strcmp(action, "NO")) {
+ rule.action = false;
+ } else
+ throw runtime_error(filename + ":" + itos(linecount) + ": '" +
+ string(action) + "' unknown action, should be YES or NO, aborting");
+
+ rules.push_back(rule);
+ } else
+ throw runtime_error(filename + ":" + itos(linecount) + ": '" +
+ string(event) + "' unknown event, aborting");
+ }
+ }
+ in.close();
+ }
+
+#ifndef NDEBUG
+ cerr << "Configuration:" << endl;
+ for (vector<rule_t>::const_iterator j = rules.begin(); j != rules.end(); j++) {
+ cerr << "\t" << (*j).pattern << "\t" << (*j).action << endl;
+ }
+ cerr << endl;
+#endif
+
+ return rules;
+}
+
+set<string> pkgadd::make_keep_list(const set<string>& files, const vector<rule_t>& rules) const
+{
+ set<string> keep_list;
+ vector<rule_t> found;
+
+ find_rules(rules, UPGRADE, found);
+
+ for (set<string>::const_iterator i = files.begin(); i != files.end(); i++) {
+ for (vector<rule_t>::reverse_iterator j = found.rbegin(); j != found.rend(); j++) {
+ if (rule_applies_to_file(*j, *i)) {
+ if (!(*j).action)
+ keep_list.insert(keep_list.end(), *i);
+
+ break;
+ }
+ }
+ }
+
+#ifndef NDEBUG
+ cerr << "Keep list:" << endl;
+ for (set<string>::const_iterator j = keep_list.begin(); j != keep_list.end(); j++) {
+ cerr << " " << (*j) << endl;
+ }
+ cerr << endl;
+#endif
+
+ return keep_list;
+}
+
+set<string> pkgadd::apply_install_rules(const string& name, pkginfo_t& info, const vector<rule_t>& rules)
+{
+ // TODO: better algo(?)
+ set<string> install_set;
+ set<string> non_install_set;
+ vector<rule_t> found;
+
+ find_rules(rules, INSTALL, found);
+
+ for (set<string>::const_iterator i = info.files.begin(); i != info.files.end(); i++) {
+ bool install_file = true;
+
+ for (vector<rule_t>::reverse_iterator j = found.rbegin(); j != found.rend(); j++) {
+ if (rule_applies_to_file(*j, *i)) {
+ install_file = (*j).action;
+ break;
+ }
+ }
+
+ if (install_file)
+ install_set.insert(install_set.end(), *i);
+ else
+ non_install_set.insert(*i);
+ }
+
+ info.files.clear();
+ info.files = install_set;
+
+#ifndef NDEBUG
+ cerr << "Install set:" << endl;
+ for (set<string>::iterator j = info.files.begin(); j != info.files.end(); j++) {
+ cerr << " " << (*j) << endl;
+ }
+ cerr << endl;
+
+ cerr << "Non-Install set:" << endl;
+ for (set<string>::iterator j = non_install_set.begin(); j != non_install_set.end(); j++) {
+ cerr << " " << (*j) << endl;
+ }
+ cerr << endl;
+#endif
+
+ return non_install_set;
+}
+
+void pkgadd::find_rules(const vector<rule_t>& rules, rule_event_t event, vector<rule_t>& found) const
+{
+ for (vector<rule_t>::const_iterator i = rules.begin(); i != rules.end(); i++)
+ if (i->event == event)
+ found.push_back(*i);
+}
+
+bool pkgadd::rule_applies_to_file(const rule_t& rule, const string& file) const
+{
+ regex_t preg;
+ bool ret;
+
+ if (regcomp(&preg, rule.pattern.c_str(), REG_EXTENDED | REG_NOSUB))
+ throw runtime_error("error compiling regular expression '" + rule.pattern + "', aborting");
+
+ ret = !regexec(&preg, file.c_str(), 0, 0, 0);
+ regfree(&preg);
+
+ return ret;
+}
diff --git a/pkgadd.h b/pkgadd.h
index b63fc5d1..a1b68e15 100644
--- a/pkgadd.h
+++ b/pkgadd.h
@@ -48,7 +48,7 @@ public:
virtual void print_help() const;
private:
- vector<rule_t> read_config() const;
+ vector<rule_t> read_config(string file) const;
set<string> make_keep_list(const set<string>& files, const vector<rule_t>& rules) const;
set<string> apply_install_rules(const string& name, pkginfo_t& info, const vector<rule_t>& rules);
void find_rules(const vector<rule_t>& rules, rule_event_t event, vector<rule_t>& found) const;

Generated by cgit