[Patch]: chdir

Pierre A. Humblet pierre@phumblet.no-ip.org
Thu May 6 04:01:00 GMT 2004


After mulling over it, I simplified chdir even more
in the interest of uniformity (it matters for unc paths).
Now cwd.set is always called with only the native_dir.

That means that cwd.set always attempts to build the
Posix wd through the mount table.
Up to now that was only the case when a symlink was
involved in the translation, or there was a ":" or a "\" 
in the directory name, or check_case was not relaxed.

Pierre

2004-05-06  Pierre Humblet <pierre.humblet@ieee.org>

	* path.cc (chdir): Do not check for trailing spaces.
	Do not set native_dir to c:\ for virtual devices.
	Pass only native_dir to cwd.set.
	(cwdstuff::set): Assume posix_cwd is already normalized.

-------------- next part --------------
Index: path.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/path.cc,v
retrieving revision 1.308
diff -u -p -r1.308 path.cc
--- path.cc	4 May 2004 15:14:48 -0000	1.308
+++ path.cc	5 May 2004 23:36:33 -0000
@@ -286,10 +286,6 @@ normalize_posix_path (const char *src, c
     }

 done:
-  /* Remove trailing dots and spaces which are ignored by Win32 functions but
-     not by native NT functions. */
-  while (dst[-1] == '.' || dst[-1] == ' ')
-    --dst;
   *dst = '\0';
   *tail = dst;

@@ -555,9 +551,19 @@ path_conv::check (const char *src, unsig
       if (tail > path_copy + 1 && isslash (*(tail - 1)))
 	{
 	  need_directory = 1;
-	  *--tail = '\0';
+	  tail--;
+	}
+      /* Remove trailing dots and spaces which are ignored by Win32 functions but
+	 not by native NT functions. */
+      while (tail[-1] == '.' || tail[-1] == ' ')
+	tail--;
+      if (tail[-1] == '/')
+        {
+	  error = ENOENT;
+          return;
 	}
       path_end = tail;
+      *tail = '\0';

       /* Scan path_copy from right to left looking either for a symlink
 	 or an actual existing file.  If an existing file is found, just
@@ -3285,80 +3291,44 @@ chdir (const char *in_dir)

   syscall_printf ("dir '%s'", in_dir);

-  char *s;
-  char dir[strlen (in_dir) + 1];
-  strcpy (dir, in_dir);
-  /* Incredibly. Windows allows you to specify a path with trailing
-     whitespace to SetCurrentDirectory.  This doesn't work too well
-     with other parts of the API, though, apparently.  So nuke trailing
-     white space. */
-  for (s = strchr (dir, '\0'); --s >= dir && isspace ((unsigned int) (*s & 0xff)); )
-    *s = '\0';
-
-  if (!*s)
-    {
-      set_errno (ENOENT);
-      return -1;
-    }
-
   /* Convert path.  First argument ensures that we don't check for NULL/empty/invalid
      again. */
-  path_conv path (PC_NONULLEMPTY, dir, PC_FULL | PC_SYM_FOLLOW);
+  path_conv path (PC_NONULLEMPTY, in_dir, PC_FULL | PC_SYM_FOLLOW);
   if (path.error)
     {
       set_errno (path.error);
-      syscall_printf ("-1 = chdir (%s)", dir);
+      syscall_printf ("-1 = chdir (%s)", in_dir);
       return -1;
     }

+  int res = -1;
   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
-     defeat the Windows 95 (i.e. MS-DOS) tendency of returning to
-     the last directory visited on the given drive. */
-  if (isdrive (native_dir) && !native_dir[2])
-    {
-      path.get_win32 ()[2] = '\\';
-      path.get_win32 ()[3] = '\0';
-    }
-  int res;
   int devn = path.get_devn ();
   if (!isvirtual_dev (devn))
-    res = SetCurrentDirectory (native_dir) ? 0 : -1;
-  else if (!path.exists ())
     {
-      set_errno (ENOENT);
-      return -1;
+      /* Check to see if path translates to something like C:.
+	 If it does, append a \ to the native directory specification to
+	 defeat the Windows 95 (i.e. MS-DOS) tendency of returning to
+	 the last directory visited on the given drive. */
+      if (isdrive (native_dir) && !native_dir[2])
+        {
+	  path.get_win32 ()[2] = '\\';
+	  path.get_win32 ()[3] = '\0';
+	}
+      if (SetCurrentDirectory (native_dir))
+        res = 0;
+      else
+        __seterrno ();
     }
+  else if (!path.exists ())
+    set_errno (ENOENT);
   else if (!path.isdir ())
-    {
-      set_errno (ENOTDIR);
-      return -1;
-    }
+    set_errno (ENOTDIR);
   else
-    {
-      native_dir = "c:\\";
-      res = 0;
-    }
+    res = 0;

-  /* If res != 0, we didn't change to a new directory.
-     Otherwise, set the current windows and posix directory cache from input.
-     If the specified directory is a MS-DOS style directory or if the directory
-     was symlinked, convert the MS-DOS path back to posix style.  Otherwise just
-     store the given directory.  This allows things like "find", which traverse
-     directory trees, to work correctly with Cygwin mounted directories.
-     FIXME: Is just storing the posixized windows directory the correct thing to
-     do when we detect a symlink?  Should we instead rebuild the posix path from
-     the input by traversing links?  This would be an expensive operation but
-     we'll see if Cygwin mailing list users whine about the current behavior. */
-  if (res)
-    __seterrno ();
-  else if ((!path.has_symlinks () && strpbrk (dir, ":\\") == NULL
-	    && pcheck_case == PCHECK_RELAXED) || isvirtual_dev (devn))
-    cygheap->cwd.set (native_dir, dir);
-  else
-    cygheap->cwd.set (native_dir, NULL);
+  if (res == 0)
+    cygheap->cwd.set (native_dir);

   /* Note that we're accessing cwd.posix without a lock here.  I didn't think
      it was worth locking just for strace. */
@@ -3711,16 +3681,12 @@ cwdstuff::set (const char *win32_cwd, co
     }

   if (!posix_cwd)
-    mount_table->conv_to_posix_path (win32, pathbuf, 0);
-  else
     {
-      char * tail;
-      (void) normalize_posix_path (posix_cwd, pathbuf, &tail);
-      if (tail > pathbuf + 1 && *(--tail) == '/')
-	*tail = 0;
+      mount_table->conv_to_posix_path (win32, pathbuf, 0);
+      posix_cwd = pathbuf;
     }
-  posix = (char *) crealloc (posix, strlen (pathbuf) + 1);
-  strcpy (posix, pathbuf);
+  posix = (char *) crealloc (posix, strlen (posix_cwd) + 1);
+  strcpy (posix, posix_cwd);

   hash = hash_path_name (0, win32);



More information about the Cygwin-patches mailing list