diff options
| author | Eli Zaretskii | 2013-11-09 14:49:02 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2013-11-09 14:49:02 +0200 |
| commit | 0b9de7cd600054dfbe6252b73995302200b8597e (patch) | |
| tree | 3561fd8af235fb8b5c7a6291adceb427024bfae9 /src | |
| parent | f5441ba43c16303b129192504a0731a0ee0df47e (diff) | |
| download | emacs-0b9de7cd600054dfbe6252b73995302200b8597e.tar.gz emacs-0b9de7cd600054dfbe6252b73995302200b8597e.zip | |
Dirent functions and directory-files are converted and work.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32.c | 320 |
1 files changed, 206 insertions, 114 deletions
| @@ -2934,25 +2934,28 @@ is_exec (const char * name) | |||
| 2934 | xstrcasecmp (p, ".cmd") == 0)); | 2934 | xstrcasecmp (p, ".cmd") == 0)); |
| 2935 | } | 2935 | } |
| 2936 | 2936 | ||
| 2937 | /* Emulate the Unix directory procedures opendir, closedir, | 2937 | /* Emulate the Unix directory procedures opendir, closedir, and |
| 2938 | and readdir. We can't use the procedures supplied in sysdep.c, | 2938 | readdir. We rename them to sys_* names because some versions of |
| 2939 | so we provide them here. */ | 2939 | MinGW startup code call opendir and readdir to glob wildcards, and |
| 2940 | the code that calls them doesn't grok UTF-8 encoded file names we | ||
| 2941 | produce in dirent->d_name[]. */ | ||
| 2940 | 2942 | ||
| 2941 | struct dirent dir_static; /* simulated directory contents */ | 2943 | struct dirent dir_static; /* simulated directory contents */ |
| 2942 | static HANDLE dir_find_handle = INVALID_HANDLE_VALUE; | 2944 | static HANDLE dir_find_handle = INVALID_HANDLE_VALUE; |
| 2943 | static int dir_is_fat; | 2945 | static int dir_is_fat; |
| 2944 | static char dir_pathname[MAXPATHLEN+1]; | 2946 | static char dir_pathname[MAX_UTF8_PATH]; |
| 2945 | static WIN32_FIND_DATA dir_find_data; | 2947 | static WIN32_FIND_DATAW dir_find_data_w; |
| 2948 | static WIN32_FIND_DATAA dir_find_data_a; | ||
| 2946 | 2949 | ||
| 2947 | /* Support shares on a network resource as subdirectories of a read-only | 2950 | /* Support shares on a network resource as subdirectories of a read-only |
| 2948 | root directory. */ | 2951 | root directory. */ |
| 2949 | static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE; | 2952 | static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE; |
| 2950 | static HANDLE open_unc_volume (const char *); | 2953 | static HANDLE open_unc_volume (const char *); |
| 2951 | static char *read_unc_volume (HANDLE, char *, int); | 2954 | static void *read_unc_volume (HANDLE, wchar_t *, char *, int); |
| 2952 | static void close_unc_volume (HANDLE); | 2955 | static void close_unc_volume (HANDLE); |
| 2953 | 2956 | ||
| 2954 | DIR * | 2957 | DIR * |
| 2955 | opendir (const char *filename) | 2958 | sys_opendir (const char *filename) |
| 2956 | { | 2959 | { |
| 2957 | DIR *dirp; | 2960 | DIR *dirp; |
| 2958 | 2961 | ||
| @@ -2981,8 +2984,8 @@ opendir (const char *filename) | |||
| 2981 | dirp->dd_loc = 0; | 2984 | dirp->dd_loc = 0; |
| 2982 | dirp->dd_size = 0; | 2985 | dirp->dd_size = 0; |
| 2983 | 2986 | ||
| 2984 | strncpy (dir_pathname, map_w32_filename (filename, NULL), MAXPATHLEN); | 2987 | strncpy (dir_pathname, map_w32_filename (filename, NULL), MAX_UTF8_PATH - 1); |
| 2985 | dir_pathname[MAXPATHLEN] = '\0'; | 2988 | dir_pathname[MAX_UTF8_PATH - 1] = '\0'; |
| 2986 | /* Note: We don't support symlinks to file names on FAT volumes. | 2989 | /* Note: We don't support symlinks to file names on FAT volumes. |
| 2987 | Doing so would mean punishing 99.99% of use cases by resolving | 2990 | Doing so would mean punishing 99.99% of use cases by resolving |
| 2988 | all the possible symlinks in FILENAME, recursively. */ | 2991 | all the possible symlinks in FILENAME, recursively. */ |
| @@ -2992,7 +2995,7 @@ opendir (const char *filename) | |||
| 2992 | } | 2995 | } |
| 2993 | 2996 | ||
| 2994 | void | 2997 | void |
| 2995 | closedir (DIR *dirp) | 2998 | sys_closedir (DIR *dirp) |
| 2996 | { | 2999 | { |
| 2997 | /* If we have a find-handle open, close it. */ | 3000 | /* If we have a find-handle open, close it. */ |
| 2998 | if (dir_find_handle != INVALID_HANDLE_VALUE) | 3001 | if (dir_find_handle != INVALID_HANDLE_VALUE) |
| @@ -3009,52 +3012,59 @@ closedir (DIR *dirp) | |||
| 3009 | } | 3012 | } |
| 3010 | 3013 | ||
| 3011 | struct dirent * | 3014 | struct dirent * |
| 3012 | readdir (DIR *dirp) | 3015 | sys_readdir (DIR *dirp) |
| 3013 | { | 3016 | { |
| 3014 | int downcase = !NILP (Vw32_downcase_file_names); | 3017 | int downcase = !NILP (Vw32_downcase_file_names); |
| 3015 | 3018 | ||
| 3016 | if (wnet_enum_handle != INVALID_HANDLE_VALUE) | 3019 | if (wnet_enum_handle != INVALID_HANDLE_VALUE) |
| 3017 | { | 3020 | { |
| 3018 | if (!read_unc_volume (wnet_enum_handle, | 3021 | if (!read_unc_volume (wnet_enum_handle, |
| 3019 | dir_find_data.cFileName, | 3022 | dir_find_data_w.cFileName, |
| 3023 | dir_find_data_a.cFileName, | ||
| 3020 | MAX_PATH)) | 3024 | MAX_PATH)) |
| 3021 | return NULL; | 3025 | return NULL; |
| 3022 | } | 3026 | } |
| 3023 | /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */ | 3027 | /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */ |
| 3024 | else if (dir_find_handle == INVALID_HANDLE_VALUE) | 3028 | else if (dir_find_handle == INVALID_HANDLE_VALUE) |
| 3025 | { | 3029 | { |
| 3026 | char filename[MAXNAMLEN + 3]; | 3030 | char filename[MAX_UTF8_PATH + 2]; |
| 3027 | int ln; | 3031 | int ln; |
| 3028 | int dbcs_p = max_filename_mbslen () > 1; | ||
| 3029 | 3032 | ||
| 3030 | strcpy (filename, dir_pathname); | 3033 | strcpy (filename, dir_pathname); |
| 3031 | ln = strlen (filename) - 1; | 3034 | ln = strlen (filename) - 1; |
| 3032 | if (!dbcs_p) | 3035 | if (!IS_DIRECTORY_SEP (filename[ln])) |
| 3036 | strcat (filename, "\\"); | ||
| 3037 | strcat (filename, "*"); | ||
| 3038 | |||
| 3039 | /* Note: No need to resolve symlinks in FILENAME, because | ||
| 3040 | FindFirst opens the directory that is the target of a | ||
| 3041 | symlink. */ | ||
| 3042 | if (w32_unicode_filenames) | ||
| 3033 | { | 3043 | { |
| 3034 | if (!IS_DIRECTORY_SEP (filename[ln])) | 3044 | wchar_t fnw[MAX_PATH]; |
| 3035 | strcat (filename, "\\"); | 3045 | |
| 3046 | filename_to_utf16 (filename, fnw); | ||
| 3047 | dir_find_handle = FindFirstFileW (fnw, &dir_find_data_w); | ||
| 3036 | } | 3048 | } |
| 3037 | else | 3049 | else |
| 3038 | { | 3050 | { |
| 3039 | char *end = filename + ln + 1; | 3051 | char fna[MAX_PATH]; |
| 3040 | char *last_char = CharPrevExA (file_name_codepage, filename, end, 0); | ||
| 3041 | 3052 | ||
| 3042 | if (!IS_DIRECTORY_SEP (*last_char)) | 3053 | filename_to_ansi (filename, fna); |
| 3043 | strcat (filename, "\\"); | 3054 | dir_find_handle = FindFirstFileA (fna, &dir_find_data_a); |
| 3044 | } | 3055 | } |
| 3045 | strcat (filename, "*"); | ||
| 3046 | |||
| 3047 | /* Note: No need to resolve symlinks in FILENAME, because | ||
| 3048 | FindFirst opens the directory that is the target of a | ||
| 3049 | symlink. */ | ||
| 3050 | dir_find_handle = FindFirstFile (filename, &dir_find_data); | ||
| 3051 | 3056 | ||
| 3052 | if (dir_find_handle == INVALID_HANDLE_VALUE) | 3057 | if (dir_find_handle == INVALID_HANDLE_VALUE) |
| 3053 | return NULL; | 3058 | return NULL; |
| 3054 | } | 3059 | } |
| 3060 | else if (w32_unicode_filenames) | ||
| 3061 | { | ||
| 3062 | if (!FindNextFileW (dir_find_handle, &dir_find_data_w)) | ||
| 3063 | return NULL; | ||
| 3064 | } | ||
| 3055 | else | 3065 | else |
| 3056 | { | 3066 | { |
| 3057 | if (!FindNextFile (dir_find_handle, &dir_find_data)) | 3067 | if (!FindNextFileA (dir_find_handle, &dir_find_data_a)) |
| 3058 | return NULL; | 3068 | return NULL; |
| 3059 | } | 3069 | } |
| 3060 | 3070 | ||
| @@ -3062,112 +3072,153 @@ readdir (DIR *dirp) | |||
| 3062 | value returned by stat(). */ | 3072 | value returned by stat(). */ |
| 3063 | dir_static.d_ino = 1; | 3073 | dir_static.d_ino = 1; |
| 3064 | 3074 | ||
| 3065 | strcpy (dir_static.d_name, dir_find_data.cFileName); | 3075 | if (w32_unicode_filenames) |
| 3066 | |||
| 3067 | /* If the file name in cFileName[] includes `?' characters, it means | ||
| 3068 | the original file name used characters that cannot be represented | ||
| 3069 | by the current ANSI codepage. To avoid total lossage, retrieve | ||
| 3070 | the short 8+3 alias of the long file name. */ | ||
| 3071 | if (_mbspbrk (dir_static.d_name, "?")) | ||
| 3072 | { | 3076 | { |
| 3073 | strcpy (dir_static.d_name, dir_find_data.cAlternateFileName); | 3077 | if (downcase || dir_is_fat) |
| 3074 | downcase = 1; /* 8+3 aliases are returned in all caps */ | 3078 | { |
| 3075 | } | 3079 | wchar_t tem[MAX_PATH]; |
| 3076 | dir_static.d_namlen = strlen (dir_static.d_name); | ||
| 3077 | dir_static.d_reclen = sizeof (struct dirent) - MAXNAMLEN + 3 + | ||
| 3078 | dir_static.d_namlen - dir_static.d_namlen % 4; | ||
| 3079 | 3080 | ||
| 3080 | /* If the file name in cFileName[] includes `?' characters, it means | 3081 | wcscpy (tem, dir_find_data_w.cFileName); |
| 3081 | the original file name used characters that cannot be represented | 3082 | CharLowerW (tem); |
| 3082 | by the current ANSI codepage. To avoid total lossage, retrieve | 3083 | filename_from_utf16 (tem, dir_static.d_name); |
| 3083 | the short 8+3 alias of the long file name. */ | 3084 | } |
| 3084 | if (_mbspbrk (dir_find_data.cFileName, "?")) | 3085 | else |
| 3085 | { | 3086 | filename_from_utf16 (dir_find_data_w.cFileName, dir_static.d_name); |
| 3086 | strcpy (dir_static.d_name, dir_find_data.cAlternateFileName); | ||
| 3087 | /* 8+3 aliases are returned in all caps, which could break | ||
| 3088 | various alists that look at filenames' extensions. */ | ||
| 3089 | downcase = 1; | ||
| 3090 | } | 3087 | } |
| 3091 | else | 3088 | else |
| 3092 | strcpy (dir_static.d_name, dir_find_data.cFileName); | ||
| 3093 | dir_static.d_namlen = strlen (dir_static.d_name); | ||
| 3094 | if (dir_is_fat) | ||
| 3095 | _mbslwr (dir_static.d_name); | ||
| 3096 | else if (downcase) | ||
| 3097 | { | 3089 | { |
| 3098 | register char *p; | 3090 | char tem[MAX_PATH]; |
| 3099 | int dbcs_p = max_filename_mbslen () > 1; | 3091 | |
| 3100 | for (p = dir_static.d_name; *p; ) | 3092 | /* If the file name in cFileName[] includes `?' characters, it |
| 3093 | means the original file name used characters that cannot be | ||
| 3094 | represented by the current ANSI codepage. To avoid total | ||
| 3095 | lossage, retrieve the short 8+3 alias of the long file | ||
| 3096 | name. */ | ||
| 3097 | if (_mbspbrk (dir_find_data_a.cFileName, "?")) | ||
| 3101 | { | 3098 | { |
| 3102 | if (*p >= 'a' && *p <= 'z') | 3099 | strcpy (tem, dir_find_data_a.cAlternateFileName); |
| 3103 | break; | 3100 | /* 8+3 aliases are returned in all caps, which could break |
| 3104 | if (dbcs_p) | 3101 | various alists that look at filenames' extensions. */ |
| 3105 | p = CharNextExA (file_name_codepage, p, 0); | 3102 | downcase = 1; |
| 3106 | else | 3103 | } |
| 3107 | p++; | 3104 | else if (downcase || dir_is_fat) |
| 3105 | strcpy (tem, dir_find_data_a.cFileName); | ||
| 3106 | else | ||
| 3107 | filename_from_ansi (dir_find_data_a.cFileName, dir_static.d_name); | ||
| 3108 | if (downcase || dir_is_fat) | ||
| 3109 | { | ||
| 3110 | _mbslwr (tem); | ||
| 3111 | filename_from_ansi (tem, dir_static.d_name); | ||
| 3108 | } | 3112 | } |
| 3109 | if (!*p) | ||
| 3110 | _mbslwr (dir_static.d_name); | ||
| 3111 | } | 3113 | } |
| 3112 | 3114 | ||
| 3115 | dir_static.d_namlen = strlen (dir_static.d_name); | ||
| 3116 | dir_static.d_reclen = sizeof (struct dirent) - MAX_UTF8_PATH + 3 + | ||
| 3117 | dir_static.d_namlen - dir_static.d_namlen % 4; | ||
| 3118 | |||
| 3113 | return &dir_static; | 3119 | return &dir_static; |
| 3114 | } | 3120 | } |
| 3115 | 3121 | ||
| 3116 | static HANDLE | 3122 | static HANDLE |
| 3117 | open_unc_volume (const char *path) | 3123 | open_unc_volume (const char *path) |
| 3118 | { | 3124 | { |
| 3119 | NETRESOURCE nr; | 3125 | const char *fn = map_w32_filename (path, NULL); |
| 3126 | DWORD result; | ||
| 3120 | HANDLE henum; | 3127 | HANDLE henum; |
| 3121 | int result; | ||
| 3122 | 3128 | ||
| 3123 | nr.dwScope = RESOURCE_GLOBALNET; | 3129 | if (w32_unicode_filenames) |
| 3124 | nr.dwType = RESOURCETYPE_DISK; | 3130 | { |
| 3125 | nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER; | 3131 | NETRESOURCEW nrw; |
| 3126 | nr.dwUsage = RESOURCEUSAGE_CONTAINER; | 3132 | wchar_t fnw[MAX_PATH]; |
| 3127 | nr.lpLocalName = NULL; | ||
| 3128 | nr.lpRemoteName = (LPSTR)map_w32_filename (path, NULL); | ||
| 3129 | nr.lpComment = NULL; | ||
| 3130 | nr.lpProvider = NULL; | ||
| 3131 | 3133 | ||
| 3132 | result = WNetOpenEnum (RESOURCE_GLOBALNET, RESOURCETYPE_DISK, | 3134 | nrw.dwScope = RESOURCE_GLOBALNET; |
| 3133 | RESOURCEUSAGE_CONNECTABLE, &nr, &henum); | 3135 | nrw.dwType = RESOURCETYPE_DISK; |
| 3136 | nrw.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER; | ||
| 3137 | nrw.dwUsage = RESOURCEUSAGE_CONTAINER; | ||
| 3138 | nrw.lpLocalName = NULL; | ||
| 3139 | filename_to_utf16 (fn, fnw); | ||
| 3140 | nrw.lpRemoteName = fnw; | ||
| 3141 | nrw.lpComment = NULL; | ||
| 3142 | nrw.lpProvider = NULL; | ||
| 3134 | 3143 | ||
| 3144 | result = WNetOpenEnumW (RESOURCE_GLOBALNET, RESOURCETYPE_DISK, | ||
| 3145 | RESOURCEUSAGE_CONNECTABLE, &nrw, &henum); | ||
| 3146 | } | ||
| 3147 | else | ||
| 3148 | { | ||
| 3149 | NETRESOURCEA nra; | ||
| 3150 | char fna[MAX_PATH]; | ||
| 3151 | |||
| 3152 | nra.dwScope = RESOURCE_GLOBALNET; | ||
| 3153 | nra.dwType = RESOURCETYPE_DISK; | ||
| 3154 | nra.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER; | ||
| 3155 | nra.dwUsage = RESOURCEUSAGE_CONTAINER; | ||
| 3156 | nra.lpLocalName = NULL; | ||
| 3157 | filename_to_ansi (fn, fna); | ||
| 3158 | nra.lpRemoteName = fna; | ||
| 3159 | nra.lpComment = NULL; | ||
| 3160 | nra.lpProvider = NULL; | ||
| 3161 | |||
| 3162 | result = WNetOpenEnumA (RESOURCE_GLOBALNET, RESOURCETYPE_DISK, | ||
| 3163 | RESOURCEUSAGE_CONNECTABLE, &nra, &henum); | ||
| 3164 | } | ||
| 3135 | if (result == NO_ERROR) | 3165 | if (result == NO_ERROR) |
| 3136 | return henum; | 3166 | return henum; |
| 3137 | else | 3167 | else |
| 3138 | return INVALID_HANDLE_VALUE; | 3168 | return INVALID_HANDLE_VALUE; |
| 3139 | } | 3169 | } |
| 3140 | 3170 | ||
| 3141 | static char * | 3171 | static void * |
| 3142 | read_unc_volume (HANDLE henum, char *readbuf, int size) | 3172 | read_unc_volume (HANDLE henum, wchar_t *fname_w, char *fname_a, int size) |
| 3143 | { | 3173 | { |
| 3144 | DWORD count; | 3174 | DWORD count; |
| 3145 | int result; | 3175 | int result; |
| 3146 | DWORD bufsize = 512; | ||
| 3147 | char *buffer; | 3176 | char *buffer; |
| 3148 | char *ptr; | 3177 | DWORD bufsize = 512; |
| 3149 | int dbcs_p = max_filename_mbslen () > 1; | 3178 | void *retval; |
| 3150 | 3179 | ||
| 3151 | count = 1; | 3180 | count = 1; |
| 3152 | buffer = alloca (bufsize); | 3181 | if (w32_unicode_filenames) |
| 3153 | result = WNetEnumResource (henum, &count, buffer, &bufsize); | 3182 | { |
| 3154 | if (result != NO_ERROR) | 3183 | wchar_t *ptrw; |
| 3155 | return NULL; | ||
| 3156 | 3184 | ||
| 3157 | /* WNetEnumResource returns \\resource\share...skip forward to "share". */ | 3185 | bufsize *= 2; |
| 3158 | ptr = ((LPNETRESOURCE) buffer)->lpRemoteName; | 3186 | buffer = alloca (bufsize); |
| 3159 | ptr += 2; | 3187 | result = WNetEnumResourceW (henum, &count, buffer, &bufsize); |
| 3160 | if (!dbcs_p) | 3188 | if (result != NO_ERROR) |
| 3161 | while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++; | 3189 | return NULL; |
| 3190 | /* WNetEnumResource returns \\resource\share...skip forward to "share". */ | ||
| 3191 | ptrw = ((LPNETRESOURCEW) buffer)->lpRemoteName; | ||
| 3192 | ptrw += 2; | ||
| 3193 | while (*ptrw && *ptrw != L'/' && *ptrw != L'\\') ptrw++; | ||
| 3194 | ptrw++; | ||
| 3195 | wcsncpy (fname_w, ptrw, size); | ||
| 3196 | retval = fname_w; | ||
| 3197 | } | ||
| 3162 | else | 3198 | else |
| 3163 | { | 3199 | { |
| 3164 | while (*ptr && !IS_DIRECTORY_SEP (*ptr)) | 3200 | int dbcs_p = max_filename_mbslen () > 1; |
| 3165 | ptr = CharNextExA (file_name_codepage, ptr, 0); | 3201 | char *ptra; |
| 3202 | |||
| 3203 | buffer = alloca (bufsize); | ||
| 3204 | result = WNetEnumResourceA (henum, &count, buffer, &bufsize); | ||
| 3205 | if (result != NO_ERROR) | ||
| 3206 | return NULL; | ||
| 3207 | ptra = ((LPNETRESOURCEA) buffer)->lpRemoteName; | ||
| 3208 | ptra += 2; | ||
| 3209 | if (!dbcs_p) | ||
| 3210 | while (*ptra && !IS_DIRECTORY_SEP (*ptra)) ptra++; | ||
| 3211 | else | ||
| 3212 | { | ||
| 3213 | while (*ptra && !IS_DIRECTORY_SEP (*ptra)) | ||
| 3214 | ptra = CharNextExA (file_name_codepage, ptra, 0); | ||
| 3215 | } | ||
| 3216 | ptra++; | ||
| 3217 | strncpy (fname_a, ptra, size); | ||
| 3218 | retval = fname_a; | ||
| 3166 | } | 3219 | } |
| 3167 | ptr++; | ||
| 3168 | 3220 | ||
| 3169 | strncpy (readbuf, ptr, size); | 3221 | return retval; |
| 3170 | return readbuf; | ||
| 3171 | } | 3222 | } |
| 3172 | 3223 | ||
| 3173 | static void | 3224 | static void |
| @@ -3198,13 +3249,12 @@ unc_volume_file_attributes (const char *path) | |||
| 3198 | static void | 3249 | static void |
| 3199 | logon_network_drive (const char *path) | 3250 | logon_network_drive (const char *path) |
| 3200 | { | 3251 | { |
| 3201 | NETRESOURCE resource; | 3252 | char share[MAX_UTF8_PATH]; |
| 3202 | char share[MAX_PATH]; | ||
| 3203 | int n_slashes; | 3253 | int n_slashes; |
| 3204 | char drive[4]; | 3254 | char drive[4]; |
| 3205 | UINT drvtype; | 3255 | UINT drvtype; |
| 3206 | char *p; | 3256 | char *p; |
| 3207 | int dbcs_p; | 3257 | DWORD val; |
| 3208 | 3258 | ||
| 3209 | if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1])) | 3259 | if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1])) |
| 3210 | drvtype = DRIVE_REMOTE; | 3260 | drvtype = DRIVE_REMOTE; |
| @@ -3224,28 +3274,70 @@ logon_network_drive (const char *path) | |||
| 3224 | return; | 3274 | return; |
| 3225 | 3275 | ||
| 3226 | n_slashes = 2; | 3276 | n_slashes = 2; |
| 3227 | strncpy (share, path, MAX_PATH); | 3277 | strncpy (share, path, MAX_UTF8_PATH); |
| 3228 | /* Truncate to just server and share name. */ | 3278 | /* Truncate to just server and share name. */ |
| 3229 | dbcs_p = max_filename_mbslen () > 1; | 3279 | for (p = share + 2; *p && p < share + MAX_UTF8_PATH; p++) |
| 3230 | for (p = share + 2; *p && p < share + MAX_PATH; ) | ||
| 3231 | { | 3280 | { |
| 3232 | if (IS_DIRECTORY_SEP (*p) && ++n_slashes > 3) | 3281 | if (IS_DIRECTORY_SEP (*p) && ++n_slashes > 3) |
| 3233 | { | 3282 | { |
| 3234 | *p = '\0'; | 3283 | *p = '\0'; |
| 3235 | break; | 3284 | break; |
| 3236 | } | 3285 | } |
| 3237 | if (dbcs_p) | ||
| 3238 | p = CharNextExA (file_name_codepage, p, 0); | ||
| 3239 | else | ||
| 3240 | p++; | ||
| 3241 | } | 3286 | } |
| 3242 | 3287 | ||
| 3243 | resource.dwType = RESOURCETYPE_DISK; | 3288 | if (w32_unicode_filenames) |
| 3244 | resource.lpLocalName = NULL; | 3289 | { |
| 3245 | resource.lpRemoteName = share; | 3290 | NETRESOURCEW resourcew; |
| 3246 | resource.lpProvider = NULL; | 3291 | wchar_t share_w[MAX_PATH]; |
| 3292 | |||
| 3293 | resourcew.dwScope = RESOURCE_GLOBALNET; | ||
| 3294 | resourcew.dwType = RESOURCETYPE_DISK; | ||
| 3295 | resourcew.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; | ||
| 3296 | resourcew.dwUsage = RESOURCEUSAGE_CONTAINER; | ||
| 3297 | resourcew.lpLocalName = NULL; | ||
| 3298 | filename_to_utf16 (share, share_w); | ||
| 3299 | resourcew.lpRemoteName = share_w; | ||
| 3300 | resourcew.lpProvider = NULL; | ||
| 3247 | 3301 | ||
| 3248 | WNetAddConnection2 (&resource, NULL, NULL, CONNECT_INTERACTIVE); | 3302 | val = WNetAddConnection2W (&resourcew, NULL, NULL, CONNECT_INTERACTIVE); |
| 3303 | } | ||
| 3304 | else | ||
| 3305 | { | ||
| 3306 | NETRESOURCEA resourcea; | ||
| 3307 | char share_a[MAX_PATH]; | ||
| 3308 | |||
| 3309 | resourcea.dwScope = RESOURCE_GLOBALNET; | ||
| 3310 | resourcea.dwType = RESOURCETYPE_DISK; | ||
| 3311 | resourcea.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE; | ||
| 3312 | resourcea.dwUsage = RESOURCEUSAGE_CONTAINER; | ||
| 3313 | resourcea.lpLocalName = NULL; | ||
| 3314 | filename_to_ansi (share, share_a); | ||
| 3315 | resourcea.lpRemoteName = share_a; | ||
| 3316 | resourcea.lpProvider = NULL; | ||
| 3317 | |||
| 3318 | val = WNetAddConnection2A (&resourcea, NULL, NULL, CONNECT_INTERACTIVE); | ||
| 3319 | } | ||
| 3320 | |||
| 3321 | switch (val) | ||
| 3322 | { | ||
| 3323 | case NO_ERROR: | ||
| 3324 | case ERROR_ALREADY_ASSIGNED: | ||
| 3325 | break; | ||
| 3326 | case ERROR_ACCESS_DENIED: | ||
| 3327 | case ERROR_LOGON_FAILURE: | ||
| 3328 | errno = EACCES; | ||
| 3329 | break; | ||
| 3330 | case ERROR_BUSY: | ||
| 3331 | errno = EAGAIN; | ||
| 3332 | break; | ||
| 3333 | case ERROR_BAD_NET_NAME: | ||
| 3334 | case ERROR_NO_NET_OR_BAD_PATH: | ||
| 3335 | case ERROR_NO_NETWORK: | ||
| 3336 | case ERROR_CANCELLED: | ||
| 3337 | default: | ||
| 3338 | errno = ENOENT; | ||
| 3339 | break; | ||
| 3340 | } | ||
| 3249 | } | 3341 | } |
| 3250 | 3342 | ||
| 3251 | /* Emulate faccessat(2). */ | 3343 | /* Emulate faccessat(2). */ |
| @@ -4338,7 +4430,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) | |||
| 4338 | && xstrcasecmp (name + len + 1, dir_static.d_name) == 0) | 4430 | && xstrcasecmp (name + len + 1, dir_static.d_name) == 0) |
| 4339 | { | 4431 | { |
| 4340 | /* This was the last entry returned by readdir. */ | 4432 | /* This was the last entry returned by readdir. */ |
| 4341 | wfd = dir_find_data; | 4433 | wfd = dir_find_data_a; /* FIXME!!! */ |
| 4342 | } | 4434 | } |
| 4343 | else | 4435 | else |
| 4344 | { | 4436 | { |