diff options
| author | Eli Zaretskii | 2008-05-09 19:03:52 +0000 |
|---|---|---|
| committer | Eli Zaretskii | 2008-05-09 19:03:52 +0000 |
| commit | 8aaaec6b622da9620c85862a7cb717d4aee2276f (patch) | |
| tree | 36df47a50386d7c7843ec718252e5a7aeb28ec52 /src | |
| parent | 71e41ffb85e94bf77260acdb71eed141e6756a6f (diff) | |
| download | emacs-8aaaec6b622da9620c85862a7cb717d4aee2276f.tar.gz emacs-8aaaec6b622da9620c85862a7cb717d4aee2276f.zip | |
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 24 | ||||
| -rw-r--r-- | src/dired.c | 45 | ||||
| -rw-r--r-- | src/w32.c | 328 |
3 files changed, 353 insertions, 44 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 888b0f8b7c3..94c2dfc284e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,10 +1,34 @@ | |||
| 1 | 2008-05-09 Eli Zaretskii <eliz@gnu.org> | 1 | 2008-05-09 Eli Zaretskii <eliz@gnu.org> |
| 2 | 2 | ||
| 3 | Support for reporting owner and group of each file on MS-Windows: | ||
| 4 | * dired.c (stat_uname, stat_gname): New functions, with special | ||
| 5 | implementation for w32. | ||
| 6 | (Ffile_attributes): Use them instead of getpwuid and getgrgid. | ||
| 7 | |||
| 3 | * w32.c: Rename the_passwd_* to dflt_passwd_*. | 8 | * w32.c: Rename the_passwd_* to dflt_passwd_*. |
| 4 | (dflt_group_name): New static variable. | 9 | (dflt_group_name): New static variable. |
| 5 | (dflt_group): Renamed from the_group. | 10 | (dflt_group): Renamed from the_group. |
| 6 | (init_user_info): Init dflt_group fields. Get user's group name | 11 | (init_user_info): Init dflt_group fields. Get user's group name |
| 7 | from LookupAccountSid. | 12 | from LookupAccountSid. |
| 13 | (g_b_init_get_file_security, g_b_init_get_security_descriptor_owner) | ||
| 14 | (g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid): | ||
| 15 | New initialization states. | ||
| 16 | (globals_of_w32): Initialize them to zero. Initialize the default | ||
| 17 | group name to "None". | ||
| 18 | (GetFileSecurity_Name): New global var, the name of the function | ||
| 19 | to call for GetFileSecurity. | ||
| 20 | (GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc) | ||
| 21 | (GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs. | ||
| 22 | (get_file_security, get_security_descriptor_owner) | ||
| 23 | (get_security_descriptor_group, is_valid_sid) | ||
| 24 | (get_file_security_desc, get_rid, get_name_and_id) | ||
| 25 | (get_file_owner_and_group): New functions. | ||
| 26 | (stat): Use get_file_security_desc and get_file_owner_and_group to | ||
| 27 | report the owner and primary group of each file. Don't ignore the | ||
| 28 | high 32 bits of file's size, now that st_size is 64-bit wide. Fix | ||
| 29 | test when to get true file attributes. | ||
| 30 | (init_user_info): Use get_rid instead of equivalent inline code. | ||
| 31 | (fstat): Don't ignore the high 32 bits of file's size. | ||
| 8 | 32 | ||
| 9 | 2008-05-09 Chong Yidong <cyd@stupidchicken.com> | 33 | 2008-05-09 Chong Yidong <cyd@stupidchicken.com> |
| 10 | 34 | ||
diff --git a/src/dired.c b/src/dired.c index d3a6e7b7cec..7b4c9166545 100644 --- a/src/dired.c +++ b/src/dired.c | |||
| @@ -899,6 +899,36 @@ make_time (time) | |||
| 899 | Fcons (make_number (time & 0177777), Qnil)); | 899 | Fcons (make_number (time & 0177777), Qnil)); |
| 900 | } | 900 | } |
| 901 | 901 | ||
| 902 | static char * | ||
| 903 | stat_uname (struct stat *st) | ||
| 904 | { | ||
| 905 | #ifdef WINDOWSNT | ||
| 906 | return st->st_uname; | ||
| 907 | #else | ||
| 908 | struct passwd *pw = (struct passwd *) getpwuid (st->st_uid); | ||
| 909 | |||
| 910 | if (pw) | ||
| 911 | return pw->pw_name; | ||
| 912 | else | ||
| 913 | return NULL; | ||
| 914 | #endif | ||
| 915 | } | ||
| 916 | |||
| 917 | static char * | ||
| 918 | stat_gname (struct stat *st) | ||
| 919 | { | ||
| 920 | #ifdef WINDOWSNT | ||
| 921 | return st->st_gname; | ||
| 922 | #else | ||
| 923 | struct group *gr = (struct group *) getgrgid (st->st_gid); | ||
| 924 | |||
| 925 | if (gr) | ||
| 926 | return gr->gr_name; | ||
| 927 | else | ||
| 928 | return NULL; | ||
| 929 | #endif | ||
| 930 | } | ||
| 931 | |||
| 902 | DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 2, 0, | 932 | DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 2, 0, |
| 903 | doc: /* Return a list of attributes of file FILENAME. | 933 | doc: /* Return a list of attributes of file FILENAME. |
| 904 | Value is nil if specified file cannot be opened. | 934 | Value is nil if specified file cannot be opened. |
| @@ -935,8 +965,6 @@ Elements of the attribute list are: | |||
| 935 | Lisp_Object values[12]; | 965 | Lisp_Object values[12]; |
| 936 | Lisp_Object encoded; | 966 | Lisp_Object encoded; |
| 937 | struct stat s; | 967 | struct stat s; |
| 938 | struct passwd *pw; | ||
| 939 | struct group *gr; | ||
| 940 | #if defined (BSD4_2) || defined (BSD4_3) | 968 | #if defined (BSD4_2) || defined (BSD4_3) |
| 941 | Lisp_Object dirname; | 969 | Lisp_Object dirname; |
| 942 | struct stat sdir; | 970 | struct stat sdir; |
| @@ -945,6 +973,7 @@ Elements of the attribute list are: | |||
| 945 | Lisp_Object handler; | 973 | Lisp_Object handler; |
| 946 | struct gcpro gcpro1; | 974 | struct gcpro gcpro1; |
| 947 | EMACS_INT ino; | 975 | EMACS_INT ino; |
| 976 | char *uname, *gname; | ||
| 948 | 977 | ||
| 949 | filename = Fexpand_file_name (filename, Qnil); | 978 | filename = Fexpand_file_name (filename, Qnil); |
| 950 | 979 | ||
| @@ -987,12 +1016,12 @@ Elements of the attribute list are: | |||
| 987 | else | 1016 | else |
| 988 | { | 1017 | { |
| 989 | BLOCK_INPUT; | 1018 | BLOCK_INPUT; |
| 990 | pw = (struct passwd *) getpwuid (s.st_uid); | 1019 | uname = stat_uname (&s); |
| 991 | values[2] = (pw ? build_string (pw->pw_name) | 1020 | values[2] = (uname ? build_string (uname) |
| 992 | : make_fixnum_or_float (s.st_uid)); | 1021 | : make_fixnum_or_float (s.st_uid)); |
| 993 | gr = (struct group *) getgrgid (s.st_gid); | 1022 | gname = stat_gname (&s); |
| 994 | values[3] = (gr ? build_string (gr->gr_name) | 1023 | values[3] = (gname ? build_string (gname) |
| 995 | : make_fixnum_or_float (s.st_gid)); | 1024 | : make_fixnum_or_float (s.st_gid)); |
| 996 | UNBLOCK_INPUT; | 1025 | UNBLOCK_INPUT; |
| 997 | } | 1026 | } |
| 998 | values[4] = make_time (s.st_atime); | 1027 | values[4] = make_time (s.st_atime); |
| @@ -106,6 +106,7 @@ typedef HRESULT (WINAPI * ShGetFolderPath_fn) | |||
| 106 | (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *); | 106 | (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *); |
| 107 | 107 | ||
| 108 | void globals_of_w32 (); | 108 | void globals_of_w32 (); |
| 109 | static DWORD get_rid (PSID); | ||
| 109 | 110 | ||
| 110 | extern Lisp_Object Vw32_downcase_file_names; | 111 | extern Lisp_Object Vw32_downcase_file_names; |
| 111 | extern Lisp_Object Vw32_generate_fake_inodes; | 112 | extern Lisp_Object Vw32_generate_fake_inodes; |
| @@ -132,6 +133,10 @@ static BOOL g_b_init_lookup_account_sid; | |||
| 132 | static BOOL g_b_init_get_sid_identifier_authority; | 133 | static BOOL g_b_init_get_sid_identifier_authority; |
| 133 | static BOOL g_b_init_get_sid_sub_authority; | 134 | static BOOL g_b_init_get_sid_sub_authority; |
| 134 | static BOOL g_b_init_get_sid_sub_authority_count; | 135 | static BOOL g_b_init_get_sid_sub_authority_count; |
| 136 | static BOOL g_b_init_get_file_security; | ||
| 137 | static BOOL g_b_init_get_security_descriptor_owner; | ||
| 138 | static BOOL g_b_init_get_security_descriptor_group; | ||
| 139 | static BOOL g_b_init_is_valid_sid; | ||
| 135 | 140 | ||
| 136 | /* | 141 | /* |
| 137 | BEGIN: Wrapper functions around OpenProcessToken | 142 | BEGIN: Wrapper functions around OpenProcessToken |
| @@ -160,8 +165,10 @@ GetProcessTimes_Proc get_process_times_fn = NULL; | |||
| 160 | 165 | ||
| 161 | #ifdef _UNICODE | 166 | #ifdef _UNICODE |
| 162 | const char * const LookupAccountSid_Name = "LookupAccountSidW"; | 167 | const char * const LookupAccountSid_Name = "LookupAccountSidW"; |
| 168 | const char * const GetFileSecurity_Name = "GetFileSecurityW"; | ||
| 163 | #else | 169 | #else |
| 164 | const char * const LookupAccountSid_Name = "LookupAccountSidA"; | 170 | const char * const LookupAccountSid_Name = "LookupAccountSidA"; |
| 171 | const char * const GetFileSecurity_Name = "GetFileSecurityA"; | ||
| 165 | #endif | 172 | #endif |
| 166 | typedef BOOL (WINAPI * LookupAccountSid_Proc) ( | 173 | typedef BOOL (WINAPI * LookupAccountSid_Proc) ( |
| 167 | LPCTSTR lpSystemName, | 174 | LPCTSTR lpSystemName, |
| @@ -178,7 +185,22 @@ typedef PDWORD (WINAPI * GetSidSubAuthority_Proc) ( | |||
| 178 | DWORD n); | 185 | DWORD n); |
| 179 | typedef PUCHAR (WINAPI * GetSidSubAuthorityCount_Proc) ( | 186 | typedef PUCHAR (WINAPI * GetSidSubAuthorityCount_Proc) ( |
| 180 | PSID pSid); | 187 | PSID pSid); |
| 181 | 188 | typedef BOOL (WINAPI * GetFileSecurity_Proc) ( | |
| 189 | LPCTSTR lpFileName, | ||
| 190 | SECURITY_INFORMATION RequestedInformation, | ||
| 191 | PSECURITY_DESCRIPTOR pSecurityDescriptor, | ||
| 192 | DWORD nLength, | ||
| 193 | LPDWORD lpnLengthNeeded); | ||
| 194 | typedef BOOL (WINAPI * GetSecurityDescriptorOwner_Proc) ( | ||
| 195 | PSECURITY_DESCRIPTOR pSecurityDescriptor, | ||
| 196 | PSID *pOwner, | ||
| 197 | LPBOOL lpbOwnerDefaulted); | ||
| 198 | typedef BOOL (WINAPI * GetSecurityDescriptorGroup_Proc) ( | ||
| 199 | PSECURITY_DESCRIPTOR pSecurityDescriptor, | ||
| 200 | PSID *pGroup, | ||
| 201 | LPBOOL lpbGroupDefaulted); | ||
| 202 | typedef BOOL (WINAPI * IsValidSid_Proc) ( | ||
| 203 | PSID sid); | ||
| 182 | 204 | ||
| 183 | /* ** A utility function ** */ | 205 | /* ** A utility function ** */ |
| 184 | static BOOL | 206 | static BOOL |
| @@ -418,6 +440,114 @@ PUCHAR WINAPI get_sid_sub_authority_count ( | |||
| 418 | return (s_pfn_Get_Sid_Sub_Authority_Count (pSid)); | 440 | return (s_pfn_Get_Sid_Sub_Authority_Count (pSid)); |
| 419 | } | 441 | } |
| 420 | 442 | ||
| 443 | BOOL WINAPI get_file_security ( | ||
| 444 | LPCTSTR lpFileName, | ||
| 445 | SECURITY_INFORMATION RequestedInformation, | ||
| 446 | PSECURITY_DESCRIPTOR pSecurityDescriptor, | ||
| 447 | DWORD nLength, | ||
| 448 | LPDWORD lpnLengthNeeded) | ||
| 449 | { | ||
| 450 | static GetFileSecurity_Proc s_pfn_Get_File_Security = NULL; | ||
| 451 | HMODULE hm_advapi32 = NULL; | ||
| 452 | if (is_windows_9x () == TRUE) | ||
| 453 | { | ||
| 454 | return FALSE; | ||
| 455 | } | ||
| 456 | if (g_b_init_get_file_security == 0) | ||
| 457 | { | ||
| 458 | g_b_init_get_file_security = 1; | ||
| 459 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | ||
| 460 | s_pfn_Get_File_Security = | ||
| 461 | (GetFileSecurity_Proc) GetProcAddress ( | ||
| 462 | hm_advapi32, GetFileSecurity_Name); | ||
| 463 | } | ||
| 464 | if (s_pfn_Get_File_Security == NULL) | ||
| 465 | { | ||
| 466 | return FALSE; | ||
| 467 | } | ||
| 468 | return (s_pfn_Get_File_Security (lpFileName, RequestedInformation, | ||
| 469 | pSecurityDescriptor, nLength, | ||
| 470 | lpnLengthNeeded)); | ||
| 471 | } | ||
| 472 | |||
| 473 | BOOL WINAPI get_security_descriptor_owner ( | ||
| 474 | PSECURITY_DESCRIPTOR pSecurityDescriptor, | ||
| 475 | PSID *pOwner, | ||
| 476 | LPBOOL lpbOwnerDefaulted) | ||
| 477 | { | ||
| 478 | static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner = NULL; | ||
| 479 | HMODULE hm_advapi32 = NULL; | ||
| 480 | if (is_windows_9x () == TRUE) | ||
| 481 | { | ||
| 482 | return FALSE; | ||
| 483 | } | ||
| 484 | if (g_b_init_get_security_descriptor_owner == 0) | ||
| 485 | { | ||
| 486 | g_b_init_get_security_descriptor_owner = 1; | ||
| 487 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | ||
| 488 | s_pfn_Get_Security_Descriptor_Owner = | ||
| 489 | (GetSecurityDescriptorOwner_Proc) GetProcAddress ( | ||
| 490 | hm_advapi32, "GetSecurityDescriptorOwner"); | ||
| 491 | } | ||
| 492 | if (s_pfn_Get_Security_Descriptor_Owner == NULL) | ||
| 493 | { | ||
| 494 | return FALSE; | ||
| 495 | } | ||
| 496 | return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor, pOwner, | ||
| 497 | lpbOwnerDefaulted)); | ||
| 498 | } | ||
| 499 | |||
| 500 | BOOL WINAPI get_security_descriptor_group ( | ||
| 501 | PSECURITY_DESCRIPTOR pSecurityDescriptor, | ||
| 502 | PSID *pGroup, | ||
| 503 | LPBOOL lpbGroupDefaulted) | ||
| 504 | { | ||
| 505 | static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group = NULL; | ||
| 506 | HMODULE hm_advapi32 = NULL; | ||
| 507 | if (is_windows_9x () == TRUE) | ||
| 508 | { | ||
| 509 | return FALSE; | ||
| 510 | } | ||
| 511 | if (g_b_init_get_security_descriptor_group == 0) | ||
| 512 | { | ||
| 513 | g_b_init_get_security_descriptor_group = 1; | ||
| 514 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | ||
| 515 | s_pfn_Get_Security_Descriptor_Group = | ||
| 516 | (GetSecurityDescriptorGroup_Proc) GetProcAddress ( | ||
| 517 | hm_advapi32, "GetSecurityDescriptorGroup"); | ||
| 518 | } | ||
| 519 | if (s_pfn_Get_Security_Descriptor_Group == NULL) | ||
| 520 | { | ||
| 521 | return FALSE; | ||
| 522 | } | ||
| 523 | return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor, pGroup, | ||
| 524 | lpbGroupDefaulted)); | ||
| 525 | } | ||
| 526 | |||
| 527 | BOOL WINAPI is_valid_sid ( | ||
| 528 | PSID sid) | ||
| 529 | { | ||
| 530 | static IsValidSid_Proc s_pfn_Is_Valid_Sid = NULL; | ||
| 531 | HMODULE hm_advapi32 = NULL; | ||
| 532 | if (is_windows_9x () == TRUE) | ||
| 533 | { | ||
| 534 | return FALSE; | ||
| 535 | } | ||
| 536 | if (g_b_init_is_valid_sid == 0) | ||
| 537 | { | ||
| 538 | g_b_init_is_valid_sid = 1; | ||
| 539 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | ||
| 540 | s_pfn_Is_Valid_Sid = | ||
| 541 | (IsValidSid_Proc) GetProcAddress ( | ||
| 542 | hm_advapi32, "IsValidSid"); | ||
| 543 | } | ||
| 544 | if (s_pfn_Is_Valid_Sid == NULL) | ||
| 545 | { | ||
| 546 | return FALSE; | ||
| 547 | } | ||
| 548 | return (s_pfn_Is_Valid_Sid (sid)); | ||
| 549 | } | ||
| 550 | |||
| 421 | /* | 551 | /* |
| 422 | END: Wrapper functions around OpenProcessToken | 552 | END: Wrapper functions around OpenProcessToken |
| 423 | and other functions in advapi32.dll that are only | 553 | and other functions in advapi32.dll that are only |
| @@ -616,8 +746,6 @@ init_user_info () | |||
| 616 | TOKEN_USER user_token; | 746 | TOKEN_USER user_token; |
| 617 | TOKEN_PRIMARY_GROUP group_token; | 747 | TOKEN_PRIMARY_GROUP group_token; |
| 618 | 748 | ||
| 619 | /* "None" is the default group name on standalone workstations. */ | ||
| 620 | strcpy (dflt_group_name, "None"); | ||
| 621 | if (open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token) | 749 | if (open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token) |
| 622 | && get_token_information (token, TokenUser, | 750 | && get_token_information (token, TokenUser, |
| 623 | (PVOID)buf, sizeof (buf), &trash) | 751 | (PVOID)buf, sizeof (buf), &trash) |
| @@ -636,34 +764,14 @@ init_user_info () | |||
| 636 | { | 764 | { |
| 637 | /* Use the last sub-authority value of the RID, the relative | 765 | /* Use the last sub-authority value of the RID, the relative |
| 638 | portion of the SID, as user/group ID. */ | 766 | portion of the SID, as user/group ID. */ |
| 639 | DWORD n_subauthorities = | 767 | dflt_passwd.pw_uid = get_rid (user_token.User.Sid); |
| 640 | *get_sid_sub_authority_count (user_token.User.Sid); | ||
| 641 | |||
| 642 | if (n_subauthorities < 1) | ||
| 643 | dflt_passwd.pw_uid = 0; /* the "World" RID */ | ||
| 644 | else | ||
| 645 | { | ||
| 646 | dflt_passwd.pw_uid = | ||
| 647 | *get_sid_sub_authority (user_token.User.Sid, | ||
| 648 | n_subauthorities - 1); | ||
| 649 | } | ||
| 650 | 768 | ||
| 651 | /* Get group id */ | 769 | /* Get group id and name. */ |
| 652 | if (get_token_information (token, TokenPrimaryGroup, | 770 | if (get_token_information (token, TokenPrimaryGroup, |
| 653 | (PVOID)buf, sizeof (buf), &trash)) | 771 | (PVOID)buf, sizeof (buf), &trash)) |
| 654 | { | 772 | { |
| 655 | memcpy (&group_token, buf, sizeof (group_token)); | 773 | memcpy (&group_token, buf, sizeof (group_token)); |
| 656 | n_subauthorities = | 774 | dflt_passwd.pw_gid = get_rid (group_token.PrimaryGroup); |
| 657 | *get_sid_sub_authority_count (group_token.PrimaryGroup); | ||
| 658 | |||
| 659 | if (n_subauthorities < 1) | ||
| 660 | dflt_passwd.pw_gid = 0; /* the "World" RID */ | ||
| 661 | else | ||
| 662 | { | ||
| 663 | dflt_passwd.pw_gid = | ||
| 664 | *get_sid_sub_authority (group_token.PrimaryGroup, | ||
| 665 | n_subauthorities - 1); | ||
| 666 | } | ||
| 667 | dlength = sizeof (domain); | 775 | dlength = sizeof (domain); |
| 668 | if (lookup_account_sid (NULL, group_token.PrimaryGroup, | 776 | if (lookup_account_sid (NULL, group_token.PrimaryGroup, |
| 669 | gname, &glength, NULL, &dlength, | 777 | gname, &glength, NULL, &dlength, |
| @@ -2548,6 +2656,136 @@ generate_inode_val (const char * name) | |||
| 2548 | 2656 | ||
| 2549 | #endif | 2657 | #endif |
| 2550 | 2658 | ||
| 2659 | static PSECURITY_DESCRIPTOR | ||
| 2660 | get_file_security_desc (const char *fname) | ||
| 2661 | { | ||
| 2662 | PSECURITY_DESCRIPTOR psd = NULL; | ||
| 2663 | DWORD sd_len, err; | ||
| 2664 | SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION | ||
| 2665 | | GROUP_SECURITY_INFORMATION /* | DACL_SECURITY_INFORMATION */ ; | ||
| 2666 | |||
| 2667 | if (!get_file_security (fname, si, psd, 0, &sd_len)) | ||
| 2668 | { | ||
| 2669 | err = GetLastError (); | ||
| 2670 | if (err != ERROR_INSUFFICIENT_BUFFER) | ||
| 2671 | return NULL; | ||
| 2672 | } | ||
| 2673 | |||
| 2674 | psd = xmalloc (sd_len); | ||
| 2675 | if (!get_file_security (fname, si, psd, sd_len, &sd_len)) | ||
| 2676 | { | ||
| 2677 | xfree (psd); | ||
| 2678 | return NULL; | ||
| 2679 | } | ||
| 2680 | |||
| 2681 | return psd; | ||
| 2682 | } | ||
| 2683 | |||
| 2684 | static DWORD | ||
| 2685 | get_rid (PSID sid) | ||
| 2686 | { | ||
| 2687 | unsigned n_subauthorities; | ||
| 2688 | |||
| 2689 | /* Use the last sub-authority value of the RID, the relative | ||
| 2690 | portion of the SID, as user/group ID. */ | ||
| 2691 | n_subauthorities = *get_sid_sub_authority_count (sid); | ||
| 2692 | if (n_subauthorities < 1) | ||
| 2693 | return 0; /* the "World" RID */ | ||
| 2694 | return *get_sid_sub_authority (sid, n_subauthorities - 1); | ||
| 2695 | } | ||
| 2696 | |||
| 2697 | #define UID 1 | ||
| 2698 | #define GID 2 | ||
| 2699 | |||
| 2700 | static int | ||
| 2701 | get_name_and_id (PSECURITY_DESCRIPTOR psd, const char *fname, | ||
| 2702 | int *id, char *nm, int what) | ||
| 2703 | { | ||
| 2704 | PSID sid = NULL; | ||
| 2705 | char machine[MAX_COMPUTERNAME_LENGTH+1]; | ||
| 2706 | BOOL dflt; | ||
| 2707 | SID_NAME_USE ignore; | ||
| 2708 | char name[UNLEN+1]; | ||
| 2709 | DWORD name_len = sizeof (name); | ||
| 2710 | char domain[1024]; | ||
| 2711 | DWORD domain_len = sizeof(domain); | ||
| 2712 | char *mp = NULL; | ||
| 2713 | int use_dflt = 0; | ||
| 2714 | int result; | ||
| 2715 | |||
| 2716 | if (what == UID) | ||
| 2717 | result = get_security_descriptor_owner (psd, &sid, &dflt); | ||
| 2718 | else if (what == GID) | ||
| 2719 | result = get_security_descriptor_group (psd, &sid, &dflt); | ||
| 2720 | else | ||
| 2721 | result = 0; | ||
| 2722 | |||
| 2723 | if (!result || !is_valid_sid (sid)) | ||
| 2724 | use_dflt = 1; | ||
| 2725 | else | ||
| 2726 | { | ||
| 2727 | /* If FNAME is a UNC, we need to lookup account on the | ||
| 2728 | specified machine. */ | ||
| 2729 | if (IS_DIRECTORY_SEP (fname[0]) && IS_DIRECTORY_SEP (fname[1]) | ||
| 2730 | && fname[2] != '\0') | ||
| 2731 | { | ||
| 2732 | const char *s; | ||
| 2733 | char *p; | ||
| 2734 | |||
| 2735 | for (s = fname + 2, p = machine; | ||
| 2736 | *s && !IS_DIRECTORY_SEP (*s); s++, p++) | ||
| 2737 | *p = *s; | ||
| 2738 | *p = '\0'; | ||
| 2739 | mp = machine; | ||
| 2740 | } | ||
| 2741 | |||
| 2742 | if (!lookup_account_sid (mp, sid, name, &name_len, | ||
| 2743 | domain, &domain_len, &ignore) | ||
| 2744 | || name_len > UNLEN+1) | ||
| 2745 | use_dflt = 1; | ||
| 2746 | else | ||
| 2747 | { | ||
| 2748 | *id = get_rid (sid); | ||
| 2749 | strcpy (nm, name); | ||
| 2750 | } | ||
| 2751 | } | ||
| 2752 | return use_dflt; | ||
| 2753 | } | ||
| 2754 | |||
| 2755 | static void | ||
| 2756 | get_file_owner_and_group ( | ||
| 2757 | PSECURITY_DESCRIPTOR psd, | ||
| 2758 | const char *fname, | ||
| 2759 | struct stat *st) | ||
| 2760 | { | ||
| 2761 | int dflt_usr = 0, dflt_grp = 0; | ||
| 2762 | |||
| 2763 | if (!psd) | ||
| 2764 | { | ||
| 2765 | dflt_usr = 1; | ||
| 2766 | dflt_grp = 1; | ||
| 2767 | } | ||
| 2768 | else | ||
| 2769 | { | ||
| 2770 | if (get_name_and_id (psd, fname, &st->st_uid, st->st_uname, UID)) | ||
| 2771 | dflt_usr = 1; | ||
| 2772 | if (get_name_and_id (psd, fname, &st->st_gid, st->st_gname, GID)) | ||
| 2773 | dflt_grp = 1; | ||
| 2774 | } | ||
| 2775 | /* Consider files to belong to current user/group, if we cannot get | ||
| 2776 | more accurate information. */ | ||
| 2777 | if (dflt_usr) | ||
| 2778 | { | ||
| 2779 | st->st_uid = dflt_passwd.pw_uid; | ||
| 2780 | strcpy (st->st_uname, dflt_passwd.pw_name); | ||
| 2781 | } | ||
| 2782 | if (dflt_grp) | ||
| 2783 | { | ||
| 2784 | st->st_gid = dflt_passwd.pw_gid; | ||
| 2785 | strcpy (st->st_gname, dflt_group.gr_name); | ||
| 2786 | } | ||
| 2787 | } | ||
| 2788 | |||
| 2551 | /* MSVC stat function can't cope with UNC names and has other bugs, so | 2789 | /* MSVC stat function can't cope with UNC names and has other bugs, so |
| 2552 | replace it with our own. This also allows us to calculate consistent | 2790 | replace it with our own. This also allows us to calculate consistent |
| 2553 | inode values without hacks in the main Emacs code. */ | 2791 | inode values without hacks in the main Emacs code. */ |
| @@ -2561,6 +2799,7 @@ stat (const char * path, struct stat * buf) | |||
| 2561 | int permission; | 2799 | int permission; |
| 2562 | int len; | 2800 | int len; |
| 2563 | int rootdir = FALSE; | 2801 | int rootdir = FALSE; |
| 2802 | PSECURITY_DESCRIPTOR psd = NULL; | ||
| 2564 | 2803 | ||
| 2565 | if (path == NULL || buf == NULL) | 2804 | if (path == NULL || buf == NULL) |
| 2566 | { | 2805 | { |
| @@ -2658,9 +2897,9 @@ stat (const char * path, struct stat * buf) | |||
| 2658 | } | 2897 | } |
| 2659 | } | 2898 | } |
| 2660 | 2899 | ||
| 2661 | if (!NILP (Vw32_get_true_file_attributes) | 2900 | if (!(NILP (Vw32_get_true_file_attributes) |
| 2662 | && !(EQ (Vw32_get_true_file_attributes, Qlocal) && | 2901 | || (EQ (Vw32_get_true_file_attributes, Qlocal) && |
| 2663 | GetDriveType (name) == DRIVE_FIXED) | 2902 | GetDriveType (name) != DRIVE_FIXED))) |
| 2664 | /* No access rights required to get info. */ | 2903 | /* No access rights required to get info. */ |
| 2665 | && (fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING, | 2904 | && (fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING, |
| 2666 | FILE_FLAG_BACKUP_SEMANTICS, NULL)) | 2905 | FILE_FLAG_BACKUP_SEMANTICS, NULL)) |
| @@ -2710,6 +2949,8 @@ stat (const char * path, struct stat * buf) | |||
| 2710 | } | 2949 | } |
| 2711 | } | 2950 | } |
| 2712 | CloseHandle (fh); | 2951 | CloseHandle (fh); |
| 2952 | psd = get_file_security_desc (name); | ||
| 2953 | get_file_owner_and_group (psd, name, buf); | ||
| 2713 | } | 2954 | } |
| 2714 | else | 2955 | else |
| 2715 | { | 2956 | { |
| @@ -2718,7 +2959,11 @@ stat (const char * path, struct stat * buf) | |||
| 2718 | S_IFDIR : S_IFREG; | 2959 | S_IFDIR : S_IFREG; |
| 2719 | buf->st_nlink = 1; | 2960 | buf->st_nlink = 1; |
| 2720 | fake_inode = 0; | 2961 | fake_inode = 0; |
| 2962 | |||
| 2963 | get_file_owner_and_group (NULL, name, buf); | ||
| 2721 | } | 2964 | } |
| 2965 | if (psd) | ||
| 2966 | xfree (psd); | ||
| 2722 | 2967 | ||
| 2723 | #if 0 | 2968 | #if 0 |
| 2724 | /* Not sure if there is any point in this. */ | 2969 | /* Not sure if there is any point in this. */ |
| @@ -2738,16 +2983,14 @@ stat (const char * path, struct stat * buf) | |||
| 2738 | else | 2983 | else |
| 2739 | buf->st_ino = fake_inode; | 2984 | buf->st_ino = fake_inode; |
| 2740 | 2985 | ||
| 2741 | /* consider files to belong to current user */ | ||
| 2742 | buf->st_uid = dflt_passwd.pw_uid; | ||
| 2743 | buf->st_gid = dflt_passwd.pw_gid; | ||
| 2744 | |||
| 2745 | /* volume_info is set indirectly by map_w32_filename */ | 2986 | /* volume_info is set indirectly by map_w32_filename */ |
| 2746 | buf->st_dev = volume_info.serialnum; | 2987 | buf->st_dev = volume_info.serialnum; |
| 2747 | buf->st_rdev = volume_info.serialnum; | 2988 | buf->st_rdev = volume_info.serialnum; |
| 2748 | 2989 | ||
| 2749 | 2990 | ||
| 2750 | buf->st_size = wfd.nFileSizeLow; | 2991 | buf->st_size = wfd.nFileSizeHigh; |
| 2992 | buf->st_size <<= 32; | ||
| 2993 | buf->st_size += wfd.nFileSizeLow; | ||
| 2751 | 2994 | ||
| 2752 | /* Convert timestamps to Unix format. */ | 2995 | /* Convert timestamps to Unix format. */ |
| 2753 | buf->st_mtime = convert_time (wfd.ftLastWriteTime); | 2996 | buf->st_mtime = convert_time (wfd.ftLastWriteTime); |
| @@ -2826,14 +3069,20 @@ fstat (int desc, struct stat * buf) | |||
| 2826 | else | 3069 | else |
| 2827 | buf->st_ino = fake_inode; | 3070 | buf->st_ino = fake_inode; |
| 2828 | 3071 | ||
| 2829 | /* consider files to belong to current user */ | 3072 | /* Consider files to belong to current user. |
| 3073 | FIXME: this should use GetSecurityInfo API, but it is only | ||
| 3074 | available for _WIN32_WINNT >= 0x501. */ | ||
| 2830 | buf->st_uid = dflt_passwd.pw_uid; | 3075 | buf->st_uid = dflt_passwd.pw_uid; |
| 2831 | buf->st_gid = dflt_passwd.pw_gid; | 3076 | buf->st_gid = dflt_passwd.pw_gid; |
| 3077 | strcpy (buf->st_uname, dflt_passwd.pw_name); | ||
| 3078 | strcpy (buf->st_gname, dflt_group.gr_name); | ||
| 2832 | 3079 | ||
| 2833 | buf->st_dev = info.dwVolumeSerialNumber; | 3080 | buf->st_dev = info.dwVolumeSerialNumber; |
| 2834 | buf->st_rdev = info.dwVolumeSerialNumber; | 3081 | buf->st_rdev = info.dwVolumeSerialNumber; |
| 2835 | 3082 | ||
| 2836 | buf->st_size = info.nFileSizeLow; | 3083 | buf->st_size = info.nFileSizeHigh; |
| 3084 | buf->st_size <<= 32; | ||
| 3085 | buf->st_size += info.nFileSizeLow; | ||
| 2837 | 3086 | ||
| 2838 | /* Convert timestamps to Unix format. */ | 3087 | /* Convert timestamps to Unix format. */ |
| 2839 | buf->st_mtime = convert_time (info.ftLastWriteTime); | 3088 | buf->st_mtime = convert_time (info.ftLastWriteTime); |
| @@ -4350,11 +4599,18 @@ globals_of_w32 () | |||
| 4350 | g_b_init_get_sid_identifier_authority = 0; | 4599 | g_b_init_get_sid_identifier_authority = 0; |
| 4351 | g_b_init_get_sid_sub_authority = 0; | 4600 | g_b_init_get_sid_sub_authority = 0; |
| 4352 | g_b_init_get_sid_sub_authority_count = 0; | 4601 | g_b_init_get_sid_sub_authority_count = 0; |
| 4602 | g_b_init_get_file_security = 0; | ||
| 4603 | g_b_init_get_security_descriptor_owner = 0; | ||
| 4604 | g_b_init_get_security_descriptor_group = 0; | ||
| 4605 | g_b_init_is_valid_sid = 0; | ||
| 4353 | /* The following sets a handler for shutdown notifications for | 4606 | /* The following sets a handler for shutdown notifications for |
| 4354 | console apps. This actually applies to Emacs in both console and | 4607 | console apps. This actually applies to Emacs in both console and |
| 4355 | GUI modes, since we had to fool windows into thinking emacs is a | 4608 | GUI modes, since we had to fool windows into thinking emacs is a |
| 4356 | console application to get console mode to work. */ | 4609 | console application to get console mode to work. */ |
| 4357 | SetConsoleCtrlHandler(shutdown_handler, TRUE); | 4610 | SetConsoleCtrlHandler(shutdown_handler, TRUE); |
| 4611 | |||
| 4612 | /* "None" is the default group name on standalone workstations. */ | ||
| 4613 | strcpy (dflt_group_name, "None"); | ||
| 4358 | } | 4614 | } |
| 4359 | 4615 | ||
| 4360 | /* end of w32.c */ | 4616 | /* end of w32.c */ |