diff -Narup portage-utils-20070115/libq/atom_compare.c portage-utils-20070115.new/libq/atom_compare.c --- portage-utils-20070115/libq/atom_compare.c 2007-01-15 19:20:13.000000000 +0100 +++ portage-utils-20070115.new/libq/atom_compare.c 2007-01-15 19:21:58.239945916 +0100 @@ -43,11 +43,27 @@ int atom_compare(const depend_atom * con /* check version */ if (a1->PV && a2->PV) { + int i; char *s1, *s2; unsigned int n1, n2; /* first we compare the version [1.0]z_alpha1 */ s1 = a1->PV; s2 = a2->PV; + /* treat the case of svn/live/scm/cvs.. version */ + n1=n2=0; + for (i=0; iPV || a2->PV) return NOT_EQUAL; - +same_version: if (a1->PR_int == a2->PR_int) return EQUAL; else if (a1->PR_int < a2->PR_int) diff -Narup portage-utils-20070115/libq/atom_explode.c portage-utils-20070115.new/libq/atom_explode.c --- portage-utils-20070115/libq/atom_explode.c 2007-01-15 19:20:13.000000000 +0100 +++ portage-utils-20070115.new/libq/atom_explode.c 2007-01-15 19:21:58.248944543 +0100 @@ -13,8 +13,21 @@ typedef enum { VER_ALPHA=0, VER_BETA, VER_PRE, VER_RC, VER_NORM, VER_P } atom_suffixes; const char * const atom_suffixes_str[] = { "_alpha", "_beta", "_pre", "_rc", "_/*bogus*/", "_p", NULL }; +const struct { + const char *version; + const size_t version_len; +} atom_version_str[] = { + {"-scm", 4}, + {"-cvs", 4}, + {"-svn", 4}, + {"-live", 5}, + {"-9999", 5} +}; + + typedef struct { + char *OVERLAY; char *CATEGORY; char *PN; int PR_int; @@ -61,6 +74,16 @@ depend_atom *atom_explode(const char *at ret->suffix = VER_NORM; memcpy(ret->CATEGORY, atom, slen); + /* find the OVERLAY, if present */ + if ((ptr_tmp=strstr(ret->CATEGORY, "::"))) { + if (*(ptr_tmp+2)) + ret->OVERLAY = ptr_tmp + 2; + else + ret->OVERLAY = NULL; + *ptr_tmp = 0; + ptr_tmp = NULL; + } + /* break up the CATEOGRY and PVR */ if ((ptr = strrchr(ret->CATEGORY, '/')) != NULL) { ret->PN = ptr+1; @@ -144,6 +167,16 @@ eat_version: ret->PV = ptr_tmp+1; ret->PV[-1] = '\0'; goto found_pv; + } + + for (i=0; iPN, atom_version_str[i].version)) && ptr_tmp == ret->PN+strlen(ret->PN)-atom_version_str[i].version_len) + break; + + if (ptr_tmp && *ptr_tmp) { + ret->PV = ptr_tmp+1; + ret->PV[-1] = '\0'; + goto found_pv; } else { /* atom has no version */ ret->PV = ret->PVR = NULL; diff -Narup portage-utils-20070115/main.c portage-utils-20070115.new/main.c --- portage-utils-20070115/main.c 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/main.c 2007-01-15 19:21:58.257943170 +0100 @@ -71,6 +71,7 @@ int rematch(const char *, const char *, static char *rmspace(char *); void initialize_portage_env(void); +void initialize_overlays (char portdir_overlay[]); void initialize_ebuild_flat(void); void reinitialize_ebuild_flat(void); void reinitialize_as_needed(void); @@ -85,13 +86,24 @@ static int quiet = 0; static char pretend = 0; static char reinitialize = 0; static char reinitialize_metacache = 0; -static char portdir[_Q_PATH_MAX] = "/usr/portage"; static char portarch[20] = ""; -static char portvdb[] = "var/db/pkg"; +static char portvdb[_Q_PATH_MAX] = "var/db/pkg"; static char portcachedir[] = "metadata/cache"; static char portroot[_Q_PATH_MAX] = "/"; static char config_protect[_Q_PATH_MAX] = "/etc/"; +typedef struct overlay_t overlay_t; +struct overlay_t { + char name[64]; + char path[_Q_PATH_MAX]; + char cache[_Q_PATH_MAX]; + struct overlay_t *next; +}; + +static overlay_t *first_overlay = NULL; +/* temporary workaround ? */ +static overlay_t *overlay_gentoo = NULL; + char pkgdir[512] = "/usr/portage/packages/"; char port_tmpdir[512] = "/var/tmp/portage/"; @@ -201,10 +213,10 @@ static void usage(int status, const char for (i = 0; opts[i].name; ++i) { assert(help[i] != NULL); /* this assert is a life saver when adding new applets. */ if (opts[i].has_arg == no_argument) - printf(" -%c, --%-15s%s*%s %s\n", opts[i].val, + printf(" -%c, --%-16s%s*%s %s\n", opts[i].val, opts[i].name, RED, NORM, _(help[i])); else - printf(" -%c, --%-8s %s%s %s*%s %s\n", opts[i].val, + printf(" -%c, --%-9s %s%s %s*%s %s\n", opts[i].val, opts[i].name, DKBLUE, NORM, RED, NORM, _(help[i])); } exit(status); @@ -467,17 +479,85 @@ char *strincr_var(const char *name, char return (char *) value; } +void initialize_overlays (char portdir_overlay[]) +{ + short merror = 0; + char buf[BUFSIZE], file[_Q_PATH_MAX], *s, *p, *t; + overlay_t *cur_overlay; + FILE *repo_nameFP; + s = portdir_overlay; + + first_overlay = xmalloc(sizeof(*first_overlay)); + cur_overlay = first_overlay; + + while (*s) { + /* except on the first loop */ + if (s!=portdir_overlay) { + cur_overlay->next = xmalloc (sizeof (*cur_overlay->next)); + cur_overlay = cur_overlay->next; + } + cur_overlay->next = NULL; + + if ((p=strchr(s,' '))) + *p = 0; + + snprintf(cur_overlay->path, sizeof(cur_overlay->path), "%s%s", (strcmp(portroot, "/") ? portroot : ""), s); + + /* find the name for the overlay */ + snprintf(file, sizeof(file), "%s/profiles/repo_name", cur_overlay->path); + + if ((repo_nameFP = fopen(file, "r"))) { + if (!(fgets(buf, sizeof(buf),repo_nameFP))) + merror++; + rmspace(buf); + if ((t = strchr(buf,'\n'))) + *t = 0; + strncpy(cur_overlay->name, buf, sizeof(cur_overlay->name)); + + fclose(repo_nameFP); + } else + merror++; + + if (merror) { + /* delete trailing '/' */ + t = cur_overlay->path + strlen(cur_overlay->path) - 1; + if (*t == '/') + *t = 0; + strncpy(file, cur_overlay->path, sizeof(file)); + strncpy(cur_overlay->name, basename(file), sizeof(cur_overlay->name)); + merror=0; + } + + if (!strncmp(cur_overlay->name, "gentoo", sizeof(cur_overlay->name))) { + snprintf(cur_overlay->cache, sizeof(cur_overlay->cache), "%s/%s", cur_overlay->path, portcachedir); + overlay_gentoo = cur_overlay; + } else + strcpy(cur_overlay->cache, "/var/empty"); + + if (p) + s = p+1; /* because portdir_overlay has no trailing space */ + else + break; + } + +} + + void initialize_portage_env(void) { char nocolor = 0; int i, f; struct stat st; FILE *fp; + char tmp_portdir[_Q_PATH_MAX]; char buf[BUFSIZE], *s, *p; char profile[_Q_PATH_MAX], portage_file[_Q_PATH_MAX]; + char portdir_overlay[BUFSIZE] = ""; + const char *files[] = {portage_file, "/etc/make.globals", "/etc/make.conf"}; typedef enum { _Q_BOOL, _Q_STR, _Q_ISTR } var_types; + struct { const char *name; const size_t name_len; @@ -491,7 +571,8 @@ void initialize_portage_env(void) {"CONFIG_PROTECT", 14, _Q_STR, config_protect, sizeof(config_protect)}, {"NOCOLOR", 7, _Q_BOOL, &nocolor, 1}, {"FEATURES", 8, _Q_ISTR, features, sizeof(features)}, - {"PORTDIR", 7, _Q_STR, portdir, sizeof(portdir)}, + {"PORTDIR", 7, _Q_STR, tmp_portdir, sizeof(tmp_portdir)}, + {"PORTDIR_OVERLAY", 15, _Q_ISTR, portdir_overlay,sizeof(portdir_overlay)}, {"PORTAGE_BINHOST", 15, _Q_STR, binhost, sizeof(binhost)}, {"PORTAGE_TMPDIR", 14, _Q_STR, port_tmpdir, sizeof(port_tmpdir)}, {"PKGDIR", 6, _Q_STR, pkgdir, sizeof(pkgdir)}, @@ -589,6 +670,14 @@ void initialize_portage_env(void) no_colors(); else color_remap(); + + snprintf(tmp_portdir, sizeof(tmp_portdir), "%s/%s", (strcmp(portroot, "/") ? portroot : ""), portvdb); + strncpy(portvdb, tmp_portdir, sizeof(portvdb)); + strincr_var("PORTDIR_OVERLAY", tmp_portdir, portdir_overlay, sizeof(portdir_overlay)); + + /* now we initiliase the overlay chained list */ + initialize_overlays(portdir_overlay); + } enum { @@ -617,20 +706,25 @@ const char *initialize_flat(int cache_ty int a, b, c, d, e, i; int frac, secs, count; FILE *fp; + overlay_t *cur_overlay; a = b = c = d = e = i = 0; count = frac = secs = 0; + cur_overlay = first_overlay; cache_file = (cache_type == CACHE_EBUILD ? CACHE_EBUILD_FILE : CACHE_METADATA_FILE); - if (chdir(portdir) != 0) { - warnp("chdir to PORTDIR '%s' failed", portdir); - goto ret; - } - - if (cache_type == CACHE_METADATA && chdir(portcachedir) != 0) { - warnp("chdir to portage cache '%s/%s' failed", portdir, portcachedir); - goto ret; + /* SAM review without gentoo! */ + if (cache_type == CACHE_METADATA) { + if (chdir(overlay_gentoo->cache) != 0) { + warnp("chdir to portage cache '%s' failed", overlay_gentoo->cache); + goto ret; + } + } else { + if (chdir(overlay_gentoo->path) != 0) { + warnp("chdir to PORTDIR '%s' failed", overlay_gentoo->path); + goto ret; + } } if ((stat(cache_file, &st)) != (-1)) @@ -645,64 +739,87 @@ const char *initialize_flat(int cache_ty unlink(cache_file); if (errno != ENOENT) { - warnfp("unlinking '%s/%s' failed", portdir, cache_file); + /* SAM review without gentoo! */ + warnfp("unlinking '%s/%s' failed", overlay_gentoo->path, cache_file); goto ret; } + /* SAM review without gentoo! */ if ((fp = fopen(cache_file, "w")) == NULL) { - warnfp("opening '%s/%s' failed", portdir, cache_file); + warnfp("opening '%s/%s' failed", (cache_type == CACHE_EBUILD ? overlay_gentoo->path : overlay_gentoo->cache), cache_file); goto ret; } gettimeofday(&start, NULL); - if ((a = scandir(".", &category, filter_hidden, alphasort)) < 0) - goto ret; - - for (i = 0; i < a; i++) { - stat(category[i]->d_name, &st); - if (!S_ISDIR(st.st_mode)) - continue; - if (strchr(category[i]->d_name, '-') == NULL) - if ((strncmp(category[i]->d_name, "virtual", 7)) != 0) + do { + switch (cache_type) { + case CACHE_EBUILD: + if (chdir(cur_overlay->path) != 0) { + warnp("chdir to '%s' failed, skipping the %s repository", cur_overlay->path, cur_overlay->name); continue; - - if ((b = scandir(category[i]->d_name, &pn, filter_hidden, alphasort)) < 0) + } + break; + case CACHE_METADATA: + if (!strcmp(cur_overlay->cache, "/var/empty")) { + if (verbose) + warnp("No cache defined for the %s repository", cur_overlay->name); + continue; + } else if (chdir(cur_overlay->cache) != 0) { + warnp("chdir to '%s' failed, skipping the %s repository",cur_overlay->cache, cur_overlay->name); + continue; + } + break; + } + if ((a = scandir(".", &category, filter_hidden, alphasort)) < 0) continue; - for (c = 0; c < b; c++) { - char de[_Q_PATH_MAX]; - snprintf(de, sizeof(de), "%s/%s", category[i]->d_name, pn[c]->d_name); + for (i = 0; i < a; i++) { + stat(category[i]->d_name, &st); + if (!S_ISDIR(st.st_mode)) + continue; + if (strchr(category[i]->d_name, '-') == NULL) + if ((strncmp(category[i]->d_name, "virtual", 7)) != 0) + continue; - if (stat(de, &st) < 0) + if ((b = scandir(category[i]->d_name, &pn, filter_hidden, alphasort)) < 0) continue; + for (c = 0; c < b; c++) { + char de[_Q_PATH_MAX]; - switch (cache_type) { - case CACHE_EBUILD: - if (!S_ISDIR(st.st_mode)) + snprintf(de, sizeof(de), "%s/%s", category[i]->d_name, pn[c]->d_name); + + if (stat(de, &st) < 0) continue; - break; - case CACHE_METADATA: - if (S_ISREG(st.st_mode)) - fprintf(fp, "%s\n", de); - continue; - break; - } - if ((e = scandir(de, &eb, filter_hidden, alphasort)) < 0) - continue; - for (d = 0; d < e; d++) { - if ((p = strrchr(eb[d]->d_name, '.')) != NULL) - if (strcmp(p, ".ebuild") == 0) { - count++; - fprintf(fp, "%s/%s/%s\n", category[i]->d_name, pn[c]->d_name, eb[d]->d_name); - } + + switch (cache_type) { + case CACHE_EBUILD: + if (!S_ISDIR(st.st_mode)) + continue; + break; + case CACHE_METADATA: + if (S_ISREG(st.st_mode)) + fprintf(fp, "%s::%s\n", de, cur_overlay->name); + continue; + break; + } + if ((e = scandir(de, &eb, filter_hidden, alphasort)) < 0) + continue; + for (d = 0; d < e; d++) { + if ((p = strrchr(eb[d]->d_name, '.')) != NULL) + if (strcmp(p, ".ebuild") == 0) { + count++; + fprintf(fp, "%s/%s/%s::%s\n", category[i]->d_name, pn[c]->d_name, eb[d]->d_name, cur_overlay->name); + } + } + while (d--) free(eb[d]); + free(eb); } - while (d--) free(eb[d]); - free(eb); + while (b--) free(pn[b]); + free(pn); } - while (b--) free(pn[b]); - free(pn); - } + } while ((cur_overlay = cur_overlay->next)); + fclose(fp); while (a--) free(category[a]); free(category); @@ -721,7 +838,7 @@ const char *initialize_flat(int cache_ty warn("Finished %u entries in %d.%06d seconds", count, secs, frac); if (secs > 100) - warn("You should consider a faster file system such as reiserfs for PORTDIR='%s'", portdir); + warn("You should consider a faster file system such as reiserfs for repositories"); ret: return cache_file; } @@ -730,8 +847,8 @@ ret: void reinitialize_ebuild_flat(void) { - if ((chdir(portdir)) != 0) { - warnp("chdir to PORTDIR '%s' failed", portdir); + if ((chdir(first_overlay->path)) != 0) { + warnp("chdir to PORTDIR '%s' failed", first_overlay->path); return; } unlink(CACHE_EBUILD_FILE); @@ -766,8 +883,8 @@ typedef struct { } portage_cache; void cache_free(portage_cache *cache); -portage_cache *cache_read_file(const char *file); -portage_cache *cache_read_file(const char *file) +portage_cache *cache_read_file(char *file); +portage_cache *cache_read_file(char *file) { struct stat s; char *ptr; @@ -775,8 +892,12 @@ portage_cache *cache_read_file(const cha portage_cache *ret = NULL; size_t len; + if ((ptr = strstr(file, "::"))) + *ptr = 0; if ((f = fopen(file, "r")) == NULL) goto err; + if (ptr) + *ptr = ':'; if (fstat(fileno(f), &s) != 0) goto err; @@ -1004,10 +1125,20 @@ fuckit: return cpf; } +/* free overlays */ +void free_overlays(overlay_t *overlay); +void free_overlays(overlay_t *overlay) +{ + if (overlay->next) + free_overlays(overlay->next); + free(overlay); +} + void cleanup() { reinitialize_as_needed(); free_sets(virtuals); + free_overlays(first_overlay); fclose(stderr); } diff -Narup portage-utils-20070115/man/q.1 portage-utils-20070115.new/man/q.1 --- portage-utils-20070115/man/q.1 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/man/q.1 2007-01-15 19:21:58.265941950 +0100 @@ -61,11 +61,14 @@ quse qxpak : manipulate xpak archives .PP -Options: \fB\-[irmvqChV]\fR +Options: \fB\-[ilrmvqChV]\fR .TP \fB\-i\fR, \fB\-\-install\fR * Install symlinks for applets .TP +\fB\-l\fR, \fB\-\-ls\-overlays\fR +* List configured overlays +.TP \fB\-r\fR, \fB\-\-reinitialize\fR * Reinitialize ebuild cache .TP diff -Narup portage-utils-20070115/man/qgrep.1 portage-utils-20070115.new/man/qgrep.1 --- portage-utils-20070115/man/qgrep.1 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/man/qgrep.1 2007-01-15 19:21:58.273940729 +0100 @@ -16,6 +16,11 @@ Options: \fB\-[IiHcevqChV]\fR \fB\-H\fR, \fB\-\-with\-filename\fR * Print the filename for each match .TP +\fB\-o\fR, \fB\-\-overlay\fR + +.BR + * Only consider the overlay +.TP \fB\-c\fR, \fB\-\-count\fR * Only print a count of matching lines per FILE .TP diff -Narup portage-utils-20070115/man/qsearch.1 portage-utils-20070115.new/man/qsearch.1 --- portage-utils-20070115/man/qsearch.1 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/man/qsearch.1 2007-01-15 19:21:58.282939357 +0100 @@ -5,7 +5,7 @@ qsearch \- search pkgname/desc .B qsearch \fI\fR .SH DESCRIPTION -Options: \fB\-[acsSNHvqChV]\fR +Options: \fB\-[aco\fR:psSNHvqChV] .TP \fB\-a\fR, \fB\-\-all\fR * List the descriptions of every package in the cache @@ -13,6 +13,14 @@ Options: \fB\-[acsSNHvqChV]\fR \fB\-c\fR, \fB\-\-cache\fR * Use the portage cache .TP +\fB\-o\fR, \fB\-\-overlay\fR + +.BR + * Search only in the overlay +.TP +\fB\-p\fR, \fB\-\-show\-path\fR +* Show the path to the ebuild +.TP \fB\-s\fR, \fB\-\-search\fR * Regex search package basenames .TP diff -Narup portage-utils-20070115/man/quse.1 portage-utils-20070115.new/man/quse.1 --- portage-utils-20070115/man/quse.1 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/man/quse.1 2007-01-15 19:21:58.290938137 +0100 @@ -5,7 +5,7 @@ quse \- find pkgs using useflags .B quse \fI\fR .SH DESCRIPTION -Options: \fB\-[eavKLDF:NvqChV]\fR +Options: \fB\-[eao\fR:vKLDF:NvqChV] .TP \fB\-e\fR, \fB\-\-exact\fR * Show exact non regexp matching using strcmp @@ -13,6 +13,11 @@ Options: \fB\-[eavKLDF:NvqChV]\fR \fB\-a\fR, \fB\-\-all\fR * Show annoying things in IUSE .TP +\fB\-o\fR, \fB\-\-overlay\fR + +.BR + * Only consider the overlay +.TP \fB\-K\fR, \fB\-\-keywords\fR * Use the KEYWORDS vs IUSE .TP diff -Narup portage-utils-20070115/qatom.c portage-utils-20070115.new/qatom.c --- portage-utils-20070115/qatom.c 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/qatom.c 2007-01-15 19:21:58.299936764 +0100 @@ -60,6 +60,7 @@ int qatom_main(int argc, char **argv) printf(" r%i", atom->PR_int); if (verbose > 1) printf(" %c", (atom->letter ? : '-')); + printf(" %s", atom->OVERLAY); putchar('\n'); atom_implode(atom); } diff -Narup portage-utils-20070115/q.c portage-utils-20070115.new/q.c --- portage-utils-20070115/q.c 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/q.c 2007-01-15 19:21:58.309935238 +0100 @@ -7,15 +7,17 @@ * Copyright 2005-2006 Mike Frysinger - */ -#define Q_FLAGS "irm" COMMON_FLAGS +#define Q_FLAGS "ilrm" COMMON_FLAGS static struct option const q_long_opts[] = { {"install", no_argument, NULL, 'i'}, + {"ls-overlays", no_argument, NULL, 'l'}, {"reinitialize", no_argument, NULL, 'r'}, {"metacache", no_argument, NULL, 'm'}, COMMON_LONG_OPTS }; static const char *q_opts_help[] = { "Install symlinks for applets", + "List configured overlays", "Reinitialize ebuild cache", "Reinitialize metadata cache", COMMON_OPTS_HELP @@ -70,6 +72,7 @@ int q_main(int argc, char **argv) int i; char *p; APPLET func; + overlay_t * cur_overlay; if (argc == 0) return 1; @@ -89,6 +92,17 @@ int q_main(int argc, char **argv) COMMON_GETOPTS_CASES(q) case 'm': reinitialize_metacache = 1; break; case 'r': reinitialize = 1; break; + case 'l': { + printf("\n%sOverlay(s) :%s\n\n", GREEN, NORM); + cur_overlay=first_overlay; + do { + printf(" Name : %s%-20.20s%s \tlocation : %s%-60.60s%s \tmetadata : %s%-60.60s%s\n", + CYAN, cur_overlay->name, NORM, CYAN, cur_overlay->path, NORM, + CYAN, cur_overlay->cache, NORM); + } while ((cur_overlay=cur_overlay->next)); + fputc('\n', stdout); + return 0; + } case 'i': { char buf[_Q_PATH_MAX]; /* always bzero a buffer before using readlink() */ diff -Narup portage-utils-20070115/qcache.c portage-utils-20070115.new/qcache.c --- portage-utils-20070115/qcache.c 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/qcache.c 2007-01-15 19:21:58.317934018 +0100 @@ -512,10 +512,10 @@ int qcache_traverse(void (*func)(qcache_ int i, j, k, len, num_cat, num_pkg, num_ebuild; struct direct **categories, **packages, **ebuilds; - len = sizeof(char) * (strlen(QCACHE_EDB) + strlen(portdir) + 1); + len = sizeof(char) * (strlen(QCACHE_EDB) + strlen(overlay_gentoo->path) + 1); catpath = xmalloc(len); memset(catpath, 0, len); - snprintf(catpath, len, "%s%s", QCACHE_EDB, portdir); + snprintf(catpath, len, "%s%s", QCACHE_EDB, overlay_gentoo->path); if (-1 == (num_cat = scandir(catpath, &categories, qcache_file_select, alphasort))) { err("%s %s", catpath, strerror(errno)); @@ -527,10 +527,10 @@ int qcache_traverse(void (*func)(qcache_ /* traverse categories */ for (i = 0; i < num_cat; i++) { - len = sizeof(char) * (strlen(portdir) + strlen("/") + strlen(categories[i]->d_name) + 1); + len = sizeof(char) * (strlen(overlay_gentoo->path) + strlen("/") + strlen(categories[i]->d_name) + 1); pkgpath = xmalloc(len); memset(pkgpath, 0, len); - snprintf(pkgpath, len, "%s/%s", portdir, categories[i]->d_name); + snprintf(pkgpath, len, "%s/%s", overlay_gentoo->path, categories[i]->d_name); if (-1 == (num_pkg = scandir(pkgpath, &packages, qcache_file_select, alphasort))) { warn("%s %s", catpath, strerror(errno)); @@ -552,10 +552,10 @@ int qcache_traverse(void (*func)(qcache_ /* traverse packages */ for (j = 0; j < num_pkg; j++) { - len = sizeof(char) * (strlen(portdir) + strlen("/") + strlen(categories[i]->d_name) + strlen("/") + strlen(packages[j]->d_name) + 1); + len = sizeof(char) * (strlen(overlay_gentoo->path) + strlen("/") + strlen(categories[i]->d_name) + strlen("/") + strlen(packages[j]->d_name) + 1); ebuildpath = xmalloc(len); memset(ebuildpath, 0, len); - snprintf(ebuildpath, len, "%s/%s/%s", portdir, categories[i]->d_name, packages[j]->d_name); + snprintf(ebuildpath, len, "%s/%s/%s", overlay_gentoo->path, categories[i]->d_name, packages[j]->d_name); if (-1 == (num_ebuild = scandir(ebuildpath, &ebuilds, qcache_ebuild_select, qcache_vercmp))) { warn("%s %s", ebuildpath, strerror(errno)); @@ -773,10 +773,10 @@ void qcache_stats(qcache_data *data) for (i = 0; archlist[i]; i++) architectures++; - len = sizeof(char) * (strlen(QCACHE_EDB) + strlen(portdir) + 1); + len = sizeof(char) * (strlen(QCACHE_EDB) + strlen(overlay_gentoo->path) + 1); catpath = xmalloc(len); memset(catpath, 0, len); - snprintf(catpath, len, "%s%s", QCACHE_EDB, portdir); + snprintf(catpath, len, "%s%s", QCACHE_EDB, overlay_gentoo->path); if (-1 == (numcat = scandir(catpath, &categories, qcache_file_select, alphasort))) { err("%s %s", catpath, strerror(errno)); @@ -928,11 +928,11 @@ int qcache_init() char *filename; unsigned int len; - len = sizeof(char) * (strlen(portdir) + strlen("/profiles/arch.list") + 1); + len = sizeof(char) * (strlen(overlay_gentoo->path) + strlen("/profiles/arch.list") + 1); filename = xmalloc(len); memset(filename, 0, len); - snprintf(filename, len, "%s/profiles/arch.list", portdir); + snprintf(filename, len, "%s/profiles/arch.list", overlay_gentoo->path); if (NULL == (archlist = qcache_read_lines(filename))) { free(filename); diff -Narup portage-utils-20070115/qcheck.c portage-utils-20070115.new/qcheck.c --- portage-utils-20070115/qcheck.c 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/qcheck.c 2007-01-15 19:21:58.326932645 +0100 @@ -49,10 +49,10 @@ int qcheck_main(int argc, char **argv) if ((argc == optind) && !search_all) qcheck_usage(EXIT_FAILURE); - if (chdir(portroot)) - errp("could not chdir(%s) for ROOT", portroot); + if (chdir(portvdb)) + errp("could not chdir(%s) for VDB", portvdb); - if (chdir(portvdb) != 0 || (dir = opendir(".")) == NULL) + if ((dir = opendir(".")) == NULL) return EXIT_FAILURE; /* open /var/db/pkg */ @@ -84,7 +84,7 @@ int qcheck_main(int argc, char **argv) continue; } - snprintf(buf, sizeof(buf), "%s%s/%s/%s/CONTENTS", portroot, portvdb, + snprintf(buf, sizeof(buf), "%s/%s/%s/CONTENTS", portvdb, dentry->d_name, de->d_name); if ((fp = fopen(buf, "r")) == NULL) continue; @@ -199,7 +199,7 @@ free_and_more_hash: fclose(fp); if (qc_update) { fclose(fpx); - snprintf(buf, sizeof(buf), "%s%s/%s/%s/CONTENTS", portroot, portvdb, + snprintf(buf, sizeof(buf), "%s/%s/%s/CONTENTS", portvdb, dentry->d_name, de->d_name); strcpy(buffer, buf); strncat(buffer, "~", sizeof(buffer)); diff -Narup portage-utils-20070115/qdepends.c portage-utils-20070115.new/qdepends.c --- portage-utils-20070115/qdepends.c 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/qdepends.c 2007-01-15 19:21:58.335931273 +0100 @@ -359,10 +359,10 @@ int qdepends_main_vdb(const char *depend char depend[16384], use[8192]; dep_node *dep_tree; - if (chdir(portroot)) - errp("could not chdir(%s) for ROOT", portroot); + if (chdir(portvdb)) + errp("could not chdir(%s) for VDB", portvdb); - if (chdir(portvdb) != 0 || (dir = opendir(".")) == NULL) + if ((dir = opendir(".")) == NULL) return EXIT_FAILURE; /* open /var/db/pkg */ @@ -390,7 +390,7 @@ int qdepends_main_vdb(const char *depend continue; IF_DEBUG(warn("matched %s/%s", dentry->d_name, de->d_name)); - snprintf(buf, sizeof(buf), "%s%s/%s/%s/%s", portroot, portvdb, + snprintf(buf, sizeof(buf), "%s/%s/%s/%s", portvdb, dentry->d_name, de->d_name, depend_file); /* >=portage-2.1_pre3 wont ensure these files always exist. @@ -421,7 +421,7 @@ int qdepends_main_vdb(const char *depend printf("%s%s/%s%s%s: ", BOLD, dentry->d_name, BLUE, de->d_name, NORM); } - snprintf(buf, sizeof(buf), "%s%s/%s/%s/USE", portroot, portvdb, + snprintf(buf, sizeof(buf), "%s/%s/%s/USE", portvdb, dentry->d_name, de->d_name); if (access(buf, R_OK) != 0) { @@ -468,10 +468,10 @@ int qdepends_vdb_deep(const char *depend char depend[16384], use[8192]; dep_node *dep_tree; - if (chdir(portroot)) - errp("could not chdir(%s) for ROOT", portroot); + if (chdir(portvdb)) + errp("could not chdir(%s) for VDB", portvdb); - if (chdir(portvdb) != 0 || (dir = opendir(".")) == NULL) + if ((dir = opendir(".")) == NULL) return EXIT_FAILURE; /* open /var/db/pkg */ @@ -487,7 +487,7 @@ int qdepends_vdb_deep(const char *depend continue; IF_DEBUG(warn("matched %s/%s", dentry->d_name, de->d_name)); - snprintf(buf, sizeof(buf), "%s%s/%s/%s/%s", portroot, portvdb, + snprintf(buf, sizeof(buf), "%s/%s/%s/%s", portvdb, dentry->d_name, de->d_name, depend_file); if (access(buf, R_OK) != 0) @@ -504,7 +504,7 @@ int qdepends_vdb_deep(const char *depend IF_DEBUG(puts(depend)); IF_DEBUG(dep_dump_tree(dep_tree)); - snprintf(buf, sizeof(buf), "%s%s/%s/%s/USE", portroot, portvdb, + snprintf(buf, sizeof(buf), "%s/%s/%s/USE", portvdb, dentry->d_name, de->d_name); assert(eat_file(buf, use, sizeof(use)) == 1); for (ptr = use; *ptr; ++ptr) diff -Narup portage-utils-20070115/qfile.c portage-utils-20070115.new/qfile.c --- portage-utils-20070115/qfile.c 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/qfile.c 2007-01-15 19:21:58.336931120 +0100 @@ -600,16 +600,14 @@ int qfile_main(int argc, char **argv) if (nb_of_queries < 0) goto exit; - if (chdir(portroot) - || chdir(portvdb) != 0 - || (dir = opendir(".")) == NULL) { - warnp("could not chdir(ROOT/%s) for installed packages database", portvdb); + if (chdir(portvdb) != 0 || (dir = opendir(".")) == NULL) { + warnp("could not chdir(%s) for installed packages database", portvdb); goto exit; } /* Iteration over VDB categories */ while (nb_of_queries && (dentry = q_vdb_get_next_dir(dir))) { - snprintf(path, _Q_PATH_MAX, "%s/%s/%s", qfile_args->real_root, portvdb, dentry->d_name); + snprintf(path, _Q_PATH_MAX, "%s/%s", portvdb, dentry->d_name); qfile(path, (assume_root_prefix ? root_prefix : NULL), qfile_args); } diff -Narup portage-utils-20070115/qfile.c.orig portage-utils-20070115.new/qfile.c.orig --- portage-utils-20070115/qfile.c.orig 1970-01-01 01:00:00.000000000 +0100 +++ portage-utils-20070115.new/qfile.c.orig 2007-01-15 19:21:05.010066468 +0100 @@ -0,0 +1,662 @@ +/* + * Copyright 2005-2006 Gentoo Foundation + * Distributed under the terms of the GNU General Public License v2 + * $Header: /var/cvsroot/gentoo-projects/portage-utils/qfile.c,v 1.42 2007/01/13 19:17:39 solar Exp $ + * + * Copyright 2005-2006 Ned Ludd - + * Copyright 2005-2006 Mike Frysinger - + */ + +#ifdef APPLET_qfile + +#define QFILE_MAX_MAX_ARGS 5000000 +#define QFILE_DEFAULT_MAX_ARGS 5000 +#define QFILE_DEFAULT_MAX_ARGS_STR "5000" + +#define QFILE_FLAGS "ef:m:oRx:" COMMON_FLAGS +static struct option const qfile_long_opts[] = { + {"exact", no_argument, NULL, 'e'}, + {"from", a_argument, NULL, 'f'}, + {"max-args", a_argument, NULL, 'm'}, + {"orphans", no_argument, NULL, 'o'}, + {"root-prefix", no_argument, NULL, 'R'}, + {"exclude", a_argument, NULL, 'x'}, + COMMON_LONG_OPTS +}; +static const char *qfile_opts_help[] = { + "Exact match", + "Read arguments from file (\"-\" for stdin)", + "Treat from file arguments by groups of (defaults to " QFILE_DEFAULT_MAX_ARGS_STR ")", + "List orphan files", + "Assume arguments are already prefixed by $ROOT", + "Don't look in package ", + COMMON_OPTS_HELP +}; +static char qfile_rcsid[] = "$Id: qfile.c,v 1.42 2007/01/13 19:17:39 solar Exp $"; +#define qfile_usage(ret) usage(ret, QFILE_FLAGS, qfile_long_opts, qfile_opts_help, lookup_applet_idx("qfile")) + +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)); +} + +typedef struct { + int length; + char **basenames; + char **dirnames; + char **realdirnames; + char *bn_firstchars; + short *non_orphans; + char *real_root; + char *exclude_pkg; + char *exclude_slot; +} qfile_args_t; + +void qfile(char *, const char *, qfile_args_t *); +void qfile(char *path, const char *root, qfile_args_t *args) +{ + FILE *fp; + DIR *dir; + struct dirent *dentry; + char *entry_basename; + char *entry_dirname; + char *p; + char buf[1024]; + char pkg[126]; + depend_atom *atom; + int i, path_ok; + char bn_firstchar; + char *real_root = args->real_root; + char **base_names = args->basenames; + char **dir_names = args->dirnames; + char **real_dir_names = args->realdirnames; + char *bn_firstchars = args->bn_firstchars; + short *non_orphans = args->non_orphans; + + if (chdir(path) != 0 || (dir = opendir(".")) == NULL) + return; + + while ((dentry = readdir(dir))) { + if (dentry->d_name[0] == '.') + continue; + + snprintf(pkg, sizeof(pkg), "%s/%s", basename(path), dentry->d_name); + atom = NULL; /* Will be exploded once at most, as needed. */ + + /* If exclude_pkg is not NULL, check it. We are looking for files + * collisions, and must exclude one package. + */ + if (args->exclude_pkg != NULL) { + if (strncmp(args->exclude_pkg, pkg, sizeof(pkg)) == 0) + goto check_pkg_slot; /* CAT/PF matches */ + if (strcmp(args->exclude_pkg, dentry->d_name) == 0) + goto check_pkg_slot; /* PF matches */ + if ((atom = atom_explode(pkg)) == NULL + || atom->PN == NULL || atom->CATEGORY == NULL) { + warn("invalid atom %s", pkg); + goto dont_skip_pkg; + } + snprintf(buf, sizeof(buf), "%s/%s", atom->CATEGORY, atom->PN); + if (strncmp(args->exclude_pkg, buf, sizeof(buf)) != 0 + && strcmp(args->exclude_pkg, atom->PN) != 0) + goto dont_skip_pkg; /* "(CAT/)?PN" doesn't match */ +check_pkg_slot: /* Also compare slots, if any was specified */ + if (args->exclude_slot == NULL) { + if (atom != NULL) + atom_implode(atom); + continue; /* "(CAT/)?(PN|PF)" matches, and no SLOT specified */ + } + buf[0] = '0'; buf[1] = '\0'; + xasprintf(&p, "%s/%s/SLOT", path, dentry->d_name); + if ((fp = fopen(p, "r")) != NULL) { + free(p); + if (fgets(buf, sizeof(buf), fp) != NULL) + if ((p = strchr(buf, '\n')) != NULL) + *p = 0; + fclose(fp); + } else { + free(p); + } + if (strncmp(args->exclude_slot, buf, sizeof(buf)) == 0) { + if (atom != NULL) + atom_implode(atom); + continue; /* "(CAT/)?(PN|PF):SLOT" matches */ + } + } +dont_skip_pkg: /* End of the package exclusion tests. */ + + xasprintf(&p, "%s/%s/CONTENTS", path, dentry->d_name); + if ((fp = fopen(p, "r")) == NULL) { + free(p); + if (atom != NULL) + atom_implode(atom); + continue; + } + free(p); + + while ((fgets(buf, sizeof(buf), fp)) != NULL) { + contents_entry *e; + e = contents_parse_line(buf); + if (!e) + continue; + + /* much faster than using basename(), since no need to strdup */ + if ((entry_basename = strrchr(e->name, '/')) == NULL) + continue; + entry_basename++; + + /* used to cut the number of strcmp() calls */ + bn_firstchar = entry_basename[0]; + + for (i = 0; i < args->length; i++) { + if (base_names[i] == NULL) + continue; + if (non_orphans != NULL && non_orphans[i]) + continue; + path_ok = (dir_names[i] == NULL && real_dir_names[i] == NULL); + + if (bn_firstchar != bn_firstchars[i] + || strcmp(entry_basename, base_names[i])) + continue; + + + if (!path_ok) { + /* check the full filepath ... */ + entry_dirname = xstrdup(e->name); + if ((p = strrchr(entry_dirname, '/')) == NULL) { + free(entry_dirname); + continue; + } + if (p == entry_dirname) + /* (e->name == "/foo") ==> dirname == "/" */ + *(p + 1) = '\0'; + else + *p = '\0'; + if (dir_names[i] != NULL && + strcmp(entry_dirname, dir_names[i]) == 0) + /* dir_name == dirname(CONTENTS) */ + path_ok = 1; + else if (real_dir_names[i] != NULL && + strcmp(entry_dirname, real_dir_names[i]) == 0) + /* real_dir_name == dirname(CONTENTS) */ + path_ok = 1; + else { + char rpath[_Q_PATH_MAX+1]; + char *fullpath = entry_dirname; + errno = 0; + if (real_root != NULL && real_root[0] != '\0') + xasprintf(&fullpath, "%s%s", real_root, entry_dirname); + realpath(fullpath, rpath); + if (errno != 0) { + if (verbose) { + warnp("Could not read real path of \"%s\" (from %s)", fullpath, pkg); + 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 + strlen(real_root), dir_names[i]) == 0) + /* dir_name == realpath(dirname(CONTENTS)) */ + path_ok = 1; + else if (real_dir_names[i] != NULL && + 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); + } + if (!path_ok) + continue; + + if (non_orphans == NULL) { + if (atom == NULL && (atom = atom_explode(pkg)) == NULL) { + warn("invalid atom %s", pkg); + continue; + } + + printf("%s%s/%s%s%s", BOLD, atom->CATEGORY, BLUE, + (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); + + } else { + non_orphans[i] = 1; + } + found++; + } + } + fclose(fp); + if (atom != NULL) + atom_implode(atom); + } + closedir(dir); + + return; +} + +qfile_args_t *create_qfile_args(); +qfile_args_t *create_qfile_args() +{ + qfile_args_t *qfile_args; + + qfile_args = xmalloc(sizeof(qfile_args_t)); + + memset(qfile_args, 0, sizeof(qfile_args_t)); + return qfile_args; +} + +void destroy_qfile_args(qfile_args_t *); +void destroy_qfile_args(qfile_args_t *qfile_args) +{ + int i; + + for (i = 0; i < qfile_args->length; ++i) { + if (qfile_args->basenames != NULL && qfile_args->basenames[i] != NULL) + free(qfile_args->basenames[i]); + if (qfile_args->dirnames != NULL && qfile_args->dirnames[i] != NULL) + free(qfile_args->dirnames[i]); + if (qfile_args->realdirnames != NULL && qfile_args->realdirnames[i] != NULL) + free(qfile_args->realdirnames[i]); + } + + if (qfile_args->basenames != NULL) + free(qfile_args->basenames); + if (qfile_args->dirnames != NULL) + free(qfile_args->dirnames); + if (qfile_args->realdirnames != NULL) + free(qfile_args->realdirnames); + + if (qfile_args->bn_firstchars != NULL) + free(qfile_args->bn_firstchars); + + if (qfile_args->non_orphans != NULL) + free(qfile_args->non_orphans); + + if (qfile_args->real_root != NULL) + free(qfile_args->real_root); + + if (qfile_args->exclude_pkg != NULL) + free(qfile_args->exclude_pkg); + /* don't free qfile_args->exclude_slot, it's the same chunk */ + + memset(qfile_args, 0, sizeof(qfile_args_t)); +} + +int prepare_qfile_args(const int, const char **, + const short, const short, const char *, qfile_args_t *); +int prepare_qfile_args(const int argc, const char **argv, + const short assume_root_prefix, const short search_orphans, + const char *exclude_pkg_arg, qfile_args_t *qfile_args) +{ + int i; + int nb_of_queries = argc; + char *pwd = NULL; + int real_root_length; + char *real_root = NULL; + char **basenames = NULL; + char **dirnames = NULL; + char **realdirnames = NULL; + char *basenames_firstchars = NULL; + char tmppath[_Q_PATH_MAX+1]; + char abspath[_Q_PATH_MAX+1]; + + /* 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); + warn("Could not get absolute path for ROOT (\"%s\"), because of missing or not absolute $PWD", tmppath); + return -1; + } + errno = 0; + realpath(tmppath, abspath); + if (errno != 0) { + free(pwd); + warnp("Could not read real path of ROOT (\"%s\")", tmppath); + return -1; + } + if (strlen(abspath) == 1) + abspath[0] = '\0'; + real_root = xstrdup(abspath); + real_root_length = strlen(real_root); + + /* 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 = xcalloc(argc, sizeof(char*)); + dirnames = xcalloc(argc, sizeof(char*)); + realdirnames = xcalloc(argc, sizeof(char*)); + /* 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 = xcalloc(argc, sizeof(char)); + + for (i = 0; i < argc; ++i) { + /* Record basename, but if it is ".", ".." or "/" */ + strncpy(abspath, argv[i], _Q_PATH_MAX); /* strncopy so that "argv" can be "const" */ + strncpy(tmppath, basename(abspath), _Q_PATH_MAX); + 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], '/') == NULL) + continue; + } + + /* Make sure we have an absolute path available (with "realpath(ROOT)" prefix) */ + if (argv[i][0] == '/') { + if (assume_root_prefix) + strncpy(abspath, argv[i], _Q_PATH_MAX); + else + snprintf(abspath, _Q_PATH_MAX, "%s%s", real_root, argv[i]); + } else if (pwd != NULL) { + if (assume_root_prefix) + snprintf(abspath, _Q_PATH_MAX, "%s/%s", pwd, argv[i]); + else + snprintf(abspath, _Q_PATH_MAX, "%s%s/%s", real_root, pwd, argv[i]); + } 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. 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(abspath, tmppath); + if (errno != 0) { + if (verbose) { + warnp("Could not read real path of \"%s\"", abspath); + warn("Results for query item \"%s\" may be inaccurate.", argv[i]); + } + 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(abspath, tmppath); + if (errno != 0) { + warnp("Could not read real path of \"%s\"", abspath); + 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; + } + 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]); + 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; + } + + if (pwd != NULL) + free(pwd); + + qfile_args->real_root = real_root; + qfile_args->basenames = basenames; + qfile_args->dirnames = dirnames; + qfile_args->realdirnames = realdirnames; + qfile_args->bn_firstchars = basenames_firstchars; + qfile_args->length = argc; + + if (search_orphans) { + qfile_args->non_orphans = xcalloc(argc, sizeof(short)); + memset(qfile_args->non_orphans, 0, argc); + } + + if (exclude_pkg_arg != NULL) { + qfile_args->exclude_pkg = xstrdup(exclude_pkg_arg); + if ((qfile_args->exclude_slot = strchr(qfile_args->exclude_pkg, ':')) != NULL) + *qfile_args->exclude_slot++ = '\0'; + /* Maybe this should be atom-exploded instead (to check syntax, etc.) */ + } + + return nb_of_queries; +} + +int qfile_main(int argc, char **argv) +{ + DIR *dir; + struct dirent *dentry; + int i, nb_of_queries; + char *p; + short search_orphans = 0; + short assume_root_prefix = 0; + char *root_prefix = NULL; + char *exclude_pkg_arg = NULL; + qfile_args_t *qfile_args = NULL; + int qargc = 0; + char **qargv = NULL; + short done = 0; + FILE *args_file = NULL; + int max_args = QFILE_DEFAULT_MAX_ARGS; + char path[_Q_PATH_MAX]; + + DBG("argc=%d argv[0]=%s argv[1]=%s", + argc, argv[0], argc > 1 ? argv[1] : "NULL?"); + + while ((i = GETOPT_LONG(QFILE, qfile, "")) != -1) { + switch (i) { + COMMON_GETOPTS_CASES(qfile) + case 'e': exact = 1; break; + case 'f': + if (args_file != NULL) { + warn("Don't use -f twice!"); + goto exit; + } + if (strcmp(optarg, "-") == 0) + args_file = stdin; + else if ((args_file = fopen(optarg, "r")) == NULL) { + warnp("%s", optarg); + goto exit; + } + break; + case 'm': + errno = 0; + max_args = strtol(optarg, &p, 10); + if (errno != 0) { + warnp("%s: not a valid integer", optarg); + goto exit; + } else if (p == optarg || *p != '\0') { + warn("%s: not a valid integer", optarg); + goto exit; + } + if (max_args <= 0 || max_args > QFILE_MAX_MAX_ARGS) { + warn("%s: silly value!", optarg); + goto exit; + } + break; + case 'o': search_orphans = 1; break; + case 'R': assume_root_prefix = 1; break; + case 'x': + if (exclude_pkg_arg != NULL) { + warn("--exclude can only be used once."); + goto exit; + } + exclude_pkg_arg = optarg; + break; + } + } + if (!exact && verbose) exact++; + if ((argc == optind) && (args_file == NULL)) + qfile_usage(EXIT_FAILURE); + + if ((args_file == NULL) && (max_args != QFILE_DEFAULT_MAX_ARGS)) + warn("--max-args is only used when reading arguments from a file (with -f)"); + + if (chdir(portroot)) { + warnp("could not chdir(%s) for ROOT", portroot); + goto exit; + } + + if (chdir(portvdb) != 0) { + warnp("could not chdir(ROOT/%s) for installed packages database", portvdb); + goto exit; + } + + /* 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'; + + /* Are we using --from ? */ + if (args_file == NULL) { + qargc = argc - optind; + qargv = argv + optind; + done = 1; + } else { + qargv = xcalloc(max_args, sizeof(char*)); + } + + do { /* This block may be repeated if using --from with a big files list */ + if (args_file != NULL) { + qargc = 0; + /* Read up to max_args files from the input file */ + while ((fgets(path, _Q_PATH_MAX, args_file)) != NULL) { + if ((p = strchr(path, '\n')) != NULL) + *p = '\0'; + if (path == p) continue; + qargv[qargc] = xstrdup(path); + qargc++; + if (qargc >= max_args) break; + } + } + + if (qargc == 0) break; + + if (qfile_args == NULL) { /* qfile_args is allocated only once */ + if ((qfile_args = create_qfile_args()) == NULL) { + warn("Out of memory"); + goto exit; + } + } else { + destroy_qfile_args(qfile_args); + } + + /* Prepare the qfile(...) arguments structure */ + nb_of_queries = prepare_qfile_args(qargc, (const char **) qargv, + assume_root_prefix, search_orphans, exclude_pkg_arg, qfile_args); + if (nb_of_queries < 0) + goto exit; + + if (chdir(portroot) + || chdir(portvdb) != 0 + || (dir = opendir(".")) == NULL) { + warnp("could not chdir(ROOT/%s) for installed packages database", portvdb); + goto exit; + } + + /* Iteration over VDB categories */ + while (nb_of_queries && (dentry = q_vdb_get_next_dir(dir))) { + snprintf(path, _Q_PATH_MAX, "%s/%s/%s", qfile_args->real_root, portvdb, dentry->d_name); + qfile(path, (assume_root_prefix ? root_prefix : NULL), qfile_args); + } + + if (qfile_args->non_orphans != NULL) { + /* display orphan files */ + for (i = 0; i < qfile_args->length; i++) { + if (qfile_args->non_orphans[i]) + continue; + if (qfile_args->basenames[i] != NULL) { + found = 0; /* ~inverse return code (as soon as an orphan is found, return non-zero) */ + if (!quiet) + printf("%s\n", qargv[i]); + else break; + } + } + } + + if (args_file != NULL && qargv != NULL) { + for (i = 0; i < qargc; i++) { + if (qargv[i] != NULL) free(qargv[i]); + qargv[i] = NULL; + } + } + } while (args_file != NULL && qargc == max_args); + +exit: + + if (args_file != NULL && qargv != NULL) { + for (i = 0; i < qargc; i++) + if (qargv[i] != NULL) free(qargv[i]); + free(qargv); + } + + if (args_file != NULL && args_file != stdin) + fclose(args_file); + + if (qfile_args != NULL) { + destroy_qfile_args(qfile_args); + free(qfile_args); + } + + if (root_prefix != NULL) + free(root_prefix); + + return (found ? EXIT_SUCCESS : EXIT_FAILURE); +} + +#else +DEFINE_APPLET_STUB(qfile) +#endif diff -Narup portage-utils-20070115/qgrep.c portage-utils-20070115.new/qgrep.c --- portage-utils-20070115/qgrep.c 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/qgrep.c 2007-01-15 19:21:58.343930052 +0100 @@ -10,11 +10,12 @@ #ifdef APPLET_qgrep -#define QGREP_FLAGS "IiHce" COMMON_FLAGS +#define QGREP_FLAGS "IiHo:ce" COMMON_FLAGS static struct option const qgrep_long_opts[] = { {"invert-match", no_argument, NULL, 'I'}, {"ignore-case", no_argument, NULL, 'i'}, {"with-filename", no_argument, NULL, 'H'}, + {"overlay", a_argument, NULL, 'o'}, {"count", no_argument, NULL, 'c'}, {"regexp", no_argument, NULL, 'e'}, COMMON_LONG_OPTS @@ -23,6 +24,7 @@ static const char *qgrep_opts_help[] = { "Select non-matching lines", "Ignore case distinctions", "Print the filename for each match", + "Only consider the overlay", "Only print a count of matching lines per FILE", "Use PATTERN as a regular expression", COMMON_OPTS_HELP @@ -34,6 +36,8 @@ int qgrep_main(int argc, char **argv) { int i; int count = 0; + short myerror = 0, repo = 0, bad_overlay=0; + char overlay_name[64], repo_search[64]; char *p; char do_count, do_regex; char show_filename; @@ -42,10 +46,15 @@ int qgrep_main(int argc, char **argv) char buf0[BUFSIZ]; int reflags = REG_NOSUB; char invert_match = 0; + overlay_t *cur_overlay, *overlay_tmp; typedef char *(*FUNC) (char *, char *); FUNC strfunc = (FUNC) strstr; + cur_overlay = first_overlay; + overlay_name[0] = 0; + repo_search[0] = 0; + DBG("argc=%d argv[0]=%s argv[1]=%s", argc, argv[0], argc > 1 ? argv[1] : "NULL?"); @@ -58,12 +67,26 @@ int qgrep_main(int argc, char **argv) strfunc = (FUNC) strcasestr; reflags |= REG_ICASE; break; + case 'H': show_filename = 1; break; + case 'o': + repo = 1; + strncpy(repo_search, optarg, sizeof(repo_search)); + break; case 'c': do_count = 1; break; case 'e': do_regex = 1; break; - case 'H': show_filename = 1; break; COMMON_GETOPTS_CASES(qgrep) } } + + if (repo) { + do { + if (!strncmp(cur_overlay->name, repo_search, sizeof(cur_overlay->name))) + break; + } while ((cur_overlay=cur_overlay->next)); + if (NULL == cur_overlay) + err("%s : Unknown overlay, try 'q --ls-overlays'", repo_search); + } + if (argc == optind) qgrep_usage(EXIT_FAILURE); @@ -75,6 +98,51 @@ int qgrep_main(int argc, char **argv) FILE *newfp; if ((p = strchr(ebuild, '\n')) != NULL) *p = 0; + + /* find the overlay, we're working on, and change to the + * corresponding (location|cache) directory */ + if ((p = strchr(ebuild, ':'))) { + /* delete the ::overlay */ + *p = 0; + + /* restrict the search to one overlay if the users wants it */ + if (repo && strncmp(repo_search, p+2, sizeof(repo_search))) + continue; + if (bad_overlay && !strncmp(overlay_name, p+2, sizeof(overlay_name))) + continue; + else { + if (strncmp(overlay_name, p+2, sizeof(overlay_name))) { + overlay_tmp=first_overlay; + do { + if (!strncmp(overlay_tmp->name, p+2, sizeof(overlay_tmp->name))) + break; + } while ((overlay_tmp=overlay_tmp->next)); + + if (overlay_tmp) { + cur_overlay = overlay_tmp; + if (chdir(cur_overlay->path) != 0) { + warnp("chdir to '%s' failed", cur_overlay->path); + myerror = 1; + } else + bad_overlay = 0; + } else + myerror = 1; + + strncpy(overlay_name, p+2, sizeof(overlay_name)); + } + } + } else + myerror=1; + + if (myerror) { + if (!reinitialize) + warnf("(cache update pending) %s : Unknown overlay", overlay_name); + bad_overlay = 1; + myerror = 0; + reinitialize = 1; + continue; + } + if ((newfp = fopen(ebuild, "r")) != NULL) { unsigned int lineno = 0; count = 0; @@ -102,7 +170,7 @@ int qgrep_main(int argc, char **argv) count++; if (do_count) continue; if (verbose || show_filename) { - printf("%s:", ebuild); + printf("%s::%s:", cur_overlay->name, ebuild); if (verbose > 1) printf("%d:", lineno); printf(" "); } @@ -110,7 +178,7 @@ int qgrep_main(int argc, char **argv) } fclose(newfp); if (do_count && count) { - if (verbose || show_filename) printf("%s:", ebuild); + if (verbose || show_filename) printf("%s::%s:", cur_overlay->name, ebuild); printf("%d", count); puts(""); } diff -Narup portage-utils-20070115/qsearch.c portage-utils-20070115.new/qsearch.c --- portage-utils-20070115/qsearch.c 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/qsearch.c 2007-01-15 19:21:58.353928527 +0100 @@ -9,10 +9,12 @@ #ifdef APPLET_qsearch -#define QSEARCH_FLAGS "acsSNH" COMMON_FLAGS +#define QSEARCH_FLAGS "aco:psSNH" COMMON_FLAGS static struct option const qsearch_long_opts[] = { {"all", no_argument, NULL, 'a'}, {"cache", no_argument, NULL, 'c'}, + {"overlay", a_argument, NULL, 'o'}, + {"show-path", no_argument, NULL, 'p'}, {"search", no_argument, NULL, 's'}, {"desc", a_argument, NULL, 'S'}, {"name-only", no_argument, NULL, 'N'}, @@ -22,6 +24,8 @@ static struct option const qsearch_long_ static const char *qsearch_opts_help[] = { "List the descriptions of every package in the cache", "Use the portage cache", + "Search only in the overlay", + "Show the path to the ebuild", "Regex search package basenames", "Regex search package descriptions", "Only show package name", @@ -40,13 +44,22 @@ int qsearch_main(int argc, char **argv) char last[126] = ""; char dp[126] = ""; char bp[126] = ""; - char *p, *q, *str; + char debuild[126] = ""; + short repo = 0; + char repo_search[64]; + char *p, *q, *str, overlay_name[64]; char *search_me = NULL; - char show_homepage = 0, show_name_only = 0; + char show_homepage = 0, show_name_only = 0, show_path_to_ebuild = 0; char search_desc = 0, search_all = 0, search_name = 1, search_cache = CACHE_EBUILD; const char *search_vars[] = { "DESCRIPTION=", "HOMEPAGE=" }; size_t search_len; - int i, idx=0; + overlay_t *cur_overlay, *overlay_tmp; + int i, idx=0, myerror=0, bad_overlay=0; + + cur_overlay = first_overlay; + overlay_name[0] = 0; + repo_search[0] = 0; + str = NULL; DBG("argc=%d argv[0]=%s argv[1]=%s", argc, argv[0], argc > 1 ? argv[1] : "NULL?"); @@ -56,6 +69,8 @@ int qsearch_main(int argc, char **argv) COMMON_GETOPTS_CASES(qsearch) case 'a': search_all = 1; break; case 'c': search_cache = CACHE_METADATA; break; + case 'o': repo = 1; strncpy(repo_search, optarg, sizeof(repo_search)); break; + case 'p': show_path_to_ebuild = 1; break; case 's': search_desc = 0; search_name = 1; break; case 'S': search_desc = 1; search_name = 0; break; case 'N': show_name_only = 1; break; @@ -63,6 +78,18 @@ int qsearch_main(int argc, char **argv) } } + if (repo) { + do { + if (! strncmp(cur_overlay->name, repo_search, sizeof(cur_overlay->name))) + break; + } while ((cur_overlay=cur_overlay->next)); + if (NULL == cur_overlay) + err("%s : Unknown overlay, try 'q --ls-overlays'", repo_search); + if (search_cache == CACHE_METADATA && !strncmp(cur_overlay->cache,"/var/empty",sizeof(cur_overlay->cache))) + err("No cache defined for the '%s' overlay", cur_overlay->name); + } + + if (search_all) { search_desc = 1; search_name = 0; @@ -86,6 +113,60 @@ int qsearch_main(int argc, char **argv) if (!ebuild[0]) continue; + /* find the overlay, we're working on, and change to the + * corresponding (location|cache) directory */ + if ((p = strchr(ebuild, ':'))) { + /* separator is '::' */ + /* restrict the search to one overlay if the users wants it */ + if (repo && strncmp(repo_search, p+2, sizeof(repo_search))) + continue; + if (bad_overlay && !strncmp(overlay_name, p+2, sizeof(overlay_name))) + continue; + if (strncmp(overlay_name, p+2, sizeof(overlay_name))) { + last[0] = 0; + overlay_tmp=first_overlay; + do { + if (!strncmp(overlay_tmp->name, p+2, sizeof(overlay_tmp->name))) + break; + } while ((overlay_tmp=overlay_tmp->next)); + + if (overlay_tmp) { + cur_overlay=overlay_tmp; + switch (search_cache) { + case CACHE_EBUILD: + if (chdir(cur_overlay->path) != 0) { + warnp("chdir to '%s' failed", cur_overlay->path); + myerror = 1; + continue; + } else + bad_overlay = 0; + break; + case CACHE_METADATA: + if (chdir(cur_overlay->cache) != 0) { + warnp("chdir to '%s' failed, skipping the %s repository", cur_overlay->cache, cur_overlay->name); + myerror = 1; + continue; + } else + bad_overlay = 0; + break; + } + } else + myerror = 1; + strncpy(overlay_name, p+2, sizeof(overlay_name)); + } + } else + myerror++; + + if (myerror) { + if (!reinitialize) + warnf("(cache update pending) %s : Unknown overlay", overlay_name); + bad_overlay = 1; + myerror = 0; + reinitialize = 1; + continue; + } + + switch (search_cache) { case CACHE_METADATA: { @@ -93,11 +174,28 @@ int qsearch_main(int argc, char **argv) if ((pcache = cache_read_file(ebuild)) != NULL) { if ((strcmp(pcache->atom->PN, last)) != 0) { strncpy(last, pcache->atom->PN, sizeof(last)); - if ((rematch(search_me, (search_desc ? pcache->DESCRIPTION : ebuild), REG_EXTENDED | REG_ICASE)) == 0) - printf("%s%s/%s%s%s %s\n", BOLD, pcache->atom->CATEGORY, BLUE, - pcache->atom->PN, NORM, - (show_name_only ? "" : - (show_homepage ? pcache->HOMEPAGE : pcache->DESCRIPTION))); + if (!search_all && (rematch(search_me, (search_desc ? pcache->DESCRIPTION : ebuild), REG_EXTENDED | REG_ICASE)) != 0) { + cache_free(pcache); + continue; + } + + if (show_path_to_ebuild) { + /* delete the ::overlay */ + *p = 0; + strncpy(debuild, ebuild, sizeof(debuild)); + printf("%s%s/%s%s%s::%s\t %s%s/%s/\n", + BOLD, pcache->atom->CATEGORY, + BLUE, pcache->atom->PN, + YELLOW, pcache->atom->OVERLAY, NORM, + cur_overlay->path, dirname(debuild)); + } else { + printf("%s%s/%s%s%s::%s %s%s\n", + BOLD, pcache->atom->CATEGORY, + BLUE, pcache->atom->PN, + YELLOW, pcache->atom->OVERLAY, NORM, + (show_name_only ? "" : + (show_homepage ? pcache->HOMEPAGE : pcache->DESCRIPTION))); + } } cache_free(pcache); } else { @@ -110,6 +208,9 @@ int qsearch_main(int argc, char **argv) case CACHE_EBUILD: { FILE *ebuildfp; + /* delete the ::overlay */ + *p = 0; + str = xstrdup(ebuild); p = (char *) dirname(str); @@ -134,9 +235,18 @@ int qsearch_main(int argc, char **argv) /* doing operations with them. */ strncpy(dp, p, sizeof(dp)); strncpy(bp, p, sizeof(bp)); - printf("%s%s/%s%s%s %s\n", - BOLD, dirname(dp), BLUE, basename(bp), NORM, + strncpy(debuild, ebuild, sizeof(debuild)); + if (show_path_to_ebuild) { + printf("%s%s/%s%s%s::%s\t %s%s/%s/\n", + BOLD, dirname(dp), BLUE, basename(bp), + YELLOW, cur_overlay->name, NORM, + cur_overlay->path, dirname(debuild)); + } else { + printf("%s%s/%s%s%s::%s %s%s\n", + BOLD, dirname(dp), BLUE, basename(bp), + YELLOW, cur_overlay->name, NORM, (show_name_only ? "" : q)); + } break; } } diff -Narup portage-utils-20070115/quse.c portage-utils-20070115.new/quse.c --- portage-utils-20070115/quse.c 2007-01-15 19:20:12.000000000 +0100 +++ portage-utils-20070115.new/quse.c 2007-01-15 19:21:58.361927307 +0100 @@ -1,7 +1,7 @@ /* * Copyright 2005-2006 Gentoo Foundation * Distributed under the terms of the GNU General Public License v2 - * $Header: /var/cvsroot/gentoo-projects/portage-utils/quse.c,v 1.55 2007/01/09 13:15:43 vapier Exp $ + * $Header: /var/cvsroot/gentoo-projects/portage-utils/quse.c,v 1.54 2006/12/25 16:38:37 solar Exp $ * * Copyright 2005-2006 Ned Ludd - * Copyright 2005-2006 Mike Frysinger - @@ -14,10 +14,11 @@ quse -Ke -- nls */ -#define QUSE_FLAGS "eavKLDF:N" COMMON_FLAGS +#define QUSE_FLAGS "eao:vKLDF:N" COMMON_FLAGS static struct option const quse_long_opts[] = { {"exact", no_argument, NULL, 'e'}, {"all", no_argument, NULL, 'a'}, + {"overlay", a_argument, NULL, 'o'}, {"keywords", no_argument, NULL, 'K'}, {"license", no_argument, NULL, 'L'}, {"describe", no_argument, NULL, 'D'}, @@ -28,6 +29,7 @@ static struct option const quse_long_opt static const char *quse_opts_help[] = { "Show exact non regexp matching using strcmp", "Show annoying things in IUSE", + "Only consider the overlay", "Use the KEYWORDS vs IUSE", "Use the LICENSE vs IUSE", "Describe the USE flag", @@ -35,10 +37,10 @@ static const char *quse_opts_help[] = { "Only show package name", COMMON_OPTS_HELP }; -static const char quse_rcsid[] = "$Id: quse.c,v 1.55 2007/01/09 13:15:43 vapier Exp $"; +static const char quse_rcsid[] = "$Id: quse.c,v 1.54 2006/12/25 16:38:37 solar Exp $"; #define quse_usage(ret) usage(ret, QUSE_FLAGS, quse_long_opts, quse_opts_help, lookup_applet_idx("quse")) -int quse_describe_flag(int ind, int argc, char **argv); +int quse_describe_flag(int ind, short repo, char repo_search[], int argc, char **argv); char quse_name_only = 0; @@ -81,7 +83,7 @@ static void print_highlighted_use_flags( } } -int quse_describe_flag(int ind, int argc, char **argv) +int quse_describe_flag(int ind, short repo, char repo_search[], int argc, char **argv) { #define NUM_SEARCH_FILES ARR_SIZE(search_files) char buf[BUFSIZE], *p; @@ -91,115 +93,152 @@ int quse_describe_flag(int ind, int argc FILE *fp[NUM_SEARCH_FILES]; DIR *d; struct dirent *de; + overlay_t *cur_overlay; - for (i = 0; i < NUM_SEARCH_FILES; ++i) { - snprintf(buf, sizeof(buf), "%s/profiles/%s", portdir, search_files[i]); - if ((fp[i] = fopen(buf, "r")) == NULL) - warnp("skipping %s", search_files[i]); - } + cur_overlay=first_overlay; - for (i = ind; i < argc; i++) { - s = strlen(argv[i]); + do { + if (repo && strncmp(repo_search, cur_overlay->name, sizeof(repo_search))) + continue; + for (i = 0; i < NUM_SEARCH_FILES; ++i) { + snprintf(buf, sizeof(buf), "%s/profiles/%s", cur_overlay->path, search_files[i]); + if ((fp[i] = fopen(buf, "r")) == NULL) + if (verbose>2) + warnp("skipping %s for the %s overlay", search_files[i], cur_overlay->name); + } - for (f = 0; f < NUM_SEARCH_FILES; ++f) { - if (fp[f] == NULL) - continue; + for (i = ind; i < argc; i++) { + s = strlen(argv[i]); - while (fgets(buf, sizeof(buf), fp[f]) != NULL) { - if (buf[0] == '#' || buf[0] == '\n') + for (f = 0; f < NUM_SEARCH_FILES; ++f) { + if (fp[f] == NULL) continue; - if ((p = strrchr(buf, '\n')) != NULL) - *p = '\0'; + while (fgets(buf, sizeof(buf), fp[f]) != NULL) { + if (buf[0] == '#' || buf[0] == '\n') + continue; - switch (f) { - case 0: /* Global use.desc */ - if (!strncmp(buf, argv[i], s)) - if (buf[s] == ' ' && buf[s+1] == '-') { - printf(" %sglobal%s:%s%s%s: %s\n", BOLD, NORM, BLUE, argv[i], NORM, buf+s+3); - goto skip_file; - } - break; + if ((p = strrchr(buf, '\n')) != NULL) + *p = '\0'; - case 1: /* Local use.local.desc */ - if ((p = strchr(buf, ':')) == NULL) + switch (f) { + case 0: /* Global use.desc */ + if (!strncmp(buf, argv[i], s)) + if (buf[s] == ' ' && buf[s+1] == '-') { + if (overlay_gentoo && cur_overlay == overlay_gentoo) + printf(" %sglobal%s:%s%s%s: %s\n", BOLD, NORM, BLUE, argv[i], NORM, buf+s+3); + else + printf(" (%s) %sglobal%s:%s%s%s: %s\n", cur_overlay->name, BOLD, NORM, BLUE, argv[i], NORM, buf+s+3); + goto skip_file; + } break; - ++p; - if (!strncmp(p, argv[i], s)) { - if (p[s] == ' ' && p[s+1] == '-') { - *p = '\0'; - printf(" %slocal%s:%s%s%s:%s%s%s %s\n", BOLD, NORM, BLUE, argv[i], NORM, BOLD, buf, NORM, p+s+3); - } - } - break; - case 2: /* Architectures arch.list */ - if (!strcmp(buf, argv[i])) { - printf(" %sarch%s:%s%s%s: %s architecture\n", BOLD, NORM, BLUE, argv[i], NORM, argv[i]); - goto skip_file; - } - break; + case 1: /* Local use.local.desc */ + if ((p = strchr(buf, ':')) == NULL) + break; + ++p; + if (!strncmp(p, argv[i], s)) { + if (p[s] == ' ' && p[s+1] == '-') { + *p = '\0'; + if (overlay_gentoo && cur_overlay == overlay_gentoo) + printf(" %slocal%s:%s%s%s:%s%s%s %s\n", BOLD, NORM, BLUE, argv[i], NORM, BOLD, buf, NORM, p+s+3); + else + printf(" (%s) %slocal%s:%s%s%s:%s%s%s %s\n", cur_overlay->name, BOLD, NORM, BLUE, argv[i], NORM, BOLD, buf, NORM, p+s+3); + } + } + break; - case 3: /* Languages lang.desc */ - if (!strncmp(buf, argv[i], s)) - if (buf[s] == ' ' && buf[s+1] == '-') { - printf(" %slang%s:%s%s%s: %s lingua\n", BOLD, NORM, BLUE, argv[i], NORM, buf+s+3); + case 2: /* Architectures arch.list */ + if (!strcmp(buf, argv[i])) { + if (overlay_gentoo && cur_overlay == overlay_gentoo) + printf(" %sarch%s:%s%s%s: %s architecture\n", BOLD, NORM, BLUE, argv[i], NORM, argv[i]); + else + printf(" (%s) %sarch%s:%s%s%s: %s architecture\n", cur_overlay->name, BOLD, NORM, BLUE, argv[i], NORM, argv[i]); goto skip_file; } - break; + break; + + case 3: /* Languages lang.desc */ + if (!strncmp(buf, argv[i], s)) + if (buf[s] == ' ' && buf[s+1] == '-') { + if (overlay_gentoo && cur_overlay == overlay_gentoo) + printf(" %slang%s:%s%s%s: %s lingua\n", BOLD, NORM, BLUE, argv[i], NORM, buf+s+3); + else + printf(" (%s) %slang%s:%s%s%s: %s lingua\n", cur_overlay->name, BOLD, NORM, BLUE, argv[i], NORM, buf+s+3); + goto skip_file; + } + break; + } } - } skip_file: - rewind(fp[f]); + rewind(fp[f]); + } + + if (i == (argc - 1)) + for (f=0; fnext)); /* now scan the desc dir */ - snprintf(buf, sizeof(buf), "%s/profiles/desc/", portdir); - d = opendir(buf); - while ((de = readdir(d)) != NULL) { - if (strcmp(de->d_name+strlen(de->d_name)-5, ".desc")) + cur_overlay=first_overlay; + do { + if (repo && strncmp(repo_search, cur_overlay->name, sizeof(repo_search))) continue; - - snprintf(buf, sizeof(buf), "%s/profiles/desc/%s", portdir, de->d_name); - if ((fp[0]=fopen(buf, "r")) == NULL) { - warn("Could not open '%s' for reading; skipping", de->d_name); + snprintf(buf, sizeof(buf), "%s/profiles/desc/", cur_overlay->path); + if (!(d = opendir(buf))) { + if (verbose>2) + warn("Could not open %s -> skipping", buf); continue; } + while ((de = readdir(d)) != NULL) { + if (strcmp(de->d_name+strlen(de->d_name)-5, ".desc")) + continue; - while (fgets(buf, sizeof(buf), fp[0]) != NULL) { - if (buf[0] == '#' || buf[0] == '\n') + snprintf(buf, sizeof(buf), "%s/profiles/desc/%s", cur_overlay->path, de->d_name); + if ((fp[0]=fopen(buf, "r")) == NULL) { + warn("Could not open '%s' for reading; skipping", de->d_name); continue; + } - if ((p = strrchr(buf, '\n')) != NULL) - *p = '\0'; + while (fgets(buf, sizeof(buf), fp[0]) != NULL) { + if (buf[0] == '#' || buf[0] == '\n') + continue; - if ((p = strchr(buf, '-')) == NULL) { + if ((p = strrchr(buf, '\n')) != NULL) + *p = '\0'; + + if ((p = strchr(buf, '-')) == NULL) { invalid_line: - warn("Invalid line in '%s': %s", de->d_name, buf); - continue; - } - while (p[-1] != ' ' && p[1] != ' ') { - /* maybe the flag has a '-' in it ... */ - if ((p = strchr(p+1, '-')) == NULL) - goto invalid_line; - } - p[-1] = '\0'; - p += 2; + warn("Invalid line in '%s': %s", de->d_name, buf); + continue; + } + while (p[-1] != ' ' && p[1] != ' ') { + /* maybe the flag has a '-' in it ... */ + if ((p = strchr(p+1, '-')) == NULL) + goto invalid_line; + } + p[-1] = '\0'; + p += 2; - for (i = ind; i < argc; i++) - if (!strcmp(argv[i], buf)) - printf(" %s%s%s:%s%s%s: %s\n", BOLD, de->d_name, NORM, BLUE, argv[i], NORM, p); - } - close(f); - } - closedir(d); + for (i = ind; i < argc; i++) + if (!strcmp(argv[i], buf)) { + if (overlay_gentoo && cur_overlay == overlay_gentoo) + printf(" %s%s%s:%s%s%s: %s\n", BOLD, de->d_name, NORM, BLUE, argv[i], NORM, p); + else + printf(" (%s) %s%s%s:%s%s%s: %s\n", cur_overlay->name, BOLD, de->d_name, NORM, BLUE, argv[i], NORM, p); + } + } + fclose(fp[0]); + } + closedir(d); + } while ((cur_overlay=cur_overlay->next)); return 0; } @@ -207,6 +246,9 @@ int quse_main(int argc, char **argv) { FILE *fp; char *p; + short myerror = 0, repo = 0; + char repo_search[64]; + char overlay_name[64]; char buf0[_Q_PATH_MAX]; char buf1[_Q_PATH_MAX]; @@ -217,8 +259,13 @@ int quse_main(int argc, char **argv) const char *search_var = NULL; const char *search_vars[] = { "IUSE=", "KEYWORDS=", "LICENSE=", search_var }; short quse_all = 0; - int regexp_matching = 1, i, idx = 0; + int regexp_matching = 1, i, idx = 0, bad_overlay = 0; size_t search_len; + overlay_t *cur_overlay, *overlay_tmp; + + cur_overlay = first_overlay; + overlay_name[0] = 0; + repo_search[0] = 0; DBG("argc=%d argv[0]=%s argv[1]=%s", argc, argv[0], argc > 1 ? argv[1] : "NULL?"); @@ -227,6 +274,10 @@ int quse_main(int argc, char **argv) switch (i) { case 'e': regexp_matching = 0; break; case 'a': quse_all = 1; break; + case 'o': + repo = 1; + strncpy(repo_search, optarg, sizeof(repo_search)); + break; case 'K': idx = 1; break; case 'L': idx = 2; break; case 'D': idx = -1; break; @@ -235,13 +286,25 @@ int quse_main(int argc, char **argv) COMMON_GETOPTS_CASES(quse) } } - if (argc == optind && !quse_all && idx >= 0) + + if (repo) { + do { + if (!strncmp(cur_overlay->name, repo_search, sizeof(cur_overlay->name))) + break; + } while ((cur_overlay=cur_overlay->next)); + if (NULL == cur_overlay) + err("%s : Unknown overlay, try 'q --ls-overlays'", repo_search); + } + + if (argc == optind && !quse_all && idx >= 0) { + if (idx == 3) + free(search_vars[idx]); quse_usage(EXIT_FAILURE); + } if (idx == -1) - return quse_describe_flag(optind, argc, argv); + return quse_describe_flag(optind, repo, repo_search, argc, argv); - if (quse_all) optind = argc; initialize_ebuild_flat(); /* sets our pwd to $PORTDIR */ search_len = strlen(search_vars[idx]); @@ -253,6 +316,54 @@ int quse_main(int argc, char **argv) FILE *newfp; if ((p = strchr(ebuild, '\n')) != NULL) *p = 0; + if ((p = strchr(ebuild, ':'))) + { + /* delete the ::overlay */ + *p = 0; + if (repo && strncmp(repo_search, p+2, sizeof(repo_search))) + continue; + if (bad_overlay && !strncmp(overlay_name, p+2, sizeof(overlay_name))) + continue; + else { + if (strncmp(overlay_name, p+2, sizeof(overlay_name))) { + overlay_tmp=first_overlay; + do { + if (!strncmp(overlay_tmp->name, p+2, sizeof(overlay_tmp->name))) + break; + } while ((overlay_tmp=overlay_tmp->next)); + if (overlay_tmp) + { + cur_overlay = overlay_tmp; + if (chdir(cur_overlay->path) != 0) { + warnp("chdir to '%s' failed", cur_overlay->path); + myerror=1; + } else + bad_overlay = 0; + } else + myerror=1; + strncpy(overlay_name, p+2, sizeof(overlay_name)); + } + } + } else + myerror=1; + + if (myerror) { + if (!reinitialize) + warnf("(cache update pending) %s : Unknown overlay", overlay_name); + bad_overlay = 1; + myerror = 0; + reinitialize = 1; + continue; + } + + if ((quse_all) && optind!=argc) { + for (i=optind;i 3) printf("%s %s %s ", *user ? user : "MISSING", *revision ? revision : "MISSING", *date ? date : "MISSING"); - printf("%s%s%s ", CYAN, ebuild, NORM); - print_highlighted_use_flags(&buf0[search_len+1], optind, argc, argv); + printf("%s%s::%s%s ", CYAN, cur_overlay->name, ebuild, NORM); + if (quse_all) + print_highlighted_use_flags(&buf0[search_len+1], argc, argc, argv); + else + print_highlighted_use_flags(&buf0[search_len+1], optind, argc, argv); puts(NORM); if (verbose > 1) { char **ARGV = NULL; int ARGC = 0; makeargv(&buf0[search_len+1], &ARGC, &ARGV); if (ARGC > 0) { - quse_describe_flag(1, ARGC, ARGV); + quse_describe_flag(1, 0, repo_search, ARGC, ARGV); for (i = 0; i < ARGC; i++) free(ARGV[i]); free(ARGV); @@ -401,6 +515,8 @@ int quse_main(int argc, char **argv) } } fclose(fp); + if (idx == 3) + free(search_vars[idx]); return EXIT_SUCCESS; }