Mercurial > hg > xemacs-beta
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); +}