diff options
author | Christopher Faylor <me@cgf.cx> | 2004-05-15 15:55:43 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2004-05-15 15:55:43 +0000 |
commit | 982c8ecdb4c8bd31c7a145117c74199e56a2dfdc (patch) | |
tree | 94df6782c957525742d0e1cdf7c64c6bf83503f3 /winsup/cygwin | |
parent | 99189153b3e43225ed351dd83c9bd08ae9171b0e (diff) | |
download | newlib-982c8ecdb4c8bd31c7a145117c74199e56a2dfdc.zip newlib-982c8ecdb4c8bd31c7a145117c74199e56a2dfdc.tar.gz newlib-982c8ecdb4c8bd31c7a145117c74199e56a2dfdc.tar.bz2 |
* cygheap.h (cwdstuff::set): Modify return value and arguments.
* path.cc (chdir): Specify PC_POSIX. Do not call SetCurrentDirectory. Set
posix_cwd in a way that does not break find.exe. Change call to cwd.set.
(cwdstuff::get_initial): Do not call GetCurrentDirectory here.
(cwdstuff::set): Call SetCurrentDirectory and GetCurrentDirectory as needed.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r-- | winsup/cygwin/ChangeLog | 12 | ||||
-rw-r--r-- | winsup/cygwin/path.cc | 92 |
2 files changed, 68 insertions, 36 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 5b43c39..c7392b5 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,13 @@ +2004-05-15 Pierre Humblet <pierre.humblet@ieee.org> + + * cygheap.h (cwdstuff::set): Modify return value and arguments. + * path.cc (chdir): Specify PC_POSIX. Do not call SetCurrentDirectory. + Set posix_cwd in a way that does not break find.exe. Change call to + cwd.set. + (cwdstuff::get_initial): Do not call GetCurrentDirectory here. + (cwdstuff::set): Call SetCurrentDirectory and GetCurrentDirectory as + needed. + 2004-05-12 Corinna Vinschen <corinna@vinschen.de> * path.cc (path_conv::check): Don't bail out with error if path is "//". @@ -8,7 +18,7 @@ * fhandler_tape.cc (mt_h): Drop in favor of cygheap based handle. (mtinfo_init): Use cygheap->mt_h handle. Protect it. -2004-05-12 Pierre Humblet <pierre.humblet@ieee.org> +2004-05-12 Pierre Humblet <pierre.humblet@ieee.org> * tty.h: Remove the %d or %x from all cygtty strings. (tty::open_output_mutex): Only declare. diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 4e0b3d8..6ab938b 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -3297,7 +3297,7 @@ chdir (const char *in_dir) /* Convert path. First argument ensures that we don't check for NULL/empty/invalid again. */ - path_conv path (PC_NONULLEMPTY, in_dir, PC_FULL | PC_SYM_FOLLOW); + path_conv path (PC_NONULLEMPTY, in_dir, PC_FULL | PC_SYM_FOLLOW | PC_POSIX); if (path.error) { set_errno (path.error); @@ -3306,7 +3306,8 @@ chdir (const char *in_dir) } int res = -1; - const char *native_dir = path; + bool doit = false; + const char *native_dir = path, *posix_cwd = NULL; int devn = path.get_devn (); if (!isvirtual_dev (devn)) { @@ -3319,20 +3320,28 @@ chdir (const char *in_dir) path.get_win32 ()[2] = '\\'; path.get_win32 ()[3] = '\0'; } - if (SetCurrentDirectory (native_dir)) - res = 0; - else - __seterrno (); + /* The sequence chdir("xx"); chdir(".."); must be a noop if xx + is not a symlink. This is exploited by find.exe. + The posix_cwd is just path.normalized_path. + In other cases we let cwd.set obtain the Posix path through + the mount table. */ + if (!path.has_symlinks () && !isabspath (in_dir)) + posix_cwd = path.normalized_path; + res = 0; + doit = true; } else if (!path.exists ()) set_errno (ENOENT); else if (!path.isdir ()) set_errno (ENOTDIR); else - res = 0; + { + posix_cwd = path.normalized_path; + res = 0; + } - if (res == 0) - cygheap->cwd.set (native_dir); + if (!res) + res = cygheap->cwd.set (native_dir, posix_cwd, doit); /* Note that we're accessing cwd.posix without a lock here. I didn't think it was worth locking just for strace. */ @@ -3648,38 +3657,50 @@ cwdstuff::get_initial () if (win32) return 1; - int i; - DWORD len, dlen; - for (i = 0, dlen = CYG_MAX_PATH, len = 0; i < 3; dlen *= 2, i++) - { - win32 = (char *) crealloc (win32, dlen + 2); - if ((len = GetCurrentDirectoryA (dlen, win32)) < dlen) - break; - } - - if (len == 0) - { - __seterrno (); - cwd_lock->release (); - debug_printf ("get_initial_cwd failed, %E"); - cwd_lock->release (); - return 0; - } - set (NULL); - return 1; /* Leaves cwd lock unreleased */ + /* Leaves cwd lock unreleased, if success */ + return !set (NULL, NULL, false); } -/* Fill out the elements of a cwdstuff struct. +/* Chdir and fill out the elements of a cwdstuff struct. It is assumed that the lock for the cwd is acquired if win32_cwd == NULL. */ -void -cwdstuff::set (const char *win32_cwd, const char *posix_cwd) +int +cwdstuff::set (const char *win32_cwd, const char *posix_cwd, bool doit) { - char pathbuf[CYG_MAX_PATH]; + char pathbuf[2 * CYG_MAX_PATH]; + int res = -1; if (win32_cwd) { - cwd_lock->acquire (); + cwd_lock->acquire (); + if (doit && !SetCurrentDirectory (win32_cwd)) + { + __seterrno (); + goto out; + } + } + /* If there is no win32 path or it has the form c:xxx, get the value */ + if (!win32_cwd || (isdrive (win32_cwd) && win32_cwd[2] != '\\')) + { + int i; + DWORD len, dlen; + for (i = 0, dlen = CYG_MAX_PATH/3; i < 2; i++, dlen = len) + { + win32 = (char *) crealloc (win32, dlen); + if ((len = GetCurrentDirectoryA (dlen, win32)) < dlen) + break; + } + if (len == 0) + { + __seterrno (); + debug_printf ("GetCurrentDirectory, %E"); + win32_cwd = pathbuf; /* Force lock release */ + goto out; + } + posix_cwd = NULL; + } + else + { win32 = (char *) crealloc (win32, strlen (win32_cwd) + 1); strcpy (win32, win32_cwd); } @@ -3694,10 +3715,11 @@ cwdstuff::set (const char *win32_cwd, const char *posix_cwd) hash = hash_path_name (0, win32); + res = 0; +out: if (win32_cwd) cwd_lock->release (); - - return; + return res; } /* Copy the value for either the posix or the win32 cwd into a buffer. */ |