From 3334a9952b11ec3cc0fcc729c67dc5fcbcc981c7 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 7 Dec 2000 14:10:21 +0000 Subject: [PATCH] (FILESYSTEM_PREFIX_LEN): Define. (dir_name_r): Declare this function as static. [BACKSLASH_IS_PATH_SEPARATOR]: Fix a bug that'd manifest itself on a name containing a mix of slashes and backslashes. Make this function work with names starting with a DOS-style drive letter and colon prefix. (dir_name): Append `.' if necessary. Based mostly on patches from Prashant TR and Eli Zaretskii. --- lib/dirname.c | 57 +++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/lib/dirname.c b/lib/dirname.c index 2225800ab0..7826d8edbf 100644 --- a/lib/dirname.c +++ b/lib/dirname.c @@ -43,17 +43,23 @@ void *memrchr (); #include "dirname.h" +#ifndef FILESYSTEM_PREFIX_LEN +# define FILESYSTEM_PREFIX_LEN(Filename) 0 +#endif + #ifndef ISSLASH # define ISSLASH(C) ((C) == '/') #endif #define BACKSLASH_IS_PATH_SEPARATOR ISSLASH ('\\') -/* Return the length of `dirname (PATH)' and set *RESULT - to point to PATH or to `"."', as appropriate. - Works properly even if there are trailing slashes - (by effectively ignoring them). */ -size_t +/* Return the length of `dirname (PATH)' and set *RESULT to point + to PATH or to `"."', as appropriate. Works properly even if + there are trailing slashes (by effectively ignoring them). + WARNING: This function doesn't work for cwd-relative names like + `a:foo' that are specified with a drive-letter prefix. That case + is handled in the caller. */ +static size_t dir_name_r (char const *path, char const **result) { char const *slash; @@ -78,10 +84,11 @@ dir_name_r (char const *path, char const **result) if (path < slash) { - slash = memrchr (path, '/', slash - path); + size_t len = slash - path; + slash = memrchr (path, '/', len); if (BACKSLASH_IS_PATH_SEPARATOR) { - char const *b = memrchr (path, '\\', slash - path); + char const *b = memrchr (path, '\\', len); if (b && slash < b) slash = b; } @@ -91,27 +98,23 @@ dir_name_r (char const *path, char const **result) if (slash == 0) { /* File is in the current directory. */ - path = "."; - length = 1; + + length = FILESYSTEM_PREFIX_LEN (path); + + if (length == 0) + { + path = "."; + length = 1; + } } else { - /* Remove any trailing slashes from the result. */ - if (BACKSLASH_IS_PATH_SEPARATOR) - { - char const *lim = ((path[0] >= 'A' && path[0] <= 'z' - && path[1] == ':') - ? path + 2 : path); + /* Remove any trailing slashes from the result. If we have a + canonicalized "d:/path", leave alone the root case "d:/". */ + char const *lim = path + FILESYSTEM_PREFIX_LEN (path); - /* If canonicalized "d:/path", leave alone the root case "d:/". */ - while (slash > lim && ISSLASH (*slash)) - --slash; - } - else - { - while (slash > path && ISSLASH (*slash)) - --slash; - } + while (slash > lim && ISSLASH (*slash)) + --slash; length = slash - path + 1; } @@ -130,10 +133,14 @@ dir_name (char const *path) { char const *result; size_t length = dir_name_r (path, &result); - char *newpath = (char *) malloc (length + 1); + int append_dot = (length && length == FILESYSTEM_PREFIX_LEN (newpath)); + char *newpath = (char *) malloc (length + append_dot + 1); if (newpath == 0) return 0; strncpy (newpath, result, length); + /* If PATH is "d:foo", return "d:.", the CWD on drive d: */ + if (append_dot) + newpath[length++] = '.'; newpath[length] = 0; return newpath; } -- 2.30.2