diff src/realpath.c @ 2526:902d5bd9b75c

[xemacs-hg @ 2005-01-28 02:36:11 by ben] Support symlinks under Windows nt.c, fileio.c: Fix sync comments. config.h.in, dired-msw.c, emacs.c, event-msw.c, fileio.c, glyphs.c, lisp.h, nt.c, process-nt.c, realpath.c, sound.c, symsinit.h, sysdep.c, sysfile.h, syswindows.h, win32.c: Add support for treating shortcuts under Windows as symbolic links. Enabled with mswindows-shortcuts-are-links (t by default). Rewrite lots of places to use PATHNAME_CONVERT_OUT, which is moved to sysfile.h. Add PATHNAME_RESOLVE_LINKS, which only does things under Windows. Add profiling section for expand_file_name calls. nt.c, sysdep.c: Unicode-ize. realpath.c: Renamed from readlink_and_correct_case. Fix some problems with Windows implementation due to incorrect understanding of workings of the function. sound.c, ntplay.c, sound.h: Rename play_sound_file to nt_play_sound_file and pass internally-formatted data to it to avoid converting out and back again. text.h: is_c -> is_ascii.
author ben
date Fri, 28 Jan 2005 02:36:28 +0000
parents ab71ad6ff3dd
children 967fea9dfad5
line wrap: on
line diff
--- a/src/realpath.c	Fri Jan 28 02:05:05 2005 +0000
+++ b/src/realpath.c	Fri Jan 28 02:36:28 2005 +0000
@@ -1,7 +1,7 @@
 /*
  * realpath.c -- canonicalize pathname by removing symlinks
  * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
- * Copyright (C) 2001, 2002 Ben Wing.
+ * Copyright (C) 2001, 2002, 2004 Ben Wing.
  *
 
 This file is part of XEmacs.
@@ -31,6 +31,8 @@
 #include <config.h>
 #include "lisp.h"
 
+#include "profile.h"
+
 #include "sysfile.h"
 #include "sysdir.h"
 
@@ -43,6 +45,8 @@
 #endif
 #endif
 
+Lisp_Object QSin_qxe_realpath;
+
 /* Length of start of absolute filename. */
 static int 
 abs_start (const Ibyte *name)
@@ -60,24 +64,30 @@
 #endif
 }
 
-/* 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.
+/* Find real name of a file by resolving symbolic links and/or shortcuts
+   under Windows (.LNK links), if such support is enabled.
+
+   If no link found, and LINKS_ONLY is false, look up the correct case in
+   the file system of the last component.
 
    Under Windows, UNC servers and shares are lower-cased.  Directories must
    be given without trailing '/'. One day, this could read Win2K's reparse
-   points. */
+   points.
+
+   Returns length of characters copied info BUF.
+   DOES NOT ZERO TERMINATE!!!!!
+*/
 
 static int
-readlink_and_correct_case (const Ibyte *name, Ibyte *buf,
-			   int size)
+readlink_or_correct_case (const Ibyte *name, Ibyte *buf, Bytecount size,
+			  Boolint links_only)
 {
 #ifndef WIN32_ANY
-  return qxe_readlink (name, buf, size);
+  return qxe_readlink (name, buf, (size_t) size);
 #else
 # ifdef CYGWIN
   Ibyte *tmp;
-  int n = qxe_readlink (name, buf, size);
+  int n = qxe_readlink (name, buf, (size_t) size);
   if (n >= 0 || errno != EINVAL)
     return n;
 
@@ -87,8 +97,33 @@
     alloca_ibytes (cygwin_posix_to_win32_path_list_buf_size ((char *) name));
   cygwin_posix_to_win32_path_list ((char *) name, (char *) tmp);
   name = tmp;
+# else
+  if (mswindows_shortcuts_are_symlinks)
+    {
+      Ibyte *tmp = mswindows_read_link (name);
+
+      if (tmp != NULL)
+	{
+	  /* Fucking fixed buffers. */
+	  Bytecount len = qxestrlen (tmp);
+	  if (len > size)
+	    {
+	      errno = ENAMETOOLONG;
+	      return -1;
+	    }
+	  memcpy (buf, tmp, len);
+	  xfree (tmp, Ibyte *);
+	  return len;
+	}
+    }
 # endif
 
+  if (links_only)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
   {
     int len = 0;
     int err = 0;
@@ -144,16 +179,16 @@
 	FindClose (dir_handle);
       }
 
-    if ((len = eilen (result)) < size)
+    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;
+          /* Signal that the name is already OK. */
+          err = EINVAL;
 	else
-	  memcpy (buf, eidata (result), len + 1);
+	  memcpy (buf, eidata (result), len);
       }
     else
       err = ENAMETOOLONG;
@@ -165,14 +200,18 @@
 }
 
 /* Mule Note: This function works with and returns
-   internally-formatted strings. */
+   internally-formatted strings.
+
+   if LINKS_ONLY is true, don't do case canonicalization under
+   Windows. */
 
 Ibyte *
-qxe_realpath (const Ibyte *path, Ibyte *resolved_path)
+qxe_realpath (const Ibyte *path, Ibyte *resolved_path, Boolint links_only)
 {
   Ibyte copy_path[PATH_MAX_INTERNAL];
   Ibyte *new_path = resolved_path;
   Ibyte *max_path;
+  Ibyte *retval = NULL;
 #if defined (HAVE_READLINK) || defined (WIN32_ANY)
   int readlinks = 0;
   Ibyte link_path[PATH_MAX_INTERNAL];
@@ -180,6 +219,10 @@
   int abslen = abs_start (path);
 #endif
 
+  PROFILE_DECLARE ();
+
+  PROFILE_RECORD_ENTERING_SECTION (QSin_qxe_realpath);
+
  restart:
 
   /* Make a copy of the source path since we may need to modify it. */
@@ -288,7 +331,7 @@
 	  if (path > max_path)
 	    {
 	      errno = ENAMETOOLONG;
-	      return NULL;
+	      goto done;
 	    }
 	  *new_path++ = *path++;
 	}
@@ -297,7 +340,8 @@
       /* See if latest pathname component is a symlink or needs case
 	 correction. */
       *new_path = '\0';
-      n = readlink_and_correct_case (resolved_path, link_path, PATH_MAX_INTERNAL - 1);
+      n = readlink_or_correct_case (resolved_path, link_path,
+				    PATH_MAX_INTERNAL - 1, links_only);
 
       if (n < 0)
 	{
@@ -308,7 +352,7 @@
 #else
 	  if (errno != EINVAL) 
 #endif
-	    return NULL;
+	    goto done;
 	}
       else
 	{
@@ -316,7 +360,7 @@
 	  if (readlinks++ > MAX_READLINKS)
 	    {
 	      errno = ELOOP;
-	      return NULL;
+	      goto done;
 	    }
 
 	  /* Note: readlink doesn't add the null byte. */
@@ -340,7 +384,7 @@
 	  if (qxestrlen (path) + n >= PATH_MAX_INTERNAL)
 	    {
 	      errno = ENAMETOOLONG;
-	      return NULL;
+	      goto done;
 	    }
 
 	  /* Insert symlink contents into path. */
@@ -360,5 +404,16 @@
   /* Make sure it's null terminated. */
   *new_path = '\0';
 
-  return resolved_path;
+  retval = resolved_path;
+done:
+  PROFILE_RECORD_EXITING_SECTION (QSin_qxe_realpath);
+  return retval;
 }
+
+void
+vars_of_realpath (void)
+{
+  QSin_qxe_realpath =
+    build_msg_string ("(in qxe_realpath)");
+  staticpro (&QSin_qxe_realpath);
+}