diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index bcd823f60..082c420e4 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,18 @@ +2009-09-21 Corinna Vinschen + + * cygheap.h (cwdstuff::get_posix): Convert to const inline method just + returning pointer to posix path. + (cwdstuff::reset_posix): Convert to non-inline method taking a wchar_t + pointer. + * path.cc (cwdstuff::set): Revert change from 2009-05-13. Set posix + to valid incoming path again. + (cwdstuff::reset_posix): New implementation setting posix path from + incoming wchar_t path. Explain usage. + (cwdstuff::get_posix): Drop implementation. + (cwdstuff::get): Drop special case to handle empty posix path. + * syscalls.cc (internal_setlocale): Store old posix cwd as wide char + path. Restore posix cwd using new charset. Explain why. + 2009-09-21 Corinna Vinschen * fhandler_disk_file.cc (fhandler_disk_file::link): Drop faking hardlink diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index 9bba99a65..7a39de627 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -211,8 +211,8 @@ public: UNICODE_STRING win32; DWORD drive_length; static muto cwd_lock; - char *get_posix (); - void reset_posix () { if (posix) posix[0] = '\0'; } + const char *get_posix () const { return posix; }; + void reset_posix (wchar_t *); char *get (char *, int = 1, int = 0, unsigned = NT_MAX_PATH); HANDLE get_handle () { return dir; } DWORD get_drive (char * dst) diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index db514d325..223cc2331 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -3306,8 +3306,8 @@ cwdstuff::set (PUNICODE_STRING nat_cwd, const char *posix_cwd, bool doit) posix_cwd = (const char *) tp.c_get (); mount_table->conv_to_posix_path (win32.Buffer, (char *) posix_cwd, 0); } - if (posix) - posix[0] = '\0'; + posix = (char *) crealloc_abort (posix, strlen (posix_cwd) + 1); + stpcpy (posix, posix_cwd); } out: @@ -3315,20 +3315,14 @@ out: return res; } -/* Copy the value for either the posix or the win32 cwd into a buffer. */ -char * -cwdstuff::get_posix () +/* Store incoming wchar_t path as current posix cwd. This is called from + setlocale so that the cwd is always stored in the right charset. */ +void +cwdstuff::reset_posix (wchar_t *w_cwd) { - if (!posix || !*posix) - { - tmp_pathbuf tp; - - char *tocopy = tp.c_get (); - mount_table->conv_to_posix_path (win32.Buffer, tocopy, 0); - posix = (char *) crealloc_abort (posix, strlen (tocopy) + 1); - stpcpy (posix, tocopy); - } - return posix; + size_t len = sys_wcstombs (NULL, (size_t) -1, w_cwd); + posix = (char *) crealloc_abort (posix, len + 1); + sys_wcstombs (posix, len + 1, w_cwd); } char * @@ -3356,13 +3350,6 @@ cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen) sys_wcstombs (tocopy, NT_MAX_PATH, win32.Buffer, win32.Length / sizeof (WCHAR)); } - else if (!posix || !*posix) - { - tocopy = tp.c_get (); - mount_table->conv_to_posix_path (win32.Buffer, tocopy, 0); - posix = (char *) crealloc_abort (posix, strlen (tocopy) + 1); - stpcpy (posix, tocopy); - } else tocopy = posix; diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index e86163886..a436afd52 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -4063,6 +4063,16 @@ unlinkat (int dirfd, const char *pathname, int flags) static char * internal_setlocale (char *ret) { + tmp_pathbuf tp; + + /* Each setlocale potentially changes the multibyte representation + of the CWD. Therefore we have to reevaluate the CWD's posix path and + store in the new charset. */ + /* FIXME: Other buffered paths might be affected as well. */ + wchar_t *w_cwd = tp.w_get (); + cwdstuff::cwd_lock.acquire (); + sys_mbstowcs (w_cwd, 32768, cygheap->cwd.get_posix ()); + if (*__locale_charset () == 'A') { cygheap->locale.mbtowc = __utf8_mbtowc; @@ -4097,11 +4107,10 @@ internal_setlocale (char *ret) cygheap->locale.wctomb = __wctomb; } strcpy (cygheap->locale.charset, __locale_charset ()); - /* Each setlocale potentially changes the multibyte representation - of the CWD. Therefore we have to reset the CWD's posix path and - reevaluate the next time it's used. */ - /* FIXME: Other buffered paths might be affected as well. */ - cygheap->cwd.reset_posix (); + + /* See above. */ + cygheap->cwd.reset_posix (w_cwd); + cwdstuff::cwd_lock.release (); return ret; }