dirname() in C: is the manual wrong?

Gui13 picture Gui13 · Dec 10, 2012 · Viewed 10.8k times · Source

Citing the manual here:

The functions dirname() and basename() break a null-terminated pathname string into directory and filename components. In the usual case, dirname() returns the string up to, but not including, the final '/', and basename() returns the component following the final '/'. Trailing '/' characters are not counted as part of the pathname.

And later on, you have this little table:

path         dirname    basename
"/usr/lib"    "/usr"    "lib"
"/usr/"       "/"       "usr"        // wat?
"usr"         "."       "usr"
"/"           "/"       "/"
"."           "."       "."
".."          "."       ".."

Why is dirname( "/usr/") returning "/" and not "/usr" ?
The sentence in the manual tells me I should get /usr as a result.
I tested the actual result in a dummy program and it behaves just like the manual says.

#include <libgen.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char const *argv[])
{
    const char *mydir="/usr/";
    char *dummy  = strdup( mydir );
    char *dummy2 = strdup( mydir );

    char *dname = dirname( dummy );
    char *bname = basename( dummy2 );


    printf("mydir: '%s', dname: '%s', bname: '%s'\n", mydir, dname, bname);

    free( dummy );
    free( dummy2 );

    return 0;
}


$ ./test  
mydir: '/usr/', dname: '/', bname: 'usr'

Now, what I would expect would be:

path         dirname    basename
"/usr/"       "/usr"       ""        // more consistent?

So.. anybody understands what's going on here?

Answer

chill picture chill · Dec 10, 2012

Trailing '/' characters are not counted as part of the pathname.

Hence "/usr/" is the same as "/usr", which might denote a file or a directory with name (directory entry named) usr in the directory /. The function dirname returns the parent directory of the path. The parent directory of /usr is /. Seems entirely consistent.