changeset 3038:e42896c5352d

(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.
author Jim Meyering <jim@meyering.net>
date Thu, 07 Dec 2000 14:10:21 +0000
parents e6757ccfb526
children cd8da840fa9d
files lib/dirname.c
diffstat 1 files changed, 32 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/lib/dirname.c
+++ b/lib/dirname.c
@@ -43,17 +43,23 @@
 
 #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 @@
 
       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 @@
   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 @@
 {
   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;
 }