bug-gnulib
[Top][All Lists]
Advanced

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

canonicalize_file_name does not support MS-Windows style file names


From: Eli Zaretskii
Subject: canonicalize_file_name does not support MS-Windows style file names
Date: Tue, 17 Jan 2012 20:17:14 +0200

With the patch below, it does.

HTH

--- lib/canonicalize-lgpl.c~0   2011-10-22 16:19:34.000000000 +0200
+++ lib/canonicalize-lgpl.c     2012-01-17 13:10:52.608428500 +0200
@@ -51,6 +51,7 @@
 # define __realpath realpath
 # include "pathmax.h"
 # include "malloca.h"
+# include "dosname.h"
 # if HAVE_GETCWD
 #  if IN_RELOCWRAPPER
     /* When building the relocatable program wrapper, use the system's getcwd
@@ -101,6 +102,7 @@ __realpath (const char *name, char *reso
   const char *start, *end, *rpath_limit;
   long int path_max;
   int num_links = 0;
+  size_t prefix_len;
 
   if (name == NULL)
     {
@@ -143,7 +145,11 @@ __realpath (const char *name, char *reso
     rpath = resolved;
   rpath_limit = rpath + path_max;
 
-  if (name[0] != '/')
+  /* This is always zero for Posix hosts, but can be 2 for MS-Windows
+     and MS-DOS X:/foo/bar file names.  */
+  prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
+
+  if (!IS_ABSOLUTE_FILE_NAME (name))
     {
       if (!__getcwd (rpath, path_max))
         {
@@ -154,13 +160,19 @@ __realpath (const char *name, char *reso
     }
   else
     {
-      rpath[0] = '/';
-      dest = rpath + 1;
-      if (DOUBLE_SLASH_IS_DISTINCT_ROOT && name[1] == '/')
+      dest = rpath;
+      if (prefix_len)
+       {
+         memcpy (rpath, name, prefix_len);
+         dest += prefix_len;
+       }
+      *dest++ = '/';
+      if (DOUBLE_SLASH_IS_DISTINCT_ROOT && ISSLASH (name[1])
+         && !prefix_len)
         *dest++ = '/';
     }
 
-  for (start = end = name; *start; start = end)
+  for (start = end = name + prefix_len; *start; start = end)
     {
 #ifdef _LIBC
       struct stat64 st;
@@ -170,11 +182,11 @@ __realpath (const char *name, char *reso
       int n;
 
       /* Skip sequence of multiple path-separators.  */
-      while (*start == '/')
+      while (ISSLASH (*start))
         ++start;
 
       /* Find end of path component.  */
-      for (end = start; *end && *end != '/'; ++end)
+      for (end = start; *end && !ISSLASH (*end); ++end)
         /* Nothing.  */;
 
       if (end - start == 0)
@@ -184,7 +196,7 @@ __realpath (const char *name, char *reso
       else if (end - start == 2 && start[0] == '.' && start[1] == '.')
         {
           /* Back up to previous component, ignore if at root already.  */
-          if (dest > rpath + 1)
+          if (dest > rpath + prefix_len + 1)
             while ((--dest)[-1] != '/');
           if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
               && *dest == '/')
@@ -205,7 +217,7 @@ __realpath (const char *name, char *reso
               if (resolved)
                 {
                   __set_errno (ENAMETOOLONG);
-                  if (dest > rpath + 1)
+                  if (dest > rpath + prefix_len + 1)
                     dest--;
                   *dest = '\0';
                   goto error;
@@ -295,17 +307,25 @@ __realpath (const char *name, char *reso
               memmove (&extra_buf[n], end, len + 1);
               name = end = memcpy (extra_buf, buf, n);
 
-              if (buf[0] == '/')
+              if (IS_ABSOLUTE_FILE_NAME (buf))
                 {
-                  dest = rpath + 1;     /* It's an absolute symlink */
-                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && buf[1] == '/')
+                 size_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
+
+                 if (pfxlen)
+                   memcpy (rpath, buf, pfxlen);
+                  dest = rpath + pfxlen;     /* It's an absolute symlink.  */
+                 *dest++ = '/';
+                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && ISSLASH (buf[1])
+                     && pfxlen == 0)
                     *dest++ = '/';
+                 /* Install the new prefix to be in effect hereafter.  */
+                 prefix_len = pfxlen;
                 }
               else
                 {
                   /* Back up to previous component, ignore if at root
                      already: */
-                  if (dest > rpath + 1)
+                  if (dest > rpath + prefix_len + 1)
                     while ((--dest)[-1] != '/');
                   if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
                       && *dest == '/')
@@ -319,7 +339,7 @@ __realpath (const char *name, char *reso
             }
         }
     }
-  if (dest > rpath + 1 && dest[-1] == '/')
+  if (dest > rpath + prefix_len + 1 && dest[-1] == '/')
     --dest;
   if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && *dest == '/')
     dest++;




reply via email to

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