bug-glibc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

There are still bugs in dirname(3) (glibc 2.2.3.pre1)


From: Michael Kerrisk
Subject: There are still bugs in dirname(3) (glibc 2.2.3.pre1)
Date: Sun, 1 Apr 2001 22:18:27 +0200

Gidday,

A while back I submitted a patch for dirname(3) for glibc 2.2.1, which was 
not correctly handling the case of trailing slashes in pathnames.  The 
version is glibc 2.2.3pre1 is improved, but still broken.  SUSv2 says 

        "Trailing '/' character**s** in the path are not counted as 
        part of the path"  

Note the plural!  (As usual for Unix pathnames, repeated slashes are 
equivalent to a single slash).  Thus the 2.2.3pre1 version of dirname(3), 
given the following paths:

       returns      Should return
a//       a                .
a////     a//              .
////a     ///              /
//a//     //a              /

I resubmit my thoroughly tested (and now modified, since I discovered my 
initial patch also broke on the last two cases) version below - with 
perrmission to copyright to FSF and use and include in glibc under the 
terms of GPL.

Cheers

Michael



char *
dirname(char *path)
{
  static const char dot[] = ".";
  char *last_slash;

  if (path == NULL || *path == '\0') {
    /* NULL path or empty string: return "." */
    path = (char *) dot;
  } else {
    last_slash = path + strlen(path) - 1;

    /* Ignore multiple slashes at end of path, step back until we find
       a non-slash, or we reach start of string */

    while (*last_slash == '/' && last_slash > path)
      --last_slash;

    if (*last_slash == '/')     /* We got to BOS and found no non-slash */
      /* Pathname consisted only of slashes, return "/" */

      path[1] = '\0';
    else {
      /* Walk backwards to find slash */
      while (*last_slash != '/' && last_slash > path)
        last_slash --;
      if (*last_slash == '/')           /* We found a slash */
        if (last_slash == path)         /* But it was the first char */
          path[1] = '\0';               /* So return "/" */
        else {                          /* Slash is not first char, so... 
*/

          /* may have multiple slashes at end of directory spec,
             so walk back till we reach a non-slash */

          while (*(last_slash-1) == '/' && last_slash > path)
            last_slash --;
          if (*last_slash  == '/')      /* We hit BOS */
            *(last_slash+1) = '\0';     /* So make next char terminator */
          else
            *last_slash = '\0';         /* dirname ends here */
        }
      else
        path = (char *) dot;            /* No slash found, return "." */
    }
  }

  return path;
}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]