diff options
| author | Eli Zaretskii | 2013-11-18 16:29:23 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2013-11-18 16:29:23 +0200 |
| commit | df87c56cdf6c8c13e8760bdc409e2eb0fda55b0b (patch) | |
| tree | 10f9b84fd94176efcc53bfa72f2a9379a60e2357 /src | |
| parent | a868f601ebc7b6e81a55b5869fa6c0ab74bde633 (diff) | |
| download | emacs-df87c56cdf6c8c13e8760bdc409e2eb0fda55b0b.tar.gz emacs-df87c56cdf6c8c13e8760bdc409e2eb0fda55b0b.zip | |
Converted and tested stat and fstatat.
Diffstat (limited to 'src')
| -rw-r--r-- | src/dired.c | 4 | ||||
| -rw-r--r-- | src/w32.c | 265 |
2 files changed, 166 insertions, 103 deletions
diff --git a/src/dired.c b/src/dired.c index 1bdb171c4d0..9520104dbc1 100644 --- a/src/dired.c +++ b/src/dired.c | |||
| @@ -958,11 +958,11 @@ file_attributes (int fd, char const *name, Lisp_Object id_format) | |||
| 958 | unblock_input (); | 958 | unblock_input (); |
| 959 | } | 959 | } |
| 960 | if (uname) | 960 | if (uname) |
| 961 | values[2] = DECODE_SYSTEM (build_string (uname)); | 961 | values[2] = DECODE_SYSTEM (build_unibyte_string (uname)); |
| 962 | else | 962 | else |
| 963 | values[2] = make_fixnum_or_float (s.st_uid); | 963 | values[2] = make_fixnum_or_float (s.st_uid); |
| 964 | if (gname) | 964 | if (gname) |
| 965 | values[3] = DECODE_SYSTEM (build_string (gname)); | 965 | values[3] = DECODE_SYSTEM (build_unibyte_string (gname)); |
| 966 | else | 966 | else |
| 967 | values[3] = make_fixnum_or_float (s.st_gid); | 967 | values[3] = make_fixnum_or_float (s.st_gid); |
| 968 | 968 | ||
| @@ -273,7 +273,8 @@ static BOOL g_b_init_lookup_account_sid; | |||
| 273 | static BOOL g_b_init_get_sid_sub_authority; | 273 | static BOOL g_b_init_get_sid_sub_authority; |
| 274 | static BOOL g_b_init_get_sid_sub_authority_count; | 274 | static BOOL g_b_init_get_sid_sub_authority_count; |
| 275 | static BOOL g_b_init_get_security_info; | 275 | static BOOL g_b_init_get_security_info; |
| 276 | static BOOL g_b_init_get_file_security; | 276 | static BOOL g_b_init_get_file_security_w; |
| 277 | static BOOL g_b_init_get_file_security_a; | ||
| 277 | static BOOL g_b_init_get_security_descriptor_owner; | 278 | static BOOL g_b_init_get_security_descriptor_owner; |
| 278 | static BOOL g_b_init_get_security_descriptor_group; | 279 | static BOOL g_b_init_get_security_descriptor_group; |
| 279 | static BOOL g_b_init_is_valid_sid; | 280 | static BOOL g_b_init_is_valid_sid; |
| @@ -327,12 +328,8 @@ GetProcessTimes_Proc get_process_times_fn = NULL; | |||
| 327 | 328 | ||
| 328 | #ifdef _UNICODE | 329 | #ifdef _UNICODE |
| 329 | const char * const LookupAccountSid_Name = "LookupAccountSidW"; | 330 | const char * const LookupAccountSid_Name = "LookupAccountSidW"; |
| 330 | const char * const GetFileSecurity_Name = "GetFileSecurityW"; | ||
| 331 | const char * const SetFileSecurity_Name = "SetFileSecurityW"; | ||
| 332 | #else | 331 | #else |
| 333 | const char * const LookupAccountSid_Name = "LookupAccountSidA"; | 332 | const char * const LookupAccountSid_Name = "LookupAccountSidA"; |
| 334 | const char * const GetFileSecurity_Name = "GetFileSecurityA"; | ||
| 335 | const char * const SetFileSecurity_Name = "SetFileSecurityA"; | ||
| 336 | #endif | 333 | #endif |
| 337 | typedef BOOL (WINAPI * LookupAccountSid_Proc) ( | 334 | typedef BOOL (WINAPI * LookupAccountSid_Proc) ( |
| 338 | LPCTSTR lpSystemName, | 335 | LPCTSTR lpSystemName, |
| @@ -356,8 +353,14 @@ typedef DWORD (WINAPI * GetSecurityInfo_Proc) ( | |||
| 356 | PACL *ppDacl, | 353 | PACL *ppDacl, |
| 357 | PACL *ppSacl, | 354 | PACL *ppSacl, |
| 358 | PSECURITY_DESCRIPTOR *ppSecurityDescriptor); | 355 | PSECURITY_DESCRIPTOR *ppSecurityDescriptor); |
| 359 | typedef BOOL (WINAPI * GetFileSecurity_Proc) ( | 356 | typedef BOOL (WINAPI * GetFileSecurityW_Proc) ( |
| 360 | LPCTSTR lpFileName, | 357 | LPCWSTR lpFileName, |
| 358 | SECURITY_INFORMATION RequestedInformation, | ||
| 359 | PSECURITY_DESCRIPTOR pSecurityDescriptor, | ||
| 360 | DWORD nLength, | ||
| 361 | LPDWORD lpnLengthNeeded); | ||
| 362 | typedef BOOL (WINAPI * GetFileSecurityA_Proc) ( | ||
| 363 | LPCSTR lpFileName, | ||
| 361 | SECURITY_INFORMATION RequestedInformation, | 364 | SECURITY_INFORMATION RequestedInformation, |
| 362 | PSECURITY_DESCRIPTOR pSecurityDescriptor, | 365 | PSECURITY_DESCRIPTOR pSecurityDescriptor, |
| 363 | DWORD nLength, | 366 | DWORD nLength, |
| @@ -678,36 +681,68 @@ get_security_info (HANDLE handle, | |||
| 678 | ppSecurityDescriptor)); | 681 | ppSecurityDescriptor)); |
| 679 | } | 682 | } |
| 680 | 683 | ||
| 684 | static int filename_to_ansi (const char *, char *); | ||
| 685 | static int filename_to_utf16 (const char *, wchar_t *); | ||
| 686 | |||
| 681 | static BOOL WINAPI | 687 | static BOOL WINAPI |
| 682 | get_file_security (LPCTSTR lpFileName, | 688 | get_file_security (const char *lpFileName, |
| 683 | SECURITY_INFORMATION RequestedInformation, | 689 | SECURITY_INFORMATION RequestedInformation, |
| 684 | PSECURITY_DESCRIPTOR pSecurityDescriptor, | 690 | PSECURITY_DESCRIPTOR pSecurityDescriptor, |
| 685 | DWORD nLength, | 691 | DWORD nLength, |
| 686 | LPDWORD lpnLengthNeeded) | 692 | LPDWORD lpnLengthNeeded) |
| 687 | { | 693 | { |
| 688 | static GetFileSecurity_Proc s_pfn_Get_File_Security = NULL; | 694 | static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA = NULL; |
| 695 | static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW = NULL; | ||
| 689 | HMODULE hm_advapi32 = NULL; | 696 | HMODULE hm_advapi32 = NULL; |
| 690 | if (is_windows_9x () == TRUE) | 697 | if (is_windows_9x () == TRUE) |
| 691 | { | 698 | { |
| 692 | errno = ENOTSUP; | 699 | errno = ENOTSUP; |
| 693 | return FALSE; | 700 | return FALSE; |
| 694 | } | 701 | } |
| 695 | if (g_b_init_get_file_security == 0) | 702 | if (w32_unicode_filenames) |
| 696 | { | 703 | { |
| 697 | g_b_init_get_file_security = 1; | 704 | wchar_t filename_w[MAX_PATH]; |
| 698 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | 705 | |
| 699 | s_pfn_Get_File_Security = | 706 | if (g_b_init_get_file_security_w == 0) |
| 700 | (GetFileSecurity_Proc) GetProcAddress ( | 707 | { |
| 701 | hm_advapi32, GetFileSecurity_Name); | 708 | g_b_init_get_file_security_w = 1; |
| 709 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | ||
| 710 | s_pfn_Get_File_SecurityW = | ||
| 711 | (GetFileSecurityW_Proc) GetProcAddress (hm_advapi32, | ||
| 712 | "GetFileSecurityW"); | ||
| 713 | } | ||
| 714 | if (s_pfn_Get_File_SecurityW == NULL) | ||
| 715 | { | ||
| 716 | errno = ENOTSUP; | ||
| 717 | return FALSE; | ||
| 718 | } | ||
| 719 | filename_to_utf16 (lpFileName, filename_w); | ||
| 720 | return (s_pfn_Get_File_SecurityW (filename_w, RequestedInformation, | ||
| 721 | pSecurityDescriptor, nLength, | ||
| 722 | lpnLengthNeeded)); | ||
| 702 | } | 723 | } |
| 703 | if (s_pfn_Get_File_Security == NULL) | 724 | else |
| 704 | { | 725 | { |
| 705 | errno = ENOTSUP; | 726 | char filename_a[MAX_PATH]; |
| 706 | return FALSE; | 727 | |
| 728 | if (g_b_init_get_file_security_a == 0) | ||
| 729 | { | ||
| 730 | g_b_init_get_file_security_a = 1; | ||
| 731 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | ||
| 732 | s_pfn_Get_File_SecurityA = | ||
| 733 | (GetFileSecurityA_Proc) GetProcAddress (hm_advapi32, | ||
| 734 | "GetFileSecurityA"); | ||
| 735 | } | ||
| 736 | if (s_pfn_Get_File_SecurityA == NULL) | ||
| 737 | { | ||
| 738 | errno = ENOTSUP; | ||
| 739 | return FALSE; | ||
| 740 | } | ||
| 741 | filename_to_ansi (lpFileName, filename_a); | ||
| 742 | return (s_pfn_Get_File_SecurityA (filename_a, RequestedInformation, | ||
| 743 | pSecurityDescriptor, nLength, | ||
| 744 | lpnLengthNeeded)); | ||
| 707 | } | 745 | } |
| 708 | return (s_pfn_Get_File_Security (lpFileName, RequestedInformation, | ||
| 709 | pSecurityDescriptor, nLength, | ||
| 710 | lpnLengthNeeded)); | ||
| 711 | } | 746 | } |
| 712 | 747 | ||
| 713 | static BOOL WINAPI | 748 | static BOOL WINAPI |
| @@ -728,7 +763,7 @@ set_file_security (LPCTSTR lpFileName, | |||
| 728 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | 763 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); |
| 729 | s_pfn_Set_File_Security = | 764 | s_pfn_Set_File_Security = |
| 730 | (SetFileSecurity_Proc) GetProcAddress ( | 765 | (SetFileSecurity_Proc) GetProcAddress ( |
| 731 | hm_advapi32, SetFileSecurity_Name); | 766 | hm_advapi32, "SetFileSecurityA"); |
| 732 | } | 767 | } |
| 733 | if (s_pfn_Set_File_Security == NULL) | 768 | if (s_pfn_Set_File_Security == NULL) |
| 734 | { | 769 | { |
| @@ -2946,6 +2981,9 @@ static int dir_is_fat; | |||
| 2946 | static char dir_pathname[MAX_UTF8_PATH]; | 2981 | static char dir_pathname[MAX_UTF8_PATH]; |
| 2947 | static WIN32_FIND_DATAW dir_find_data_w; | 2982 | static WIN32_FIND_DATAW dir_find_data_w; |
| 2948 | static WIN32_FIND_DATAA dir_find_data_a; | 2983 | static WIN32_FIND_DATAA dir_find_data_a; |
| 2984 | #define DIR_FIND_DATA_W 1 | ||
| 2985 | #define DIR_FIND_DATA_A 2 | ||
| 2986 | static int last_dir_find_data = -1; | ||
| 2949 | 2987 | ||
| 2950 | /* Support shares on a network resource as subdirectories of a read-only | 2988 | /* Support shares on a network resource as subdirectories of a read-only |
| 2951 | root directory. */ | 2989 | root directory. */ |
| @@ -3051,7 +3089,13 @@ sys_readdir (DIR *dirp) | |||
| 3051 | char fna[MAX_PATH]; | 3089 | char fna[MAX_PATH]; |
| 3052 | 3090 | ||
| 3053 | filename_to_ansi (filename, fna); | 3091 | filename_to_ansi (filename, fna); |
| 3054 | dir_find_handle = FindFirstFileA (fna, &dir_find_data_a); | 3092 | /* If FILENAME is not representable by the current ANSI |
| 3093 | codepage, we don't want FindFirstFileA to interpret the | ||
| 3094 | '?' characters as a wildcard. */ | ||
| 3095 | if (_mbspbrk (fna, "?")) | ||
| 3096 | dir_find_handle = INVALID_HANDLE_VALUE; | ||
| 3097 | else | ||
| 3098 | dir_find_handle = FindFirstFileA (fna, &dir_find_data_a); | ||
| 3055 | } | 3099 | } |
| 3056 | 3100 | ||
| 3057 | if (dir_find_handle == INVALID_HANDLE_VALUE) | 3101 | if (dir_find_handle == INVALID_HANDLE_VALUE) |
| @@ -3084,6 +3128,7 @@ sys_readdir (DIR *dirp) | |||
| 3084 | } | 3128 | } |
| 3085 | else | 3129 | else |
| 3086 | filename_from_utf16 (dir_find_data_w.cFileName, dir_static.d_name); | 3130 | filename_from_utf16 (dir_find_data_w.cFileName, dir_static.d_name); |
| 3131 | last_dir_find_data = DIR_FIND_DATA_W; | ||
| 3087 | } | 3132 | } |
| 3088 | else | 3133 | else |
| 3089 | { | 3134 | { |
| @@ -3110,6 +3155,7 @@ sys_readdir (DIR *dirp) | |||
| 3110 | _mbslwr (tem); | 3155 | _mbslwr (tem); |
| 3111 | filename_from_ansi (tem, dir_static.d_name); | 3156 | filename_from_ansi (tem, dir_static.d_name); |
| 3112 | } | 3157 | } |
| 3158 | last_dir_find_data = DIR_FIND_DATA_A; | ||
| 3113 | } | 3159 | } |
| 3114 | 3160 | ||
| 3115 | dir_static.d_namlen = strlen (dir_static.d_name); | 3161 | dir_static.d_namlen = strlen (dir_static.d_name); |
| @@ -4324,18 +4370,21 @@ is_slow_fs (const char *name) | |||
| 4324 | } | 4370 | } |
| 4325 | 4371 | ||
| 4326 | /* If this is non-zero, the caller wants accurate information about | 4372 | /* If this is non-zero, the caller wants accurate information about |
| 4327 | file's owner and group, which could be expensive to get. */ | 4373 | file's owner and group, which could be expensive to get. dired.c |
| 4374 | uses this flag when needed for the job at hand. */ | ||
| 4328 | int w32_stat_get_owner_group; | 4375 | int w32_stat_get_owner_group; |
| 4329 | 4376 | ||
| 4330 | /* MSVC stat function can't cope with UNC names and has other bugs, so | 4377 | /* MSVC stat function can't cope with UNC names and has other bugs, so |
| 4331 | replace it with our own. This also allows us to calculate consistent | 4378 | replace it with our own. This also allows us to calculate consistent |
| 4332 | inode values and owner/group without hacks in the main Emacs code. */ | 4379 | inode values and owner/group without hacks in the main Emacs code, |
| 4380 | and support file names encoded in UTF-8. */ | ||
| 4333 | 4381 | ||
| 4334 | static int | 4382 | static int |
| 4335 | stat_worker (const char * path, struct stat * buf, int follow_symlinks) | 4383 | stat_worker (const char * path, struct stat * buf, int follow_symlinks) |
| 4336 | { | 4384 | { |
| 4337 | char *name, *save_name, *r; | 4385 | char *name, *save_name, *r; |
| 4338 | WIN32_FIND_DATA wfd; | 4386 | WIN32_FIND_DATAW wfd_w; |
| 4387 | WIN32_FIND_DATAA wfd_a; | ||
| 4339 | HANDLE fh; | 4388 | HANDLE fh; |
| 4340 | unsigned __int64 fake_inode = 0; | 4389 | unsigned __int64 fake_inode = 0; |
| 4341 | int permission; | 4390 | int permission; |
| @@ -4347,7 +4396,8 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) | |||
| 4347 | DWORD access_rights = 0; | 4396 | DWORD access_rights = 0; |
| 4348 | DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1; | 4397 | DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1; |
| 4349 | FILETIME ctime, atime, wtime; | 4398 | FILETIME ctime, atime, wtime; |
| 4350 | int dbcs_p; | 4399 | wchar_t name_w[MAX_PATH]; |
| 4400 | char name_a[MAX_PATH]; | ||
| 4351 | 4401 | ||
| 4352 | if (path == NULL || buf == NULL) | 4402 | if (path == NULL || buf == NULL) |
| 4353 | { | 4403 | { |
| @@ -4357,11 +4407,8 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) | |||
| 4357 | 4407 | ||
| 4358 | save_name = name = (char *) map_w32_filename (path, &path); | 4408 | save_name = name = (char *) map_w32_filename (path, &path); |
| 4359 | /* Must be valid filename, no wild cards or other invalid | 4409 | /* Must be valid filename, no wild cards or other invalid |
| 4360 | characters. We use _mbspbrk to support multibyte strings that | 4410 | characters. */ |
| 4361 | might look to strpbrk as if they included literal *, ?, and other | 4411 | if (strpbrk (name, "*?|<>\"")) |
| 4362 | characters mentioned below that are disallowed by Windows | ||
| 4363 | filesystems. */ | ||
| 4364 | if (_mbspbrk (name, "*?|<>\"")) | ||
| 4365 | { | 4412 | { |
| 4366 | errno = ENOENT; | 4413 | errno = ENOENT; |
| 4367 | return -1; | 4414 | return -1; |
| @@ -4412,13 +4459,26 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) | |||
| 4412 | if (is_windows_9x () != TRUE) | 4459 | if (is_windows_9x () != TRUE) |
| 4413 | access_rights |= READ_CONTROL; | 4460 | access_rights |= READ_CONTROL; |
| 4414 | 4461 | ||
| 4415 | fh = CreateFile (name, access_rights, 0, NULL, OPEN_EXISTING, | 4462 | if (w32_unicode_filenames) |
| 4416 | file_flags, NULL); | 4463 | { |
| 4417 | /* If CreateFile fails with READ_CONTROL, try again with zero as | 4464 | filename_to_utf16 (name, name_w); |
| 4418 | access rights. */ | 4465 | fh = CreateFileW (name_w, access_rights, 0, NULL, OPEN_EXISTING, |
| 4419 | if (fh == INVALID_HANDLE_VALUE && access_rights) | 4466 | file_flags, NULL); |
| 4420 | fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING, | 4467 | /* If CreateFile fails with READ_CONTROL, try again with |
| 4421 | file_flags, NULL); | 4468 | zero as access rights. */ |
| 4469 | if (fh == INVALID_HANDLE_VALUE && access_rights) | ||
| 4470 | fh = CreateFileW (name_w, 0, 0, NULL, OPEN_EXISTING, | ||
| 4471 | file_flags, NULL); | ||
| 4472 | } | ||
| 4473 | else | ||
| 4474 | { | ||
| 4475 | filename_to_ansi (name, name_a); | ||
| 4476 | fh = CreateFileA (name_a, access_rights, 0, NULL, OPEN_EXISTING, | ||
| 4477 | file_flags, NULL); | ||
| 4478 | if (fh == INVALID_HANDLE_VALUE && access_rights) | ||
| 4479 | fh = CreateFileA (name_a, 0, 0, NULL, OPEN_EXISTING, | ||
| 4480 | file_flags, NULL); | ||
| 4481 | } | ||
| 4422 | if (fh == INVALID_HANDLE_VALUE) | 4482 | if (fh == INVALID_HANDLE_VALUE) |
| 4423 | goto no_true_file_attributes; | 4483 | goto no_true_file_attributes; |
| 4424 | 4484 | ||
| @@ -4545,7 +4605,6 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) | |||
| 4545 | did not ask for extra precision, resolving symlinks will fly | 4605 | did not ask for extra precision, resolving symlinks will fly |
| 4546 | in the face of that request, since the user then wants the | 4606 | in the face of that request, since the user then wants the |
| 4547 | lightweight version of the code. */ | 4607 | lightweight version of the code. */ |
| 4548 | dbcs_p = max_filename_mbslen () > 1; | ||
| 4549 | rootdir = (path >= save_name + len - 1 | 4608 | rootdir = (path >= save_name + len - 1 |
| 4550 | && (IS_DIRECTORY_SEP (*path) || *path == 0)); | 4609 | && (IS_DIRECTORY_SEP (*path) || *path == 0)); |
| 4551 | 4610 | ||
| @@ -4573,19 +4632,8 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) | |||
| 4573 | } | 4632 | } |
| 4574 | else if (rootdir) | 4633 | else if (rootdir) |
| 4575 | { | 4634 | { |
| 4576 | if (!dbcs_p) | 4635 | if (!IS_DIRECTORY_SEP (name[len-1])) |
| 4577 | { | 4636 | strcat (name, "\\"); |
| 4578 | if (!IS_DIRECTORY_SEP (name[len-1])) | ||
| 4579 | strcat (name, "\\"); | ||
| 4580 | } | ||
| 4581 | else | ||
| 4582 | { | ||
| 4583 | char *end = name + len; | ||
| 4584 | char *n = CharPrevExA (file_name_codepage, name, end, 0); | ||
| 4585 | |||
| 4586 | if (!IS_DIRECTORY_SEP (*n)) | ||
| 4587 | strcat (name, "\\"); | ||
| 4588 | } | ||
| 4589 | if (GetDriveType (name) < 2) | 4637 | if (GetDriveType (name) < 2) |
| 4590 | { | 4638 | { |
| 4591 | errno = ENOENT; | 4639 | errno = ENOENT; |
| @@ -4597,51 +4645,65 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) | |||
| 4597 | } | 4645 | } |
| 4598 | else | 4646 | else |
| 4599 | { | 4647 | { |
| 4600 | if (!dbcs_p) | 4648 | int have_wfd = -1; |
| 4601 | { | ||
| 4602 | if (IS_DIRECTORY_SEP (name[len-1])) | ||
| 4603 | name[len - 1] = 0; | ||
| 4604 | } | ||
| 4605 | else | ||
| 4606 | { | ||
| 4607 | char *end = name + len; | ||
| 4608 | char *n = CharPrevExA (file_name_codepage, name, end, 0); | ||
| 4609 | 4649 | ||
| 4610 | if (IS_DIRECTORY_SEP (*n)) | 4650 | if (IS_DIRECTORY_SEP (name[len-1])) |
| 4611 | *n = 0; | 4651 | name[len - 1] = 0; |
| 4612 | } | ||
| 4613 | 4652 | ||
| 4614 | /* (This is hacky, but helps when doing file completions on | 4653 | /* (This is hacky, but helps when doing file completions on |
| 4615 | network drives.) Optimize by using information available from | 4654 | network drives.) Optimize by using information available from |
| 4616 | active readdir if possible. */ | 4655 | active readdir if possible. */ |
| 4617 | len = strlen (dir_pathname); | 4656 | len = strlen (dir_pathname); |
| 4618 | if (!dbcs_p) | 4657 | if (IS_DIRECTORY_SEP (dir_pathname[len-1])) |
| 4619 | { | 4658 | len--; |
| 4620 | if (IS_DIRECTORY_SEP (dir_pathname[len-1])) | ||
| 4621 | len--; | ||
| 4622 | } | ||
| 4623 | else | ||
| 4624 | { | ||
| 4625 | char *end = dir_pathname + len; | ||
| 4626 | char *n = CharPrevExA (file_name_codepage, dir_pathname, end, 0); | ||
| 4627 | |||
| 4628 | if (IS_DIRECTORY_SEP (*n)) | ||
| 4629 | len--; | ||
| 4630 | } | ||
| 4631 | if (dir_find_handle != INVALID_HANDLE_VALUE | 4659 | if (dir_find_handle != INVALID_HANDLE_VALUE |
| 4660 | && last_dir_find_data != -1 | ||
| 4632 | && !(is_a_symlink && follow_symlinks) | 4661 | && !(is_a_symlink && follow_symlinks) |
| 4633 | && strnicmp (save_name, dir_pathname, len) == 0 | 4662 | /* The 2 file-name comparisons below support only ASCII |
| 4663 | characters, and will lose (compare not equal) when | ||
| 4664 | the file names include non-ASCII charcaters that are | ||
| 4665 | the same but for the case. However, doing this | ||
| 4666 | properly involves: (a) converting both file names to | ||
| 4667 | UTF-16, (b) lower-casing both names using CharLowerW, | ||
| 4668 | and (c) comparing the results; this would be quite a | ||
| 4669 | bit slower, whereas Plan B is for users who want | ||
| 4670 | lightweight albeit inaccurate version of 'stat'. */ | ||
| 4671 | && c_strncasecmp (save_name, dir_pathname, len) == 0 | ||
| 4634 | && IS_DIRECTORY_SEP (name[len]) | 4672 | && IS_DIRECTORY_SEP (name[len]) |
| 4635 | && xstrcasecmp (name + len + 1, dir_static.d_name) == 0) | 4673 | && xstrcasecmp (name + len + 1, dir_static.d_name) == 0) |
| 4636 | { | 4674 | { |
| 4675 | have_wfd = last_dir_find_data; | ||
| 4637 | /* This was the last entry returned by readdir. */ | 4676 | /* This was the last entry returned by readdir. */ |
| 4638 | wfd = dir_find_data_a; /* FIXME!!! */ | 4677 | if (last_dir_find_data == DIR_FIND_DATA_W) |
| 4678 | wfd_w = dir_find_data_w; | ||
| 4679 | else | ||
| 4680 | wfd_a = dir_find_data_a; | ||
| 4639 | } | 4681 | } |
| 4640 | else | 4682 | else |
| 4641 | { | 4683 | { |
| 4642 | logon_network_drive (name); | 4684 | logon_network_drive (name); |
| 4643 | 4685 | ||
| 4644 | fh = FindFirstFile (name, &wfd); | 4686 | if (w32_unicode_filenames) |
| 4687 | { | ||
| 4688 | filename_to_utf16 (name, name_w); | ||
| 4689 | fh = FindFirstFileW (name_w, &wfd_w); | ||
| 4690 | have_wfd = DIR_FIND_DATA_W; | ||
| 4691 | } | ||
| 4692 | else | ||
| 4693 | { | ||
| 4694 | filename_to_ansi (name, name_a); | ||
| 4695 | /* If NAME includes characters not representable by | ||
| 4696 | the current ANSI codepage, filename_to_ansi | ||
| 4697 | usually replaces them with a '?'. We don't want | ||
| 4698 | to let FindFirstFileA interpret those as widlcards, | ||
| 4699 | and "succeed", returning us data from some random | ||
| 4700 | file in the same directory. */ | ||
| 4701 | if (_mbspbrk (name_a, "?")) | ||
| 4702 | fh = INVALID_HANDLE_VALUE; | ||
| 4703 | else | ||
| 4704 | fh = FindFirstFileA (name_a, &wfd_a); | ||
| 4705 | have_wfd = DIR_FIND_DATA_A; | ||
| 4706 | } | ||
| 4645 | if (fh == INVALID_HANDLE_VALUE) | 4707 | if (fh == INVALID_HANDLE_VALUE) |
| 4646 | { | 4708 | { |
| 4647 | errno = ENOENT; | 4709 | errno = ENOENT; |
| @@ -4651,12 +4713,24 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) | |||
| 4651 | } | 4713 | } |
| 4652 | /* Note: if NAME is a symlink, the information we get from | 4714 | /* Note: if NAME is a symlink, the information we get from |
| 4653 | FindFirstFile is for the symlink, not its target. */ | 4715 | FindFirstFile is for the symlink, not its target. */ |
| 4654 | fattrs = wfd.dwFileAttributes; | 4716 | if (have_wfd == DIR_FIND_DATA_W) |
| 4655 | ctime = wfd.ftCreationTime; | 4717 | { |
| 4656 | atime = wfd.ftLastAccessTime; | 4718 | fattrs = wfd_w.dwFileAttributes; |
| 4657 | wtime = wfd.ftLastWriteTime; | 4719 | ctime = wfd_w.ftCreationTime; |
| 4658 | fs_high = wfd.nFileSizeHigh; | 4720 | atime = wfd_w.ftLastAccessTime; |
| 4659 | fs_low = wfd.nFileSizeLow; | 4721 | wtime = wfd_w.ftLastWriteTime; |
| 4722 | fs_high = wfd_w.nFileSizeHigh; | ||
| 4723 | fs_low = wfd_w.nFileSizeLow; | ||
| 4724 | } | ||
| 4725 | else | ||
| 4726 | { | ||
| 4727 | fattrs = wfd_a.dwFileAttributes; | ||
| 4728 | ctime = wfd_a.ftCreationTime; | ||
| 4729 | atime = wfd_a.ftLastAccessTime; | ||
| 4730 | wtime = wfd_a.ftLastWriteTime; | ||
| 4731 | fs_high = wfd_a.nFileSizeHigh; | ||
| 4732 | fs_low = wfd_a.nFileSizeLow; | ||
| 4733 | } | ||
| 4660 | fake_inode = 0; | 4734 | fake_inode = 0; |
| 4661 | nlinks = 1; | 4735 | nlinks = 1; |
| 4662 | serialnum = volume_info.serialnum; | 4736 | serialnum = volume_info.serialnum; |
| @@ -4671,18 +4745,6 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) | |||
| 4671 | get_file_owner_and_group (NULL, buf); | 4745 | get_file_owner_and_group (NULL, buf); |
| 4672 | } | 4746 | } |
| 4673 | 4747 | ||
| 4674 | #if 0 | ||
| 4675 | /* Not sure if there is any point in this. */ | ||
| 4676 | if (!NILP (Vw32_generate_fake_inodes)) | ||
| 4677 | fake_inode = generate_inode_val (name); | ||
| 4678 | else if (fake_inode == 0) | ||
| 4679 | { | ||
| 4680 | /* For want of something better, try to make everything unique. */ | ||
| 4681 | static DWORD gen_num = 0; | ||
| 4682 | fake_inode = ++gen_num; | ||
| 4683 | } | ||
| 4684 | #endif | ||
| 4685 | |||
| 4686 | buf->st_ino = fake_inode; | 4748 | buf->st_ino = fake_inode; |
| 4687 | 4749 | ||
| 4688 | buf->st_dev = serialnum; | 4750 | buf->st_dev = serialnum; |
| @@ -4741,7 +4803,7 @@ fstatat (int fd, char const *name, struct stat *st, int flags) | |||
| 4741 | 4803 | ||
| 4742 | FIXME: Add proper support for fdopendir, fstatat, readlinkat. | 4804 | FIXME: Add proper support for fdopendir, fstatat, readlinkat. |
| 4743 | Gnulib does this and can serve as a model. */ | 4805 | Gnulib does this and can serve as a model. */ |
| 4744 | char fullname[MAX_PATH]; | 4806 | char fullname[MAX_UTF8_PATH]; |
| 4745 | 4807 | ||
| 4746 | if (fd != AT_FDCWD) | 4808 | if (fd != AT_FDCWD) |
| 4747 | { | 4809 | { |
| @@ -8404,7 +8466,8 @@ globals_of_w32 (void) | |||
| 8404 | g_b_init_get_sid_sub_authority = 0; | 8466 | g_b_init_get_sid_sub_authority = 0; |
| 8405 | g_b_init_get_sid_sub_authority_count = 0; | 8467 | g_b_init_get_sid_sub_authority_count = 0; |
| 8406 | g_b_init_get_security_info = 0; | 8468 | g_b_init_get_security_info = 0; |
| 8407 | g_b_init_get_file_security = 0; | 8469 | g_b_init_get_file_security_w = 0; |
| 8470 | g_b_init_get_file_security_a = 0; | ||
| 8408 | g_b_init_get_security_descriptor_owner = 0; | 8471 | g_b_init_get_security_descriptor_owner = 0; |
| 8409 | g_b_init_get_security_descriptor_group = 0; | 8472 | g_b_init_get_security_descriptor_group = 0; |
| 8410 | g_b_init_is_valid_sid = 0; | 8473 | g_b_init_is_valid_sid = 0; |