OSDN Git Service

* fhandler.h (FH_ENC): New enum.
authorcgf <cgf>
Fri, 4 Jul 2003 03:07:01 +0000 (03:07 +0000)
committercgf <cgf>
Fri, 4 Jul 2003 03:07:01 +0000 (03:07 +0000)
(fhandler_base::get_encoded): New function.
(fhandler_base::set_encoded): Ditto.
* fhandler_disk_file.cc (fhandler_disk_file::opendir): Set encoded flag in
fhandler, as appropriate.
(fhandler_disk_file::readdir): Unmunge filename as appropriate based on new
encoding flag.
* path.cc (normalize_posix_path): Don't punt on files with colons.
(special_char): New function.
(mount_item::fnmunge): Ditto.
(fnunmunge): Ditto.
(special_name): Ditto.
(mount_item::build_win32): Avoid drive considerations when file is encoded.
(mount_info::conv_to_win32_path): Handle encoded filenames.
(mount_info::conv_to_posix_path): Ditto.
(fillout_mntent): Add posix string when directory is encoded.
* path.h (fnunmunge): Declare.
(path_conv::is_encoded): Declare.

winsup/cygwin/ChangeLog
winsup/cygwin/fhandler.h
winsup/cygwin/fhandler_disk_file.cc
winsup/cygwin/path.cc
winsup/cygwin/path.h

index a65c92d..82045de 100644 (file)
@@ -1,3 +1,25 @@
+2003-07-02  Christopher Faylor  <cgf@redhat.com>
+
+       * fhandler.h (FH_ENC): New enum.
+       (fhandler_base::get_encoded): New function.
+       (fhandler_base::set_encoded): Ditto.
+       * fhandler_disk_file.cc (fhandler_disk_file::opendir): Set encoded flag
+       in fhandler, as appropriate.
+       (fhandler_disk_file::readdir): Unmunge filename as appropriate based on
+       new encoding flag.
+       * path.cc (normalize_posix_path): Don't punt on files with colons.
+       (special_char): New function.
+       (mount_item::fnmunge): Ditto.
+       (fnunmunge): Ditto.
+       (special_name): Ditto.
+       (mount_item::build_win32): Avoid drive considerations when file is
+       encoded.
+       (mount_info::conv_to_win32_path): Handle encoded filenames.
+       (mount_info::conv_to_posix_path): Ditto.
+       (fillout_mntent): Add posix string when directory is encoded.
+       * path.h (fnunmunge): Declare.
+       (path_conv::is_encoded): Declare.
+
 2003-07-03  Christopher Faylor  <cgf@redhat.com>
 
        * fhandler_tty.cc (fhandler_tty_slave::open): Conditionalize a little
index ae3becc..9d037d6 100644 (file)
@@ -23,8 +23,7 @@ enum
   FH_WBINSET   = 0x00010000,   /* binary write mode has been explicitly set */
   FH_APPEND    = 0x00020000,   /* always append */
   FH_ASYNC     = 0x00040000,   /* async I/O */
-  FH_SIGCLOSE  = 0x00080000,   /* signal handler should close fd on interrupt */
-
+  FH_ENC       = 0x00080000,   /* native path is encoded */
   FH_SYMLINK   = 0x00100000,   /* is a symlink */
   FH_EXECABL   = 0x00200000,   /* file looked like it would run:
                                 * ends in .exe or .bat or begins with #! */
@@ -242,6 +241,9 @@ class fhandler_base
   bool get_need_fork_fixup () { return FHISSETF (FFIXUP); }
   void set_need_fork_fixup () { FHSETF (FFIXUP); }
 
+  bool get_encoded () { return FHISSETF (ENC);}
+  void set_encoded () { FHSETF (ENC);}
+
   virtual void set_close_on_exec (int val);
 
   virtual void fixup_before_fork_exec (DWORD) {}
index 48778f4..29206bb 100644 (file)
@@ -607,6 +607,8 @@ fhandler_disk_file::opendir (path_conv& real_name)
 
          res = dir;
        }
+      if (real_name.isencoded ())
+       set_encoded ();
     }
 
   syscall_printf ("%p = opendir (%s)", res, get_name ());
@@ -633,9 +635,7 @@ fhandler_disk_file::readdir (DIR *dir)
        }
     }
   else if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE)
-    {
-      return res;
-    }
+    return res;
   else if (!FindNextFileA (dir->__d_u.__d_data.__handle, &buf))
     {
       DWORD lasterr = GetLastError ();
@@ -650,7 +650,10 @@ fhandler_disk_file::readdir (DIR *dir)
     }
 
   /* We get here if `buf' contains valid data.  */
-  strcpy (dir->__d_dirent->d_name, buf.cFileName);
+  if (get_encoded ())
+    (void) fnunmunge (dir->__d_dirent->d_name, buf.cFileName);
+  else
+    strcpy (dir->__d_dirent->d_name, buf.cFileName);
 
   /* Check for Windows shortcut. If it's a Cygwin or U/WIN
      symlink, drop the .lnk suffix. */
index d064819..ab3e51f 100644 (file)
@@ -203,7 +203,7 @@ normalize_posix_path (const char *src, char *dst)
 
   syscall_printf ("src %s", src);
 
-  if (isdrive (src) || strpbrk (src, "\\:"))
+  if (isdrive (src))
     {
       int err = normalize_win32_path (src, dst);
       if (!err && isdrive (dst))
@@ -499,7 +499,7 @@ path_conv::check (const char *src, unsigned opt,
 
       /* Scan path_copy from right to left looking either for a symlink
         or an actual existing file.  If an existing file is found, just
-        return.  If a symlink is found exit the for loop.
+        return.  If a symlink is found, exit the for loop.
         Also: be careful to preserve the errno returned from
         symlink.check as the caller may need it. */
       /* FIXME: Do we have to worry about multiple \'s here? */
@@ -1390,10 +1390,99 @@ set_flags (unsigned *flags, unsigned val)
     }
 }
 
+char special_chars[] =
+    "\001" "\002" "\003" "\004" "\005" "\006" "\007" "\010"
+    "\011" "\012" "\013" "\014" "\015" "\016" "\017" "\020"
+    "\021" "\022" "\023" "\024" "\025" "\026" "\027" "\030"
+    "\031" "\032" "\033" "\034" "\035" "\036" "\037"
+    ":"    "\\"   "*"    "?"    "%"
+    "A"    "B"    "C"    "D"    "E"    "F"    "G"    "H"
+    "I"    "J"    "K"    "L"    "M"    "N"    "O"    "P"
+    "Q"    "R"    "S"    "T"    "U"    "V"    "W"    "X"
+    "Y"    "Z";
+
+static inline char
+special_char (const char *s)
+{
+  char *p = strechr (special_chars, *s);
+  if (*p == '%' && strlen (p) >= 3)
+    {
+      char hex[] = {s[1], s[2], '\0'};
+      unsigned char c = strtoul (hex, &p, 16);
+      p = strechr (special_chars, c);
+    }
+  return *p;
+}
+
+bool
+fnunmunge (char *dst, const char *src) 
+{
+  bool converted = false;
+  char c;
+
+  while (*src)
+    if (*src != '%' || !(c = special_char (src)))
+      *dst++ = *src++;
+    else
+      {
+       converted = true;
+       *dst++ = c;
+       src += 3;
+      }
+
+  *dst = *src;
+  return converted;
+}
+
+/* Determines if name is "special".  Assumes that name is empty or "absolute" */
+static int
+special_name (const char *s)
+{
+  if (!*s)
+    return false;
+
+  if (strpbrk (++s, special_chars))
+    return !strncasematch (s, "%2f", 3);
+
+  if (strcasematch (s, "nul")
+      || strcasematch (s, "aux")
+      || strcasematch (s, "prn"))
+    return -1;
+  if (!strncasematch (s, "com", 3)
+      && !strncasematch (s, "lpt", 3))
+    return false;
+  char *p;
+  (void) strtol (s, &p, 10);
+  return -(*p == '\0');
+}
+
 void
 mount_item::fnmunge (char *dst, const char *src)
 {
-  strcpy (dst, src);
+  int name_type;
+  if (!(flags & MOUNT_ENC) || !(name_type = special_name (src)))
+    strcpy (dst, src);
+  else
+    {
+      char *d = dst;
+      *d++ = *src++;
+      if (name_type < 0)
+       {
+         __small_sprintf (d, "%%%02x", (unsigned char) *src++);
+         d += 3;
+       }
+
+      while (*src)
+       if (!special_char (src))
+         *d++ = *src++;
+       else
+         {
+           __small_sprintf (d, "%%%02x", (unsigned char) *src++);
+           d += 3;
+         }
+      *d = *src;
+    }
+
   backslashify (dst, dst, 0);
 }
 
@@ -1420,7 +1509,7 @@ mount_item::build_win32 (char *dst, const char *src, unsigned *outflags, unsigne
   const char *p = src + real_posix_pathlen;
   if (*p == '/')
     /* nothing */;
-  else if ((isdrive (dst) && !dst[2]) || *p)
+  else if ((!(flags & MOUNT_ENC) && isdrive (dst) && !dst[2]) || *p)
     dst[n++] = '\\';
   fnmunge (dst + n, p);
 }
@@ -1475,22 +1564,6 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst,
   if (dst == NULL)
     goto out;          /* Sanity check. */
 
-  /* An MS-DOS spec has either a : or a \.  If this is found, short
-     circuit most of the rest of this function. */
-  if (strpbrk (src_path, ":\\") != NULL || slash_unc_prefix_p (src_path))
-    {
-      debug_printf ("%s already win32", src_path);
-      rc = normalize_win32_path (src_path, dst);
-      if (rc)
-       {
-         debug_printf ("normalize_win32_path failed, rc %d", rc);
-         return rc;
-       }
-
-      set_flags (flags, (unsigned) set_flags_from_win32_path (dst));
-      goto out;
-    }
-
   /* Normalize the path, taking out ../../ stuff, we need to do this
      so that we can move from one mounted directory to another with relative
      stuff.
@@ -1587,16 +1660,21 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst,
        break;
     }
 
-  if (i >= nmounts)
+  if (i < nmounts)
     {
-      backslashify (pathbuf, dst, 0);  /* just convert */
-      set_flags (flags, PATH_BINARY);
-      chroot_ok = !cygheap->root.exists ();
+      mi->build_win32 (dst, pathbuf, flags, chroot_pathlen);
+      chroot_ok = true;
     }
   else
     {
-      mi->build_win32 (dst, pathbuf, flags, chroot_pathlen);
-      chroot_ok = true;
+      if (strpbrk (src_path, ":\\") != NULL || slash_unc_prefix_p (src_path))
+       rc = normalize_win32_path (src_path, dst);
+      else
+       {
+         backslashify (pathbuf, dst, 0);       /* just convert */
+         set_flags (flags, PATH_BINARY);
+       }
+      chroot_ok = !cygheap->root.exists ();
     }
 
   if (!isvirtual_dev (devn))
@@ -1760,6 +1838,12 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path,
          const char *p = cygheap->root.unchroot (posix_path);
          memmove (posix_path, p, strlen (p) + 1);
        }
+      if (mi.flags & MOUNT_ENC)
+       {
+         char tmpbuf[MAX_PATH + 1];
+         if (fnunmunge (tmpbuf, posix_path))
+           strcpy (posix_path, tmpbuf);
+       }
       goto out;
     }
 
@@ -2420,6 +2504,8 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
     strcat (_reent_winsup ()->mnt_opts, (char *) ",exec");
   else if (flags & MOUNT_NOTEXEC)
     strcat (_reent_winsup ()->mnt_opts, (char *) ",noexec");
+  if (flags & MOUNT_ENC)
+    strcat (_reent_winsup ()->mnt_opts, ",posix");
 
   if ((flags & MOUNT_CYGDRIVE))                /* cygdrive */
     strcat (_reent_winsup ()->mnt_opts, (char *) ",noumount");
@@ -3344,7 +3430,7 @@ chdir (const char *in_dir)
       return -1;
     }
 
-  const char *native_dir = path.get_win32 ();
+  const char *native_dir = path;
 
   /* Check to see if path translates to something like C:.
      If it does, append a \ to the native directory specification to
index bd5b4a2..f92e2d3 100644 (file)
@@ -46,6 +46,7 @@ enum path_types
   PATH_EXEC = MOUNT_EXEC,
   PATH_NOTEXEC = MOUNT_NOTEXEC,
   PATH_CYGWIN_EXEC = MOUNT_CYGWIN_EXEC,
+  PATH_ENC = MOUNT_ENC,
   PATH_ALL_EXEC = (PATH_CYGWIN_EXEC | PATH_EXEC),
   PATH_LNK =         0x01000000,
   PATH_TEXT =        0x02000000,
@@ -89,6 +90,7 @@ class path_conv
   int has_symlinks () const {return path_flags & PATH_HAS_SYMLINKS;}
   int hasgood_inode () const {return path_flags & PATH_HASACLS;}  // Not strictly correct
   int has_buggy_open () const {return path_flags & PATH_HASBUGGYOPEN;}
+  bool isencoded () {return path_flags & PATH_ENC;}
   int binmode () const
   {
     if (path_flags & PATH_BINARY)
@@ -210,6 +212,8 @@ has_exec_chars (const char *buf, int len)
 int pathmatch (const char *path1, const char *path2) __attribute__ ((regparm (2)));
 int pathnmatch (const char *path1, const char *path2, int len) __attribute__ ((regparm (2)));
 
+bool fnunmunge (char *, const char *) __attribute__ ((regparm (2)));
+
 int path_prefix_p (const char *path1, const char *path2, int len1) __attribute__ ((regparm (3)));
 
 /* FIXME: Move to own include file eventually */