[pacman-dev] [PATCH] Allow querying directory ownership

Allan McRae allan at archlinux.org
Mon May 21 11:27:13 EDT 2012


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 <andrew.gregory.8 at gmail.com>
> Original-work-by: Dan McGee <dan at archlinux.org>
> Signed-off-by: Allan McRae <allan at archlinux.org>
> ---
> 
> 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...


More information about the pacman-dev mailing list