* 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.
This commit is contained in:
		| @@ -1,3 +1,22 @@ | |||||||
|  | 2009-05-13  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
|  | 	* 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  <me+cygwin@cgf.cx> | 2009-05-09  Christopher Faylor  <me+cygwin@cgf.cx> | ||||||
|  |  | ||||||
| 	* cygwin/version.h (CYGWIN_VERSION_CYGWIN_CONV): New define. | 	* cygwin/version.h (CYGWIN_VERSION_CYGWIN_CONV): New define. | ||||||
|   | |||||||
| @@ -225,13 +225,17 @@ public: | |||||||
|  |  | ||||||
| class muto; | class muto; | ||||||
|  |  | ||||||
| struct cwdstuff | class cwdstuff | ||||||
| { | { | ||||||
|  | private: | ||||||
|   char *posix; |   char *posix; | ||||||
|   UNICODE_STRING win32; |  | ||||||
|   HANDLE dir; |   HANDLE dir; | ||||||
|  | public: | ||||||
|  |   UNICODE_STRING win32; | ||||||
|   DWORD drive_length; |   DWORD drive_length; | ||||||
|   static muto cwd_lock; |   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); |   char *get (char *, int = 1, int = 0, unsigned = NT_MAX_PATH); | ||||||
|   HANDLE get_handle () { return dir; } |   HANDLE get_handle () { return dir; } | ||||||
|   DWORD get_drive (char * dst) |   DWORD get_drive (char * dst) | ||||||
|   | |||||||
| @@ -931,7 +931,7 @@ dll_crt0_1 (void *) | |||||||
|      LoadLibrary serialization. */ |      LoadLibrary serialization. */ | ||||||
|   ld_preload (); |   ld_preload (); | ||||||
|   /* Reset current locale to "C" per POSIX */ |   /* Reset current locale to "C" per POSIX */ | ||||||
|   _setlocale_r (_GLOBAL_REENT, LC_CTYPE, "C"); |   setlocale (LC_CTYPE, "C"); | ||||||
|   if (user_data->main) |   if (user_data->main) | ||||||
|     cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr)); |     cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr)); | ||||||
|   __asm__ ("				\n\ |   __asm__ ("				\n\ | ||||||
|   | |||||||
| @@ -790,16 +790,13 @@ environ_init (char **envp, int envc) | |||||||
|       	{ |       	{ | ||||||
| 	  char *buf = (char *) alloca (i); | 	  char *buf = (char *) alloca (i); | ||||||
| 	  GetEnvironmentVariableA (lc_arr[lc], buf, i); | 	  GetEnvironmentVariableA (lc_arr[lc], buf, i); | ||||||
| 	  if (_setlocale_r (_GLOBAL_REENT, LC_CTYPE, buf)) | 	  if (setlocale (LC_CTYPE, buf)) | ||||||
| 	    { | 	    { | ||||||
| 	      got_lc = true; | 	      got_lc = true; | ||||||
| 	      break; | 	      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 |   /* We also need the CYGWIN variable early to know the value of the | ||||||
|      CYGWIN=upcaseenv setting for the below loop. */ |      CYGWIN=upcaseenv setting for the below loop. */ | ||||||
|   if ((i = GetEnvironmentVariableA ("CYGWIN", NULL, 0))) |   if ((i = GetEnvironmentVariableA ("CYGWIN", NULL, 0))) | ||||||
|   | |||||||
| @@ -2599,7 +2599,7 @@ chdir (const char *in_dir) | |||||||
|   /* Note that we're accessing cwd.posix without a lock here.  I didn't think |   /* Note that we're accessing cwd.posix without a lock here.  I didn't think | ||||||
|      it was worth locking just for strace. */ |      it was worth locking just for strace. */ | ||||||
|   syscall_printf ("%d = chdir() cygheap->cwd.posix '%s' native '%S'", res, |   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; |   MALLOC_CHECK; | ||||||
|   return res; |   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 (); | 	  posix_cwd = (const char *) tp.c_get (); | ||||||
| 	  mount_table->conv_to_posix_path (win32.Buffer, (char *) posix_cwd, 0); | 	  mount_table->conv_to_posix_path (win32.Buffer, (char *) posix_cwd, 0); | ||||||
| 	} | 	} | ||||||
|       posix = (char *) crealloc_abort (posix, strlen (posix_cwd) + 1); |       if (posix) | ||||||
|       stpcpy (posix, posix_cwd); |       	posix[0] = '\0'; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| out: | out: | ||||||
| @@ -3240,6 +3240,21 @@ out: | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Copy the value for either the posix or the win32 cwd into a buffer. */ | /* 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 * | char * | ||||||
| cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen) | 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, |       sys_wcstombs (tocopy, NT_MAX_PATH, win32.Buffer, | ||||||
| 		    win32.Length / sizeof (WCHAR)); | 		    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 |   else | ||||||
|     tocopy = posix; |     tocopy = posix; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -418,6 +418,8 @@ sys_cp_wcstombs (wctomb_p f_wctomb, char *charset, char *dst, size_t len, | |||||||
|   mbstate_t ps; |   mbstate_t ps; | ||||||
|   save_errno save; |   save_errno save; | ||||||
|  |  | ||||||
|  |   if (f_wctomb == __ascii_wctomb) | ||||||
|  |     f_wctomb = __utf8_wctomb; | ||||||
|   memset (&ps, 0, sizeof ps); |   memset (&ps, 0, sizeof ps); | ||||||
|   if (dst == NULL) |   if (dst == NULL) | ||||||
|     len = (size_t) -1; |     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; |   mbstate_t ps; | ||||||
|   save_errno save; |   save_errno save; | ||||||
|  |  | ||||||
|  |   if (f_mbtowc == __ascii_mbtowc) | ||||||
|  |     f_mbtowc = __utf8_mbtowc; | ||||||
|   memset (&ps, 0, sizeof ps); |   memset (&ps, 0, sizeof ps); | ||||||
|   if (dst == NULL) |   if (dst == NULL) | ||||||
|     len = (size_t)-1; |     len = (size_t)-1; | ||||||
|   | |||||||
| @@ -35,6 +35,7 @@ details. */ | |||||||
| #include <utmpx.h> | #include <utmpx.h> | ||||||
| #include <sys/uio.h> | #include <sys/uio.h> | ||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
|  | #include <locale.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| #include <sys/wait.h> | #include <sys/wait.h> | ||||||
| #include <rpc.h> | #include <rpc.h> | ||||||
| @@ -3726,7 +3727,11 @@ gen_full_path_at (char *path_ret, int dirfd, const char *pathname, | |||||||
|       char *p; |       char *p; | ||||||
|  |  | ||||||
|       if (dirfd == AT_FDCWD) |       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 |       else | ||||||
| 	{ | 	{ | ||||||
| 	  cygheap_fdget cfd (dirfd); | 	  cygheap_fdget cfd (dirfd); | ||||||
| @@ -4000,3 +4005,16 @@ unlinkat (int dirfd, const char *pathname, int flags) | |||||||
|     return -1; |     return -1; | ||||||
|   return (flags & AT_REMOVEDIR) ? rmdir (path) : unlink (path); |   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; | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user