// Copyright (c) 2000-2002 by Per Liden #include "pkgadd.h" #include #include #include #include #include int 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") { check_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 == "-v" || option == "--version") { print_version(); } else if (option == "-h" || option == "--help") { print_help(); } else if (option[0] == '-' || !o_package.empty()) { print_invalid_option(option); } else { o_package = option; } } if (o_package.empty()) print_option_missing(); // // Check UID // if (getuid()) { print_error() << "only root can install/upgrade packages" << endl; return EXIT_ERROR; } // // Install/upgrade package // db_open(o_root); pair package = pkg_open(o_package); bool installed = db_find_pkg(package.first); if (installed && !o_upgrade) { print_error() << "package " << package.first << " already installed (use -u to upgrade)" << endl; return EXIT_ERROR; } else if (!installed && o_upgrade) { print_error() << "package " << package.first << " not previously installed (skip -u to install)" << endl; return EXIT_ERROR; } set files = db_find_conflicts(package.first, package.second); if (!files.empty()) { if (o_force) { db_rm_files(files); // Remove conflicts } else { copy(files.begin(), files.end(), ostream_iterator(cerr, "\n")); print_error() << "listed file(s) already installed (use -f to ignore and overwrite)" << endl; return EXIT_ERROR; } } if (o_upgrade) db_rm_pkg(package.first, make_keep_list(package.second.files, read_config())); db_add_pkg(package.first, package.second); db_commit(); pkg_install(o_package); return EXIT_OK; } void pkgadd::print_help() const { cout << "usage: " << name() << " [options] " << endl << "options:" << endl << " -u, --upgrade upgrade package with the same name" << endl << " -f, --force force install, overwrite conflicting files" << endl << " -r, --root specify alternative installation root" << endl << " -v, --version print version and exit" << endl << " -h, --help print help and exit" << endl; exit(EXIT_OK); } vector pkgadd::read_config() const { vector 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) { print_error() << filename << ":" << linecount << ": line too long, aborting" << endl; exit(EXIT_ERROR); } 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\n", event, pattern, action, dummy) != 3) { print_error() << filename << ":" << linecount << ": too many arguments, aborting" << endl; exit(EXIT_ERROR); } if (!strcmp(event, "UPGRADE")) { rule_t rule; rule.event = rule_t::UPGRADE; rule.pattern = pattern; if (!strcmp(action, "YES")) { rule.action = true; } else if (!strcmp(action, "NO")) { rule.action = false; } else { print_error() << filename << ":" << linecount << ": '" << action << "' unknown action, should be YES or NO, aborting" << endl; exit(EXIT_ERROR); } rules.push_back(rule); } else { print_error() << filename << ":" << linecount << ": '" << event << "' unknown event, aborting" << endl; exit(EXIT_ERROR); } } } in.close(); } #ifndef NDEBUG cerr << "Configuration:" << endl; for (vector::const_iterator j = rules.begin(); j != rules.end(); j++) { cerr << " " << (*j).pattern << "\t" << (*j).action << endl; } cerr << endl; #endif return rules; } set pkgadd::make_keep_list(const set& files, const vector& rules) const { set keep_list; for (set::const_iterator i = files.begin(); i != files.end(); i++) { for (vector::const_reverse_iterator j = rules.rbegin(); j != rules.rend(); j++) { if ((*j).event == rule_t::UPGRADE) { regex_t preg; if (regcomp(&preg, (*j).pattern.c_str(), REG_EXTENDED | REG_NOSUB)) { print_error() << "error compiling regular expression '" << (*j).pattern << "', aborting" << endl; exit(EXIT_ERROR); } if (!regexec(&preg, (*i).c_str(), 0, 0, 0)) { if (!(*j).action) keep_list.insert(keep_list.end(), *i); break; } } } } #ifndef NDEBUG cerr << "Keep list:" << endl; for (set::const_iterator j = keep_list.begin(); j != keep_list.end(); j++) { cerr << " " << (*j) << endl; } cerr << endl; #endif return keep_list; }