aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2013-01-26 14:49:34 +0200
committerEli Zaretskii2013-01-26 14:49:34 +0200
commit806fed21f15908cee4e3cfdb18e21d988e08ea48 (patch)
treeccb5ee9599c7b45ed9c698ca56f495d61c135feb
parent26854e9c9ee5469474bcaa496b94273082772c18 (diff)
downloademacs-806fed21f15908cee4e3cfdb18e21d988e08ea48.tar.gz
emacs-806fed21f15908cee4e3cfdb18e21d988e08ea48.zip
Fix bug #13553 with usage of IS_DIRECTORY_SEP on MS-Windows under DBCS.
src/w32.c (parse_root, get_volume_info, readdir, read_unc_volume) (logon_network_drive, stat_worker, symlink, chase_symlinks): Use CharNextExA and CharPrevExA to iterate over file names encoded in DBCS.
-rw-r--r--src/ChangeLog7
-rw-r--r--src/w32.c173
2 files changed, 158 insertions, 22 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index cd71fa73db0..a5108f79f3d 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
12013-01-26 Eli Zaretskii <eliz@gnu.org>
2
3 * w32.c (parse_root, get_volume_info, readdir, read_unc_volume)
4 (logon_network_drive, stat_worker, symlink, chase_symlinks): Use
5 CharNextExA and CharPrevExA to iterate over file names encoded in
6 DBCS. (Bug#13553)
7
12013-01-25 Eli Zaretskii <eliz@gnu.org> 82013-01-25 Eli Zaretskii <eliz@gnu.org>
2 9
3 * w32.c (w32_get_long_filename, init_environment, readlink): 10 * w32.c (w32_get_long_filename, init_environment, readlink):
diff --git a/src/w32.c b/src/w32.c
index 86b4ea72a22..3e300d1b9a3 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -1503,12 +1503,17 @@ parse_root (char * name, char ** pPath)
1503 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) 1503 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
1504 { 1504 {
1505 int slashes = 2; 1505 int slashes = 2;
1506 int dbcs_p = max_filename_mbslen () > 1;
1507
1506 name += 2; 1508 name += 2;
1507 do 1509 do
1508 { 1510 {
1509 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) 1511 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
1510 break; 1512 break;
1511 name++; 1513 if (dbcs_p)
1514 name = CharNextExA (file_name_codepage, name, 0);
1515 else
1516 name++;
1512 } 1517 }
1513 while ( *name ); 1518 while ( *name );
1514 if (IS_DIRECTORY_SEP (name[0])) 1519 if (IS_DIRECTORY_SEP (name[0]))
@@ -2369,12 +2374,23 @@ get_volume_info (const char * name, const char ** pPath)
2369 { 2374 {
2370 char *str = temp; 2375 char *str = temp;
2371 int slashes = 4; 2376 int slashes = 4;
2377 int dbcs_p = max_filename_mbslen () > 1;
2378
2372 rootname = temp; 2379 rootname = temp;
2373 do 2380 do
2374 { 2381 {
2375 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) 2382 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
2376 break; 2383 break;
2377 *str++ = *name++; 2384 if (!dbcs_p)
2385 *str++ = *name++;
2386 else
2387 {
2388 const char *p = name;
2389
2390 name = CharNextExA (file_name_codepage, name, 0);
2391 memcpy (str, p, name - p);
2392 str += name - p;
2393 }
2378 } 2394 }
2379 while ( *name ); 2395 while ( *name );
2380 2396
@@ -2610,11 +2626,23 @@ readdir (DIR *dirp)
2610 { 2626 {
2611 char filename[MAXNAMLEN + 3]; 2627 char filename[MAXNAMLEN + 3];
2612 int ln; 2628 int ln;
2629 int dbcs_p = max_filename_mbslen () > 1;
2613 2630
2614 strcpy (filename, dir_pathname); 2631 strcpy (filename, dir_pathname);
2615 ln = strlen (filename) - 1; 2632 ln = strlen (filename) - 1;
2616 if (!IS_DIRECTORY_SEP (filename[ln])) 2633 if (!dbcs_p)
2617 strcat (filename, "\\"); 2634 {
2635 if (!IS_DIRECTORY_SEP (filename[ln]))
2636 strcat (filename, "\\");
2637 }
2638 else
2639 {
2640 char *end = filename + ln + 1;
2641 char *last_char = CharPrevExA (file_name_codepage, filename, end, 0);
2642
2643 if (!IS_DIRECTORY_SEP (*last_char))
2644 strcat (filename, "\\");
2645 }
2618 strcat (filename, "*"); 2646 strcat (filename, "*");
2619 2647
2620 /* Note: No need to resolve symlinks in FILENAME, because 2648 /* Note: No need to resolve symlinks in FILENAME, because
@@ -2719,6 +2747,7 @@ read_unc_volume (HANDLE henum, char *readbuf, int size)
2719 DWORD bufsize = 512; 2747 DWORD bufsize = 512;
2720 char *buffer; 2748 char *buffer;
2721 char *ptr; 2749 char *ptr;
2750 int dbcs_p = max_filename_mbslen () > 1;
2722 2751
2723 count = 1; 2752 count = 1;
2724 buffer = alloca (bufsize); 2753 buffer = alloca (bufsize);
@@ -2729,7 +2758,13 @@ read_unc_volume (HANDLE henum, char *readbuf, int size)
2729 /* WNetEnumResource returns \\resource\share...skip forward to "share". */ 2758 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
2730 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName; 2759 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName;
2731 ptr += 2; 2760 ptr += 2;
2732 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++; 2761 if (!dbcs_p)
2762 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++;
2763 else
2764 {
2765 while (*ptr && !IS_DIRECTORY_SEP (*ptr))
2766 ptr = CharNextExA (file_name_codepage, ptr, 0);
2767 }
2733 ptr++; 2768 ptr++;
2734 2769
2735 strncpy (readbuf, ptr, size); 2770 strncpy (readbuf, ptr, size);
@@ -2766,9 +2801,11 @@ logon_network_drive (const char *path)
2766{ 2801{
2767 NETRESOURCE resource; 2802 NETRESOURCE resource;
2768 char share[MAX_PATH]; 2803 char share[MAX_PATH];
2769 int i, n_slashes; 2804 int n_slashes;
2770 char drive[4]; 2805 char drive[4];
2771 UINT drvtype; 2806 UINT drvtype;
2807 char *p;
2808 int dbcs_p;
2772 2809
2773 if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1])) 2810 if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1]))
2774 drvtype = DRIVE_REMOTE; 2811 drvtype = DRIVE_REMOTE;
@@ -2790,13 +2827,18 @@ logon_network_drive (const char *path)
2790 n_slashes = 2; 2827 n_slashes = 2;
2791 strncpy (share, path, MAX_PATH); 2828 strncpy (share, path, MAX_PATH);
2792 /* Truncate to just server and share name. */ 2829 /* Truncate to just server and share name. */
2793 for (i = 2; i < MAX_PATH; i++) 2830 dbcs_p = max_filename_mbslen () > 1;
2831 for (p = share + 2; *p && p < share + MAX_PATH; )
2794 { 2832 {
2795 if (IS_DIRECTORY_SEP (share[i]) && ++n_slashes > 3) 2833 if (IS_DIRECTORY_SEP (*p) && ++n_slashes > 3)
2796 { 2834 {
2797 share[i] = '\0'; 2835 *p = '\0';
2798 break; 2836 break;
2799 } 2837 }
2838 if (dbcs_p)
2839 p = CharNextExA (file_name_codepage, p, 0);
2840 else
2841 p++;
2800 } 2842 }
2801 2843
2802 resource.dwType = RESOURCETYPE_DISK; 2844 resource.dwType = RESOURCETYPE_DISK;
@@ -3557,6 +3599,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3557 DWORD access_rights = 0; 3599 DWORD access_rights = 0;
3558 DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1; 3600 DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1;
3559 FILETIME ctime, atime, wtime; 3601 FILETIME ctime, atime, wtime;
3602 int dbcs_p;
3560 3603
3561 if (path == NULL || buf == NULL) 3604 if (path == NULL || buf == NULL)
3562 { 3605 {
@@ -3751,6 +3794,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3751 did not ask for extra precision, resolving symlinks will fly 3794 did not ask for extra precision, resolving symlinks will fly
3752 in the face of that request, since the user then wants the 3795 in the face of that request, since the user then wants the
3753 lightweight version of the code. */ 3796 lightweight version of the code. */
3797 dbcs_p = max_filename_mbslen () > 1;
3754 rootdir = (path >= save_name + len - 1 3798 rootdir = (path >= save_name + len - 1
3755 && (IS_DIRECTORY_SEP (*path) || *path == 0)); 3799 && (IS_DIRECTORY_SEP (*path) || *path == 0));
3756 3800
@@ -3778,8 +3822,19 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3778 } 3822 }
3779 else if (rootdir) 3823 else if (rootdir)
3780 { 3824 {
3781 if (!IS_DIRECTORY_SEP (name[len-1])) 3825 if (!dbcs_p)
3782 strcat (name, "\\"); 3826 {
3827 if (!IS_DIRECTORY_SEP (name[len-1]))
3828 strcat (name, "\\");
3829 }
3830 else
3831 {
3832 char *end = name + len;
3833 char *n = CharPrevExA (file_name_codepage, name, end, 0);
3834
3835 if (!IS_DIRECTORY_SEP (*n))
3836 strcat (name, "\\");
3837 }
3783 if (GetDriveType (name) < 2) 3838 if (GetDriveType (name) < 2)
3784 { 3839 {
3785 errno = ENOENT; 3840 errno = ENOENT;
@@ -3791,15 +3846,37 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3791 } 3846 }
3792 else 3847 else
3793 { 3848 {
3794 if (IS_DIRECTORY_SEP (name[len-1])) 3849 if (!dbcs_p)
3795 name[len - 1] = 0; 3850 {
3851 if (IS_DIRECTORY_SEP (name[len-1]))
3852 name[len - 1] = 0;
3853 }
3854 else
3855 {
3856 char *end = name + len;
3857 char *n = CharPrevExA (file_name_codepage, name, end, 0);
3858
3859 if (IS_DIRECTORY_SEP (*n))
3860 *n = 0;
3861 }
3796 3862
3797 /* (This is hacky, but helps when doing file completions on 3863 /* (This is hacky, but helps when doing file completions on
3798 network drives.) Optimize by using information available from 3864 network drives.) Optimize by using information available from
3799 active readdir if possible. */ 3865 active readdir if possible. */
3800 len = strlen (dir_pathname); 3866 len = strlen (dir_pathname);
3801 if (IS_DIRECTORY_SEP (dir_pathname[len-1])) 3867 if (!dbcs_p)
3802 len--; 3868 {
3869 if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
3870 len--;
3871 }
3872 else
3873 {
3874 char *end = dir_pathname + len;
3875 char *n = CharPrevExA (file_name_codepage, dir_pathname, end, 0);
3876
3877 if (IS_DIRECTORY_SEP (*n))
3878 len--;
3879 }
3803 if (dir_find_handle != INVALID_HANDLE_VALUE 3880 if (dir_find_handle != INVALID_HANDLE_VALUE
3804 && !(is_a_symlink && follow_symlinks) 3881 && !(is_a_symlink && follow_symlinks)
3805 && strnicmp (save_name, dir_pathname, len) == 0 3882 && strnicmp (save_name, dir_pathname, len) == 0
@@ -4060,6 +4137,7 @@ symlink (char const *filename, char const *linkname)
4060 char linkfn[MAX_PATH], *tgtfn; 4137 char linkfn[MAX_PATH], *tgtfn;
4061 DWORD flags = 0; 4138 DWORD flags = 0;
4062 int dir_access, filename_ends_in_slash; 4139 int dir_access, filename_ends_in_slash;
4140 int dbcs_p;
4063 4141
4064 /* Diagnostics follows Posix as much as possible. */ 4142 /* Diagnostics follows Posix as much as possible. */
4065 if (filename == NULL || linkname == NULL) 4143 if (filename == NULL || linkname == NULL)
@@ -4085,6 +4163,8 @@ symlink (char const *filename, char const *linkname)
4085 return -1; 4163 return -1;
4086 } 4164 }
4087 4165
4166 dbcs_p = max_filename_mbslen () > 1;
4167
4088 /* Note: since empty FILENAME was already rejected, we can safely 4168 /* Note: since empty FILENAME was already rejected, we can safely
4089 refer to FILENAME[1]. */ 4169 refer to FILENAME[1]. */
4090 if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1]))) 4170 if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1])))
@@ -4099,8 +4179,21 @@ symlink (char const *filename, char const *linkname)
4099 char tem[MAX_PATH]; 4179 char tem[MAX_PATH];
4100 char *p = linkfn + strlen (linkfn); 4180 char *p = linkfn + strlen (linkfn);
4101 4181
4102 while (p > linkfn && !IS_ANY_SEP (p[-1])) 4182 if (!dbcs_p)
4103 p--; 4183 {
4184 while (p > linkfn && !IS_ANY_SEP (p[-1]))
4185 p--;
4186 }
4187 else
4188 {
4189 char *p1 = CharPrevExA (file_name_codepage, linkfn, p, 0);
4190
4191 while (p > linkfn && !IS_ANY_SEP (*p1))
4192 {
4193 p = p1;
4194 p1 = CharPrevExA (file_name_codepage, linkfn, p1, 0);
4195 }
4196 }
4104 if (p > linkfn) 4197 if (p > linkfn)
4105 strncpy (tem, linkfn, p - linkfn); 4198 strncpy (tem, linkfn, p - linkfn);
4106 tem[p - linkfn] = '\0'; 4199 tem[p - linkfn] = '\0';
@@ -4115,7 +4208,15 @@ symlink (char const *filename, char const *linkname)
4115 exist, but ends in a slash, we create a symlink to directory. If 4208 exist, but ends in a slash, we create a symlink to directory. If
4116 FILENAME exists and is a directory, we always create a symlink to 4209 FILENAME exists and is a directory, we always create a symlink to
4117 directory. */ 4210 directory. */
4118 filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]); 4211 if (!dbcs_p)
4212 filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]);
4213 else
4214 {
4215 const char *end = filename + strlen (filename);
4216 const char *n = CharPrevExA (file_name_codepage, filename, end, 0);
4217
4218 filename_ends_in_slash = IS_DIRECTORY_SEP (*n);
4219 }
4119 if (dir_access == 0 || filename_ends_in_slash) 4220 if (dir_access == 0 || filename_ends_in_slash)
4120 flags = SYMBOLIC_LINK_FLAG_DIRECTORY; 4221 flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
4121 4222
@@ -4440,6 +4541,7 @@ chase_symlinks (const char *file)
4440 char link[MAX_PATH]; 4541 char link[MAX_PATH];
4441 ssize_t res, link_len; 4542 ssize_t res, link_len;
4442 int loop_count = 0; 4543 int loop_count = 0;
4544 int dbcs_p;
4443 4545
4444 if (is_windows_9x () == TRUE || !is_symlink (file)) 4546 if (is_windows_9x () == TRUE || !is_symlink (file))
4445 return (char *)file; 4547 return (char *)file;
@@ -4447,13 +4549,27 @@ chase_symlinks (const char *file)
4447 if ((link_len = GetFullPathName (file, MAX_PATH, link, NULL)) == 0) 4549 if ((link_len = GetFullPathName (file, MAX_PATH, link, NULL)) == 0)
4448 return (char *)file; 4550 return (char *)file;
4449 4551
4552 dbcs_p = max_filename_mbslen () > 1;
4450 target[0] = '\0'; 4553 target[0] = '\0';
4451 do { 4554 do {
4452 4555
4453 /* Remove trailing slashes, as we want to resolve the last 4556 /* Remove trailing slashes, as we want to resolve the last
4454 non-trivial part of the link name. */ 4557 non-trivial part of the link name. */
4455 while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1])) 4558 if (!dbcs_p)
4456 link[link_len--] = '\0'; 4559 {
4560 while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1]))
4561 link[link_len--] = '\0';
4562 }
4563 else if (link_len > 3)
4564 {
4565 char *n = CharPrevExA (file_name_codepage, link, link + link_len, 0);
4566
4567 while (n >= link + 2 && IS_DIRECTORY_SEP (*n))
4568 {
4569 n[1] = '\0';
4570 n = CharPrevExA (file_name_codepage, link, n, 0);
4571 }
4572 }
4457 4573
4458 res = readlink (link, target, MAX_PATH); 4574 res = readlink (link, target, MAX_PATH);
4459 if (res > 0) 4575 if (res > 0)
@@ -4466,8 +4582,21 @@ chase_symlinks (const char *file)
4466 the symlink, then copy the result back to target. */ 4582 the symlink, then copy the result back to target. */
4467 char *p = link + link_len; 4583 char *p = link + link_len;
4468 4584
4469 while (p > link && !IS_ANY_SEP (p[-1])) 4585 if (!dbcs_p)
4470 p--; 4586 {
4587 while (p > link && !IS_ANY_SEP (p[-1]))
4588 p--;
4589 }
4590 else
4591 {
4592 char *p1 = CharPrevExA (file_name_codepage, link, p, 0);
4593
4594 while (p > link && !IS_ANY_SEP (*p1))
4595 {
4596 p = p1;
4597 p1 = CharPrevExA (file_name_codepage, link, p1, 0);
4598 }
4599 }
4471 strcpy (p, target); 4600 strcpy (p, target);
4472 strcpy (target, link); 4601 strcpy (target, link);
4473 } 4602 }