On 22/05/12 01:22, Allan McRae wrote: > The restriction of not checking the ownership of a directory is > unnecessary given that all the package filelists contain this > information. Remove this restriction, with the expectation that you > might get multiple packages returned for a given directory. > Additionally attempt to minimise the number of files getting through > to the slow realpath call. > > This combines ideas from two patches that have been around for a long > time. > > Original-work-by: Andrew Gregory <[email protected]> > Original-work-by: Dan McGee <[email protected]> > Signed-off-by: Allan McRae <[email protected]> > --- > > Not having this feature is beginning to annoy me! Hopefully I have > captured the important bits of both patches... > > src/pacman/query.c | 38 +++++++++++++++++++++++++++----------- > 1 file changed, 27 insertions(+), 11 deletions(-) > > diff --git a/src/pacman/query.c b/src/pacman/query.c > index 464efbf..beaf76c 100644 > --- a/src/pacman/query.c > +++ b/src/pacman/query.c > @@ -113,6 +113,7 @@ static int query_fileowner(alpm_list_t *targets) > size_t rootlen; > alpm_list_t *t; > alpm_db_t *db_local; > + alpm_list_t *packages; > > /* This code is here for safety only */ > if(targets == NULL) { > @@ -133,13 +134,14 @@ static int query_fileowner(alpm_list_t *targets) > strcpy(path, root); > > db_local = alpm_get_localdb(config->handle); > + packages = alpm_db_get_pkgcache(db_local); > > for(t = targets; t; t = alpm_list_next(t)) { > char *filename, *dname, *rpath; > const char *bname; > struct stat buf; > alpm_list_t *i; > - int found = 0; > + size_t found = 0, isdir, bname_len, dname_len; > > filename = strdup(t->data); > > @@ -162,16 +164,20 @@ static int query_fileowner(alpm_list_t *targets) > } > } > > - if(S_ISDIR(buf.st_mode)) { > - pm_printf(ALPM_LOG_ERROR, > - _("cannot determine ownership of directory > '%s'\n"), filename); > - ret++; > - free(filename); > - continue; > + /* make sure directories have a trailing '/' */ > + if((isdir = S_ISDIR(buf.st_mode))) { > + size_t len = strlen(filename); > + if(filename[len-1] != '/') { > + filename = realloc(filename, sizeof(char) * > (len + 2)); > + strcat(filename, "/"); > + } > } > > bname = mbasename(filename); > + bname_len = strlen(bname); > dname = mdirname(filename); > + dname_len = strlen(dname); > + > /* for files in '/', there is no directory name to match */ > if(strcmp(dname, "") == 0) { > rpath = NULL; > @@ -190,7 +196,7 @@ static int query_fileowner(alpm_list_t *targets) > } > free(dname); > > - for(i = alpm_db_get_pkgcache(db_local); i && !found; i = > alpm_list_next(i)) { > + for(i = packages; i && (!found || isdir); i = > alpm_list_next(i)) { > alpm_pkg_t *info = i->data; > alpm_filelist_t *filelist = alpm_pkg_get_files(info); > size_t j; > @@ -199,17 +205,27 @@ static int query_fileowner(alpm_list_t *targets) > const alpm_file_t *file = filelist->files + j; > char *ppath, *pdname; > const char *pkgfile = file->name; > + size_t pkgfile_len = strlen(pkgfile); > > - /* avoid the costly resolve_path usage if the > basenames don't match */ > - if(strcmp(mbasename(pkgfile), bname) != 0) { > + /* avoid the costly resolve_path usage if the > basenames don't match; > + * we can also cheat by comparing the final > characters first and avoid > + * a full string comparison */ > + if(!isdir && (pkgfile[pkgfile_len - 1] != > bname[bname_len - 1] || > + strcmp(mbasename(pkgfile), > bname) != 0)) { > continue; > + } else if(isdir) { > + /* database path needs trailing slash */ > + if(pkgfile[pkgfile_len - 1] != '/' && > + pkgfile[pkgfile_len - > 2] != dname[dname_len - 2]) {
BAD! Will fix...
