Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 93084 Details for
Bug 142217
app-portage/portage-utils-0.20: better $ROOT support for qfile
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
qfile-0.20-better-ROOT-support.patch
qfile-0.20-better-ROOT-support.patch (text/plain), 12.64 KB, created by
TGL
on 2006-07-30 13:37:51 UTC
(
hide
)
Description:
qfile-0.20-better-ROOT-support.patch
Filename:
MIME Type:
Creator:
TGL
Created:
2006-07-30 13:37:51 UTC
Size:
12.64 KB
patch
obsolete
>--- qfile.c.orig 2006-07-26 20:28:36.000000000 +0200 >+++ qfile.c 2006-07-30 20:52:08.000000000 +0200 >@@ -9,22 +9,33 @@ > > #ifdef APPLET_qfile > >-#define QFILE_FLAGS "eo" COMMON_FLAGS >+#define QFILE_FLAGS "eoR" COMMON_FLAGS > static struct option const qfile_long_opts[] = { > {"exact", no_argument, NULL, 'e'}, > {"orphans", no_argument, NULL, 'o'}, >+ {"root-prefix", no_argument, NULL, 'R'}, > COMMON_LONG_OPTS > }; > static const char *qfile_opts_help[] = { > "Exact match", > "List orphan files", >+ "Assume arguments are already prefixed by $ROOT", > COMMON_OPTS_HELP > }; > static char qfile_rcsid[] = "$Id: qfile.c,v 1.34 2006/07/19 16:20:41 solar Exp $"; > #define qfile_usage(ret) usage(ret, QFILE_FLAGS, qfile_long_opts, qfile_opts_help, lookup_applet_idx("qfile")) > >-void qfile(char *path, int argc, char **base_names, char **dir_names, char **real_dir_names, short * non_orphans); >-void qfile(char *path, int argc, char **base_names, char **dir_names, char **real_dir_names, short * non_orphans) >+static inline short qfile_is_prefix(const char* path, const char* prefix, int prefix_length) { >+ return !prefix_length >+ || (strlen(path) >= prefix_length >+ && (path[prefix_length] == '/' || path[prefix_length] == '\0') >+ && !strncmp(path, prefix, prefix_length)); >+} >+ >+void qfile(char *path, int argc, char* root, char* real_root, char* bn_firstchars, >+ char **base_names, char **dir_names, char **real_dir_names, short * non_orphans); >+void qfile(char *path, int argc, char* root, char* real_root, char* bn_firstchars, >+ char **base_names, char **dir_names, char **real_dir_names, short * non_orphans) > { > FILE *fp; > DIR *dir; >@@ -36,6 +47,7 @@ > char pkg[126]; > depend_atom *atom; > int i, path_ok; >+ char bn_firstchar; > > if (chdir(path) != 0 || (dir = opendir(".")) == NULL) > return; >@@ -62,6 +74,9 @@ > continue; > entry_basename++; > >+ // used to cut the number of strcmp() calls >+ bn_firstchar = entry_basename[0]; >+ > for(i = 0; i < argc; i++) { > if (base_names[i] == NULL) > continue; >@@ -69,7 +84,8 @@ > continue; > path_ok = (dir_names[i] == NULL && real_dir_names[i] == NULL); > >- if (strcmp(entry_basename, base_names[i]) != 0) >+ if (bn_firstchar != bn_firstchars[i] >+ || strcmp(entry_basename, base_names[i])) > continue; > > if (!path_ok) { >@@ -93,22 +109,32 @@ > // real_dir_name == dirname(CONTENTS) > path_ok = 1; > else { >- char rpath[_Q_PATH_MAX]; >+ char rpath[_Q_PATH_MAX+1]; >+ char * fullpath = entry_dirname; > errno = 0; >- realpath(entry_dirname, rpath); >+ if (real_root != NULL && real_root[0] != '\0') >+ xasprintf(&fullpath, "%s%s", real_root, entry_dirname); >+ realpath(fullpath, rpath); > if (errno != 0) { > if (verbose) { >- warn("Could not read real path of \"%s\": %s", p, strerror(errno)); >- warn("We'll never know whether it was a result for your query..."); >+ warn("Could not read real path of \"%s\" (from %s): %s", >+ fullpath, pkg, strerror(errno)); >+ warn("We'll never know whether \"%s/%s\" was a result for your query...", >+ entry_dirname, entry_basename); > } >+ } else if (!qfile_is_prefix(rpath, real_root, strlen(real_root))) { >+ if (verbose) >+ warn("Real path of \"%s\" is not under ROOT: %s", fullpath, rpath); > } else if (dir_names[i] != NULL && >- strcmp(rpath, dir_names[i]) == 0) >+ strcmp(rpath + strlen(real_root), dir_names[i]) == 0) > // dir_name == realpath(dirname(CONTENTS)) > path_ok = 1; > else if (real_dir_names[i] != NULL && >- strcmp(rpath, real_dir_names[i]) == 0) >+ strcmp(rpath + strlen(real_root), real_dir_names[i]) == 0) > // real_dir_name == realpath(dirname(CONTENTS)) > path_ok = 1; >+ if (fullpath != entry_dirname) >+ free(fullpath); > } > free(entry_dirname); > } >@@ -125,6 +151,8 @@ > (exact ? dentry->d_name : atom->PN), NORM); > if (quiet) > puts(""); >+ else if (root != NULL) >+ printf(" (%s%s)\n", root, e->name); > else > printf(" (%s)\n", e->name); > >@@ -146,14 +174,21 @@ > { > DIR *dir; > struct dirent *dentry; >- int i; >+ int i, nb_of_queries; > char *p; > char ** basenames; > char ** dirnames; > char ** realdirnames; >- char * pwd; >+ char * basenames_firstchars; >+ char * pwd = NULL; > short * non_orphans = NULL; > short search_orphans = 0; >+ short assume_root_prefix = 0; >+ char * root_prefix; >+ char * real_root; >+ int real_root_length; >+ char tmppath[_Q_PATH_MAX+1]; >+ char abspath[_Q_PATH_MAX+1]; > > DBG("argc=%d argv[0]=%s argv[1]=%s", > argc, argv[0], argc > 1 ? argv[1] : "NULL?"); >@@ -163,92 +198,165 @@ > COMMON_GETOPTS_CASES(qfile) > case 'e': exact = 1; break; > case 'o': search_orphans = 1; break; >+ case 'R': assume_root_prefix = 1; break; > } > } > if (!exact && verbose) exact++; > if (argc == optind) > qfile_usage(EXIT_FAILURE); >+ nb_of_queries = argc - optind; > > if (chdir(portroot)) > errp("could not chdir(%s) for ROOT", portroot); > > if (chdir(portvdb) != 0 || (dir = opendir(".")) == NULL) >- return EXIT_FAILURE; >- >- if (search_orphans) >- non_orphans = xmalloc((argc-optind) * sizeof(short)); >+ errp("could not chdir(ROOT/%s) for installed packages database", portvdb); > >- // For each argument, we store its basename, its dirname, >- // and the realpath of its dirname. >+ // Try to get $PWD. Must be absolute, with no trailing slash >+ if ((pwd = getenv("PWD")) != NULL && pwd[0] == '/') { >+ pwd = xstrdup(pwd); >+ if ((pwd[strlen(pwd) - 1] == '/')) >+ pwd[strlen(pwd) - 1] = '\0'; >+ } else >+ pwd = NULL; >+ >+ // Get realpath of $ROOT, with no trailing slash >+ if (portroot[0] == '/') >+ strncpy(tmppath, portroot, _Q_PATH_MAX); >+ else if (pwd != NULL) >+ snprintf(tmppath, _Q_PATH_MAX, "%s/%s", pwd, portroot); >+ else { >+ free(pwd); >+ errp("Could not get absolute path for ROOT (\"%s\"), because of missing or not absolute $PWD", tmppath); >+ } >+ errno = 0; >+ realpath(tmppath, abspath); >+ if (errno != 0) { >+ free(pwd); >+ errp("Could not read real path of ROOT (\"%s\"): %s", tmppath, strerror(errno)); >+ } >+ if (strlen(abspath) == 1) >+ abspath[0] = '\0'; >+ real_root = xstrdup(abspath); >+ real_root_length = strlen(real_root); >+ >+ // Get a copy of $ROOT, with no trailing slash >+ // (this one is just for qfile(...) output) >+ root_prefix = xstrdup(portroot); >+ if (root_prefix[strlen(root_prefix) - 1] == '/') >+ root_prefix[strlen(root_prefix) - 1] = '\0'; >+ >+ // For each argument, we store its basename, its absolute dirname, >+ // and the realpath of its dirname. Dirnames and their realpaths >+ // are stored without their $ROOT prefix, but $ROOT is used when >+ // checking realpaths. > basenames = xmalloc((argc-optind) * sizeof(char*)); > dirnames = xmalloc((argc-optind) * sizeof(char*)); > realdirnames = xmalloc((argc-optind) * sizeof(char*)); >- if ((pwd = getenv("PWD")) != NULL) { >- int pwdlen = strlen(pwd); >- if ((pwdlen > 0) && (pwd[pwdlen-1] == '/')) >- pwd[pwdlen-1] = '\0'; >- } >+ // For optimization of qfile(), we also give it an array of the first char >+ // of each basename. This way we avoid numerous strcmp() calls. >+ basenames_firstchars = xmalloc((argc-optind) * sizeof(char)); >+ // Finally, if searching for orphans, we need an array to store the results >+ if (search_orphans) >+ non_orphans = xmalloc((argc-optind) * sizeof(short)); > for (i = 0; i < (argc-optind); ++i) { >- char tmppath[_Q_PATH_MAX]; >- char abspath[_Q_PATH_MAX]; >- > basenames[i] = NULL; > dirnames[i] = NULL; > realdirnames[i] = NULL; > >- // Record basename, but if it is "." or ".." >+ // Record basename, but if it is ".", ".." or "/" > strncpy(tmppath, basename(argv[i+optind]), _Q_PATH_MAX); >- if ((strlen(tmppath) > 2) || strncmp(tmppath, "..", strlen(tmppath))) { >+ if ((strlen(tmppath) > 2) || >+ (strncmp(tmppath, "..", strlen(tmppath)) >+ && strncmp(tmppath, "/", strlen(tmppath)))) { > basenames[i] = xstrdup(tmppath); >+ basenames_firstchars[i] = basenames[i][0]; > // If there is no "/" in the argument, then it's over. > // (we are searching a simple file name) > if (strchr(argv[i+optind], '/') == NULL) > continue; > } > >- // Make sure we have an absolute path available >- if (argv[i+optind][0] == '/') >- strncpy(abspath, argv[i+optind], _Q_PATH_MAX); >- else if (pwd != NULL) >- snprintf(abspath, _Q_PATH_MAX, "%s/%s", pwd, argv[i+optind]); >- else { >- warn("$PWD not found in environment."); >- warn("Skipping query item \"%s\".", argv[i+optind]); >- continue; >+ // Make sure we have an absolute path available (with "realpath(ROOT)" prefix) >+ if (argv[i+optind][0] == '/') { >+ if (assume_root_prefix) >+ strncpy(abspath, argv[i+optind], _Q_PATH_MAX); >+ else >+ snprintf(abspath, _Q_PATH_MAX, "%s%s", real_root, argv[i+optind]); >+ } else if (pwd != NULL) { >+ if (assume_root_prefix) >+ snprintf(abspath, _Q_PATH_MAX, "%s/%s", pwd, argv[i+optind]); >+ else >+ snprintf(abspath, _Q_PATH_MAX, "%s%s/%s", real_root, pwd, argv[i+optind]); >+ } else { >+ warn("$PWD was not found in environment, or is not an absolute path"); >+ goto skip_query_item; > } > > if (basenames[i] != NULL) { >- // Get both the dirname and its realpath >- dirnames[i] = xstrdup(dirname(abspath)); >+ // Get both the dirname and its realpath. This paths will >+ // have no trailing slash, but if it is the only char (ie., >+ // when searching for "/foobar"). >+ strncpy(tmppath, abspath, _Q_PATH_MAX); >+ strncpy(abspath, dirname(tmppath), _Q_PATH_MAX); >+ if (abspath[real_root_length] == '\0') >+ strncat(abspath, "/", 1); >+ dirnames[i] = xstrdup(abspath + real_root_length); > errno = 0; >- realpath(dirnames[i], tmppath); >+ realpath(abspath, tmppath); > if (errno != 0) { > if (verbose) { >- warn("Could not read real path of \"%s\": %s", dirnames[i], strerror(errno)); >- warn("Results for query item \"%s\" may not be accurate.", argv[i+optind]); >+ warn("Could not read real path of \"%s\": %s", abspath, strerror(errno)); >+ warn("Results for query item \"%s\" may be inaccurate.", argv[i+optind]); > } >- } else if (strcmp(dirnames[i], tmppath)) >- realdirnames[i] = xstrdup(tmppath); >+ continue; >+ } >+ if (!qfile_is_prefix(tmppath, real_root, real_root_length)) { >+ warn("Real path of \"%s\" is not under ROOT: %s", abspath, tmppath); >+ goto skip_query_item; >+ } >+ if (tmppath[real_root_length] == '\0') >+ strncat(tmppath, "/", 1); >+ if (strcmp(dirnames[i], tmppath + real_root_length)) >+ realdirnames[i] = xstrdup(tmppath + real_root_length); > } else { > // No basename means we are looking for something like "/foo/bar/.." > // Dirname is meaningless here, we can only get realpath of the full > // path and then split it. > errno = 0; >- realpath(tmppath, abspath); >+ realpath(abspath, tmppath); > if (errno != 0) { >- warn("Could not read real path of \"%s\": %s", tmppath, strerror(errno)); >- warn("Skipping query item \"%s\".", argv[i+optind]); >- continue; >+ warn("Could not read real path of \"%s\": %s", abspath, strerror(errno)); >+ goto skip_query_item; >+ } >+ if (!qfile_is_prefix(tmppath, real_root, real_root_length)) { >+ warn("Real path of \"%s\" is not under ROOT: %s", abspath, tmppath); >+ goto skip_query_item; > } >- basenames[i] = xstrdup(basename(tmppath)); >- realdirnames[i] = xstrdup(dirname(tmppath)); >+ strncpy(abspath, tmppath, _Q_PATH_MAX); >+ basenames[i] = xstrdup(basename(abspath)); >+ basenames_firstchars[i] = basenames[i][0]; >+ strncpy(abspath, dirname(tmppath), _Q_PATH_MAX); >+ if (tmppath[real_root_length] == '\0') >+ strncat(tmppath, "/", 1); >+ realdirnames[i] = xstrdup(abspath + real_root_length); > } >+ continue; >+ >+ skip_query_item: >+ --nb_of_queries; >+ warn("Skipping query item \"%s\".", argv[i+optind]); >+ if (basenames[i] != NULL) free(basenames[i]); >+ if (dirnames[i] != NULL) free(dirnames[i]); >+ if (realdirnames[i] != NULL) free(realdirnames[i]); >+ basenames[i] = dirnames[i] = realdirnames[i] = NULL; > } > >- /* open /var/db/pkg */ >- while ((dentry = q_vdb_get_next_dir(dir))) { >- xasprintf(&p, "%s%s/%s", portroot, portvdb, dentry->d_name); >- qfile(p, (argc-optind), basenames, dirnames, realdirnames, non_orphans); >+ /* open /var/db/pkg (but if all query items were skipped) */ >+ while (nb_of_queries && (dentry = q_vdb_get_next_dir(dir))) { >+ xasprintf(&p, "%s/%s/%s", real_root, portvdb, dentry->d_name); >+ qfile(p, (argc-optind), (assume_root_prefix ? root_prefix : NULL), real_root, >+ basenames_firstchars, basenames, dirnames, realdirnames, non_orphans); > free(p); > } > >@@ -273,6 +381,13 @@ > } > free(basenames); free(dirnames); free(realdirnames); > >+ free(basenames_firstchars); >+ >+ if (pwd != NULL) >+ free(pwd); >+ >+ free(real_root); free(root_prefix); >+ > return (found ? EXIT_SUCCESS : EXIT_FAILURE); > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 142217
: 93084 |
94694