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

Dan McGee dpmcgee at gmail.com
Sun Oct 11 17:09:41 EDT 2009


On Fri, Nov 7, 2008 at 2:51 AM, Jatheendra <jatheendra at gmail.com> wrote:
> On Fri, Nov 7, 2008 at 1:18 PM, Jatheendra <jatheendra at gmail.com> wrote:
>> On Thu, Nov 6, 2008 at 10:17 PM, Allan McRae <allan at archlinux.org> wrote:
>>> 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"))?
>>
>> The problem was that subsequent calls to getenv are returning the same
>> mem location. And we are mutilating that location (envpath) by calling
>> strsep.
>> So if we have more than one targets passed to Qo , then from second
>> target onwards it will search only along the mutilated path..
>> I dont know if it is some mistake i made or the implimentation of getenv.
>>
> >From man getenv
>  As typically implemented, getenv() returns a pointer to a string
> within the environment list.  The caller must take care not to modify
> this string, since that would change the environment of the process.
>
>> About strdup(getenv("PATH")) , will it be possible to handle the error
>> if getenv fails ? I am not sure what strdup(NULL) will do..
>>
>>
>>>
>>>> +       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?
>>
>> Will try :-)
>>
>>>
>>>>                }
>>>>
>>>> +
>>>>                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;
>>>>  }

This looks like it got dropped on the floor (but is linked in the
comments of FS#8798). Anyone want to dust it off and resubmit?

-Dan


More information about the pacman-dev mailing list