📄 options.cc
字号:
//=======================================================================// Options.cc//-----------------------------------------------------------------------// This file is part of the package paco// Copyright (C) 2004-2007 David Rosal <david.3r@gmail.com>// For more information visit http://paco.sourceforge.net//=======================================================================#include "config.h"#include "global.h"#include "Options.h"#include "PkgSet.h"#include <fstream>#include <iostream>#include <getopt.h>using std::string;using std::endl;using std::cout;using std::cerr;using namespace Paco;// Forward declarationsstatic SortType getSortType(string const& s);static void help();static void version();static int toSizeUnit(char* arg);static string getDirname();static void dieHelp(string const& msg = "");Options::Options(int argc, char* argv[]): std::bitset<N_BITS>(0), mSortType(NO_SORT), mSizeUnit(HUMAN_READABLE), mSkip(), mLogPkg(), mInclude(Config::include()), mExclude(Config::exclude()), mMode(PKGLIST), mArgs(){ if (argc == 1) dieHelp("No input packages"); set(LOG_IGNORE_ERRORS, Config::logIgnoreErrors()); enum { OPT_SORT = 1, OPT_REMOVE_SHARED, OPT_VERSION, OPT_LOG_IGNORE_ERRORS, OPT_LOG_MISSING, OPT_LOG_IGNORE_SHARED }; struct option opt[] = { // General options { "help", 0, 0, 'h' }, { "version", 0, 0, OPT_VERSION }, { "logdir", 1, 0, 'L' }, { "verbose", 0, 0, 'v' }, { "all", 0, 0, 'a' }, { "expand", 0, 0, 'x' }, // Database maintenance options { "update", 0, 0, 'u' }, { "unlog", 0, 0, 'U' }, // List options { "date", 0, 0, 'd' }, { "sort", 1, 0, OPT_SORT }, { "block-size", 1, 0, 'b' }, { "kilobytes", 0, 0, 'k' }, { "size", 0, 0, 's' }, { "missing-size", 0, 0, 'n' }, { "files", 0, 0, 'f' }, { "missing-files", 0, 0, 'm' }, { "shared", 0, 0, 'c' }, { "non-shared", 0, 0, 'N' }, { "who-shares", 0, 0, 'w' }, { "reverse", 0, 0, 'R' }, { "total", 0, 0, 't' }, { "one-column", 0, 0, '1' }, { "symlinks", 0, 0, 'y' }, { "no-package-name", 0, 0, 'z' }, // Info options { "info", 0, 0, 'i' }, { "query", 0, 0, 'q' }, { "owner", 0, 0, 'q' }, { "configure-options", 0, 0, 'o' }, // Remove options { "remove", 0, 0, 'r' }, { "remove-shared", 0, 0, OPT_REMOVE_SHARED }, { "batch", 0, 0, 'B' }, { "skip", 1, 0, 'e' }, // Log options { "log", 0, 0, 'l' }, { "package", 1, 0, 'p' }, { "include", 1, 0, 'I' }, { "exclude", 1, 0, 'E' }, { "append", 0, 0, '+' }, { "dirname", 0, 0, 'D' }, { "log-missing", 0, 0, OPT_LOG_MISSING }, { "ignore-errors", 0, 0, OPT_LOG_IGNORE_ERRORS }, { "ignore-shared", 0, 0, OPT_LOG_IGNORE_SHARED }, { NULL ,0, 0, 0 }, }; // Deal with the weird non-getopt-friendly '-p+' option for (int i = 1; i < argc; ++i) { if (argv[i][0] == '-' && argv[i][1] != '-') { for (char* p = argv[i]; (p = strstr(p, "p+")); ) memcpy(p, "+p", 2); } } int op, r = 0; bool cLower(false); while ((op = getopt_long(argc, argv, "1+aBb:cCdDe:E:fFhiI:klL:nNmMop:qrRstuUvwxyz", opt, 0)) >= 0) { switch (op) { // General options case OPT_VERSION: version(); case 'h': help(); case 'L': Config::logdir(optarg); break; case 'v': gOut.verbosity()++; break; case 'a': set(ALL_PKGS); break; case 'x': break; // obsolete // Database options case 'U': setMode(UNLOG, op); break; case 'u': setMode(UPDATE, op); break; // Info options case 'i': setMode(INFO, op); break; case 'o': setMode(CONFOPTS, op); break; case 'q': setMode(QUERYFILES, op); break; // General list options case OPT_SORT: mSortType = getSortType(optarg); break; case 'R': set(REVERSE_SORT); break; case 't': set(PRINT_TOTALS); break; case 's': set(PRINT_SIZE); break; case 'b': mSizeUnit = toSizeUnit(optarg); break; case 'k': mSizeUnit = KILOBYTE; break; // Package list options case 'd': case 'n': case 'F': case 'M': case 'C': case '1': setMode(PKGLIST, op); switch (op) { case 'd': set(test(PRINT_DAY) ? PRINT_HOUR : PRINT_DAY); break; case 'n': set(PRINT_SIZE_MISS); break; case 'F': set(PRINT_FILES_INST); break; case 'M': set(PRINT_FILES_MISS); break; case 'C': set(PRINT_FILES_SHARED); break; case '1': set(ONE_COLUMN_LIST); break; } break; // File list options case 'f': case 'm': case 'c': case 'N': case 'y': case 'z': case 'w': setMode(FILELIST, op); switch (op) { case 'f': set(PRINT_FILES_INST); break; case 'm': set(PRINT_FILES_MISS); break; case 'c': set(PRINT_FILES_SHARED); cLower = true; break; case 'N': set(PRINT_FILES_NON_SHARED); break; case 'y': set(PRINT_SYMLINKS); break; case 'z': set(NO_PRINT_PKG_NAME); break; case 'w': set(PRINT_WHO_SHARES); break; } break; // Remove options case 'r': setMode(REMOVE, op); set(REMOVE_UNLOG, (r++ > 0)); break; case 'e': setMode(REMOVE, op); mSkip = optarg; break; case 'B': setMode(REMOVE, op); set(REMOVE_BATCH); break; case OPT_REMOVE_SHARED: set(REMOVE_SHARED); break; // Log options case 'l': case 'p': case 'D': case 'I': case 'E': case '+': setMode(LOG, op); switch (op) { case 'p': mLogPkg = optarg; break; case 'D': mLogPkg = getDirname(); break; case 'I': mInclude = optarg; break; case 'E': mExclude = optarg; break; case '+': set(LOG_APPEND); break; } break; case OPT_LOG_MISSING: set(LOG_MISSING); break; case OPT_LOG_IGNORE_ERRORS: set(LOG_IGNORE_ERRORS); break; case OPT_LOG_IGNORE_SHARED: set(LOG_IGNORE_SHARED); break; default: dieHelp(); } } mArgs.assign(argv + optind, argv + argc); if (mArgs.empty()) { if (mMode == QUERYFILES) dieHelp("No input files"); else if ((!allPkgs() && mMode != LOG) || mMode == REMOVE) dieHelp("No input packages"); } if (filesShared() && filesNonShared()) dieHelp("-cN: Incompatible options"); else if (!filesInst() && !filesMiss()) { if (filesShared() && cLower) dieHelp("Option -c requires at least one of -f or -m"); else if (filesNonShared()) dieHelp("Option -N requires at least one of -f or -m"); } if (mMode == LOG && !mLogPkg.empty()) { if (!isalnum(mLogPkg.at(0)) || mLogPkg.find('/') != string::npos) throw X(mLogPkg + ": Invalid package name"); } if (inPaths(Config::logdir(), "/dev:/proc:/sys")) throw X(Config::logdir() + ": Invalid log directory"); else if (!Config::logdirWritable()) { if (mMode == UPDATE || mMode == UNLOG || mMode == REMOVE) throw XErrno(Config::logdir()); else if (mMode == LOG && !mLogPkg.empty()) { if (errno != ENOENT || mkdir(Config::logdir().c_str(), 0755) < 0) throw XErrno(Config::logdir()); } }}void Options::setMode(Mode m, char optchar){ static char modes[NMODES] = { 0 }; string optstr("-"); modes[m] = optchar; for (int i = 0; i < NMODES; ++i) { if (modes[i]) { optstr += modes[i]; if (optstr.size() > 2) dieHelp(optstr + ": Incompatible options"); } } mMode = m;}static void help(){cout <<"paco - the source code pacKAGE oRGANIZER\n\n""Usage:\n"" paco [OPTIONS] <packages|files|command>\n\n""General options:\n"" -L, --logdir=DIR Use DIR as the log directory.\n"" -a, --all Apply to all logged packages (not with -r).\n"" -v, --verbose Verbose output (-vv produces debugging messages).\n"" -h, --help Display this help message.\n"" --version Display version information.\n\n""Database maintenance options:\n"" -u, --update Update the log of the package.\n"" -U, --unlog Remove the log of the package.\n\n""General list options:\n"" -b, --block-size=SIZE Use blocks of SIZE bytes for the sizes.\n"" -k, --kilobytes Like '--block-size=1024'.\n"" -R, --reverse Reverse order while sorting.\n"" --sort=WORD Sort by WORD: 'name', 'date' (or 'time'), 'size',\n"" 'files', 'missing-size' or 'missing-files'.\n"" -t, --total Print totals.\n\n""Package list options:\n"" -1, --one-column Print one package per line.\n"" -F Print the number of installed files.\n"" -M Print the number of missing files.\n"" -C Print the number of shared files.\n"" -d, --date Print the installation day (-dd prints the hour too).\n"" -s, --size Print the installed size of each package.\n"" -n, --missing-size Print the missing size of each package.\n\n""File list options:\n"" -f, --files List installed files.\n"" -m, --missing-files List missing files.\n"" -c, --shared With -f and/or -m: List only the shared files.\n"" -N, --non-shared With -f and/or -m: List only the non shared files.\n"" -w, --who-shares With -c: Print the packages that share each file.\n"" -y, --symlinks Print the contents of symbolic links.\n"" -z, --no-package-name Don't print the name of the package.\n"" -s, --size Show the size of each file.\n\n""Information options:\n"" Note: Information may be not available for all packages.\n"" -i, --info Print package information.\n"" -o, --configure-options Print the options passed to configure when the\n"" package was installed.\n"" -q, --query, --owner Query for the packages that own one or more files.\n\n""Remove options:\n"" -r, --remove Remove the (non shared) files of the package. '-rr'\n"" forces the package to be removed from the database.\n"" --remove-shared Remove also the shared files.\n"" -B, --batch Do not ask for confirmation when removing.\n"" -e, --skip=PATH:... Do not remove files in PATHs (see the man page).\n\n""Log options:\n"" -l, --log Enable log mode. See the man page.\n"" -p, --package=PKG Name of the package to log.\n" " -D, --dirname Use the name of the current directory as the name\n"" of the package.\n"" -+, --append With -p or -D: If the package is already logged,\n"" append the list of files to its log.\n"" --log-missing Do not skip missing files.\n"" --ignore-shared With -p or -D: Do not log the shared files.\n"" --ignore-errors Do not exit if the install command fails.\n"" -I, --include=PATH:... List of paths to scan.\n"" -E, --exclude=PATH:... List of paths to skip.\n\n""Note: The package list mode is enabled by default.\n\n""Send bugs to: David Rosal <" PACKAGE_BUGREPORT "s>" << endl; exit(EXIT_SUCCESS);}static void version(){ cout << "paco-" PACKAGE_VERSION " (" RELEASEDATE ")\n" "Copyright (C) David Rosal <" PACKAGE_BUGREPORT ">\n" "Protected by the GNU General Public License" << endl; exit(EXIT_SUCCESS);}static string getDirname(){ char dirname[8192]; if (!getcwd(dirname, sizeof(dirname))) throw XErrno("getcwd()"); return strrchr(dirname, '/') + 1;}// // Process the '--block-size=SIZE' option//static int toSizeUnit(char* arg){ int i = -1, b = 0, unit; while (isdigit(arg[++i])); switch (arg[i]) { case 'k': case 'K': b = KILOBYTE; break; case 'm': case 'M': b = MEGABYTE; break; case 'b': case 'B': case 0: b = 1; break; default: goto ____invalid; } if ((unit = i ? (Paco::str2num<int>(arg) * b) : b)) return unit ? unit : HUMAN_READABLE;____invalid: throw X(string(arg) + ": Invalid block size");}//// Process the '--sort=WORD' option//static SortType getSortType(string const& s){ SortType ret(SORT_NAME); if (!s.size()) goto ____failure; else if (!s.compare(0, s.size(), "size", s.size())) ret = SORT_SIZE; else if (!s.compare(0, s.size(), "date", s.size()) || !s.compare(0, s.size(), "time", s.size())) ret = SORT_DATE; else if (!s.compare(0, s.size(), "missing-size", s.size()) && s.size() > 8) ret = SORT_SIZE_MISS; else if (!s.compare(0, s.size(), "missing-files", s.size()) && s.size() > 8) ret = SORT_FILES_MISS; else if (!s.compare(0, s.size(), "files", s.size())) ret = SORT_FILES_INST; else if (s.compare(0, s.size(), "name", s.size())) { ____failure: throw X(string("Invalid argument '") + s + "' for option '--sort'.\nValid arguments are:\n" " - 'name'\n" " - 'size'\n" " - 'date' or 'time'\n" " - 'files'\n" " - 'missing-files'\n" " - 'missing-size'"); } return ret;}static void dieHelp(string const& msg /* = "" */){ string out(msg); if (!out.empty()) { out.insert(0, "paco: "); out += '\n'; } cerr << out << "Try 'paco --help' for more information\n"; exit(EXIT_FAILURE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -