diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index cc988a008..a540211e3 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,12 @@ +2005-08-25 Corinna Vinschen + + * path.cc (normalize_posix_path): Keep two leading slashes + intact throughout. + (normalize_win32_path): Revert to only checking for slash. + (realpath): Convert drive letters to cygdrive paths before + doing anything else. + * shared_info.h (mount_info::cygdrive_posix_path): Make public. + 2005-08-25 Corinna Vinschen * path.cc (realpath): Drop call to mount_info::conv_to_posix_path diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index d4640898d..364053997 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -215,6 +215,7 @@ static int normalize_posix_path (const char *src, char *dst, char *&tail) { const char *in_src = src; + char *dst_start = dst; syscall_printf ("src %s", src); if (isdrive (src) || *src == '\\') @@ -226,9 +227,11 @@ normalize_posix_path (const char *src, char *dst, char *&tail) if (!cygheap->cwd.get (dst)) return get_errno (); tail = strchr (tail, '\0'); + if (isslash (dst[0]) && isslash (dst[1])) + ++dst_start; if (*src == '.') { - if (tail == dst + 1 && *dst == '/') + if (tail == dst_start + 1 && *dst_start == '/') tail--; goto sawdot; } @@ -237,7 +240,10 @@ normalize_posix_path (const char *src, char *dst, char *&tail) } /* Two leading /'s? If so, preserve them. */ else if (isslash (src[1]) && !isslash (src[2])) - *tail++ = *src++; + { + *tail++ = *src++; + ++dst_start; + } while (*src) { @@ -271,7 +277,7 @@ normalize_posix_path (const char *src, char *dst, char *&tail) break; else { - while (tail > dst && !isslash (*--tail)) + while (tail > dst_start && !isslash (*--tail)) continue; src++; } @@ -1111,7 +1117,7 @@ normalize_win32_path (const char *src, char *dst, char *&tail) } } } - if (tail == dst && !isdrive(src) && isdirsep (*src)) + if (tail == dst && !isdrive (src) && *src != '/') { if (beg_src_slash) tail += cygheap->cwd.get_drive (dst); @@ -3661,13 +3667,26 @@ realpath (const char *path, char *resolved) return NULL; } - path_conv real_path (path, PC_SYM_FOLLOW | PC_POSIX, stat_suffixes); - - /* Guard writing to a potentially invalid resolved. */ + /* Guard reading from a potentially invalid path and writing to a + potentially invalid resolved. */ myfault efault; if (efault.faulted (EFAULT)) return NULL; + char *tpath; + if (isdrive (path)) + { + tpath = (char *) alloca (strlen (path) + + strlen (mount_table->cygdrive) + + 1); + mount_table->cygdrive_posix_path (path, tpath, 0); + } + else + tpath = (char *) path; + + path_conv real_path (tpath, PC_SYM_FOLLOW | PC_POSIX, stat_suffixes); + + /* Linux has this funny non-standard extension. If "resolved" is NULL, realpath mallocs the space by itself and returns it to the application. The application is responsible for calling free() then. This extension diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h index cfe222a72..d654ef1f9 100644 --- a/winsup/cygwin/shared_info.h +++ b/winsup/cygwin/shared_info.h @@ -90,6 +90,7 @@ class mount_info int remove_cygdrive_info_from_registry (const char *cygdrive_prefix, unsigned flags); int get_cygdrive_info (char *user, char *system, char* user_flags, char* system_flags); + void cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p); private: @@ -99,7 +100,6 @@ class mount_info void to_registry (); int cygdrive_win32_path (const char *src, char *dst, int& unit); - void cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p); void read_cygdrive_info_from_registry (); };