aboutsummaryrefslogtreecommitdiffstats
path: root/src/w32.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/w32.c')
-rw-r--r--src/w32.c1334
1 files changed, 1079 insertions, 255 deletions
diff --git a/src/w32.c b/src/w32.c
index c8e16dfaa94..431826c4b82 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -1,5 +1,5 @@
1/* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API. 1/* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
2 Copyright (C) 1994-1995, 2000-2012 Free Software Foundation, Inc. 2 Copyright (C) 1994-1995, 2000-2013 Free Software Foundation, Inc.
3 3
4This file is part of GNU Emacs. 4This file is part of GNU Emacs.
5 5
@@ -29,15 +29,15 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
29#include <ctype.h> 29#include <ctype.h>
30#include <signal.h> 30#include <signal.h>
31#include <sys/file.h> 31#include <sys/file.h>
32#include <time.h> /* must be before nt/inc/sys/time.h, for MinGW64 */
32#include <sys/time.h> 33#include <sys/time.h>
33#include <sys/utime.h> 34#include <sys/utime.h>
34#include <math.h> 35#include <math.h>
35#include <time.h>
36 36
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 */ 40#include <mbstring.h> /* for _mbspbrk, _mbslwr, _mbsrchr, ... */
41 41
42#undef access 42#undef access
43#undef chdir 43#undef chdir
@@ -69,7 +69,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
69#include <pwd.h> 69#include <pwd.h>
70#include <grp.h> 70#include <grp.h>
71 71
72#ifdef __GNUC__ 72/* MinGW64 (_W64) defines these in its _mingw.h. */
73#if defined(__GNUC__) && !defined(_W64)
73#define _ANONYMOUS_UNION 74#define _ANONYMOUS_UNION
74#define _ANONYMOUS_STRUCT 75#define _ANONYMOUS_STRUCT
75#endif 76#endif
@@ -96,33 +97,44 @@ typedef struct _MEMORY_STATUS_EX {
96#ifndef _MSC_VER 97#ifndef _MSC_VER
97#include <w32api.h> 98#include <w32api.h>
98#endif 99#endif
100#if _WIN32_WINNT < 0x0500
99#if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15) 101#if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
100/* This either is not in psapi.h or guarded by higher value of 102/* This either is not in psapi.h or guarded by higher value of
101 _WIN32_WINNT than what we use. w32api supplied with MinGW 3.15 103 _WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
102 defines it in psapi.h */ 104 defines it in psapi.h */
103typedef struct _PROCESS_MEMORY_COUNTERS_EX { 105typedef struct _PROCESS_MEMORY_COUNTERS_EX {
104 DWORD cb; 106 DWORD cb;
105 DWORD PageFaultCount; 107 DWORD PageFaultCount;
106 DWORD PeakWorkingSetSize; 108 SIZE_T PeakWorkingSetSize;
107 DWORD WorkingSetSize; 109 SIZE_T WorkingSetSize;
108 DWORD QuotaPeakPagedPoolUsage; 110 SIZE_T QuotaPeakPagedPoolUsage;
109 DWORD QuotaPagedPoolUsage; 111 SIZE_T QuotaPagedPoolUsage;
110 DWORD QuotaPeakNonPagedPoolUsage; 112 SIZE_T QuotaPeakNonPagedPoolUsage;
111 DWORD QuotaNonPagedPoolUsage; 113 SIZE_T QuotaNonPagedPoolUsage;
112 DWORD PagefileUsage; 114 SIZE_T PagefileUsage;
113 DWORD PeakPagefileUsage; 115 SIZE_T PeakPagefileUsage;
114 DWORD PrivateUsage; 116 SIZE_T PrivateUsage;
115} PROCESS_MEMORY_COUNTERS_EX,*PPROCESS_MEMORY_COUNTERS_EX; 117} PROCESS_MEMORY_COUNTERS_EX,*PPROCESS_MEMORY_COUNTERS_EX;
116#endif 118#endif
119#endif
117 120
118#include <winioctl.h> 121#include <winioctl.h>
119#include <aclapi.h> 122#include <aclapi.h>
123#include <sddl.h>
120 124
121#ifdef _MSC_VER 125#include <sys/acl.h>
122/* MSVC doesn't provide the definition of REPARSE_DATA_BUFFER and the 126
123 associated macros, except on ntifs.h, which cannot be included 127/* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
124 because it triggers conflicts with other Windows API headers. So 128 define them by hand if not already defined. */
125 we define it here by hand. */ 129#ifndef SDDL_REVISION_1
130#define SDDL_REVISION_1 1
131#endif /* SDDL_REVISION_1 */
132
133#if defined(_MSC_VER) || defined(_W64)
134/* MSVC and MinGW64 don't provide the definition of
135 REPARSE_DATA_BUFFER and the associated macros, except on ntifs.h,
136 which cannot be included because it triggers conflicts with other
137 Windows API headers. So we define it here by hand. */
126 138
127typedef struct _REPARSE_DATA_BUFFER { 139typedef struct _REPARSE_DATA_BUFFER {
128 ULONG ReparseTag; 140 ULONG ReparseTag;
@@ -150,13 +162,24 @@ typedef struct _REPARSE_DATA_BUFFER {
150 } DUMMYUNIONNAME; 162 } DUMMYUNIONNAME;
151} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; 163} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
152 164
165#ifndef FILE_DEVICE_FILE_SYSTEM
153#define FILE_DEVICE_FILE_SYSTEM 9 166#define FILE_DEVICE_FILE_SYSTEM 9
167#endif
168#ifndef METHOD_BUFFERED
154#define METHOD_BUFFERED 0 169#define METHOD_BUFFERED 0
170#endif
171#ifndef FILE_ANY_ACCESS
155#define FILE_ANY_ACCESS 0x00000000 172#define FILE_ANY_ACCESS 0x00000000
173#endif
174#ifndef CTL_CODE
156#define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m)) 175#define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
176#endif
177/* MinGW64 defines FSCTL_GET_REPARSE_POINT on winioctl.h. */
178#ifndef FSCTL_GET_REPARSE_POINT
157#define FSCTL_GET_REPARSE_POINT \ 179#define FSCTL_GET_REPARSE_POINT \
158 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) 180 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
159#endif 181#endif
182#endif
160 183
161/* TCP connection support. */ 184/* TCP connection support. */
162#include <sys/socket.h> 185#include <sys/socket.h>
@@ -249,6 +272,11 @@ static BOOL g_b_init_copy_sid;
249static BOOL g_b_init_get_native_system_info; 272static BOOL g_b_init_get_native_system_info;
250static BOOL g_b_init_get_system_times; 273static BOOL g_b_init_get_system_times;
251static BOOL g_b_init_create_symbolic_link; 274static BOOL g_b_init_create_symbolic_link;
275static BOOL g_b_init_get_security_descriptor_dacl;
276static BOOL g_b_init_convert_sd_to_sddl;
277static BOOL g_b_init_convert_sddl_to_sd;
278static BOOL g_b_init_is_valid_security_descriptor;
279static BOOL g_b_init_set_file_security;
252 280
253/* 281/*
254 BEGIN: Wrapper functions around OpenProcessToken 282 BEGIN: Wrapper functions around OpenProcessToken
@@ -278,9 +306,11 @@ GetProcessTimes_Proc get_process_times_fn = NULL;
278#ifdef _UNICODE 306#ifdef _UNICODE
279const char * const LookupAccountSid_Name = "LookupAccountSidW"; 307const char * const LookupAccountSid_Name = "LookupAccountSidW";
280const char * const GetFileSecurity_Name = "GetFileSecurityW"; 308const char * const GetFileSecurity_Name = "GetFileSecurityW";
309const char * const SetFileSecurity_Name = "SetFileSecurityW";
281#else 310#else
282const char * const LookupAccountSid_Name = "LookupAccountSidA"; 311const char * const LookupAccountSid_Name = "LookupAccountSidA";
283const char * const GetFileSecurity_Name = "GetFileSecurityA"; 312const char * const GetFileSecurity_Name = "GetFileSecurityA";
313const char * const SetFileSecurity_Name = "SetFileSecurityA";
284#endif 314#endif
285typedef BOOL (WINAPI * LookupAccountSid_Proc) ( 315typedef BOOL (WINAPI * LookupAccountSid_Proc) (
286 LPCTSTR lpSystemName, 316 LPCTSTR lpSystemName,
@@ -310,6 +340,10 @@ typedef BOOL (WINAPI * GetFileSecurity_Proc) (
310 PSECURITY_DESCRIPTOR pSecurityDescriptor, 340 PSECURITY_DESCRIPTOR pSecurityDescriptor,
311 DWORD nLength, 341 DWORD nLength,
312 LPDWORD lpnLengthNeeded); 342 LPDWORD lpnLengthNeeded);
343typedef BOOL (WINAPI *SetFileSecurity_Proc) (
344 LPCTSTR lpFileName,
345 SECURITY_INFORMATION SecurityInformation,
346 PSECURITY_DESCRIPTOR pSecurityDescriptor);
313typedef BOOL (WINAPI * GetSecurityDescriptorOwner_Proc) ( 347typedef BOOL (WINAPI * GetSecurityDescriptorOwner_Proc) (
314 PSECURITY_DESCRIPTOR pSecurityDescriptor, 348 PSECURITY_DESCRIPTOR pSecurityDescriptor,
315 PSID *pOwner, 349 PSID *pOwner,
@@ -318,6 +352,11 @@ typedef BOOL (WINAPI * GetSecurityDescriptorGroup_Proc) (
318 PSECURITY_DESCRIPTOR pSecurityDescriptor, 352 PSECURITY_DESCRIPTOR pSecurityDescriptor,
319 PSID *pGroup, 353 PSID *pGroup,
320 LPBOOL lpbGroupDefaulted); 354 LPBOOL lpbGroupDefaulted);
355typedef BOOL (WINAPI *GetSecurityDescriptorDacl_Proc) (
356 PSECURITY_DESCRIPTOR pSecurityDescriptor,
357 LPBOOL lpbDaclPresent,
358 PACL *pDacl,
359 LPBOOL lpbDaclDefaulted);
321typedef BOOL (WINAPI * IsValidSid_Proc) ( 360typedef BOOL (WINAPI * IsValidSid_Proc) (
322 PSID sid); 361 PSID sid);
323typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_Proc) ( 362typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_Proc) (
@@ -343,8 +382,8 @@ typedef BOOL (WINAPI * GetProcessMemoryInfo_Proc) (
343 DWORD cb); 382 DWORD cb);
344typedef BOOL (WINAPI * GetProcessWorkingSetSize_Proc) ( 383typedef BOOL (WINAPI * GetProcessWorkingSetSize_Proc) (
345 HANDLE hProcess, 384 HANDLE hProcess,
346 DWORD * lpMinimumWorkingSetSize, 385 PSIZE_T lpMinimumWorkingSetSize,
347 DWORD * lpMaximumWorkingSetSize); 386 PSIZE_T lpMaximumWorkingSetSize);
348typedef BOOL (WINAPI * GlobalMemoryStatus_Proc) ( 387typedef BOOL (WINAPI * GlobalMemoryStatus_Proc) (
349 LPMEMORYSTATUS lpBuffer); 388 LPMEMORYSTATUS lpBuffer);
350typedef BOOL (WINAPI * GlobalMemoryStatusEx_Proc) ( 389typedef BOOL (WINAPI * GlobalMemoryStatusEx_Proc) (
@@ -368,6 +407,18 @@ typedef BOOLEAN (WINAPI *CreateSymbolicLink_Proc) (
368 LPTSTR lpSymlinkFileName, 407 LPTSTR lpSymlinkFileName,
369 LPTSTR lpTargetFileName, 408 LPTSTR lpTargetFileName,
370 DWORD dwFlags); 409 DWORD dwFlags);
410typedef BOOL (WINAPI *ConvertStringSecurityDescriptorToSecurityDescriptor_Proc) (
411 LPCTSTR StringSecurityDescriptor,
412 DWORD StringSDRevision,
413 PSECURITY_DESCRIPTOR *SecurityDescriptor,
414 PULONG SecurityDescriptorSize);
415typedef BOOL (WINAPI *ConvertSecurityDescriptorToStringSecurityDescriptor_Proc) (
416 PSECURITY_DESCRIPTOR SecurityDescriptor,
417 DWORD RequestedStringSDRevision,
418 SECURITY_INFORMATION SecurityInformation,
419 LPTSTR *StringSecurityDescriptor,
420 PULONG StringSecurityDescriptorLen);
421typedef BOOL (WINAPI *IsValidSecurityDescriptor_Proc) (PSECURITY_DESCRIPTOR);
371 422
372 /* ** A utility function ** */ 423 /* ** A utility function ** */
373static BOOL 424static BOOL
@@ -613,6 +664,7 @@ get_file_security (LPCTSTR lpFileName,
613 HMODULE hm_advapi32 = NULL; 664 HMODULE hm_advapi32 = NULL;
614 if (is_windows_9x () == TRUE) 665 if (is_windows_9x () == TRUE)
615 { 666 {
667 errno = ENOTSUP;
616 return FALSE; 668 return FALSE;
617 } 669 }
618 if (g_b_init_get_file_security == 0) 670 if (g_b_init_get_file_security == 0)
@@ -625,6 +677,7 @@ get_file_security (LPCTSTR lpFileName,
625 } 677 }
626 if (s_pfn_Get_File_Security == NULL) 678 if (s_pfn_Get_File_Security == NULL)
627 { 679 {
680 errno = ENOTSUP;
628 return FALSE; 681 return FALSE;
629 } 682 }
630 return (s_pfn_Get_File_Security (lpFileName, RequestedInformation, 683 return (s_pfn_Get_File_Security (lpFileName, RequestedInformation,
@@ -633,6 +686,35 @@ get_file_security (LPCTSTR lpFileName,
633} 686}
634 687
635static BOOL WINAPI 688static BOOL WINAPI
689set_file_security (LPCTSTR lpFileName,
690 SECURITY_INFORMATION SecurityInformation,
691 PSECURITY_DESCRIPTOR pSecurityDescriptor)
692{
693 static SetFileSecurity_Proc s_pfn_Set_File_Security = NULL;
694 HMODULE hm_advapi32 = NULL;
695 if (is_windows_9x () == TRUE)
696 {
697 errno = ENOTSUP;
698 return FALSE;
699 }
700 if (g_b_init_set_file_security == 0)
701 {
702 g_b_init_set_file_security = 1;
703 hm_advapi32 = LoadLibrary ("Advapi32.dll");
704 s_pfn_Set_File_Security =
705 (SetFileSecurity_Proc) GetProcAddress (
706 hm_advapi32, SetFileSecurity_Name);
707 }
708 if (s_pfn_Set_File_Security == NULL)
709 {
710 errno = ENOTSUP;
711 return FALSE;
712 }
713 return (s_pfn_Set_File_Security (lpFileName, SecurityInformation,
714 pSecurityDescriptor));
715}
716
717static BOOL WINAPI
636get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor, 718get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
637 PSID *pOwner, 719 PSID *pOwner,
638 LPBOOL lpbOwnerDefaulted) 720 LPBOOL lpbOwnerDefaulted)
@@ -641,6 +723,7 @@ get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
641 HMODULE hm_advapi32 = NULL; 723 HMODULE hm_advapi32 = NULL;
642 if (is_windows_9x () == TRUE) 724 if (is_windows_9x () == TRUE)
643 { 725 {
726 errno = ENOTSUP;
644 return FALSE; 727 return FALSE;
645 } 728 }
646 if (g_b_init_get_security_descriptor_owner == 0) 729 if (g_b_init_get_security_descriptor_owner == 0)
@@ -653,6 +736,7 @@ get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
653 } 736 }
654 if (s_pfn_Get_Security_Descriptor_Owner == NULL) 737 if (s_pfn_Get_Security_Descriptor_Owner == NULL)
655 { 738 {
739 errno = ENOTSUP;
656 return FALSE; 740 return FALSE;
657 } 741 }
658 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor, pOwner, 742 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor, pOwner,
@@ -668,6 +752,7 @@ get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
668 HMODULE hm_advapi32 = NULL; 752 HMODULE hm_advapi32 = NULL;
669 if (is_windows_9x () == TRUE) 753 if (is_windows_9x () == TRUE)
670 { 754 {
755 errno = ENOTSUP;
671 return FALSE; 756 return FALSE;
672 } 757 }
673 if (g_b_init_get_security_descriptor_group == 0) 758 if (g_b_init_get_security_descriptor_group == 0)
@@ -680,6 +765,7 @@ get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
680 } 765 }
681 if (s_pfn_Get_Security_Descriptor_Group == NULL) 766 if (s_pfn_Get_Security_Descriptor_Group == NULL)
682 { 767 {
768 errno = ENOTSUP;
683 return FALSE; 769 return FALSE;
684 } 770 }
685 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor, pGroup, 771 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor, pGroup,
@@ -687,6 +773,37 @@ get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
687} 773}
688 774
689static BOOL WINAPI 775static BOOL WINAPI
776get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor,
777 LPBOOL lpbDaclPresent,
778 PACL *pDacl,
779 LPBOOL lpbDaclDefaulted)
780{
781 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl = NULL;
782 HMODULE hm_advapi32 = NULL;
783 if (is_windows_9x () == TRUE)
784 {
785 errno = ENOTSUP;
786 return FALSE;
787 }
788 if (g_b_init_get_security_descriptor_dacl == 0)
789 {
790 g_b_init_get_security_descriptor_dacl = 1;
791 hm_advapi32 = LoadLibrary ("Advapi32.dll");
792 s_pfn_Get_Security_Descriptor_Dacl =
793 (GetSecurityDescriptorDacl_Proc) GetProcAddress (
794 hm_advapi32, "GetSecurityDescriptorDacl");
795 }
796 if (s_pfn_Get_Security_Descriptor_Dacl == NULL)
797 {
798 errno = ENOTSUP;
799 return FALSE;
800 }
801 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor,
802 lpbDaclPresent, pDacl,
803 lpbDaclDefaulted));
804}
805
806static BOOL WINAPI
690is_valid_sid (PSID sid) 807is_valid_sid (PSID sid)
691{ 808{
692 static IsValidSid_Proc s_pfn_Is_Valid_Sid = NULL; 809 static IsValidSid_Proc s_pfn_Is_Valid_Sid = NULL;
@@ -880,6 +997,120 @@ create_symbolic_link (LPTSTR lpSymlinkFilename,
880 } 997 }
881 return retval; 998 return retval;
882} 999}
1000
1001static BOOL WINAPI
1002is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor)
1003{
1004 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc = NULL;
1005
1006 if (is_windows_9x () == TRUE)
1007 {
1008 errno = ENOTSUP;
1009 return FALSE;
1010 }
1011
1012 if (g_b_init_is_valid_security_descriptor == 0)
1013 {
1014 g_b_init_is_valid_security_descriptor = 1;
1015 s_pfn_Is_Valid_Security_Descriptor_Proc =
1016 (IsValidSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1017 "IsValidSecurityDescriptor");
1018 }
1019 if (s_pfn_Is_Valid_Security_Descriptor_Proc == NULL)
1020 {
1021 errno = ENOTSUP;
1022 return FALSE;
1023 }
1024
1025 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor);
1026}
1027
1028static BOOL WINAPI
1029convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor,
1030 DWORD RequestedStringSDRevision,
1031 SECURITY_INFORMATION SecurityInformation,
1032 LPTSTR *StringSecurityDescriptor,
1033 PULONG StringSecurityDescriptorLen)
1034{
1035 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL = NULL;
1036 BOOL retval;
1037
1038 if (is_windows_9x () == TRUE)
1039 {
1040 errno = ENOTSUP;
1041 return FALSE;
1042 }
1043
1044 if (g_b_init_convert_sd_to_sddl == 0)
1045 {
1046 g_b_init_convert_sd_to_sddl = 1;
1047#ifdef _UNICODE
1048 s_pfn_Convert_SD_To_SDDL =
1049 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1050 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1051#else
1052 s_pfn_Convert_SD_To_SDDL =
1053 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1054 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1055#endif
1056 }
1057 if (s_pfn_Convert_SD_To_SDDL == NULL)
1058 {
1059 errno = ENOTSUP;
1060 return FALSE;
1061 }
1062
1063 retval = s_pfn_Convert_SD_To_SDDL (SecurityDescriptor,
1064 RequestedStringSDRevision,
1065 SecurityInformation,
1066 StringSecurityDescriptor,
1067 StringSecurityDescriptorLen);
1068
1069 return retval;
1070}
1071
1072static BOOL WINAPI
1073convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor,
1074 DWORD StringSDRevision,
1075 PSECURITY_DESCRIPTOR *SecurityDescriptor,
1076 PULONG SecurityDescriptorSize)
1077{
1078 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD = NULL;
1079 BOOL retval;
1080
1081 if (is_windows_9x () == TRUE)
1082 {
1083 errno = ENOTSUP;
1084 return FALSE;
1085 }
1086
1087 if (g_b_init_convert_sddl_to_sd == 0)
1088 {
1089 g_b_init_convert_sddl_to_sd = 1;
1090#ifdef _UNICODE
1091 s_pfn_Convert_SDDL_To_SD =
1092 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1093 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1094#else
1095 s_pfn_Convert_SDDL_To_SD =
1096 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1097 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1098#endif
1099 }
1100 if (s_pfn_Convert_SDDL_To_SD == NULL)
1101 {
1102 errno = ENOTSUP;
1103 return FALSE;
1104 }
1105
1106 retval = s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor,
1107 StringSDRevision,
1108 SecurityDescriptor,
1109 SecurityDescriptorSize);
1110
1111 return retval;
1112}
1113
883 1114
884 1115
885/* Return 1 if P is a valid pointer to an object of size SIZE. Return 1116/* Return 1 if P is a valid pointer to an object of size SIZE. Return
@@ -1306,35 +1537,110 @@ srandom (int seed)
1306 srand (seed); 1537 srand (seed);
1307} 1538}
1308 1539
1540/* Current codepage for encoding file names. */
1541static int file_name_codepage;
1542
1543/* Return the maximum length in bytes of a multibyte character
1544 sequence encoded in the current ANSI codepage. This is required to
1545 correctly walk the encoded file names one character at a time. */
1546static int
1547max_filename_mbslen (void)
1548{
1549 /* A simple cache to avoid calling GetCPInfo every time we need to
1550 normalize a file name. The file-name encoding is not supposed to
1551 be changed too frequently, if ever. */
1552 static Lisp_Object last_file_name_encoding;
1553 static int last_max_mbslen;
1554 Lisp_Object current_encoding;
1555
1556 current_encoding = Vfile_name_coding_system;
1557 if (NILP (current_encoding))
1558 current_encoding = Vdefault_file_name_coding_system;
1559
1560 if (!EQ (last_file_name_encoding, current_encoding))
1561 {
1562 CPINFO cp_info;
1563
1564 last_file_name_encoding = current_encoding;
1565 /* Default to the current ANSI codepage. */
1566 file_name_codepage = w32_ansi_code_page;
1567 if (!NILP (current_encoding))
1568 {
1569 char *cpname = SDATA (SYMBOL_NAME (current_encoding));
1570 char *cp = NULL, *end;
1571 int cpnum;
1572
1573 if (strncmp (cpname, "cp", 2) == 0)
1574 cp = cpname + 2;
1575 else if (strncmp (cpname, "windows-", 8) == 0)
1576 cp = cpname + 8;
1577
1578 if (cp)
1579 {
1580 end = cp;
1581 cpnum = strtol (cp, &end, 10);
1582 if (cpnum && *end == '\0' && end - cp >= 2)
1583 file_name_codepage = cpnum;
1584 }
1585 }
1586
1587 if (!file_name_codepage)
1588 file_name_codepage = CP_ACP; /* CP_ACP = 0, but let's not assume that */
1589
1590 if (!GetCPInfo (file_name_codepage, &cp_info))
1591 {
1592 file_name_codepage = CP_ACP;
1593 if (!GetCPInfo (file_name_codepage, &cp_info))
1594 emacs_abort ();
1595 }
1596 last_max_mbslen = cp_info.MaxCharSize;
1597 }
1598
1599 return last_max_mbslen;
1600}
1309 1601
1310/* Normalize filename by converting all path separators to 1602/* Normalize filename by converting all path separators to
1311 the specified separator. Also conditionally convert upper 1603 the specified separator. Also conditionally convert upper
1312 case path name components to lower case. */ 1604 case path name components to lower case. */
1313 1605
1314static void 1606static void
1315normalize_filename (register char *fp, char path_sep) 1607normalize_filename (register char *fp, char path_sep, int multibyte)
1316{ 1608{
1317 char sep; 1609 char sep;
1318 char *elem; 1610 char *elem, *p2;
1611 int dbcs_p = max_filename_mbslen () > 1;
1612
1613 /* Multibyte file names are in the Emacs internal representation, so
1614 we can traverse them by bytes with no problems. */
1615 if (multibyte)
1616 dbcs_p = 0;
1319 1617
1320 /* Always lower-case drive letters a-z, even if the filesystem 1618 /* Always lower-case drive letters a-z, even if the filesystem
1321 preserves case in filenames. 1619 preserves case in filenames.
1322 This is so filenames can be compared by string comparison 1620 This is so filenames can be compared by string comparison
1323 functions that are case-sensitive. Even case-preserving filesystems 1621 functions that are case-sensitive. Even case-preserving filesystems
1324 do not distinguish case in drive letters. */ 1622 do not distinguish case in drive letters. */
1325 if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z') 1623 if (dbcs_p)
1624 p2 = CharNextExA (file_name_codepage, fp, 0);
1625 else
1626 p2 = fp + 1;
1627
1628 if (*p2 == ':' && *fp >= 'A' && *fp <= 'Z')
1326 { 1629 {
1327 *fp += 'a' - 'A'; 1630 *fp += 'a' - 'A';
1328 fp += 2; 1631 fp += 2;
1329 } 1632 }
1330 1633
1331 if (NILP (Vw32_downcase_file_names)) 1634 if (multibyte || NILP (Vw32_downcase_file_names))
1332 { 1635 {
1333 while (*fp) 1636 while (*fp)
1334 { 1637 {
1335 if (*fp == '/' || *fp == '\\') 1638 if (*fp == '/' || *fp == '\\')
1336 *fp = path_sep; 1639 *fp = path_sep;
1337 fp++; 1640 if (!dbcs_p)
1641 fp++;
1642 else
1643 fp = CharNextExA (file_name_codepage, fp, 0);
1338 } 1644 }
1339 return; 1645 return;
1340 } 1646 }
@@ -1357,27 +1663,36 @@ normalize_filename (register char *fp, char path_sep)
1357 if (elem && elem != fp) 1663 if (elem && elem != fp)
1358 { 1664 {
1359 *fp = 0; /* temporary end of string */ 1665 *fp = 0; /* temporary end of string */
1360 _strlwr (elem); /* while we convert to lower case */ 1666 _mbslwr (elem); /* while we convert to lower case */
1361 } 1667 }
1362 *fp = sep; /* convert (or restore) path separator */ 1668 *fp = sep; /* convert (or restore) path separator */
1363 elem = fp + 1; /* next element starts after separator */ 1669 elem = fp + 1; /* next element starts after separator */
1364 sep = path_sep; 1670 sep = path_sep;
1365 } 1671 }
1366 } while (*fp++); 1672 if (*fp)
1673 {
1674 if (!dbcs_p)
1675 fp++;
1676 else
1677 fp = CharNextExA (file_name_codepage, fp, 0);
1678 }
1679 } while (*fp);
1367} 1680}
1368 1681
1369/* Destructively turn backslashes into slashes. */ 1682/* Destructively turn backslashes into slashes. MULTIBYTE non-zero
1683 means the file name is a multibyte string in Emacs's internal
1684 representation. */
1370void 1685void
1371dostounix_filename (register char *p) 1686dostounix_filename (register char *p, int multibyte)
1372{ 1687{
1373 normalize_filename (p, '/'); 1688 normalize_filename (p, '/', multibyte);
1374} 1689}
1375 1690
1376/* Destructively turn slashes into backslashes. */ 1691/* Destructively turn slashes into backslashes. */
1377void 1692void
1378unixtodos_filename (register char *p) 1693unixtodos_filename (register char *p)
1379{ 1694{
1380 normalize_filename (p, '\\'); 1695 normalize_filename (p, '\\', 0);
1381} 1696}
1382 1697
1383/* Remove all CR's that are followed by a LF. 1698/* Remove all CR's that are followed by a LF.
@@ -1428,12 +1743,17 @@ parse_root (char * name, char ** pPath)
1428 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) 1743 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
1429 { 1744 {
1430 int slashes = 2; 1745 int slashes = 2;
1746 int dbcs_p = max_filename_mbslen () > 1;
1747
1431 name += 2; 1748 name += 2;
1432 do 1749 do
1433 { 1750 {
1434 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) 1751 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
1435 break; 1752 break;
1436 name++; 1753 if (dbcs_p)
1754 name = CharNextExA (file_name_codepage, name, 0);
1755 else
1756 name++;
1437 } 1757 }
1438 while ( *name ); 1758 while ( *name );
1439 if (IS_DIRECTORY_SEP (name[0])) 1759 if (IS_DIRECTORY_SEP (name[0]))
@@ -1498,7 +1818,7 @@ w32_get_long_filename (char * name, char * buf, int size)
1498 while (p != NULL && *p) 1818 while (p != NULL && *p)
1499 { 1819 {
1500 q = p; 1820 q = p;
1501 p = strchr (q, '\\'); 1821 p = _mbschr (q, '\\');
1502 if (p) *p = '\0'; 1822 if (p) *p = '\0';
1503 len = get_long_basename (full, o, size); 1823 len = get_long_basename (full, o, size);
1504 if (len > 0) 1824 if (len > 0)
@@ -1536,6 +1856,51 @@ is_unc_volume (const char *filename)
1536 return 1; 1856 return 1;
1537} 1857}
1538 1858
1859/* Emulate the Posix unsetenv. */
1860int
1861unsetenv (const char *name)
1862{
1863 char *var;
1864 size_t name_len;
1865 int retval;
1866
1867 if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
1868 {
1869 errno = EINVAL;
1870 return -1;
1871 }
1872 name_len = strlen (name);
1873 /* MS docs says an environment variable cannot be longer than 32K. */
1874 if (name_len > 32767)
1875 {
1876 errno = ENOMEM;
1877 return 0;
1878 }
1879 /* It is safe to use 'alloca' with 32K size, since the stack is at
1880 least 2MB, and we set it to 8MB in the link command line. */
1881 var = alloca (name_len + 2);
1882 strncpy (var, name, name_len);
1883 var[name_len++] = '=';
1884 var[name_len] = '\0';
1885 return _putenv (var);
1886}
1887
1888/* MS _putenv doesn't support removing a variable when the argument
1889 does not include the '=' character, so we fix that here. */
1890int
1891sys_putenv (char *str)
1892{
1893 const char *const name_end = strchr (str, '=');
1894
1895 if (name_end == NULL)
1896 {
1897 /* Remove the variable from the environment. */
1898 return unsetenv (str);
1899 }
1900
1901 return _putenv (str);
1902}
1903
1539#define REG_ROOT "SOFTWARE\\GNU\\Emacs" 1904#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
1540 1905
1541LPBYTE 1906LPBYTE
@@ -1725,16 +2090,16 @@ init_environment (char ** argv)
1725 2090
1726 if (!GetModuleFileName (NULL, modname, MAX_PATH)) 2091 if (!GetModuleFileName (NULL, modname, MAX_PATH))
1727 emacs_abort (); 2092 emacs_abort ();
1728 if ((p = strrchr (modname, '\\')) == NULL) 2093 if ((p = _mbsrchr (modname, '\\')) == NULL)
1729 emacs_abort (); 2094 emacs_abort ();
1730 *p = 0; 2095 *p = 0;
1731 2096
1732 if ((p = strrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0) 2097 if ((p = _mbsrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0)
1733 { 2098 {
1734 char buf[SET_ENV_BUF_SIZE]; 2099 char buf[SET_ENV_BUF_SIZE];
1735 2100
1736 *p = 0; 2101 *p = 0;
1737 for (p = modname; *p; p++) 2102 for (p = modname; *p; p = CharNext (p))
1738 if (*p == '\\') *p = '/'; 2103 if (*p == '\\') *p = '/';
1739 2104
1740 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); 2105 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname);
@@ -1749,17 +2114,17 @@ init_environment (char ** argv)
1749 || xstrcasecmp (p, "\\AMD64") == 0)) 2114 || xstrcasecmp (p, "\\AMD64") == 0))
1750 { 2115 {
1751 *p = 0; 2116 *p = 0;
1752 p = strrchr (modname, '\\'); 2117 p = _mbsrchr (modname, '\\');
1753 if (p != NULL) 2118 if (p != NULL)
1754 { 2119 {
1755 *p = 0; 2120 *p = 0;
1756 p = strrchr (modname, '\\'); 2121 p = _mbsrchr (modname, '\\');
1757 if (p && xstrcasecmp (p, "\\src") == 0) 2122 if (p && xstrcasecmp (p, "\\src") == 0)
1758 { 2123 {
1759 char buf[SET_ENV_BUF_SIZE]; 2124 char buf[SET_ENV_BUF_SIZE];
1760 2125
1761 *p = 0; 2126 *p = 0;
1762 for (p = modname; *p; p++) 2127 for (p = modname; *p; p = CharNext (p))
1763 if (*p == '\\') *p = '/'; 2128 if (*p == '\\') *p = '/';
1764 2129
1765 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); 2130 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname);
@@ -1870,7 +2235,7 @@ emacs_root_dir (void)
1870 emacs_abort (); 2235 emacs_abort ();
1871 strcpy (root_dir, p); 2236 strcpy (root_dir, p);
1872 root_dir[parse_root (root_dir, NULL)] = '\0'; 2237 root_dir[parse_root (root_dir, NULL)] = '\0';
1873 dostounix_filename (root_dir); 2238 dostounix_filename (root_dir, 0);
1874 return root_dir; 2239 return root_dir;
1875} 2240}
1876 2241
@@ -2294,12 +2659,23 @@ get_volume_info (const char * name, const char ** pPath)
2294 { 2659 {
2295 char *str = temp; 2660 char *str = temp;
2296 int slashes = 4; 2661 int slashes = 4;
2662 int dbcs_p = max_filename_mbslen () > 1;
2663
2297 rootname = temp; 2664 rootname = temp;
2298 do 2665 do
2299 { 2666 {
2300 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) 2667 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
2301 break; 2668 break;
2302 *str++ = *name++; 2669 if (!dbcs_p)
2670 *str++ = *name++;
2671 else
2672 {
2673 const char *p = name;
2674
2675 name = CharNextExA (file_name_codepage, name, 0);
2676 memcpy (str, p, name - p);
2677 str += name - p;
2678 }
2303 } 2679 }
2304 while ( *name ); 2680 while ( *name );
2305 2681
@@ -2462,7 +2838,7 @@ static char *read_unc_volume (HANDLE, char *, int);
2462static void close_unc_volume (HANDLE); 2838static void close_unc_volume (HANDLE);
2463 2839
2464DIR * 2840DIR *
2465opendir (char *filename) 2841opendir (const char *filename)
2466{ 2842{
2467 DIR *dirp; 2843 DIR *dirp;
2468 2844
@@ -2535,11 +2911,23 @@ readdir (DIR *dirp)
2535 { 2911 {
2536 char filename[MAXNAMLEN + 3]; 2912 char filename[MAXNAMLEN + 3];
2537 int ln; 2913 int ln;
2914 int dbcs_p = max_filename_mbslen () > 1;
2538 2915
2539 strcpy (filename, dir_pathname); 2916 strcpy (filename, dir_pathname);
2540 ln = strlen (filename) - 1; 2917 ln = strlen (filename) - 1;
2541 if (!IS_DIRECTORY_SEP (filename[ln])) 2918 if (!dbcs_p)
2542 strcat (filename, "\\"); 2919 {
2920 if (!IS_DIRECTORY_SEP (filename[ln]))
2921 strcat (filename, "\\");
2922 }
2923 else
2924 {
2925 char *end = filename + ln + 1;
2926 char *last_char = CharPrevExA (file_name_codepage, filename, end, 0);
2927
2928 if (!IS_DIRECTORY_SEP (*last_char))
2929 strcat (filename, "\\");
2930 }
2543 strcat (filename, "*"); 2931 strcat (filename, "*");
2544 2932
2545 /* Note: No need to resolve symlinks in FILENAME, because 2933 /* Note: No need to resolve symlinks in FILENAME, because
@@ -2590,15 +2978,22 @@ readdir (DIR *dirp)
2590 strcpy (dir_static.d_name, dir_find_data.cFileName); 2978 strcpy (dir_static.d_name, dir_find_data.cFileName);
2591 dir_static.d_namlen = strlen (dir_static.d_name); 2979 dir_static.d_namlen = strlen (dir_static.d_name);
2592 if (dir_is_fat) 2980 if (dir_is_fat)
2593 _strlwr (dir_static.d_name); 2981 _mbslwr (dir_static.d_name);
2594 else if (downcase) 2982 else if (downcase)
2595 { 2983 {
2596 register char *p; 2984 register char *p;
2597 for (p = dir_static.d_name; *p; p++) 2985 int dbcs_p = max_filename_mbslen () > 1;
2598 if (*p >= 'a' && *p <= 'z') 2986 for (p = dir_static.d_name; *p; )
2599 break; 2987 {
2988 if (*p >= 'a' && *p <= 'z')
2989 break;
2990 if (dbcs_p)
2991 p = CharNextExA (file_name_codepage, p, 0);
2992 else
2993 p++;
2994 }
2600 if (!*p) 2995 if (!*p)
2601 _strlwr (dir_static.d_name); 2996 _mbslwr (dir_static.d_name);
2602 } 2997 }
2603 2998
2604 return &dir_static; 2999 return &dir_static;
@@ -2637,6 +3032,7 @@ read_unc_volume (HANDLE henum, char *readbuf, int size)
2637 DWORD bufsize = 512; 3032 DWORD bufsize = 512;
2638 char *buffer; 3033 char *buffer;
2639 char *ptr; 3034 char *ptr;
3035 int dbcs_p = max_filename_mbslen () > 1;
2640 3036
2641 count = 1; 3037 count = 1;
2642 buffer = alloca (bufsize); 3038 buffer = alloca (bufsize);
@@ -2647,7 +3043,13 @@ read_unc_volume (HANDLE henum, char *readbuf, int size)
2647 /* WNetEnumResource returns \\resource\share...skip forward to "share". */ 3043 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
2648 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName; 3044 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName;
2649 ptr += 2; 3045 ptr += 2;
2650 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++; 3046 if (!dbcs_p)
3047 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++;
3048 else
3049 {
3050 while (*ptr && !IS_DIRECTORY_SEP (*ptr))
3051 ptr = CharNextExA (file_name_codepage, ptr, 0);
3052 }
2651 ptr++; 3053 ptr++;
2652 3054
2653 strncpy (readbuf, ptr, size); 3055 strncpy (readbuf, ptr, size);
@@ -2684,9 +3086,11 @@ logon_network_drive (const char *path)
2684{ 3086{
2685 NETRESOURCE resource; 3087 NETRESOURCE resource;
2686 char share[MAX_PATH]; 3088 char share[MAX_PATH];
2687 int i, n_slashes; 3089 int n_slashes;
2688 char drive[4]; 3090 char drive[4];
2689 UINT drvtype; 3091 UINT drvtype;
3092 char *p;
3093 int dbcs_p;
2690 3094
2691 if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1])) 3095 if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1]))
2692 drvtype = DRIVE_REMOTE; 3096 drvtype = DRIVE_REMOTE;
@@ -2708,13 +3112,18 @@ logon_network_drive (const char *path)
2708 n_slashes = 2; 3112 n_slashes = 2;
2709 strncpy (share, path, MAX_PATH); 3113 strncpy (share, path, MAX_PATH);
2710 /* Truncate to just server and share name. */ 3114 /* Truncate to just server and share name. */
2711 for (i = 2; i < MAX_PATH; i++) 3115 dbcs_p = max_filename_mbslen () > 1;
3116 for (p = share + 2; *p && p < share + MAX_PATH; )
2712 { 3117 {
2713 if (IS_DIRECTORY_SEP (share[i]) && ++n_slashes > 3) 3118 if (IS_DIRECTORY_SEP (*p) && ++n_slashes > 3)
2714 { 3119 {
2715 share[i] = '\0'; 3120 *p = '\0';
2716 break; 3121 break;
2717 } 3122 }
3123 if (dbcs_p)
3124 p = CharNextExA (file_name_codepage, p, 0);
3125 else
3126 p++;
2718 } 3127 }
2719 3128
2720 resource.dwType = RESOURCETYPE_DISK; 3129 resource.dwType = RESOURCETYPE_DISK;
@@ -2817,14 +3226,6 @@ sys_chmod (const char * path, int mode)
2817} 3226}
2818 3227
2819int 3228int
2820sys_chown (const char *path, uid_t owner, gid_t group)
2821{
2822 if (sys_chmod (path, S_IREAD) == -1) /* check if file exists */
2823 return -1;
2824 return 0;
2825}
2826
2827int
2828sys_creat (const char * path, int mode) 3229sys_creat (const char * path, int mode)
2829{ 3230{
2830 return _creat (map_w32_filename (path, NULL), mode); 3231 return _creat (map_w32_filename (path, NULL), mode);
@@ -3007,17 +3408,27 @@ int
3007sys_open (const char * path, int oflag, int mode) 3408sys_open (const char * path, int oflag, int mode)
3008{ 3409{
3009 const char* mpath = map_w32_filename (path, NULL); 3410 const char* mpath = map_w32_filename (path, NULL);
3010 /* Try to open file without _O_CREAT, to be able to write to hidden 3411 int res = -1;
3011 and system files. Force all file handles to be 3412
3012 non-inheritable. */ 3413 /* If possible, try to open file without _O_CREAT, to be able to
3013 int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); 3414 write to existing hidden and system files. Force all file
3014 if (res >= 0) 3415 handles to be non-inheritable. */
3015 return res; 3416 if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
3016 return _open (mpath, oflag | _O_NOINHERIT, mode); 3417 res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
3418 if (res < 0)
3419 res = _open (mpath, oflag | _O_NOINHERIT, mode);
3420
3421 return res;
3017} 3422}
3018 3423
3019int 3424int
3020sys_rename (const char * oldname, const char * newname) 3425fchmod (int fd, mode_t mode)
3426{
3427 return 0;
3428}
3429
3430int
3431sys_rename_replace (const char *oldname, const char *newname, BOOL force)
3021{ 3432{
3022 BOOL result; 3433 BOOL result;
3023 char temp[MAX_PATH]; 3434 char temp[MAX_PATH];
@@ -3073,7 +3484,7 @@ sys_rename (const char * oldname, const char * newname)
3073 return -1; 3484 return -1;
3074 } 3485 }
3075 3486
3076 /* Emulate Unix behavior - newname is deleted if it already exists 3487 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
3077 (at least if it is a file; don't do this for directories). 3488 (at least if it is a file; don't do this for directories).
3078 3489
3079 Since we mustn't do this if we are just changing the case of the 3490 Since we mustn't do this if we are just changing the case of the
@@ -3091,7 +3502,7 @@ sys_rename (const char * oldname, const char * newname)
3091 3502
3092 result = rename (temp, newname); 3503 result = rename (temp, newname);
3093 3504
3094 if (result < 0) 3505 if (result < 0 && force)
3095 { 3506 {
3096 DWORD w32err = GetLastError (); 3507 DWORD w32err = GetLastError ();
3097 3508
@@ -3131,6 +3542,12 @@ sys_rename (const char * oldname, const char * newname)
3131} 3542}
3132 3543
3133int 3544int
3545sys_rename (char const *old, char const *new)
3546{
3547 return sys_rename_replace (old, new, TRUE);
3548}
3549
3550int
3134sys_rmdir (const char * path) 3551sys_rmdir (const char * path)
3135{ 3552{
3136 return _rmdir (map_w32_filename (path, NULL)); 3553 return _rmdir (map_w32_filename (path, NULL));
@@ -3375,18 +3792,15 @@ w32_add_to_cache (PSID sid, unsigned id, char *name)
3375#define GID 2 3792#define GID 2
3376 3793
3377static int 3794static int
3378get_name_and_id (PSECURITY_DESCRIPTOR psd, const char *fname, 3795get_name_and_id (PSECURITY_DESCRIPTOR psd, unsigned *id, char *nm, int what)
3379 unsigned *id, char *nm, int what)
3380{ 3796{
3381 PSID sid = NULL; 3797 PSID sid = NULL;
3382 char machine[MAX_COMPUTERNAME_LENGTH+1];
3383 BOOL dflt; 3798 BOOL dflt;
3384 SID_NAME_USE ignore; 3799 SID_NAME_USE ignore;
3385 char name[UNLEN+1]; 3800 char name[UNLEN+1];
3386 DWORD name_len = sizeof (name); 3801 DWORD name_len = sizeof (name);
3387 char domain[1024]; 3802 char domain[1024];
3388 DWORD domain_len = sizeof (domain); 3803 DWORD domain_len = sizeof (domain);
3389 char *mp = NULL;
3390 int use_dflt = 0; 3804 int use_dflt = 0;
3391 int result; 3805 int result;
3392 3806
@@ -3401,22 +3815,7 @@ get_name_and_id (PSECURITY_DESCRIPTOR psd, const char *fname,
3401 use_dflt = 1; 3815 use_dflt = 1;
3402 else if (!w32_cached_id (sid, id, nm)) 3816 else if (!w32_cached_id (sid, id, nm))
3403 { 3817 {
3404 /* If FNAME is a UNC, we need to lookup account on the 3818 if (!lookup_account_sid (NULL, sid, name, &name_len,
3405 specified machine. */
3406 if (IS_DIRECTORY_SEP (fname[0]) && IS_DIRECTORY_SEP (fname[1])
3407 && fname[2] != '\0')
3408 {
3409 const char *s;
3410 char *p;
3411
3412 for (s = fname + 2, p = machine;
3413 *s && !IS_DIRECTORY_SEP (*s); s++, p++)
3414 *p = *s;
3415 *p = '\0';
3416 mp = machine;
3417 }
3418
3419 if (!lookup_account_sid (mp, sid, name, &name_len,
3420 domain, &domain_len, &ignore) 3819 domain, &domain_len, &ignore)
3421 || name_len > UNLEN+1) 3820 || name_len > UNLEN+1)
3422 use_dflt = 1; 3821 use_dflt = 1;
@@ -3431,9 +3830,7 @@ get_name_and_id (PSECURITY_DESCRIPTOR psd, const char *fname,
3431} 3830}
3432 3831
3433static void 3832static void
3434get_file_owner_and_group (PSECURITY_DESCRIPTOR psd, 3833get_file_owner_and_group (PSECURITY_DESCRIPTOR psd, struct stat *st)
3435 const char *fname,
3436 struct stat *st)
3437{ 3834{
3438 int dflt_usr = 0, dflt_grp = 0; 3835 int dflt_usr = 0, dflt_grp = 0;
3439 3836
@@ -3444,9 +3841,9 @@ get_file_owner_and_group (PSECURITY_DESCRIPTOR psd,
3444 } 3841 }
3445 else 3842 else
3446 { 3843 {
3447 if (get_name_and_id (psd, fname, &st->st_uid, st->st_uname, UID)) 3844 if (get_name_and_id (psd, &st->st_uid, st->st_uname, UID))
3448 dflt_usr = 1; 3845 dflt_usr = 1;
3449 if (get_name_and_id (psd, fname, &st->st_gid, st->st_gname, GID)) 3846 if (get_name_and_id (psd, &st->st_gid, st->st_gname, GID))
3450 dflt_grp = 1; 3847 dflt_grp = 1;
3451 } 3848 }
3452 /* Consider files to belong to current user/group, if we cannot get 3849 /* Consider files to belong to current user/group, if we cannot get
@@ -3485,6 +3882,10 @@ is_slow_fs (const char *name)
3485 return !(devtype == DRIVE_FIXED || devtype == DRIVE_RAMDISK); 3882 return !(devtype == DRIVE_FIXED || devtype == DRIVE_RAMDISK);
3486} 3883}
3487 3884
3885/* If this is non-zero, the caller wants accurate information about
3886 file's owner and group, which could be expensive to get. */
3887int w32_stat_get_owner_group;
3888
3488/* MSVC stat function can't cope with UNC names and has other bugs, so 3889/* MSVC stat function can't cope with UNC names and has other bugs, so
3489 replace it with our own. This also allows us to calculate consistent 3890 replace it with our own. This also allows us to calculate consistent
3490 inode values and owner/group without hacks in the main Emacs code. */ 3891 inode values and owner/group without hacks in the main Emacs code. */
@@ -3505,6 +3906,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3505 DWORD access_rights = 0; 3906 DWORD access_rights = 0;
3506 DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1; 3907 DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1;
3507 FILETIME ctime, atime, wtime; 3908 FILETIME ctime, atime, wtime;
3909 int dbcs_p;
3508 3910
3509 if (path == NULL || buf == NULL) 3911 if (path == NULL || buf == NULL)
3510 { 3912 {
@@ -3656,6 +4058,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3656 /* We produce the fallback owner and group data, based on the 4058 /* We produce the fallback owner and group data, based on the
3657 current user that runs Emacs, in the following cases: 4059 current user that runs Emacs, in the following cases:
3658 4060
4061 . caller didn't request owner and group info
3659 . this is Windows 9X 4062 . this is Windows 9X
3660 . getting security by handle failed, and we need to produce 4063 . getting security by handle failed, and we need to produce
3661 information for the target of a symlink (this is better 4064 information for the target of a symlink (this is better
@@ -3664,23 +4067,25 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3664 4067
3665 If getting security by handle fails, and we don't need to 4068 If getting security by handle fails, and we don't need to
3666 resolve symlinks, we try getting security by name. */ 4069 resolve symlinks, we try getting security by name. */
3667 if (is_windows_9x () != TRUE) 4070 if (!w32_stat_get_owner_group || is_windows_9x () == TRUE)
3668 psd = get_file_security_desc_by_handle (fh); 4071 get_file_owner_and_group (NULL, buf);
3669 if (psd) 4072 else
3670 {
3671 get_file_owner_and_group (psd, name, buf);
3672 LocalFree (psd);
3673 }
3674 else if (is_windows_9x () == TRUE)
3675 get_file_owner_and_group (NULL, name, buf);
3676 else if (!(is_a_symlink && follow_symlinks))
3677 { 4073 {
3678 psd = get_file_security_desc_by_name (name); 4074 psd = get_file_security_desc_by_handle (fh);
3679 get_file_owner_and_group (psd, name, buf); 4075 if (psd)
3680 xfree (psd); 4076 {
4077 get_file_owner_and_group (psd, buf);
4078 LocalFree (psd);
4079 }
4080 else if (!(is_a_symlink && follow_symlinks))
4081 {
4082 psd = get_file_security_desc_by_name (name);
4083 get_file_owner_and_group (psd, buf);
4084 xfree (psd);
4085 }
4086 else
4087 get_file_owner_and_group (NULL, buf);
3681 } 4088 }
3682 else
3683 get_file_owner_and_group (NULL, name, buf);
3684 CloseHandle (fh); 4089 CloseHandle (fh);
3685 } 4090 }
3686 else 4091 else
@@ -3699,6 +4104,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3699 did not ask for extra precision, resolving symlinks will fly 4104 did not ask for extra precision, resolving symlinks will fly
3700 in the face of that request, since the user then wants the 4105 in the face of that request, since the user then wants the
3701 lightweight version of the code. */ 4106 lightweight version of the code. */
4107 dbcs_p = max_filename_mbslen () > 1;
3702 rootdir = (path >= save_name + len - 1 4108 rootdir = (path >= save_name + len - 1
3703 && (IS_DIRECTORY_SEP (*path) || *path == 0)); 4109 && (IS_DIRECTORY_SEP (*path) || *path == 0));
3704 4110
@@ -3726,8 +4132,19 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3726 } 4132 }
3727 else if (rootdir) 4133 else if (rootdir)
3728 { 4134 {
3729 if (!IS_DIRECTORY_SEP (name[len-1])) 4135 if (!dbcs_p)
3730 strcat (name, "\\"); 4136 {
4137 if (!IS_DIRECTORY_SEP (name[len-1]))
4138 strcat (name, "\\");
4139 }
4140 else
4141 {
4142 char *end = name + len;
4143 char *n = CharPrevExA (file_name_codepage, name, end, 0);
4144
4145 if (!IS_DIRECTORY_SEP (*n))
4146 strcat (name, "\\");
4147 }
3731 if (GetDriveType (name) < 2) 4148 if (GetDriveType (name) < 2)
3732 { 4149 {
3733 errno = ENOENT; 4150 errno = ENOENT;
@@ -3739,15 +4156,37 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3739 } 4156 }
3740 else 4157 else
3741 { 4158 {
3742 if (IS_DIRECTORY_SEP (name[len-1])) 4159 if (!dbcs_p)
3743 name[len - 1] = 0; 4160 {
4161 if (IS_DIRECTORY_SEP (name[len-1]))
4162 name[len - 1] = 0;
4163 }
4164 else
4165 {
4166 char *end = name + len;
4167 char *n = CharPrevExA (file_name_codepage, name, end, 0);
4168
4169 if (IS_DIRECTORY_SEP (*n))
4170 *n = 0;
4171 }
3744 4172
3745 /* (This is hacky, but helps when doing file completions on 4173 /* (This is hacky, but helps when doing file completions on
3746 network drives.) Optimize by using information available from 4174 network drives.) Optimize by using information available from
3747 active readdir if possible. */ 4175 active readdir if possible. */
3748 len = strlen (dir_pathname); 4176 len = strlen (dir_pathname);
3749 if (IS_DIRECTORY_SEP (dir_pathname[len-1])) 4177 if (!dbcs_p)
3750 len--; 4178 {
4179 if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
4180 len--;
4181 }
4182 else
4183 {
4184 char *end = dir_pathname + len;
4185 char *n = CharPrevExA (file_name_codepage, dir_pathname, end, 0);
4186
4187 if (IS_DIRECTORY_SEP (*n))
4188 len--;
4189 }
3751 if (dir_find_handle != INVALID_HANDLE_VALUE 4190 if (dir_find_handle != INVALID_HANDLE_VALUE
3752 && !(is_a_symlink && follow_symlinks) 4191 && !(is_a_symlink && follow_symlinks)
3753 && strnicmp (save_name, dir_pathname, len) == 0 4192 && strnicmp (save_name, dir_pathname, len) == 0
@@ -3788,7 +4227,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3788 else 4227 else
3789 buf->st_mode = S_IFREG; 4228 buf->st_mode = S_IFREG;
3790 4229
3791 get_file_owner_and_group (NULL, name, buf); 4230 get_file_owner_and_group (NULL, buf);
3792 } 4231 }
3793 4232
3794#if 0 4233#if 0
@@ -3853,6 +4292,30 @@ lstat (const char * path, struct stat * buf)
3853 return stat_worker (path, buf, 0); 4292 return stat_worker (path, buf, 0);
3854} 4293}
3855 4294
4295int
4296fstatat (int fd, char const *name, struct stat *st, int flags)
4297{
4298 /* Rely on a hack: an open directory is modeled as file descriptor 0.
4299 This is good enough for the current usage in Emacs, but is fragile.
4300
4301 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
4302 Gnulib does this and can serve as a model. */
4303 char fullname[MAX_PATH];
4304
4305 if (fd != AT_FDCWD)
4306 {
4307 if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name)
4308 < 0)
4309 {
4310 errno = ENAMETOOLONG;
4311 return -1;
4312 }
4313 name = fullname;
4314 }
4315
4316 return stat_worker (name, st, ! (flags & AT_SYMLINK_NOFOLLOW));
4317}
4318
3856/* Provide fstat and utime as well as stat for consistent handling of 4319/* Provide fstat and utime as well as stat for consistent handling of
3857 file timestamps. */ 4320 file timestamps. */
3858int 4321int
@@ -3907,13 +4370,23 @@ fstat (int desc, struct stat * buf)
3907 else 4370 else
3908 buf->st_ino = fake_inode; 4371 buf->st_ino = fake_inode;
3909 4372
3910 /* Consider files to belong to current user. 4373 /* If the caller so requested, get the true file owner and group.
3911 FIXME: this should use GetSecurityInfo API, but it is only 4374 Otherwise, consider the file to belong to the current user. */
3912 available for _WIN32_WINNT >= 0x501. */ 4375 if (!w32_stat_get_owner_group || is_windows_9x () == TRUE)
3913 buf->st_uid = dflt_passwd.pw_uid; 4376 get_file_owner_and_group (NULL, buf);
3914 buf->st_gid = dflt_passwd.pw_gid; 4377 else
3915 strcpy (buf->st_uname, dflt_passwd.pw_name); 4378 {
3916 strcpy (buf->st_gname, dflt_group.gr_name); 4379 PSECURITY_DESCRIPTOR psd = NULL;
4380
4381 psd = get_file_security_desc_by_handle (fh);
4382 if (psd)
4383 {
4384 get_file_owner_and_group (psd, buf);
4385 LocalFree (psd);
4386 }
4387 else
4388 get_file_owner_and_group (NULL, buf);
4389 }
3917 4390
3918 buf->st_dev = info.dwVolumeSerialNumber; 4391 buf->st_dev = info.dwVolumeSerialNumber;
3919 buf->st_rdev = info.dwVolumeSerialNumber; 4392 buf->st_rdev = info.dwVolumeSerialNumber;
@@ -4008,6 +4481,7 @@ symlink (char const *filename, char const *linkname)
4008 char linkfn[MAX_PATH], *tgtfn; 4481 char linkfn[MAX_PATH], *tgtfn;
4009 DWORD flags = 0; 4482 DWORD flags = 0;
4010 int dir_access, filename_ends_in_slash; 4483 int dir_access, filename_ends_in_slash;
4484 int dbcs_p;
4011 4485
4012 /* Diagnostics follows Posix as much as possible. */ 4486 /* Diagnostics follows Posix as much as possible. */
4013 if (filename == NULL || linkname == NULL) 4487 if (filename == NULL || linkname == NULL)
@@ -4033,6 +4507,8 @@ symlink (char const *filename, char const *linkname)
4033 return -1; 4507 return -1;
4034 } 4508 }
4035 4509
4510 dbcs_p = max_filename_mbslen () > 1;
4511
4036 /* Note: since empty FILENAME was already rejected, we can safely 4512 /* Note: since empty FILENAME was already rejected, we can safely
4037 refer to FILENAME[1]. */ 4513 refer to FILENAME[1]. */
4038 if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1]))) 4514 if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1])))
@@ -4047,8 +4523,21 @@ symlink (char const *filename, char const *linkname)
4047 char tem[MAX_PATH]; 4523 char tem[MAX_PATH];
4048 char *p = linkfn + strlen (linkfn); 4524 char *p = linkfn + strlen (linkfn);
4049 4525
4050 while (p > linkfn && !IS_ANY_SEP (p[-1])) 4526 if (!dbcs_p)
4051 p--; 4527 {
4528 while (p > linkfn && !IS_ANY_SEP (p[-1]))
4529 p--;
4530 }
4531 else
4532 {
4533 char *p1 = CharPrevExA (file_name_codepage, linkfn, p, 0);
4534
4535 while (p > linkfn && !IS_ANY_SEP (*p1))
4536 {
4537 p = p1;
4538 p1 = CharPrevExA (file_name_codepage, linkfn, p1, 0);
4539 }
4540 }
4052 if (p > linkfn) 4541 if (p > linkfn)
4053 strncpy (tem, linkfn, p - linkfn); 4542 strncpy (tem, linkfn, p - linkfn);
4054 tem[p - linkfn] = '\0'; 4543 tem[p - linkfn] = '\0';
@@ -4063,7 +4552,15 @@ symlink (char const *filename, char const *linkname)
4063 exist, but ends in a slash, we create a symlink to directory. If 4552 exist, but ends in a slash, we create a symlink to directory. If
4064 FILENAME exists and is a directory, we always create a symlink to 4553 FILENAME exists and is a directory, we always create a symlink to
4065 directory. */ 4554 directory. */
4066 filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]); 4555 if (!dbcs_p)
4556 filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]);
4557 else
4558 {
4559 const char *end = filename + strlen (filename);
4560 const char *n = CharPrevExA (file_name_codepage, filename, end, 0);
4561
4562 filename_ends_in_slash = IS_DIRECTORY_SEP (*n);
4563 }
4067 if (dir_access == 0 || filename_ends_in_slash) 4564 if (dir_access == 0 || filename_ends_in_slash)
4068 flags = SYMBOLIC_LINK_FLAG_DIRECTORY; 4565 flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
4069 4566
@@ -4242,7 +4739,7 @@ readlink (const char *name, char *buf, size_t buf_size)
4242 errno = EINVAL; 4739 errno = EINVAL;
4243 else 4740 else
4244 { 4741 {
4245 /* Copy the link target name, in wide characters, fro 4742 /* Copy the link target name, in wide characters, from
4246 reparse_data, then convert it to multibyte encoding in 4743 reparse_data, then convert it to multibyte encoding in
4247 the current locale's codepage. */ 4744 the current locale's codepage. */
4248 WCHAR *lwname; 4745 WCHAR *lwname;
@@ -4253,6 +4750,8 @@ readlink (const char *name, char *buf, size_t buf_size)
4253 WCHAR *lwname_src = 4750 WCHAR *lwname_src =
4254 reparse_data->SymbolicLinkReparseBuffer.PathBuffer 4751 reparse_data->SymbolicLinkReparseBuffer.PathBuffer
4255 + reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR); 4752 + reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR);
4753 /* This updates file_name_codepage which we need below. */
4754 int dbcs_p = max_filename_mbslen () > 1;
4256 4755
4257 /* According to MSDN, PrintNameLength does not include the 4756 /* According to MSDN, PrintNameLength does not include the
4258 terminating null character. */ 4757 terminating null character. */
@@ -4260,9 +4759,7 @@ readlink (const char *name, char *buf, size_t buf_size)
4260 memcpy (lwname, lwname_src, lwname_len); 4759 memcpy (lwname, lwname_src, lwname_len);
4261 lwname[lwname_len/sizeof(WCHAR)] = 0; /* null-terminate */ 4760 lwname[lwname_len/sizeof(WCHAR)] = 0; /* null-terminate */
4262 4761
4263 /* FIXME: Should we use the current file-name coding system 4762 lname_len = WideCharToMultiByte (file_name_codepage, 0, lwname, -1,
4264 instead of the fixed value of the ANSI codepage? */
4265 lname_len = WideCharToMultiByte (w32_ansi_code_page, 0, lwname, -1,
4266 lname, MAX_PATH, NULL, NULL); 4763 lname, MAX_PATH, NULL, NULL);
4267 if (!lname_len) 4764 if (!lname_len)
4268 { 4765 {
@@ -4288,18 +4785,33 @@ readlink (const char *name, char *buf, size_t buf_size)
4288 else 4785 else
4289 { 4786 {
4290 size_t size_to_copy = buf_size; 4787 size_t size_to_copy = buf_size;
4291 BYTE *p = lname; 4788 BYTE *p = lname, *p2;
4292 BYTE *pend = p + lname_len; 4789 BYTE *pend = p + lname_len;
4293 4790
4294 /* Normalize like dostounix_filename does, but we don't 4791 /* Normalize like dostounix_filename does, but we don't
4295 want to assume that lname is null-terminated. */ 4792 want to assume that lname is null-terminated. */
4296 if (*p && p[1] == ':' && *p >= 'A' && *p <= 'Z') 4793 if (dbcs_p)
4297 *p += 'a' - 'A'; 4794 p2 = CharNextExA (file_name_codepage, p, 0);
4795 else
4796 p2 = p + 1;
4797 if (*p && *p2 == ':' && *p >= 'A' && *p <= 'Z')
4798 {
4799 *p += 'a' - 'A';
4800 p += 2;
4801 }
4298 while (p <= pend) 4802 while (p <= pend)
4299 { 4803 {
4300 if (*p == '\\') 4804 if (*p == '\\')
4301 *p = '/'; 4805 *p = '/';
4302 ++p; 4806 if (dbcs_p)
4807 {
4808 p = CharNextExA (file_name_codepage, p, 0);
4809 /* CharNextExA doesn't advance at null character. */
4810 if (!*p)
4811 break;
4812 }
4813 else
4814 ++p;
4303 } 4815 }
4304 /* Testing for null-terminated LNAME is paranoia: 4816 /* Testing for null-terminated LNAME is paranoia:
4305 WideCharToMultiByte should always return a 4817 WideCharToMultiByte should always return a
@@ -4346,6 +4858,28 @@ readlink (const char *name, char *buf, size_t buf_size)
4346 return retval; 4858 return retval;
4347} 4859}
4348 4860
4861ssize_t
4862readlinkat (int fd, char const *name, char *buffer,
4863 size_t buffer_size)
4864{
4865 /* Rely on a hack: an open directory is modeled as file descriptor 0,
4866 as in fstatat. FIXME: Add proper support for readlinkat. */
4867 char fullname[MAX_PATH];
4868
4869 if (fd != AT_FDCWD)
4870 {
4871 if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name)
4872 < 0)
4873 {
4874 errno = ENAMETOOLONG;
4875 return -1;
4876 }
4877 name = fullname;
4878 }
4879
4880 return readlink (name, buffer, buffer_size);
4881}
4882
4349/* If FILE is a symlink, return its target (stored in a static 4883/* If FILE is a symlink, return its target (stored in a static
4350 buffer); otherwise return FILE. 4884 buffer); otherwise return FILE.
4351 4885
@@ -4373,6 +4907,7 @@ chase_symlinks (const char *file)
4373 char link[MAX_PATH]; 4907 char link[MAX_PATH];
4374 ssize_t res, link_len; 4908 ssize_t res, link_len;
4375 int loop_count = 0; 4909 int loop_count = 0;
4910 int dbcs_p;
4376 4911
4377 if (is_windows_9x () == TRUE || !is_symlink (file)) 4912 if (is_windows_9x () == TRUE || !is_symlink (file))
4378 return (char *)file; 4913 return (char *)file;
@@ -4380,13 +4915,27 @@ chase_symlinks (const char *file)
4380 if ((link_len = GetFullPathName (file, MAX_PATH, link, NULL)) == 0) 4915 if ((link_len = GetFullPathName (file, MAX_PATH, link, NULL)) == 0)
4381 return (char *)file; 4916 return (char *)file;
4382 4917
4918 dbcs_p = max_filename_mbslen () > 1;
4383 target[0] = '\0'; 4919 target[0] = '\0';
4384 do { 4920 do {
4385 4921
4386 /* Remove trailing slashes, as we want to resolve the last 4922 /* Remove trailing slashes, as we want to resolve the last
4387 non-trivial part of the link name. */ 4923 non-trivial part of the link name. */
4388 while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1])) 4924 if (!dbcs_p)
4389 link[link_len--] = '\0'; 4925 {
4926 while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1]))
4927 link[link_len--] = '\0';
4928 }
4929 else if (link_len > 3)
4930 {
4931 char *n = CharPrevExA (file_name_codepage, link, link + link_len, 0);
4932
4933 while (n >= link + 2 && IS_DIRECTORY_SEP (*n))
4934 {
4935 n[1] = '\0';
4936 n = CharPrevExA (file_name_codepage, link, n, 0);
4937 }
4938 }
4390 4939
4391 res = readlink (link, target, MAX_PATH); 4940 res = readlink (link, target, MAX_PATH);
4392 if (res > 0) 4941 if (res > 0)
@@ -4399,8 +4948,21 @@ chase_symlinks (const char *file)
4399 the symlink, then copy the result back to target. */ 4948 the symlink, then copy the result back to target. */
4400 char *p = link + link_len; 4949 char *p = link + link_len;
4401 4950
4402 while (p > link && !IS_ANY_SEP (p[-1])) 4951 if (!dbcs_p)
4403 p--; 4952 {
4953 while (p > link && !IS_ANY_SEP (p[-1]))
4954 p--;
4955 }
4956 else
4957 {
4958 char *p1 = CharPrevExA (file_name_codepage, link, p, 0);
4959
4960 while (p > link && !IS_ANY_SEP (*p1))
4961 {
4962 p = p1;
4963 p1 = CharPrevExA (file_name_codepage, link, p1, 0);
4964 }
4965 }
4404 strcpy (p, target); 4966 strcpy (p, target);
4405 strcpy (target, link); 4967 strcpy (target, link);
4406 } 4968 }
@@ -4418,6 +4980,245 @@ chase_symlinks (const char *file)
4418 return target; 4980 return target;
4419} 4981}
4420 4982
4983
4984/* Posix ACL emulation. */
4985
4986int
4987acl_valid (acl_t acl)
4988{
4989 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR)acl) ? 0 : -1;
4990}
4991
4992char *
4993acl_to_text (acl_t acl, ssize_t *size)
4994{
4995 LPTSTR str_acl;
4996 SECURITY_INFORMATION flags =
4997 OWNER_SECURITY_INFORMATION |
4998 GROUP_SECURITY_INFORMATION |
4999 DACL_SECURITY_INFORMATION;
5000 char *retval = NULL;
5001 ULONG local_size;
5002 int e = errno;
5003
5004 errno = 0;
5005
5006 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR)acl, SDDL_REVISION_1, flags, &str_acl, &local_size))
5007 {
5008 errno = e;
5009 /* We don't want to mix heaps, so we duplicate the string in our
5010 heap and free the one allocated by the API. */
5011 retval = xstrdup (str_acl);
5012 if (size)
5013 *size = local_size;
5014 LocalFree (str_acl);
5015 }
5016 else if (errno != ENOTSUP)
5017 errno = EINVAL;
5018
5019 return retval;
5020}
5021
5022acl_t
5023acl_from_text (const char *acl_str)
5024{
5025 PSECURITY_DESCRIPTOR psd, retval = NULL;
5026 ULONG sd_size;
5027 int e = errno;
5028
5029 errno = 0;
5030
5031 if (convert_sddl_to_sd (acl_str, SDDL_REVISION_1, &psd, &sd_size))
5032 {
5033 errno = e;
5034 retval = xmalloc (sd_size);
5035 memcpy (retval, psd, sd_size);
5036 LocalFree (psd);
5037 }
5038 else if (errno != ENOTSUP)
5039 errno = EINVAL;
5040
5041 return retval;
5042}
5043
5044int
5045acl_free (void *ptr)
5046{
5047 xfree (ptr);
5048 return 0;
5049}
5050
5051acl_t
5052acl_get_file (const char *fname, acl_type_t type)
5053{
5054 PSECURITY_DESCRIPTOR psd = NULL;
5055 const char *filename;
5056
5057 if (type == ACL_TYPE_ACCESS)
5058 {
5059 DWORD sd_len, err;
5060 SECURITY_INFORMATION si =
5061 OWNER_SECURITY_INFORMATION |
5062 GROUP_SECURITY_INFORMATION |
5063 DACL_SECURITY_INFORMATION ;
5064 int e = errno;
5065
5066 filename = map_w32_filename (fname, NULL);
5067 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
5068 fname = chase_symlinks (filename);
5069 else
5070 fname = filename;
5071
5072 errno = 0;
5073 if (!get_file_security (fname, si, psd, 0, &sd_len)
5074 && errno != ENOTSUP)
5075 {
5076 err = GetLastError ();
5077 if (err == ERROR_INSUFFICIENT_BUFFER)
5078 {
5079 psd = xmalloc (sd_len);
5080 if (!get_file_security (fname, si, psd, sd_len, &sd_len))
5081 {
5082 xfree (psd);
5083 errno = EIO;
5084 psd = NULL;
5085 }
5086 }
5087 else if (err == ERROR_FILE_NOT_FOUND
5088 || err == ERROR_PATH_NOT_FOUND)
5089 errno = ENOENT;
5090 else
5091 errno = EIO;
5092 }
5093 else if (!errno)
5094 errno = e;
5095 }
5096 else if (type != ACL_TYPE_DEFAULT)
5097 errno = EINVAL;
5098
5099 return psd;
5100}
5101
5102int
5103acl_set_file (const char *fname, acl_type_t type, acl_t acl)
5104{
5105 TOKEN_PRIVILEGES old1, old2;
5106 DWORD err;
5107 int st = 0, retval = -1;
5108 SECURITY_INFORMATION flags = 0;
5109 PSID psid;
5110 PACL pacl;
5111 BOOL dflt;
5112 BOOL dacl_present;
5113 int e;
5114 const char *filename;
5115
5116 if (acl_valid (acl) != 0
5117 || (type != ACL_TYPE_DEFAULT && type != ACL_TYPE_ACCESS))
5118 {
5119 errno = EINVAL;
5120 return -1;
5121 }
5122
5123 if (type == ACL_TYPE_DEFAULT)
5124 {
5125 errno = ENOSYS;
5126 return -1;
5127 }
5128
5129 filename = map_w32_filename (fname, NULL);
5130 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
5131 fname = chase_symlinks (filename);
5132 else
5133 fname = filename;
5134
5135 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR)acl, &psid, &dflt)
5136 && psid)
5137 flags |= OWNER_SECURITY_INFORMATION;
5138 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR)acl, &psid, &dflt)
5139 && psid)
5140 flags |= GROUP_SECURITY_INFORMATION;
5141 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR)acl, &dacl_present,
5142 &pacl, &dflt)
5143 && dacl_present)
5144 flags |= DACL_SECURITY_INFORMATION;
5145 if (!flags)
5146 return 0;
5147
5148 /* According to KB-245153, setting the owner will succeed if either:
5149 (1) the caller is the user who will be the new owner, and has the
5150 SE_TAKE_OWNERSHIP privilege, or
5151 (2) the caller has the SE_RESTORE privilege, in which case she can
5152 set any valid user or group as the owner
5153
5154 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
5155 privileges, and disregard any failures in obtaining them. If
5156 these privileges cannot be obtained, and do not already exist in
5157 the calling thread's security token, this function could fail
5158 with EPERM. */
5159 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME, TRUE, &old1))
5160 st++;
5161 if (enable_privilege (SE_RESTORE_NAME, TRUE, &old2))
5162 st++;
5163
5164 e = errno;
5165 errno = 0;
5166 if (!set_file_security ((char *)fname, flags, (PSECURITY_DESCRIPTOR)acl))
5167 {
5168 err = GetLastError ();
5169
5170 if (errno == ENOTSUP)
5171 ;
5172 else if (err == ERROR_INVALID_OWNER
5173 || err == ERROR_NOT_ALL_ASSIGNED
5174 || err == ERROR_ACCESS_DENIED)
5175 {
5176 /* Maybe the requested ACL and the one the file already has
5177 are identical, in which case we can silently ignore the
5178 failure. (And no, Windows doesn't.) */
5179 acl_t current_acl = acl_get_file (fname, ACL_TYPE_ACCESS);
5180
5181 errno = EPERM;
5182 if (current_acl)
5183 {
5184 char *acl_from = acl_to_text (current_acl, NULL);
5185 char *acl_to = acl_to_text (acl, NULL);
5186
5187 if (acl_from && acl_to && xstrcasecmp (acl_from, acl_to) == 0)
5188 {
5189 retval = 0;
5190 errno = e;
5191 }
5192 if (acl_from)
5193 acl_free (acl_from);
5194 if (acl_to)
5195 acl_free (acl_to);
5196 acl_free (current_acl);
5197 }
5198 }
5199 else if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
5200 errno = ENOENT;
5201 else
5202 errno = EACCES;
5203 }
5204 else
5205 {
5206 retval = 0;
5207 errno = e;
5208 }
5209
5210 if (st)
5211 {
5212 if (st >= 2)
5213 restore_privilege (&old2);
5214 restore_privilege (&old1);
5215 revert_to_self ();
5216 }
5217
5218 return retval;
5219}
5220
5221
4421/* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We 5222/* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
4422 have a fixed max size for file names, so we don't need the kind of 5223 have a fixed max size for file names, so we don't need the kind of
4423 alloc/malloc/realloc dance the gnulib version does. We also don't 5224 alloc/malloc/realloc dance the gnulib version does. We also don't
@@ -4431,12 +5232,6 @@ careadlinkat (int fd, char const *filename,
4431 char linkname[MAX_PATH]; 5232 char linkname[MAX_PATH];
4432 ssize_t link_size; 5233 ssize_t link_size;
4433 5234
4434 if (fd != AT_FDCWD)
4435 {
4436 errno = EINVAL;
4437 return NULL;
4438 }
4439
4440 link_size = preadlinkat (fd, filename, linkname, sizeof(linkname)); 5235 link_size = preadlinkat (fd, filename, linkname, sizeof(linkname));
4441 5236
4442 if (link_size > 0) 5237 if (link_size > 0)
@@ -4454,14 +5249,6 @@ careadlinkat (int fd, char const *filename,
4454 return NULL; 5249 return NULL;
4455} 5250}
4456 5251
4457ssize_t
4458careadlinkatcwd (int fd, char const *filename, char *buffer,
4459 size_t buffer_size)
4460{
4461 (void) fd;
4462 return readlink (filename, buffer, buffer_size);
4463}
4464
4465 5252
4466/* Support for browsing other processes and their attributes. See 5253/* Support for browsing other processes and their attributes. See
4467 process.c for the Lisp bindings. */ 5254 process.c for the Lisp bindings. */
@@ -4633,8 +5420,8 @@ get_process_memory_info (HANDLE h_proc,
4633 5420
4634static BOOL WINAPI 5421static BOOL WINAPI
4635get_process_working_set_size (HANDLE h_proc, 5422get_process_working_set_size (HANDLE h_proc,
4636 DWORD *minrss, 5423 PSIZE_T minrss,
4637 DWORD *maxrss) 5424 PSIZE_T maxrss)
4638{ 5425{
4639 static GetProcessWorkingSetSize_Proc 5426 static GetProcessWorkingSetSize_Proc
4640 s_pfn_Get_Process_Working_Set_Size = NULL; 5427 s_pfn_Get_Process_Working_Set_Size = NULL;
@@ -4799,10 +5586,8 @@ ltime (ULONGLONG time_100ns)
4799{ 5586{
4800 ULONGLONG time_sec = time_100ns / 10000000; 5587 ULONGLONG time_sec = time_100ns / 10000000;
4801 int subsec = time_100ns % 10000000; 5588 int subsec = time_100ns % 10000000;
4802 return list4 (make_number (time_sec >> 16), 5589 return list4i (time_sec >> 16, time_sec & 0xffff,
4803 make_number (time_sec & 0xffff), 5590 subsec / 10, subsec % 10 * 100000);
4804 make_number (subsec / 10),
4805 make_number (subsec % 10 * 100000));
4806} 5591}
4807 5592
4808#define U64_TO_LISP_TIME(time) ltime (time) 5593#define U64_TO_LISP_TIME(time) ltime (time)
@@ -4879,7 +5664,7 @@ system_process_attributes (Lisp_Object pid)
4879 unsigned egid; 5664 unsigned egid;
4880 PROCESS_MEMORY_COUNTERS mem; 5665 PROCESS_MEMORY_COUNTERS mem;
4881 PROCESS_MEMORY_COUNTERS_EX mem_ex; 5666 PROCESS_MEMORY_COUNTERS_EX mem_ex;
4882 DWORD minrss, maxrss; 5667 SIZE_T minrss, maxrss;
4883 MEMORYSTATUS memst; 5668 MEMORYSTATUS memst;
4884 MEMORY_STATUS_EX memstex; 5669 MEMORY_STATUS_EX memstex;
4885 double totphys = 0.0; 5670 double totphys = 0.0;
@@ -5107,7 +5892,7 @@ system_process_attributes (Lisp_Object pid)
5107 && get_process_memory_info (h_proc, (PROCESS_MEMORY_COUNTERS *)&mem_ex, 5892 && get_process_memory_info (h_proc, (PROCESS_MEMORY_COUNTERS *)&mem_ex,
5108 sizeof (mem_ex))) 5893 sizeof (mem_ex)))
5109 { 5894 {
5110 DWORD rss = mem_ex.WorkingSetSize / 1024; 5895 SIZE_T rss = mem_ex.WorkingSetSize / 1024;
5111 5896
5112 attrs = Fcons (Fcons (Qmajflt, 5897 attrs = Fcons (Fcons (Qmajflt,
5113 make_fixnum_or_float (mem_ex.PageFaultCount)), 5898 make_fixnum_or_float (mem_ex.PageFaultCount)),
@@ -5122,7 +5907,7 @@ system_process_attributes (Lisp_Object pid)
5122 else if (h_proc 5907 else if (h_proc
5123 && get_process_memory_info (h_proc, &mem, sizeof (mem))) 5908 && get_process_memory_info (h_proc, &mem, sizeof (mem)))
5124 { 5909 {
5125 DWORD rss = mem_ex.WorkingSetSize / 1024; 5910 SIZE_T rss = mem_ex.WorkingSetSize / 1024;
5126 5911
5127 attrs = Fcons (Fcons (Qmajflt, 5912 attrs = Fcons (Fcons (Qmajflt,
5128 make_fixnum_or_float (mem.PageFaultCount)), 5913 make_fixnum_or_float (mem.PageFaultCount)),
@@ -5316,35 +6101,39 @@ init_winsock (int load_now)
5316 6101
5317int h_errno = 0; 6102int h_errno = 0;
5318 6103
5319/* function to set h_errno for compatibility; map winsock error codes to 6104/* Function to map winsock error codes to errno codes for those errno
5320 normal system codes where they overlap (non-overlapping definitions 6105 code defined in errno.h (errno values not defined by errno.h are
5321 are already in <sys/socket.h> */ 6106 already in nt/inc/sys/socket.h). */
5322static void 6107static void
5323set_errno (void) 6108set_errno (void)
5324{ 6109{
6110 int wsa_err;
6111
6112 h_errno = 0;
5325 if (winsock_lib == NULL) 6113 if (winsock_lib == NULL)
5326 h_errno = EINVAL; 6114 wsa_err = EINVAL;
5327 else 6115 else
5328 h_errno = pfn_WSAGetLastError (); 6116 wsa_err = pfn_WSAGetLastError ();
5329 6117
5330 switch (h_errno) 6118 switch (wsa_err)
5331 { 6119 {
5332 case WSAEACCES: h_errno = EACCES; break; 6120 case WSAEACCES: errno = EACCES; break;
5333 case WSAEBADF: h_errno = EBADF; break; 6121 case WSAEBADF: errno = EBADF; break;
5334 case WSAEFAULT: h_errno = EFAULT; break; 6122 case WSAEFAULT: errno = EFAULT; break;
5335 case WSAEINTR: h_errno = EINTR; break; 6123 case WSAEINTR: errno = EINTR; break;
5336 case WSAEINVAL: h_errno = EINVAL; break; 6124 case WSAEINVAL: errno = EINVAL; break;
5337 case WSAEMFILE: h_errno = EMFILE; break; 6125 case WSAEMFILE: errno = EMFILE; break;
5338 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break; 6126 case WSAENAMETOOLONG: errno = ENAMETOOLONG; break;
5339 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break; 6127 case WSAENOTEMPTY: errno = ENOTEMPTY; break;
6128 default: errno = wsa_err; break;
5340 } 6129 }
5341 errno = h_errno;
5342} 6130}
5343 6131
5344static void 6132static void
5345check_errno (void) 6133check_errno (void)
5346{ 6134{
5347 if (h_errno == 0 && winsock_lib != NULL) 6135 h_errno = 0;
6136 if (winsock_lib != NULL)
5348 pfn_WSASetLastError (0); 6137 pfn_WSASetLastError (0);
5349} 6138}
5350 6139
@@ -5456,7 +6245,7 @@ sys_socket (int af, int type, int protocol)
5456 6245
5457 if (winsock_lib == NULL) 6246 if (winsock_lib == NULL)
5458 { 6247 {
5459 h_errno = ENETDOWN; 6248 errno = ENETDOWN;
5460 return INVALID_SOCKET; 6249 return INVALID_SOCKET;
5461 } 6250 }
5462 6251
@@ -5533,6 +6322,7 @@ socket_to_fd (SOCKET s)
5533 } 6322 }
5534 } 6323 }
5535 } 6324 }
6325 eassert (fd < MAXDESC);
5536 fd_info[fd].hnd = (HANDLE) s; 6326 fd_info[fd].hnd = (HANDLE) s;
5537 6327
5538 /* set our own internal flags */ 6328 /* set our own internal flags */
@@ -5561,8 +6351,9 @@ socket_to_fd (SOCKET s)
5561 /* clean up */ 6351 /* clean up */
5562 _close (fd); 6352 _close (fd);
5563 } 6353 }
6354 else
5564 pfn_closesocket (s); 6355 pfn_closesocket (s);
5565 h_errno = EMFILE; 6356 errno = EMFILE;
5566 return -1; 6357 return -1;
5567} 6358}
5568 6359
@@ -5571,7 +6362,7 @@ sys_bind (int s, const struct sockaddr * addr, int namelen)
5571{ 6362{
5572 if (winsock_lib == NULL) 6363 if (winsock_lib == NULL)
5573 { 6364 {
5574 h_errno = ENOTSOCK; 6365 errno = ENOTSOCK;
5575 return SOCKET_ERROR; 6366 return SOCKET_ERROR;
5576 } 6367 }
5577 6368
@@ -5583,7 +6374,7 @@ sys_bind (int s, const struct sockaddr * addr, int namelen)
5583 set_errno (); 6374 set_errno ();
5584 return rc; 6375 return rc;
5585 } 6376 }
5586 h_errno = ENOTSOCK; 6377 errno = ENOTSOCK;
5587 return SOCKET_ERROR; 6378 return SOCKET_ERROR;
5588} 6379}
5589 6380
@@ -5592,7 +6383,7 @@ sys_connect (int s, const struct sockaddr * name, int namelen)
5592{ 6383{
5593 if (winsock_lib == NULL) 6384 if (winsock_lib == NULL)
5594 { 6385 {
5595 h_errno = ENOTSOCK; 6386 errno = ENOTSOCK;
5596 return SOCKET_ERROR; 6387 return SOCKET_ERROR;
5597 } 6388 }
5598 6389
@@ -5604,7 +6395,7 @@ sys_connect (int s, const struct sockaddr * name, int namelen)
5604 set_errno (); 6395 set_errno ();
5605 return rc; 6396 return rc;
5606 } 6397 }
5607 h_errno = ENOTSOCK; 6398 errno = ENOTSOCK;
5608 return SOCKET_ERROR; 6399 return SOCKET_ERROR;
5609} 6400}
5610 6401
@@ -5633,12 +6424,20 @@ int
5633sys_gethostname (char * name, int namelen) 6424sys_gethostname (char * name, int namelen)
5634{ 6425{
5635 if (winsock_lib != NULL) 6426 if (winsock_lib != NULL)
5636 return pfn_gethostname (name, namelen); 6427 {
6428 int retval;
6429
6430 check_errno ();
6431 retval = pfn_gethostname (name, namelen);
6432 if (retval == SOCKET_ERROR)
6433 set_errno ();
6434 return retval;
6435 }
5637 6436
5638 if (namelen > MAX_COMPUTERNAME_LENGTH) 6437 if (namelen > MAX_COMPUTERNAME_LENGTH)
5639 return !GetComputerName (name, (DWORD *)&namelen); 6438 return !GetComputerName (name, (DWORD *)&namelen);
5640 6439
5641 h_errno = EFAULT; 6440 errno = EFAULT;
5642 return SOCKET_ERROR; 6441 return SOCKET_ERROR;
5643} 6442}
5644 6443
@@ -5646,17 +6445,24 @@ struct hostent *
5646sys_gethostbyname (const char * name) 6445sys_gethostbyname (const char * name)
5647{ 6446{
5648 struct hostent * host; 6447 struct hostent * host;
6448 int h_err = h_errno;
5649 6449
5650 if (winsock_lib == NULL) 6450 if (winsock_lib == NULL)
5651 { 6451 {
5652 h_errno = ENETDOWN; 6452 h_errno = NO_RECOVERY;
6453 errno = ENETDOWN;
5653 return NULL; 6454 return NULL;
5654 } 6455 }
5655 6456
5656 check_errno (); 6457 check_errno ();
5657 host = pfn_gethostbyname (name); 6458 host = pfn_gethostbyname (name);
5658 if (!host) 6459 if (!host)
5659 set_errno (); 6460 {
6461 set_errno ();
6462 h_errno = errno;
6463 }
6464 else
6465 h_errno = h_err;
5660 return host; 6466 return host;
5661} 6467}
5662 6468
@@ -5667,7 +6473,7 @@ sys_getservbyname (const char * name, const char * proto)
5667 6473
5668 if (winsock_lib == NULL) 6474 if (winsock_lib == NULL)
5669 { 6475 {
5670 h_errno = ENETDOWN; 6476 errno = ENETDOWN;
5671 return NULL; 6477 return NULL;
5672 } 6478 }
5673 6479
@@ -5683,7 +6489,7 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen)
5683{ 6489{
5684 if (winsock_lib == NULL) 6490 if (winsock_lib == NULL)
5685 { 6491 {
5686 h_errno = ENETDOWN; 6492 errno = ENETDOWN;
5687 return SOCKET_ERROR; 6493 return SOCKET_ERROR;
5688 } 6494 }
5689 6495
@@ -5695,7 +6501,7 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen)
5695 set_errno (); 6501 set_errno ();
5696 return rc; 6502 return rc;
5697 } 6503 }
5698 h_errno = ENOTSOCK; 6504 errno = ENOTSOCK;
5699 return SOCKET_ERROR; 6505 return SOCKET_ERROR;
5700} 6506}
5701 6507
@@ -5704,7 +6510,7 @@ sys_shutdown (int s, int how)
5704{ 6510{
5705 if (winsock_lib == NULL) 6511 if (winsock_lib == NULL)
5706 { 6512 {
5707 h_errno = ENETDOWN; 6513 errno = ENETDOWN;
5708 return SOCKET_ERROR; 6514 return SOCKET_ERROR;
5709 } 6515 }
5710 6516
@@ -5716,7 +6522,7 @@ sys_shutdown (int s, int how)
5716 set_errno (); 6522 set_errno ();
5717 return rc; 6523 return rc;
5718 } 6524 }
5719 h_errno = ENOTSOCK; 6525 errno = ENOTSOCK;
5720 return SOCKET_ERROR; 6526 return SOCKET_ERROR;
5721} 6527}
5722 6528
@@ -5725,7 +6531,7 @@ sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
5725{ 6531{
5726 if (winsock_lib == NULL) 6532 if (winsock_lib == NULL)
5727 { 6533 {
5728 h_errno = ENETDOWN; 6534 errno = ENETDOWN;
5729 return SOCKET_ERROR; 6535 return SOCKET_ERROR;
5730 } 6536 }
5731 6537
@@ -5738,7 +6544,7 @@ sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
5738 set_errno (); 6544 set_errno ();
5739 return rc; 6545 return rc;
5740 } 6546 }
5741 h_errno = ENOTSOCK; 6547 errno = ENOTSOCK;
5742 return SOCKET_ERROR; 6548 return SOCKET_ERROR;
5743} 6549}
5744 6550
@@ -5747,7 +6553,7 @@ sys_listen (int s, int backlog)
5747{ 6553{
5748 if (winsock_lib == NULL) 6554 if (winsock_lib == NULL)
5749 { 6555 {
5750 h_errno = ENETDOWN; 6556 errno = ENETDOWN;
5751 return SOCKET_ERROR; 6557 return SOCKET_ERROR;
5752 } 6558 }
5753 6559
@@ -5761,7 +6567,7 @@ sys_listen (int s, int backlog)
5761 fd_info[s].flags |= FILE_LISTEN; 6567 fd_info[s].flags |= FILE_LISTEN;
5762 return rc; 6568 return rc;
5763 } 6569 }
5764 h_errno = ENOTSOCK; 6570 errno = ENOTSOCK;
5765 return SOCKET_ERROR; 6571 return SOCKET_ERROR;
5766} 6572}
5767 6573
@@ -5770,7 +6576,7 @@ sys_getsockname (int s, struct sockaddr * name, int * namelen)
5770{ 6576{
5771 if (winsock_lib == NULL) 6577 if (winsock_lib == NULL)
5772 { 6578 {
5773 h_errno = ENETDOWN; 6579 errno = ENETDOWN;
5774 return SOCKET_ERROR; 6580 return SOCKET_ERROR;
5775 } 6581 }
5776 6582
@@ -5782,7 +6588,7 @@ sys_getsockname (int s, struct sockaddr * name, int * namelen)
5782 set_errno (); 6588 set_errno ();
5783 return rc; 6589 return rc;
5784 } 6590 }
5785 h_errno = ENOTSOCK; 6591 errno = ENOTSOCK;
5786 return SOCKET_ERROR; 6592 return SOCKET_ERROR;
5787} 6593}
5788 6594
@@ -5791,7 +6597,7 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen)
5791{ 6597{
5792 if (winsock_lib == NULL) 6598 if (winsock_lib == NULL)
5793 { 6599 {
5794 h_errno = ENETDOWN; 6600 errno = ENETDOWN;
5795 return -1; 6601 return -1;
5796 } 6602 }
5797 6603
@@ -5805,11 +6611,14 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen)
5805 else 6611 else
5806 fd = socket_to_fd (t); 6612 fd = socket_to_fd (t);
5807 6613
5808 fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED; 6614 if (fd >= 0)
5809 ResetEvent (fd_info[s].cp->char_avail); 6615 {
6616 fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
6617 ResetEvent (fd_info[s].cp->char_avail);
6618 }
5810 return fd; 6619 return fd;
5811 } 6620 }
5812 h_errno = ENOTSOCK; 6621 errno = ENOTSOCK;
5813 return -1; 6622 return -1;
5814} 6623}
5815 6624
@@ -5819,7 +6628,7 @@ sys_recvfrom (int s, char * buf, int len, int flags,
5819{ 6628{
5820 if (winsock_lib == NULL) 6629 if (winsock_lib == NULL)
5821 { 6630 {
5822 h_errno = ENETDOWN; 6631 errno = ENETDOWN;
5823 return SOCKET_ERROR; 6632 return SOCKET_ERROR;
5824 } 6633 }
5825 6634
@@ -5831,7 +6640,7 @@ sys_recvfrom (int s, char * buf, int len, int flags,
5831 set_errno (); 6640 set_errno ();
5832 return rc; 6641 return rc;
5833 } 6642 }
5834 h_errno = ENOTSOCK; 6643 errno = ENOTSOCK;
5835 return SOCKET_ERROR; 6644 return SOCKET_ERROR;
5836} 6645}
5837 6646
@@ -5841,7 +6650,7 @@ sys_sendto (int s, const char * buf, int len, int flags,
5841{ 6650{
5842 if (winsock_lib == NULL) 6651 if (winsock_lib == NULL)
5843 { 6652 {
5844 h_errno = ENETDOWN; 6653 errno = ENETDOWN;
5845 return SOCKET_ERROR; 6654 return SOCKET_ERROR;
5846 } 6655 }
5847 6656
@@ -5853,7 +6662,7 @@ sys_sendto (int s, const char * buf, int len, int flags,
5853 set_errno (); 6662 set_errno ();
5854 return rc; 6663 return rc;
5855 } 6664 }
5856 h_errno = ENOTSOCK; 6665 errno = ENOTSOCK;
5857 return SOCKET_ERROR; 6666 return SOCKET_ERROR;
5858} 6667}
5859 6668
@@ -5864,7 +6673,7 @@ fcntl (int s, int cmd, int options)
5864{ 6673{
5865 if (winsock_lib == NULL) 6674 if (winsock_lib == NULL)
5866 { 6675 {
5867 h_errno = ENETDOWN; 6676 errno = ENETDOWN;
5868 return -1; 6677 return -1;
5869 } 6678 }
5870 6679
@@ -5883,11 +6692,11 @@ fcntl (int s, int cmd, int options)
5883 } 6692 }
5884 else 6693 else
5885 { 6694 {
5886 h_errno = EINVAL; 6695 errno = EINVAL;
5887 return SOCKET_ERROR; 6696 return SOCKET_ERROR;
5888 } 6697 }
5889 } 6698 }
5890 h_errno = ENOTSOCK; 6699 errno = ENOTSOCK;
5891 return SOCKET_ERROR; 6700 return SOCKET_ERROR;
5892} 6701}
5893 6702
@@ -5934,20 +6743,34 @@ sys_close (int fd)
5934 6743
5935 winsock_inuse--; /* count open sockets */ 6744 winsock_inuse--; /* count open sockets */
5936 } 6745 }
5937 delete_child (cp); 6746 /* If the process handle is NULL, it's either a socket
6747 or serial connection, or a subprocess that was
6748 already reaped by reap_subprocess, but whose
6749 resources were not yet freed, because its output was
6750 not fully read yet by the time it was reaped. (This
6751 usually happens with async subprocesses whose output
6752 is being read by Emacs.) Otherwise, this process was
6753 not reaped yet, so we set its FD to a negative value
6754 to make sure sys_select will eventually get to
6755 calling the SIGCHLD handler for it, which will then
6756 invoke waitpid and reap_subprocess. */
6757 if (cp->procinfo.hProcess == NULL)
6758 delete_child (cp);
6759 else
6760 cp->fd = -1;
5938 } 6761 }
5939 } 6762 }
5940 } 6763 }
5941 6764
6765 if (fd >= 0 && fd < MAXDESC)
6766 fd_info[fd].flags = 0;
6767
5942 /* Note that sockets do not need special treatment here (at least on 6768 /* Note that sockets do not need special treatment here (at least on
5943 NT and Windows 95 using the standard tcp/ip stacks) - it appears that 6769 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
5944 closesocket is equivalent to CloseHandle, which is to be expected 6770 closesocket is equivalent to CloseHandle, which is to be expected
5945 because socket handles are fully fledged kernel handles. */ 6771 because socket handles are fully fledged kernel handles. */
5946 rc = _close (fd); 6772 rc = _close (fd);
5947 6773
5948 if (rc == 0 && fd < MAXDESC)
5949 fd_info[fd].flags = 0;
5950
5951 return rc; 6774 return rc;
5952} 6775}
5953 6776
@@ -6010,6 +6833,7 @@ sys_pipe (int * phandles)
6010 { 6833 {
6011 _close (phandles[0]); 6834 _close (phandles[0]);
6012 _close (phandles[1]); 6835 _close (phandles[1]);
6836 errno = EMFILE;
6013 rc = -1; 6837 rc = -1;
6014 } 6838 }
6015 else 6839 else
@@ -6026,7 +6850,8 @@ sys_pipe (int * phandles)
6026} 6850}
6027 6851
6028/* Function to do blocking read of one byte, needed to implement 6852/* Function to do blocking read of one byte, needed to implement
6029 select. It is only allowed on sockets and pipes. */ 6853 select. It is only allowed on communication ports, sockets, or
6854 pipes. */
6030int 6855int
6031_sys_read_ahead (int fd) 6856_sys_read_ahead (int fd)
6032{ 6857{
@@ -6082,19 +6907,31 @@ _sys_read_ahead (int fd)
6082 6907
6083 /* Configure timeouts for blocking read. */ 6908 /* Configure timeouts for blocking read. */
6084 if (!GetCommTimeouts (hnd, &ct)) 6909 if (!GetCommTimeouts (hnd, &ct))
6085 return STATUS_READ_ERROR; 6910 {
6911 cp->status = STATUS_READ_ERROR;
6912 return STATUS_READ_ERROR;
6913 }
6086 ct.ReadIntervalTimeout = 0; 6914 ct.ReadIntervalTimeout = 0;
6087 ct.ReadTotalTimeoutMultiplier = 0; 6915 ct.ReadTotalTimeoutMultiplier = 0;
6088 ct.ReadTotalTimeoutConstant = 0; 6916 ct.ReadTotalTimeoutConstant = 0;
6089 if (!SetCommTimeouts (hnd, &ct)) 6917 if (!SetCommTimeouts (hnd, &ct))
6090 return STATUS_READ_ERROR; 6918 {
6919 cp->status = STATUS_READ_ERROR;
6920 return STATUS_READ_ERROR;
6921 }
6091 6922
6092 if (!ReadFile (hnd, &cp->chr, sizeof (char), (DWORD*) &rc, ovl)) 6923 if (!ReadFile (hnd, &cp->chr, sizeof (char), (DWORD*) &rc, ovl))
6093 { 6924 {
6094 if (GetLastError () != ERROR_IO_PENDING) 6925 if (GetLastError () != ERROR_IO_PENDING)
6095 return STATUS_READ_ERROR; 6926 {
6927 cp->status = STATUS_READ_ERROR;
6928 return STATUS_READ_ERROR;
6929 }
6096 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE)) 6930 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE))
6097 return STATUS_READ_ERROR; 6931 {
6932 cp->status = STATUS_READ_ERROR;
6933 return STATUS_READ_ERROR;
6934 }
6098 } 6935 }
6099 } 6936 }
6100 else if (fd_info[fd].flags & FILE_SOCKET) 6937 else if (fd_info[fd].flags & FILE_SOCKET)
@@ -6290,7 +7127,7 @@ sys_read (int fd, char * buffer, unsigned int count)
6290 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting); 7127 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
6291 if (waiting == 0 && nchars == 0) 7128 if (waiting == 0 && nchars == 0)
6292 { 7129 {
6293 h_errno = errno = EWOULDBLOCK; 7130 errno = EWOULDBLOCK;
6294 return -1; 7131 return -1;
6295 } 7132 }
6296 7133
@@ -6788,6 +7625,11 @@ globals_of_w32 (void)
6788 g_b_init_get_native_system_info = 0; 7625 g_b_init_get_native_system_info = 0;
6789 g_b_init_get_system_times = 0; 7626 g_b_init_get_system_times = 0;
6790 g_b_init_create_symbolic_link = 0; 7627 g_b_init_create_symbolic_link = 0;
7628 g_b_init_get_security_descriptor_dacl = 0;
7629 g_b_init_convert_sd_to_sddl = 0;
7630 g_b_init_convert_sddl_to_sd = 0;
7631 g_b_init_is_valid_security_descriptor = 0;
7632 g_b_init_set_file_security = 0;
6791 num_of_processors = 0; 7633 num_of_processors = 0;
6792 /* The following sets a handler for shutdown notifications for 7634 /* The following sets a handler for shutdown notifications for
6793 console apps. This actually applies to Emacs in both console and 7635 console apps. This actually applies to Emacs in both console and
@@ -6797,6 +7639,9 @@ globals_of_w32 (void)
6797 7639
6798 /* "None" is the default group name on standalone workstations. */ 7640 /* "None" is the default group name on standalone workstations. */
6799 strcpy (dflt_group_name, "None"); 7641 strcpy (dflt_group_name, "None");
7642
7643 /* Reset, in case it has some value inherited from dump time. */
7644 w32_stat_get_owner_group = 0;
6800} 7645}
6801 7646
6802/* For make-serial-process */ 7647/* For make-serial-process */
@@ -6994,47 +7839,26 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
6994ssize_t 7839ssize_t
6995emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz) 7840emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
6996{ 7841{
6997 int n, sc, err; 7842 int n, err;
6998 SELECT_TYPE fdset; 7843 SELECT_TYPE fdset;
6999 EMACS_TIME timeout; 7844 EMACS_TIME timeout;
7000 struct Lisp_Process *process = (struct Lisp_Process *)p; 7845 struct Lisp_Process *process = (struct Lisp_Process *)p;
7001 int fd = process->infd; 7846 int fd = process->infd;
7002 7847
7003 for (;;) 7848 n = sys_read (fd, (char*)buf, sz);
7004 {
7005 n = sys_read (fd, (char*)buf, sz);
7006 7849
7007 if (n >= 0) 7850 if (n >= 0)
7008 return n; 7851 return n;
7009 7852
7010 err = errno; 7853 err = errno;
7011 7854
7012 if (err == EWOULDBLOCK) 7855 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
7013 { 7856 if (err == EWOULDBLOCK)
7014 /* Set a small timeout. */ 7857 err = EAGAIN;
7015 timeout = make_emacs_time (1, 0);
7016 FD_ZERO (&fdset);
7017 FD_SET ((int)fd, &fdset);
7018
7019 /* Use select with the timeout to poll the selector. */
7020 sc = select (fd + 1, &fdset, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
7021 &timeout, NULL);
7022
7023 if (sc > 0)
7024 continue; /* Try again. */
7025
7026 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN.
7027 Also accept select return 0 as an indicator to EAGAIN. */
7028 if (sc == 0 || errno == EWOULDBLOCK)
7029 err = EAGAIN;
7030 else
7031 err = errno; /* Other errors are just passed on. */
7032 }
7033 7858
7034 emacs_gnutls_transport_set_errno (process->gnutls_state, err); 7859 emacs_gnutls_transport_set_errno (process->gnutls_state, err);
7035 7860
7036 return -1; 7861 return -1;
7037 }
7038} 7862}
7039 7863
7040ssize_t 7864ssize_t