diff options
Diffstat (limited to 'src/w32.c')
| -rw-r--r-- | src/w32.c | 233 |
1 files changed, 190 insertions, 43 deletions
| @@ -37,7 +37,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 37 | /* must include CRT headers *before* config.h */ | 37 | /* must include CRT headers *before* config.h */ |
| 38 | 38 | ||
| 39 | #include <config.h> | 39 | #include <config.h> |
| 40 | #include <mbstring.h> /* for _mbspbrk and _mbslwr */ | 40 | #include <mbstring.h> /* for _mbspbrk, _mbslwr, _mbsrchr, ... */ |
| 41 | 41 | ||
| 42 | #undef access | 42 | #undef access |
| 43 | #undef chdir | 43 | #undef chdir |
| @@ -1730,12 +1730,17 @@ parse_root (char * name, char ** pPath) | |||
| 1730 | else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) | 1730 | else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) |
| 1731 | { | 1731 | { |
| 1732 | int slashes = 2; | 1732 | int slashes = 2; |
| 1733 | int dbcs_p = max_filename_mbslen () > 1; | ||
| 1734 | |||
| 1733 | name += 2; | 1735 | name += 2; |
| 1734 | do | 1736 | do |
| 1735 | { | 1737 | { |
| 1736 | if (IS_DIRECTORY_SEP (*name) && --slashes == 0) | 1738 | if (IS_DIRECTORY_SEP (*name) && --slashes == 0) |
| 1737 | break; | 1739 | break; |
| 1738 | name++; | 1740 | if (dbcs_p) |
| 1741 | name = CharNextExA (file_name_codepage, name, 0); | ||
| 1742 | else | ||
| 1743 | name++; | ||
| 1739 | } | 1744 | } |
| 1740 | while ( *name ); | 1745 | while ( *name ); |
| 1741 | if (IS_DIRECTORY_SEP (name[0])) | 1746 | if (IS_DIRECTORY_SEP (name[0])) |
| @@ -1800,7 +1805,7 @@ w32_get_long_filename (char * name, char * buf, int size) | |||
| 1800 | while (p != NULL && *p) | 1805 | while (p != NULL && *p) |
| 1801 | { | 1806 | { |
| 1802 | q = p; | 1807 | q = p; |
| 1803 | p = strchr (q, '\\'); | 1808 | p = _mbschr (q, '\\'); |
| 1804 | if (p) *p = '\0'; | 1809 | if (p) *p = '\0'; |
| 1805 | len = get_long_basename (full, o, size); | 1810 | len = get_long_basename (full, o, size); |
| 1806 | if (len > 0) | 1811 | if (len > 0) |
| @@ -2072,16 +2077,16 @@ init_environment (char ** argv) | |||
| 2072 | 2077 | ||
| 2073 | if (!GetModuleFileName (NULL, modname, MAX_PATH)) | 2078 | if (!GetModuleFileName (NULL, modname, MAX_PATH)) |
| 2074 | emacs_abort (); | 2079 | emacs_abort (); |
| 2075 | if ((p = strrchr (modname, '\\')) == NULL) | 2080 | if ((p = _mbsrchr (modname, '\\')) == NULL) |
| 2076 | emacs_abort (); | 2081 | emacs_abort (); |
| 2077 | *p = 0; | 2082 | *p = 0; |
| 2078 | 2083 | ||
| 2079 | if ((p = strrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0) | 2084 | if ((p = _mbsrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0) |
| 2080 | { | 2085 | { |
| 2081 | char buf[SET_ENV_BUF_SIZE]; | 2086 | char buf[SET_ENV_BUF_SIZE]; |
| 2082 | 2087 | ||
| 2083 | *p = 0; | 2088 | *p = 0; |
| 2084 | for (p = modname; *p; p++) | 2089 | for (p = modname; *p; p = CharNext (p)) |
| 2085 | if (*p == '\\') *p = '/'; | 2090 | if (*p == '\\') *p = '/'; |
| 2086 | 2091 | ||
| 2087 | _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); | 2092 | _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); |
| @@ -2096,17 +2101,17 @@ init_environment (char ** argv) | |||
| 2096 | || xstrcasecmp (p, "\\AMD64") == 0)) | 2101 | || xstrcasecmp (p, "\\AMD64") == 0)) |
| 2097 | { | 2102 | { |
| 2098 | *p = 0; | 2103 | *p = 0; |
| 2099 | p = strrchr (modname, '\\'); | 2104 | p = _mbsrchr (modname, '\\'); |
| 2100 | if (p != NULL) | 2105 | if (p != NULL) |
| 2101 | { | 2106 | { |
| 2102 | *p = 0; | 2107 | *p = 0; |
| 2103 | p = strrchr (modname, '\\'); | 2108 | p = _mbsrchr (modname, '\\'); |
| 2104 | if (p && xstrcasecmp (p, "\\src") == 0) | 2109 | if (p && xstrcasecmp (p, "\\src") == 0) |
| 2105 | { | 2110 | { |
| 2106 | char buf[SET_ENV_BUF_SIZE]; | 2111 | char buf[SET_ENV_BUF_SIZE]; |
| 2107 | 2112 | ||
| 2108 | *p = 0; | 2113 | *p = 0; |
| 2109 | for (p = modname; *p; p++) | 2114 | for (p = modname; *p; p = CharNext (p)) |
| 2110 | if (*p == '\\') *p = '/'; | 2115 | if (*p == '\\') *p = '/'; |
| 2111 | 2116 | ||
| 2112 | _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); | 2117 | _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); |
| @@ -2641,12 +2646,23 @@ get_volume_info (const char * name, const char ** pPath) | |||
| 2641 | { | 2646 | { |
| 2642 | char *str = temp; | 2647 | char *str = temp; |
| 2643 | int slashes = 4; | 2648 | int slashes = 4; |
| 2649 | int dbcs_p = max_filename_mbslen () > 1; | ||
| 2650 | |||
| 2644 | rootname = temp; | 2651 | rootname = temp; |
| 2645 | do | 2652 | do |
| 2646 | { | 2653 | { |
| 2647 | if (IS_DIRECTORY_SEP (*name) && --slashes == 0) | 2654 | if (IS_DIRECTORY_SEP (*name) && --slashes == 0) |
| 2648 | break; | 2655 | break; |
| 2649 | *str++ = *name++; | 2656 | if (!dbcs_p) |
| 2657 | *str++ = *name++; | ||
| 2658 | else | ||
| 2659 | { | ||
| 2660 | const char *p = name; | ||
| 2661 | |||
| 2662 | name = CharNextExA (file_name_codepage, name, 0); | ||
| 2663 | memcpy (str, p, name - p); | ||
| 2664 | str += name - p; | ||
| 2665 | } | ||
| 2650 | } | 2666 | } |
| 2651 | while ( *name ); | 2667 | while ( *name ); |
| 2652 | 2668 | ||
| @@ -2882,11 +2898,23 @@ readdir (DIR *dirp) | |||
| 2882 | { | 2898 | { |
| 2883 | char filename[MAXNAMLEN + 3]; | 2899 | char filename[MAXNAMLEN + 3]; |
| 2884 | int ln; | 2900 | int ln; |
| 2901 | int dbcs_p = max_filename_mbslen () > 1; | ||
| 2885 | 2902 | ||
| 2886 | strcpy (filename, dir_pathname); | 2903 | strcpy (filename, dir_pathname); |
| 2887 | ln = strlen (filename) - 1; | 2904 | ln = strlen (filename) - 1; |
| 2888 | if (!IS_DIRECTORY_SEP (filename[ln])) | 2905 | if (!dbcs_p) |
| 2889 | strcat (filename, "\\"); | 2906 | { |
| 2907 | if (!IS_DIRECTORY_SEP (filename[ln])) | ||
| 2908 | strcat (filename, "\\"); | ||
| 2909 | } | ||
| 2910 | else | ||
| 2911 | { | ||
| 2912 | char *end = filename + ln + 1; | ||
| 2913 | char *last_char = CharPrevExA (file_name_codepage, filename, end, 0); | ||
| 2914 | |||
| 2915 | if (!IS_DIRECTORY_SEP (*last_char)) | ||
| 2916 | strcat (filename, "\\"); | ||
| 2917 | } | ||
| 2890 | strcat (filename, "*"); | 2918 | strcat (filename, "*"); |
| 2891 | 2919 | ||
| 2892 | /* Note: No need to resolve symlinks in FILENAME, because | 2920 | /* Note: No need to resolve symlinks in FILENAME, because |
| @@ -2991,6 +3019,7 @@ read_unc_volume (HANDLE henum, char *readbuf, int size) | |||
| 2991 | DWORD bufsize = 512; | 3019 | DWORD bufsize = 512; |
| 2992 | char *buffer; | 3020 | char *buffer; |
| 2993 | char *ptr; | 3021 | char *ptr; |
| 3022 | int dbcs_p = max_filename_mbslen () > 1; | ||
| 2994 | 3023 | ||
| 2995 | count = 1; | 3024 | count = 1; |
| 2996 | buffer = alloca (bufsize); | 3025 | buffer = alloca (bufsize); |
| @@ -3001,7 +3030,13 @@ read_unc_volume (HANDLE henum, char *readbuf, int size) | |||
| 3001 | /* WNetEnumResource returns \\resource\share...skip forward to "share". */ | 3030 | /* WNetEnumResource returns \\resource\share...skip forward to "share". */ |
| 3002 | ptr = ((LPNETRESOURCE) buffer)->lpRemoteName; | 3031 | ptr = ((LPNETRESOURCE) buffer)->lpRemoteName; |
| 3003 | ptr += 2; | 3032 | ptr += 2; |
| 3004 | while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++; | 3033 | if (!dbcs_p) |
| 3034 | while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++; | ||
| 3035 | else | ||
| 3036 | { | ||
| 3037 | while (*ptr && !IS_DIRECTORY_SEP (*ptr)) | ||
| 3038 | ptr = CharNextExA (file_name_codepage, ptr, 0); | ||
| 3039 | } | ||
| 3005 | ptr++; | 3040 | ptr++; |
| 3006 | 3041 | ||
| 3007 | strncpy (readbuf, ptr, size); | 3042 | strncpy (readbuf, ptr, size); |
| @@ -3038,9 +3073,11 @@ logon_network_drive (const char *path) | |||
| 3038 | { | 3073 | { |
| 3039 | NETRESOURCE resource; | 3074 | NETRESOURCE resource; |
| 3040 | char share[MAX_PATH]; | 3075 | char share[MAX_PATH]; |
| 3041 | int i, n_slashes; | 3076 | int n_slashes; |
| 3042 | char drive[4]; | 3077 | char drive[4]; |
| 3043 | UINT drvtype; | 3078 | UINT drvtype; |
| 3079 | char *p; | ||
| 3080 | int dbcs_p; | ||
| 3044 | 3081 | ||
| 3045 | if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1])) | 3082 | if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1])) |
| 3046 | drvtype = DRIVE_REMOTE; | 3083 | drvtype = DRIVE_REMOTE; |
| @@ -3062,13 +3099,18 @@ logon_network_drive (const char *path) | |||
| 3062 | n_slashes = 2; | 3099 | n_slashes = 2; |
| 3063 | strncpy (share, path, MAX_PATH); | 3100 | strncpy (share, path, MAX_PATH); |
| 3064 | /* Truncate to just server and share name. */ | 3101 | /* Truncate to just server and share name. */ |
| 3065 | for (i = 2; i < MAX_PATH; i++) | 3102 | dbcs_p = max_filename_mbslen () > 1; |
| 3103 | for (p = share + 2; *p && p < share + MAX_PATH; ) | ||
| 3066 | { | 3104 | { |
| 3067 | if (IS_DIRECTORY_SEP (share[i]) && ++n_slashes > 3) | 3105 | if (IS_DIRECTORY_SEP (*p) && ++n_slashes > 3) |
| 3068 | { | 3106 | { |
| 3069 | share[i] = '\0'; | 3107 | *p = '\0'; |
| 3070 | break; | 3108 | break; |
| 3071 | } | 3109 | } |
| 3110 | if (dbcs_p) | ||
| 3111 | p = CharNextExA (file_name_codepage, p, 0); | ||
| 3112 | else | ||
| 3113 | p++; | ||
| 3072 | } | 3114 | } |
| 3073 | 3115 | ||
| 3074 | resource.dwType = RESOURCETYPE_DISK; | 3116 | resource.dwType = RESOURCETYPE_DISK; |
| @@ -3365,9 +3407,12 @@ sys_open (const char * path, int oflag, int mode) | |||
| 3365 | and system files. Force all file handles to be | 3407 | and system files. Force all file handles to be |
| 3366 | non-inheritable. */ | 3408 | non-inheritable. */ |
| 3367 | int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); | 3409 | int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); |
| 3368 | if (res >= 0) | 3410 | if (res < 0) |
| 3369 | return res; | 3411 | res = _open (mpath, oflag | _O_NOINHERIT, mode); |
| 3370 | return _open (mpath, oflag | _O_NOINHERIT, mode); | 3412 | if (res >= 0 && res < MAXDESC) |
| 3413 | fd_info[res].flags = 0; | ||
| 3414 | |||
| 3415 | return res; | ||
| 3371 | } | 3416 | } |
| 3372 | 3417 | ||
| 3373 | int | 3418 | int |
| @@ -3843,6 +3888,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) | |||
| 3843 | DWORD access_rights = 0; | 3888 | DWORD access_rights = 0; |
| 3844 | DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1; | 3889 | DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1; |
| 3845 | FILETIME ctime, atime, wtime; | 3890 | FILETIME ctime, atime, wtime; |
| 3891 | int dbcs_p; | ||
| 3846 | 3892 | ||
| 3847 | if (path == NULL || buf == NULL) | 3893 | if (path == NULL || buf == NULL) |
| 3848 | { | 3894 | { |
| @@ -4040,6 +4086,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) | |||
| 4040 | did not ask for extra precision, resolving symlinks will fly | 4086 | did not ask for extra precision, resolving symlinks will fly |
| 4041 | in the face of that request, since the user then wants the | 4087 | in the face of that request, since the user then wants the |
| 4042 | lightweight version of the code. */ | 4088 | lightweight version of the code. */ |
| 4089 | dbcs_p = max_filename_mbslen () > 1; | ||
| 4043 | rootdir = (path >= save_name + len - 1 | 4090 | rootdir = (path >= save_name + len - 1 |
| 4044 | && (IS_DIRECTORY_SEP (*path) || *path == 0)); | 4091 | && (IS_DIRECTORY_SEP (*path) || *path == 0)); |
| 4045 | 4092 | ||
| @@ -4067,8 +4114,19 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) | |||
| 4067 | } | 4114 | } |
| 4068 | else if (rootdir) | 4115 | else if (rootdir) |
| 4069 | { | 4116 | { |
| 4070 | if (!IS_DIRECTORY_SEP (name[len-1])) | 4117 | if (!dbcs_p) |
| 4071 | strcat (name, "\\"); | 4118 | { |
| 4119 | if (!IS_DIRECTORY_SEP (name[len-1])) | ||
| 4120 | strcat (name, "\\"); | ||
| 4121 | } | ||
| 4122 | else | ||
| 4123 | { | ||
| 4124 | char *end = name + len; | ||
| 4125 | char *n = CharPrevExA (file_name_codepage, name, end, 0); | ||
| 4126 | |||
| 4127 | if (!IS_DIRECTORY_SEP (*n)) | ||
| 4128 | strcat (name, "\\"); | ||
| 4129 | } | ||
| 4072 | if (GetDriveType (name) < 2) | 4130 | if (GetDriveType (name) < 2) |
| 4073 | { | 4131 | { |
| 4074 | errno = ENOENT; | 4132 | errno = ENOENT; |
| @@ -4080,15 +4138,37 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) | |||
| 4080 | } | 4138 | } |
| 4081 | else | 4139 | else |
| 4082 | { | 4140 | { |
| 4083 | if (IS_DIRECTORY_SEP (name[len-1])) | 4141 | if (!dbcs_p) |
| 4084 | name[len - 1] = 0; | 4142 | { |
| 4143 | if (IS_DIRECTORY_SEP (name[len-1])) | ||
| 4144 | name[len - 1] = 0; | ||
| 4145 | } | ||
| 4146 | else | ||
| 4147 | { | ||
| 4148 | char *end = name + len; | ||
| 4149 | char *n = CharPrevExA (file_name_codepage, name, end, 0); | ||
| 4150 | |||
| 4151 | if (IS_DIRECTORY_SEP (*n)) | ||
| 4152 | *n = 0; | ||
| 4153 | } | ||
| 4085 | 4154 | ||
| 4086 | /* (This is hacky, but helps when doing file completions on | 4155 | /* (This is hacky, but helps when doing file completions on |
| 4087 | network drives.) Optimize by using information available from | 4156 | network drives.) Optimize by using information available from |
| 4088 | active readdir if possible. */ | 4157 | active readdir if possible. */ |
| 4089 | len = strlen (dir_pathname); | 4158 | len = strlen (dir_pathname); |
| 4090 | if (IS_DIRECTORY_SEP (dir_pathname[len-1])) | 4159 | if (!dbcs_p) |
| 4091 | len--; | 4160 | { |
| 4161 | if (IS_DIRECTORY_SEP (dir_pathname[len-1])) | ||
| 4162 | len--; | ||
| 4163 | } | ||
| 4164 | else | ||
| 4165 | { | ||
| 4166 | char *end = dir_pathname + len; | ||
| 4167 | char *n = CharPrevExA (file_name_codepage, dir_pathname, end, 0); | ||
| 4168 | |||
| 4169 | if (IS_DIRECTORY_SEP (*n)) | ||
| 4170 | len--; | ||
| 4171 | } | ||
| 4092 | if (dir_find_handle != INVALID_HANDLE_VALUE | 4172 | if (dir_find_handle != INVALID_HANDLE_VALUE |
| 4093 | && !(is_a_symlink && follow_symlinks) | 4173 | && !(is_a_symlink && follow_symlinks) |
| 4094 | && strnicmp (save_name, dir_pathname, len) == 0 | 4174 | && strnicmp (save_name, dir_pathname, len) == 0 |
| @@ -4359,6 +4439,7 @@ symlink (char const *filename, char const *linkname) | |||
| 4359 | char linkfn[MAX_PATH], *tgtfn; | 4439 | char linkfn[MAX_PATH], *tgtfn; |
| 4360 | DWORD flags = 0; | 4440 | DWORD flags = 0; |
| 4361 | int dir_access, filename_ends_in_slash; | 4441 | int dir_access, filename_ends_in_slash; |
| 4442 | int dbcs_p; | ||
| 4362 | 4443 | ||
| 4363 | /* Diagnostics follows Posix as much as possible. */ | 4444 | /* Diagnostics follows Posix as much as possible. */ |
| 4364 | if (filename == NULL || linkname == NULL) | 4445 | if (filename == NULL || linkname == NULL) |
| @@ -4384,6 +4465,8 @@ symlink (char const *filename, char const *linkname) | |||
| 4384 | return -1; | 4465 | return -1; |
| 4385 | } | 4466 | } |
| 4386 | 4467 | ||
| 4468 | dbcs_p = max_filename_mbslen () > 1; | ||
| 4469 | |||
| 4387 | /* Note: since empty FILENAME was already rejected, we can safely | 4470 | /* Note: since empty FILENAME was already rejected, we can safely |
| 4388 | refer to FILENAME[1]. */ | 4471 | refer to FILENAME[1]. */ |
| 4389 | if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1]))) | 4472 | if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1]))) |
| @@ -4398,8 +4481,21 @@ symlink (char const *filename, char const *linkname) | |||
| 4398 | char tem[MAX_PATH]; | 4481 | char tem[MAX_PATH]; |
| 4399 | char *p = linkfn + strlen (linkfn); | 4482 | char *p = linkfn + strlen (linkfn); |
| 4400 | 4483 | ||
| 4401 | while (p > linkfn && !IS_ANY_SEP (p[-1])) | 4484 | if (!dbcs_p) |
| 4402 | p--; | 4485 | { |
| 4486 | while (p > linkfn && !IS_ANY_SEP (p[-1])) | ||
| 4487 | p--; | ||
| 4488 | } | ||
| 4489 | else | ||
| 4490 | { | ||
| 4491 | char *p1 = CharPrevExA (file_name_codepage, linkfn, p, 0); | ||
| 4492 | |||
| 4493 | while (p > linkfn && !IS_ANY_SEP (*p1)) | ||
| 4494 | { | ||
| 4495 | p = p1; | ||
| 4496 | p1 = CharPrevExA (file_name_codepage, linkfn, p1, 0); | ||
| 4497 | } | ||
| 4498 | } | ||
| 4403 | if (p > linkfn) | 4499 | if (p > linkfn) |
| 4404 | strncpy (tem, linkfn, p - linkfn); | 4500 | strncpy (tem, linkfn, p - linkfn); |
| 4405 | tem[p - linkfn] = '\0'; | 4501 | tem[p - linkfn] = '\0'; |
| @@ -4414,7 +4510,15 @@ symlink (char const *filename, char const *linkname) | |||
| 4414 | exist, but ends in a slash, we create a symlink to directory. If | 4510 | exist, but ends in a slash, we create a symlink to directory. If |
| 4415 | FILENAME exists and is a directory, we always create a symlink to | 4511 | FILENAME exists and is a directory, we always create a symlink to |
| 4416 | directory. */ | 4512 | directory. */ |
| 4417 | filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]); | 4513 | if (!dbcs_p) |
| 4514 | filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]); | ||
| 4515 | else | ||
| 4516 | { | ||
| 4517 | const char *end = filename + strlen (filename); | ||
| 4518 | const char *n = CharPrevExA (file_name_codepage, filename, end, 0); | ||
| 4519 | |||
| 4520 | filename_ends_in_slash = IS_DIRECTORY_SEP (*n); | ||
| 4521 | } | ||
| 4418 | if (dir_access == 0 || filename_ends_in_slash) | 4522 | if (dir_access == 0 || filename_ends_in_slash) |
| 4419 | flags = SYMBOLIC_LINK_FLAG_DIRECTORY; | 4523 | flags = SYMBOLIC_LINK_FLAG_DIRECTORY; |
| 4420 | 4524 | ||
| @@ -4604,6 +4708,8 @@ readlink (const char *name, char *buf, size_t buf_size) | |||
| 4604 | WCHAR *lwname_src = | 4708 | WCHAR *lwname_src = |
| 4605 | reparse_data->SymbolicLinkReparseBuffer.PathBuffer | 4709 | reparse_data->SymbolicLinkReparseBuffer.PathBuffer |
| 4606 | + reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR); | 4710 | + reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR); |
| 4711 | /* This updates file_name_codepage which we need below. */ | ||
| 4712 | int dbcs_p = max_filename_mbslen () > 1; | ||
| 4607 | 4713 | ||
| 4608 | /* According to MSDN, PrintNameLength does not include the | 4714 | /* According to MSDN, PrintNameLength does not include the |
| 4609 | terminating null character. */ | 4715 | terminating null character. */ |
| @@ -4611,9 +4717,7 @@ readlink (const char *name, char *buf, size_t buf_size) | |||
| 4611 | memcpy (lwname, lwname_src, lwname_len); | 4717 | memcpy (lwname, lwname_src, lwname_len); |
| 4612 | lwname[lwname_len/sizeof(WCHAR)] = 0; /* null-terminate */ | 4718 | lwname[lwname_len/sizeof(WCHAR)] = 0; /* null-terminate */ |
| 4613 | 4719 | ||
| 4614 | /* FIXME: Should we use the current file-name coding system | 4720 | lname_len = WideCharToMultiByte (file_name_codepage, 0, lwname, -1, |
| 4615 | instead of the fixed value of the ANSI codepage? */ | ||
| 4616 | lname_len = WideCharToMultiByte (w32_ansi_code_page, 0, lwname, -1, | ||
| 4617 | lname, MAX_PATH, NULL, NULL); | 4721 | lname, MAX_PATH, NULL, NULL); |
| 4618 | if (!lname_len) | 4722 | if (!lname_len) |
| 4619 | { | 4723 | { |
| @@ -4639,18 +4743,33 @@ readlink (const char *name, char *buf, size_t buf_size) | |||
| 4639 | else | 4743 | else |
| 4640 | { | 4744 | { |
| 4641 | size_t size_to_copy = buf_size; | 4745 | size_t size_to_copy = buf_size; |
| 4642 | BYTE *p = lname; | 4746 | BYTE *p = lname, *p2; |
| 4643 | BYTE *pend = p + lname_len; | 4747 | BYTE *pend = p + lname_len; |
| 4644 | 4748 | ||
| 4645 | /* Normalize like dostounix_filename does, but we don't | 4749 | /* Normalize like dostounix_filename does, but we don't |
| 4646 | want to assume that lname is null-terminated. */ | 4750 | want to assume that lname is null-terminated. */ |
| 4647 | if (*p && p[1] == ':' && *p >= 'A' && *p <= 'Z') | 4751 | if (dbcs_p) |
| 4648 | *p += 'a' - 'A'; | 4752 | p2 = CharNextExA (file_name_codepage, p, 0); |
| 4753 | else | ||
| 4754 | p2 = p + 1; | ||
| 4755 | if (*p && *p2 == ':' && *p >= 'A' && *p <= 'Z') | ||
| 4756 | { | ||
| 4757 | *p += 'a' - 'A'; | ||
| 4758 | p += 2; | ||
| 4759 | } | ||
| 4649 | while (p <= pend) | 4760 | while (p <= pend) |
| 4650 | { | 4761 | { |
| 4651 | if (*p == '\\') | 4762 | if (*p == '\\') |
| 4652 | *p = '/'; | 4763 | *p = '/'; |
| 4653 | ++p; | 4764 | if (dbcs_p) |
| 4765 | { | ||
| 4766 | p = CharNextExA (file_name_codepage, p, 0); | ||
| 4767 | /* CharNextExA doesn't advance at null character. */ | ||
| 4768 | if (!*p) | ||
| 4769 | break; | ||
| 4770 | } | ||
| 4771 | else | ||
| 4772 | ++p; | ||
| 4654 | } | 4773 | } |
| 4655 | /* Testing for null-terminated LNAME is paranoia: | 4774 | /* Testing for null-terminated LNAME is paranoia: |
| 4656 | WideCharToMultiByte should always return a | 4775 | WideCharToMultiByte should always return a |
| @@ -4724,6 +4843,7 @@ chase_symlinks (const char *file) | |||
| 4724 | char link[MAX_PATH]; | 4843 | char link[MAX_PATH]; |
| 4725 | ssize_t res, link_len; | 4844 | ssize_t res, link_len; |
| 4726 | int loop_count = 0; | 4845 | int loop_count = 0; |
| 4846 | int dbcs_p; | ||
| 4727 | 4847 | ||
| 4728 | if (is_windows_9x () == TRUE || !is_symlink (file)) | 4848 | if (is_windows_9x () == TRUE || !is_symlink (file)) |
| 4729 | return (char *)file; | 4849 | return (char *)file; |
| @@ -4731,13 +4851,27 @@ chase_symlinks (const char *file) | |||
| 4731 | if ((link_len = GetFullPathName (file, MAX_PATH, link, NULL)) == 0) | 4851 | if ((link_len = GetFullPathName (file, MAX_PATH, link, NULL)) == 0) |
| 4732 | return (char *)file; | 4852 | return (char *)file; |
| 4733 | 4853 | ||
| 4854 | dbcs_p = max_filename_mbslen () > 1; | ||
| 4734 | target[0] = '\0'; | 4855 | target[0] = '\0'; |
| 4735 | do { | 4856 | do { |
| 4736 | 4857 | ||
| 4737 | /* Remove trailing slashes, as we want to resolve the last | 4858 | /* Remove trailing slashes, as we want to resolve the last |
| 4738 | non-trivial part of the link name. */ | 4859 | non-trivial part of the link name. */ |
| 4739 | while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1])) | 4860 | if (!dbcs_p) |
| 4740 | link[link_len--] = '\0'; | 4861 | { |
| 4862 | while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1])) | ||
| 4863 | link[link_len--] = '\0'; | ||
| 4864 | } | ||
| 4865 | else if (link_len > 3) | ||
| 4866 | { | ||
| 4867 | char *n = CharPrevExA (file_name_codepage, link, link + link_len, 0); | ||
| 4868 | |||
| 4869 | while (n >= link + 2 && IS_DIRECTORY_SEP (*n)) | ||
| 4870 | { | ||
| 4871 | n[1] = '\0'; | ||
| 4872 | n = CharPrevExA (file_name_codepage, link, n, 0); | ||
| 4873 | } | ||
| 4874 | } | ||
| 4741 | 4875 | ||
| 4742 | res = readlink (link, target, MAX_PATH); | 4876 | res = readlink (link, target, MAX_PATH); |
| 4743 | if (res > 0) | 4877 | if (res > 0) |
| @@ -4750,8 +4884,21 @@ chase_symlinks (const char *file) | |||
| 4750 | the symlink, then copy the result back to target. */ | 4884 | the symlink, then copy the result back to target. */ |
| 4751 | char *p = link + link_len; | 4885 | char *p = link + link_len; |
| 4752 | 4886 | ||
| 4753 | while (p > link && !IS_ANY_SEP (p[-1])) | 4887 | if (!dbcs_p) |
| 4754 | p--; | 4888 | { |
| 4889 | while (p > link && !IS_ANY_SEP (p[-1])) | ||
| 4890 | p--; | ||
| 4891 | } | ||
| 4892 | else | ||
| 4893 | { | ||
| 4894 | char *p1 = CharPrevExA (file_name_codepage, link, p, 0); | ||
| 4895 | |||
| 4896 | while (p > link && !IS_ANY_SEP (*p1)) | ||
| 4897 | { | ||
| 4898 | p = p1; | ||
| 4899 | p1 = CharPrevExA (file_name_codepage, link, p1, 0); | ||
| 4900 | } | ||
| 4901 | } | ||
| 4755 | strcpy (p, target); | 4902 | strcpy (p, target); |
| 4756 | strcpy (target, link); | 4903 | strcpy (target, link); |
| 4757 | } | 4904 | } |
| @@ -6543,15 +6690,15 @@ sys_close (int fd) | |||
| 6543 | } | 6690 | } |
| 6544 | } | 6691 | } |
| 6545 | 6692 | ||
| 6693 | if (fd >= 0 && fd < MAXDESC) | ||
| 6694 | fd_info[fd].flags = 0; | ||
| 6695 | |||
| 6546 | /* Note that sockets do not need special treatment here (at least on | 6696 | /* Note that sockets do not need special treatment here (at least on |
| 6547 | NT and Windows 95 using the standard tcp/ip stacks) - it appears that | 6697 | NT and Windows 95 using the standard tcp/ip stacks) - it appears that |
| 6548 | closesocket is equivalent to CloseHandle, which is to be expected | 6698 | closesocket is equivalent to CloseHandle, which is to be expected |
| 6549 | because socket handles are fully fledged kernel handles. */ | 6699 | because socket handles are fully fledged kernel handles. */ |
| 6550 | rc = _close (fd); | 6700 | rc = _close (fd); |
| 6551 | 6701 | ||
| 6552 | if (rc == 0 && fd < MAXDESC) | ||
| 6553 | fd_info[fd].flags = 0; | ||
| 6554 | |||
| 6555 | return rc; | 6702 | return rc; |
| 6556 | } | 6703 | } |
| 6557 | 6704 | ||