From b6c6ea43f30ee958ca1f0af950af01f683f7b5c9 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 13 May 2009 15:00:06 +0000 Subject: [PATCH] * cygheap.h (cwdstuff): Convert to class. Make posix and dir private. (cwdstuff::get_posix): New method. (cwdstuff::reset_posix): New method. * dcrt0.cc (dll_crt0_1): Call setlocale rather than _setlocale_r. * environ.cc (environ_init): Ditto. Prefer "C" locale over current codepage default locale. * path.cc (chdir): Use cwdstuff::get_posix method instead of accessing cwdstuff::posix directly. (cwdstuff::set): Defer creating posix path to first usage. (cwdstuff::get_posix): Create posix path if it's empty, and return it. (cwdstuff::get): Create posix path if it's empty. * strfuncs.cc (sys_cp_wcstombs): Use UTF-8 conversion in the "C" locale. (sys_cp_mbstowcs): Ditto. * syscalls.cc (gen_full_path_at): Fetch CWD posix path locked. (setlocale): Implement here. Reset CWD posix path. --- winsup/cygwin/ChangeLog | 19 +++++++++++++++++++ winsup/cygwin/cygheap.h | 8 ++++++-- winsup/cygwin/dcrt0.cc | 2 +- winsup/cygwin/environ.cc | 5 +---- winsup/cygwin/path.cc | 28 +++++++++++++++++++++++++--- winsup/cygwin/strfuncs.cc | 4 ++++ winsup/cygwin/syscalls.cc | 20 +++++++++++++++++++- 7 files changed, 75 insertions(+), 11 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 0390de431..869196956 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,22 @@ +2009-05-13 Corinna Vinschen + + * cygheap.h (cwdstuff): Convert to class. Make posix and dir private. + (cwdstuff::get_posix): New method. + (cwdstuff::reset_posix): New method. + * dcrt0.cc (dll_crt0_1): Call setlocale rather than _setlocale_r. + * environ.cc (environ_init): Ditto. Prefer "C" locale over current + codepage default locale. + * path.cc (chdir): Use cwdstuff::get_posix method instead of accessing + cwdstuff::posix directly. + (cwdstuff::set): Defer creating posix path to first usage. + (cwdstuff::get_posix): Create posix path if it's empty, and return it. + (cwdstuff::get): Create posix path if it's empty. + * strfuncs.cc (sys_cp_wcstombs): Use UTF-8 conversion in the "C" + locale. + (sys_cp_mbstowcs): Ditto. + * syscalls.cc (gen_full_path_at): Fetch CWD posix path locked. + (setlocale): Implement here. Reset CWD posix path. + 2009-05-09 Christopher Faylor * cygwin/version.h (CYGWIN_VERSION_CYGWIN_CONV): New define. diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index fe2333c74..0932f865d 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -225,13 +225,17 @@ public: class muto; -struct cwdstuff +class cwdstuff { +private: char *posix; - UNICODE_STRING win32; HANDLE dir; +public: + UNICODE_STRING win32; DWORD drive_length; static muto cwd_lock; + char *get_posix (); + void reset_posix () { if (posix) posix[0] = '\0'; } 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/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 90960afd0..12365b7b7 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -931,7 +931,7 @@ dll_crt0_1 (void *) LoadLibrary serialization. */ ld_preload (); /* Reset current locale to "C" per POSIX */ - _setlocale_r (_GLOBAL_REENT, LC_CTYPE, "C"); + setlocale (LC_CTYPE, "C"); if (user_data->main) cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr)); __asm__ (" \n\ diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index 8124e68b2..161b9d98f 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -790,16 +790,13 @@ environ_init (char **envp, int envc) { char *buf = (char *) alloca (i); GetEnvironmentVariableA (lc_arr[lc], buf, i); - if (_setlocale_r (_GLOBAL_REENT, LC_CTYPE, buf)) + if (setlocale (LC_CTYPE, buf)) { got_lc = true; break; } } } - /* No matching POSIX environment variable, use current codepage. */ - if (!got_lc) - _setlocale_r (_GLOBAL_REENT, LC_CTYPE, "en_US"); /* We also need the CYGWIN variable early to know the value of the CYGWIN=upcaseenv setting for the below loop. */ if ((i = GetEnvironmentVariableA ("CYGWIN", NULL, 0))) diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index ec5c40b5c..ca2df5872 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2599,7 +2599,7 @@ chdir (const char *in_dir) /* Note that we're accessing cwd.posix without a lock here. I didn't think it was worth locking just for strace. */ syscall_printf ("%d = chdir() cygheap->cwd.posix '%s' native '%S'", res, - cygheap->cwd.posix, path.get_nt_native_path ()); + cygheap->cwd.get_posix (), path.get_nt_native_path ()); MALLOC_CHECK; return res; } @@ -3230,8 +3230,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); } - posix = (char *) crealloc_abort (posix, strlen (posix_cwd) + 1); - stpcpy (posix, posix_cwd); + if (posix) + posix[0] = '\0'; } out: @@ -3240,6 +3240,21 @@ out: } /* Copy the value for either the posix or the win32 cwd into a buffer. */ +char * +cwdstuff::get_posix () +{ + 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; +} + char * cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen) { @@ -3265,6 +3280,13 @@ 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/strfuncs.cc b/winsup/cygwin/strfuncs.cc index e0395745d..150f51ff4 100644 --- a/winsup/cygwin/strfuncs.cc +++ b/winsup/cygwin/strfuncs.cc @@ -418,6 +418,8 @@ sys_cp_wcstombs (wctomb_p f_wctomb, char *charset, char *dst, size_t len, mbstate_t ps; save_errno save; + if (f_wctomb == __ascii_wctomb) + f_wctomb = __utf8_wctomb; memset (&ps, 0, sizeof ps); if (dst == NULL) len = (size_t) -1; @@ -525,6 +527,8 @@ sys_cp_mbstowcs (mbtowc_p f_mbtowc, char *charset, wchar_t *dst, size_t dlen, mbstate_t ps; save_errno save; + if (f_mbtowc == __ascii_mbtowc) + f_mbtowc = __utf8_mbtowc; memset (&ps, 0, sizeof ps); if (dst == NULL) len = (size_t)-1; diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 64c25348e..ab319225c 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -35,6 +35,7 @@ details. */ #include #include #include +#include #include #include #include @@ -3726,7 +3727,11 @@ gen_full_path_at (char *path_ret, int dirfd, const char *pathname, char *p; if (dirfd == AT_FDCWD) - p = stpcpy (path_ret, cygheap->cwd.posix); + { + cwdstuff::cwd_lock.acquire (); + p = stpcpy (path_ret, cygheap->cwd.get_posix ()); + cwdstuff::cwd_lock.release (); + } else { cygheap_fdget cfd (dirfd); @@ -4000,3 +4005,16 @@ unlinkat (int dirfd, const char *pathname, int flags) return -1; return (flags & AT_REMOVEDIR) ? rmdir (path) : unlink (path); } + +extern "C" char * +setlocale (int category, const char *locale) +{ + /* Each setlocale potentially changes the multibyte representation + of the CWD. Therefore we have to rest the CWD's posix path and + reevaluate the next time it's used. */ + /* FIXME: Other buffered paths might be affected as well. */ + char *ret = _setlocale_r (_REENT, category, locale); + if (ret) + cygheap->cwd.reset_posix (); + return ret; +}