changeset 1116:3bcd77d0bf93

[xemacs-hg @ 2002-11-22 12:57:09 by ben] file-truename and other crash fileio.c: Fix crashes due to incorrectly ported code from FSF. realpath.c: Don't return EIO when a filename is incorrect, since the I/O error gets passed all the way up. Clean up this file and avoid using macros as a poor-man's dispatch mechanism -- it just makes it impossible to follow the code.
author ben
date Fri, 22 Nov 2002 12:57:11 +0000
parents cb1d0fc87e10
children b3fcaf7cb856
files src/ChangeLog src/fileio.c src/realpath.c
diffstat 3 files changed, 152 insertions(+), 165 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Thu Nov 21 22:53:01 2002 +0000
+++ b/src/ChangeLog	Fri Nov 22 12:57:11 2002 +0000
@@ -1,3 +1,13 @@
+2002-11-22  Ben Wing  <ben@xemacs.org>
+
+	* fileio.c: Fix crashes due to incorrectly ported code from
+	FSF.
+
+	* realpath.c: Don't return EIO when a filename is incorrect,
+	since the I/O error gets passed all the way up.  Clean up this
+	file and avoid using macros as a poor-man's dispatch mechanism --
+	it just makes it impossible to follow the code.
+
 2002-11-17  Ben Wing  <ben@xemacs.org>
 
 	* s/cygwin32.h:
--- a/src/fileio.c	Thu Nov 21 22:53:01 2002 +0000
+++ b/src/fileio.c	Fri Nov 22 12:57:11 2002 +0000
@@ -374,10 +374,12 @@
       
       res = alloca_array (Ibyte,
 			  (wd ? qxestrlen (wd) : 0) + 10); /* go overboard */
+      res[0] = '\0';
       if (p == beg + 4 && IS_DIRECTORY_SEP (*beg) && beg[1] == ':')
 	{
 	  qxestrncpy (res, beg, 2);
 	  beg += 2;
+	  res[2] = '\0';
 	}
 
       if (wd)
--- a/src/realpath.c	Thu Nov 21 22:53:01 2002 +0000
+++ b/src/realpath.c	Fri Nov 22 12:57:11 2002 +0000
@@ -1,7 +1,7 @@
 /*
  * realpath.c -- canonicalize pathname by removing symlinks
  * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
- * Copyright (C) 2001 Ben Wing.
+ * Copyright (C) 2001, 2002 Ben Wing.
  *
 
 This file is part of XEmacs.
@@ -32,155 +32,22 @@
 #include "lisp.h"
 
 #include "sysfile.h"
+#include "sysdir.h"
 
 #define MAX_READLINKS 32
 
-#if defined (HAVE_SYS_PARAM_H) && !defined (WIN32_NATIVE)
-#include <sys/param.h>
-#endif
-
-#ifdef WIN32_NATIVE
-#include <direct.h>
-#endif
-
-#include <sys/stat.h>			/* for S_IFLNK */
-
-#if defined(WIN32_NATIVE) || defined(CYGWIN)
-#define WIN32_FILENAMES
-#endif
-
-/* First char after start of absolute filename. */
-#define ABS_START(name) (name + ABS_LENGTH (name))
-
-#if defined (WIN32_NATIVE)
-/* Length of start of absolute filename. */
-# define ABS_LENGTH(name) (mswindows_abs_start (name))
-static int mswindows_abs_start (const Ibyte *name);
-# define readlink_and_correct_case mswindows_readlink_and_correct_case
-#else
-# ifdef CYGWIN
-#  ifdef WIN32_FILENAMES
-#   define ABS_LENGTH(name) (mswindows_abs_start (name))
-static int mswindows_abs_start (const Ibyte * name);
-#  else
-#   define ABS_LENGTH(name) (IS_DIRECTORY_SEP (*name) ? \
-                             (IS_DIRECTORY_SEP (name[1]) ? 2 : 1) : 0)
-#  endif
-#  define readlink_and_correct_case cygwin_readlink_and_correct_case
-# else
-#  define ABS_LENGTH(name) (IS_DIRECTORY_SEP (*name) ? 1 : 0)
-#  define readlink_and_correct_case qxe_readlink
-# endif /* CYGWIN */
-#endif /* WIN32_NATIVE */
-
-#if defined (WIN32_NATIVE) || defined (CYGWIN)
+#ifdef WIN32_ANY
 #include "syswindows.h"
-/* "Emulate" readlink on mswindows - finds real name (i.e. correct
-   case) of a file. (#### "readlink" is used extremely misleadingly
-   here.  This is much more like "truename"!) UNC servers and shares
-   are lower-cased. Directories must be given without trailing
-   '/'. One day, this could read Win2K's reparse points. */
-static int
-mswindows_readlink_and_correct_case (const Ibyte *name, Ibyte *buf,
-				     int size)
-{
-  int len = 0;
-  int err = 0;
-  const Ibyte *lastname;
-  int count = 0;
-  const Ibyte *tmp;
-  DECLARE_EISTRING (result);
-  
-  assert (*name);
-  
-  /* Sort of check we have a valid filename. */
-  if (qxestrpbrk (name, "*?|<>\"") || qxestrlen (name) >= PATH_MAX)
-    {
-      errno = EIO;
-      return -1;
-    }
-  
-  /* Find start of filename */
-  lastname = name + qxestrlen (name);
-  while (lastname > name && !IS_DIRECTORY_SEP (lastname[-1]))
-    --lastname;
-
-  /* Count slashes in unc path */
-  if (ABS_LENGTH (name) == 2)
-    for (tmp = name; *tmp; tmp++)
-      if (IS_DIRECTORY_SEP (*tmp))
-	count++;
-
-  if (count >= 2 && count < 4)
-    {
-      eicpy_rawz (result, lastname);
-      eilwr (result);
-    }
-  else
-    {
-      WIN32_FIND_DATAW find_data;
-      Extbyte *nameext;
-      HANDLE dir_handle;
-
-      C_STRING_TO_TSTR (name, nameext);
-      dir_handle = qxeFindFirstFile (nameext, &find_data);
-      if (dir_handle == INVALID_HANDLE_VALUE)
-	{
-	  errno = ENOENT;
-	  return -1;
-	}
-      eicpy_ext (result, (Extbyte *) find_data.cFileName, Qmswindows_tstr);
-      FindClose (dir_handle);
-    }
-
-  if ((len = eilen (result)) < size)
-    {
-      DECLARE_EISTRING (eilastname);
-
-      eicpy_rawz (eilastname, lastname);
-      if (eicmp_ei (eilastname, result) == 0)
-	/* Signal that the name is already OK. */
-	err = EINVAL;
-      else
-	memcpy (buf, eidata (result), len + 1);
-    }
-  else
-    err = ENAMETOOLONG;
-
-  errno = err;
-  return err ? -1 : len;
-}
-#endif /* WIN32_NATIVE || CYGWIN */
-
-#ifdef CYGWIN
-/* Call readlink and try to find out the correct case for the file. */
-static int
-cygwin_readlink_and_correct_case (const Ibyte *name, Ibyte *buf,
-				  int size)
-{
-  int n = qxe_readlink (name, buf, size);
-  if (n < 0 && errno == EINVAL)
-    {
-      /* The file may exist, but isn't a symlink. Try to find the
-         right name. */
-      Ibyte *tmp =
-	(Ibyte *) ALLOCA (cygwin_posix_to_win32_path_list_buf_size
-			    ((char *) name));
-      cygwin_posix_to_win32_path_list ((char *) name, (char *) tmp);
-      n = mswindows_readlink_and_correct_case (tmp, buf, size);
-    }
-  return n;
-}
-#endif /* CYGWIN */
-
-#ifdef WIN32_FILENAMES
 #ifndef ELOOP
 #define ELOOP 10062 /* = WSAELOOP in winsock.h */
 #endif
+#endif
+
 /* Length of start of absolute filename. */
 static int 
-mswindows_abs_start (const Ibyte *name)
+abs_start (const Ibyte *name)
 {
+#ifdef WIN32_ANY
   if (isalpha (*name) && IS_DEVICE_SEP (name[1])
       && IS_DIRECTORY_SEP (name[2]))
     return 3;
@@ -188,8 +55,114 @@
     return IS_DIRECTORY_SEP (name[1]) ? 2 : 1;
   else 
     return 0;
+#else /* not WIN32_ANY */
+  return IS_DIRECTORY_SEP (*name) ? 1 : 0;
+#endif
 }
-#endif /* WIN32_NATIVE */
+
+/* Find real name of a file by resolving symbolic links and (under Windows)
+   looking up the correct case of the file as it appears on the file
+   system.
+
+   Under Windows, UNC servers and shares are lower-cased.  Directories must
+   be given without trailing '/'. One day, this could read Win2K's reparse
+   points. */
+
+static int
+readlink_and_correct_case (const Ibyte *name, Ibyte *buf,
+			   int size)
+{
+#ifndef WIN32_ANY
+  return qxe_readlink (name, buf, size);
+#else
+# ifdef CYGWIN
+  Ibyte *tmp;
+  int n = qxe_readlink (name, buf, size);
+  if (n >= 0 || errno != EINVAL)
+    return n;
+
+  /* The file may exist, but isn't a symlink. Try to find the
+     right name. */
+  tmp = (Ibyte *) ALLOCA (cygwin_posix_to_win32_path_list_buf_size
+			  ((char *) name));
+  cygwin_posix_to_win32_path_list ((char *) name, (char *) tmp);
+  name = tmp;
+# endif
+
+  {
+    int len = 0;
+    int err = 0;
+    const Ibyte *lastname;
+    int count = 0;
+    const Ibyte *tmp;
+    DECLARE_EISTRING (result);
+  
+    assert (*name);
+  
+    /* Sort of check we have a valid filename. */
+    if (qxestrpbrk (name, "*?|<>\""))
+      {
+	errno = ENOENT;
+	return -1;
+      }
+    else if (qxestrlen (name) >= PATH_MAX)
+      {
+	errno = ENAMETOOLONG;
+	return -1;
+      }
+  
+    /* Find start of filename */
+    lastname = name + qxestrlen (name);
+    while (lastname > name && !IS_DIRECTORY_SEP (lastname[-1]))
+      --lastname;
+
+    /* Count slashes in unc path */
+    if (abs_start (name) == 2)
+      for (tmp = name; *tmp; tmp++)
+	if (IS_DIRECTORY_SEP (*tmp))
+	  count++;
+
+    if (count >= 2 && count < 4)
+      {
+	eicpy_rawz (result, lastname);
+	eilwr (result);
+      }
+    else
+      {
+	WIN32_FIND_DATAW find_data;
+	Extbyte *nameext;
+	HANDLE dir_handle;
+
+	C_STRING_TO_TSTR (name, nameext);
+	dir_handle = qxeFindFirstFile (nameext, &find_data);
+	if (dir_handle == INVALID_HANDLE_VALUE)
+	  {
+	    errno = ENOENT;
+	    return -1;
+	  }
+	eicpy_ext (result, (Extbyte *) find_data.cFileName, Qmswindows_tstr);
+	FindClose (dir_handle);
+      }
+
+    if ((len = eilen (result)) < size)
+      {
+	DECLARE_EISTRING (eilastname);
+
+	eicpy_rawz (eilastname, lastname);
+	if (eicmp_ei (eilastname, result) == 0)
+	  /* Signal that the name is already OK. */
+	  err = EINVAL;
+	else
+	  memcpy (buf, eidata (result), len + 1);
+      }
+    else
+      err = ENAMETOOLONG;
+
+    errno = err;
+    return err ? -1 : len;
+  }
+#endif /* WIN32_ANY */
+}
 
 /* Mule Note: This function works with and returns
    internally-formatted strings. */
@@ -200,11 +173,11 @@
   Ibyte copy_path[PATH_MAX];
   Ibyte *new_path = resolved_path;
   Ibyte *max_path;
-#if defined (HAVE_READLINK) || defined (WIN32_NATIVE)
+#if defined (HAVE_READLINK) || defined (WIN32_ANY)
   int readlinks = 0;
   Ibyte link_path[PATH_MAX];
   int n;
-  int abslen = ABS_LENGTH (path);
+  int abslen = abs_start (path);
 #endif
 
   /* Make a copy of the source path since we may need to modify it. */
@@ -214,25 +187,27 @@
 
   if (0)
     ;
-#ifdef WIN32_FILENAMES
+#ifdef WIN32_ANY
   /* Check for c:/... or //server/... */
   else if (abslen == 3 || abslen == 2)
     {
       /* Make sure drive letter is lowercased. */
-      if (abslen == 3) {
-	*new_path = tolower (*path);
-	new_path++;
-	path++;
-	abslen--;
-      }
+      if (abslen == 3)
+	{
+	  *new_path = tolower (*path);
+	  new_path++;
+	  path++;
+	  abslen--;
+	}
       /* Coerce directory chars. */
-      while (abslen-- > 0) {
-	if (IS_DIRECTORY_SEP (*path))
-	  *new_path++ = DIRECTORY_SEP;
-	else
-	  *new_path++ = *path;
-	path++;
-      }
+      while (abslen-- > 0)
+	{
+	  if (IS_DIRECTORY_SEP (*path))
+	    *new_path++ = DIRECTORY_SEP;
+	  else
+	    *new_path++ = *path;
+	  path++;
+	}
     }
 #endif
 #ifdef WIN32_NATIVE
@@ -244,7 +219,7 @@
       path++;
     }
   /* Just a path name, prepend the current directory */
-  else if (1)
+  else
     {
       get_initial_directory (new_path, PATH_MAX - 1);
       new_path += qxestrlen (new_path);
@@ -294,7 +269,7 @@
 	      path += 2;
 
 	      /* Ignore ".." at root. */
-	      if (new_path == ABS_START (resolved_path))
+	      if (new_path == resolved_path + abs_start (resolved_path))
 		continue;
 
 	      /* Handle ".." by backing up. */
@@ -316,7 +291,7 @@
 	  *new_path++ = *path++;
 	}
 
-#if defined (HAVE_READLINK) || defined (WIN32_NATIVE)
+#if defined (HAVE_READLINK) || defined (WIN32_ANY)
       /* See if latest pathname component is a symlink or needs case
 	 correction. */
       *new_path = '\0';
@@ -326,7 +301,7 @@
 	{
 	  /* EINVAL means the file exists but isn't a symlink or doesn't
 	     need case correction. */
-#ifdef CYGWIN
+#ifdef WIN32_ANY
 	  if (errno != EINVAL && errno != ENOENT)
 #else
 	  if (errno != EINVAL) 
@@ -345,9 +320,9 @@
 	  /* Note: readlink doesn't add the null byte. */
 	  link_path[n] = '\0';
 	  
-	  if (ABS_LENGTH (link_path) > 0)
+	  if (abs_start (link_path) > 0)
 	    /* Start over for an absolute symlink. */
-	    new_path = resolved_path + ABS_LENGTH (link_path) - 1;
+	    new_path = resolved_path + abs_start (link_path) - 1;
 	  else
 	    /* Otherwise back up over this component. */
 	    for (--new_path; !IS_DIRECTORY_SEP (*new_path); --new_path)
@@ -365,12 +340,12 @@
 	  qxestrcpy (copy_path, link_path);
 	  path = copy_path;
 	}
-#endif /* HAVE_READLINK || WIN32_NATIVE */
+#endif /* HAVE_READLINK || WIN32_ANY */
       *new_path++ = DIRECTORY_SEP;
     }
 
   /* Delete trailing slash but don't whomp a lone slash. */
-  if (new_path != ABS_START (resolved_path) &&
+  if (new_path != resolved_path + abs_start (resolved_path) &&
       IS_DIRECTORY_SEP (new_path[-1]))
     new_path--;