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