[pacman-dev] [PATCH] FS#8798 - Allow -Qo to perform a functional 'which'

Allan McRae allan at archlinux.org
Thu Nov 6 11:47:54 EST 2008


Jatheendra wrote:
> Hi all,
>
> This is a simple patch to add a "which" like functionality to pacman
> -Qo[Bug FS#8798]. This is my first patch ,so any constructive
> criticism is most welcome.
>
> Thanks,
> Shankar
>   

Nice work.  This is a really nice feature to implement.


> ---
>  src/pacman/query.c |   62 +++++++++++++++++++++++++++++++++++++++++++++++----
>  1 files changed, 57 insertions(+), 5 deletions(-)
>
> diff --git a/src/pacman/query.c b/src/pacman/query.c
> index 0d48638..fb3bb92 100644
> --- a/src/pacman/query.c
> +++ b/src/pacman/query.c
> @@ -55,6 +55,43 @@ static char *resolve_path(const char* file)
>  	return(str);
>  }
>
> +/* check if filename exists in PATH */
> +static int search_path(char *filename, struct stat * bufptr)
> +{
> +	char *envpath, *path, *fullname;
> +	int len;
> +
> +	if ((envpath = getenv("PATH")) == NULL) {
> +		return(-1);
> +	}
> +
> +	if ((envpath = strdup(envpath)) == NULL) {
> +		return(-1);
> +	}
> +	
>   

Do we need the strdup here?  I realize that getenv can return static 
data the may be overwritten by the next getenv, but we are not calling 
getenv again.  Or how about an all in one strdup(getenv("PATH"))?

> +	fullname = calloc(PATH_MAX+1, sizeof(char));
> +
> +	while ((path = strsep(&envpath, ":")) != NULL) {
> +			len = strlen(path);
> +
> +			/* strip trailing '/' */
> +			while (path[len-1] == '/') {
> +					path[--len] = '\0';
> +			}
> +			
> +			snprintf(fullname, PATH_MAX+1, "%s/%s", path, filename);
> +
> +			if(stat(fullname,bufptr) == 0) {
> +				strncpy(filename,fullname,PATH_MAX+1);
> +				free(fullname);
> +				return(0);
> +			}
>   

+1 to Aaron's comment here.

> +	}
> +	free(fullname);
> +	return(-1);
> +}
> +
> +
>  static int query_fileowner(alpm_list_t *targets)
>  {
>  	int ret = 0;
> @@ -66,21 +103,35 @@ static int query_fileowner(alpm_list_t *targets)
>  		return(1);
>  	}
>
> +	char *filename = calloc(PATH_MAX+1, sizeof(char));
> +
>  	for(t = targets; t; t = alpm_list_next(t)) {
>  		int found = 0;
> -		char *filename = alpm_list_getdata(t);
> +		strncpy(filename,alpm_list_getdata(t),PATH_MAX+1);
> +
>  		char *bname, *dname, *rpath;
>  		const char *root;
>  		struct stat buf;
>  		alpm_list_t *i, *j;
>
>  		if(stat(filename, &buf) == -1) {
> -			pm_fprintf(stderr, PM_LOG_ERROR, _("failed to read file '%s': %s\n"),
> -					filename, strerror(errno));
> -			ret++;
> -			continue;
> +			/*  if it is not a path but a program name, then check in PATH */
> +			if(strchr(filename,'/') == NULL) {
> +				if((search_path(filename,&buf)) == -1) {
> +					pm_fprintf(stderr, PM_LOG_ERROR, _("failed to read file '%s': %s\n"),
> +							filename, strerror(errno));
> +					ret++;
> +					continue;
> +				}
> +			} else {
> +				pm_fprintf(stderr, PM_LOG_ERROR, _("failed to read file '%s': %s\n"),
> +						filename, strerror(errno));
> +				ret++;
> +				continue;
> +			}
>   

Is there a way to have this error message not duplicated without making 
the if statement look really complicated?

>  		}
>
> +
>  		if(S_ISDIR(buf.st_mode)) {
>  			pm_fprintf(stderr, PM_LOG_ERROR,
>  				_("cannot determine ownership of a directory\n"));
> @@ -140,6 +191,7 @@ static int query_fileowner(alpm_list_t *targets)
>  		free(rpath);
>  	}
>
> +	free(filename);
>  	return ret;
>  }
>
>   






More information about the pacman-dev mailing list