_WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
defines it in psapi.h */
typedef struct _PROCESS_MEMORY_COUNTERS_EX {
- DWORD cb;
- DWORD PageFaultCount;
- DWORD PeakWorkingSetSize;
- DWORD WorkingSetSize;
- DWORD QuotaPeakPagedPoolUsage;
- DWORD QuotaPagedPoolUsage;
- DWORD QuotaPeakNonPagedPoolUsage;
- DWORD QuotaNonPagedPoolUsage;
- DWORD PagefileUsage;
- DWORD PeakPagefileUsage;
- DWORD PrivateUsage;
+ DWORD cb;
+ DWORD PageFaultCount;
+ SIZE_T PeakWorkingSetSize;
+ SIZE_T WorkingSetSize;
+ SIZE_T QuotaPeakPagedPoolUsage;
+ SIZE_T QuotaPagedPoolUsage;
+ SIZE_T QuotaPeakNonPagedPoolUsage;
+ SIZE_T QuotaNonPagedPoolUsage;
+ SIZE_T PagefileUsage;
+ SIZE_T PeakPagefileUsage;
+ SIZE_T PrivateUsage;
} PROCESS_MEMORY_COUNTERS_EX,*PPROCESS_MEMORY_COUNTERS_EX;
#endif
#include <winioctl.h>
#include <aclapi.h>
+#include <sddl.h>
+
+#include <sys/acl.h>
+
+/* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
+ define them by hand if not already defined. */
+#ifndef SDDL_REVISION_1
+#define SDDL_REVISION_1 1
+#endif /* SDDL_REVISION_1 */
#ifdef _MSC_VER
-/* MSVC doesn't provide the definition of REPARSE_DATA_BUFFER, except
- on ntifs.h, which cannot be included because it triggers conflicts
- with other Windows API headers. So we define it here by hand. */
+/* MSVC doesn't provide the definition of REPARSE_DATA_BUFFER and the
+ associated macros, except on ntifs.h, which cannot be included
+ because it triggers conflicts with other Windows API headers. So
+ we define it here by hand. */
typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
} DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+#ifndef FILE_DEVICE_FILE_SYSTEM
+#define FILE_DEVICE_FILE_SYSTEM 9
+#endif
+#ifndef METHOD_BUFFERED
+#define METHOD_BUFFERED 0
+#endif
+#ifndef FILE_ANY_ACCESS
+#define FILE_ANY_ACCESS 0x00000000
+#endif
+#ifndef CTL_CODE
+#define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
+#endif
+#define FSCTL_GET_REPARSE_POINT \
+ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif
/* TCP connection support. */
#undef sendto
#include "w32.h"
-#include "ndir.h"
+#include <dirent.h>
#include "w32common.h"
#include "w32heap.h"
#include "w32select.h"
static BOOL g_b_init_get_native_system_info;
static BOOL g_b_init_get_system_times;
static BOOL g_b_init_create_symbolic_link;
+static BOOL g_b_init_get_security_descriptor_dacl;
+static BOOL g_b_init_convert_sd_to_sddl;
+static BOOL g_b_init_convert_sddl_to_sd;
+static BOOL g_b_init_is_valid_security_descriptor;
+static BOOL g_b_init_set_file_security;
/*
BEGIN: Wrapper functions around OpenProcessToken
#ifdef _UNICODE
const char * const LookupAccountSid_Name = "LookupAccountSidW";
const char * const GetFileSecurity_Name = "GetFileSecurityW";
+const char * const SetFileSecurity_Name = "SetFileSecurityW";
#else
const char * const LookupAccountSid_Name = "LookupAccountSidA";
const char * const GetFileSecurity_Name = "GetFileSecurityA";
+const char * const SetFileSecurity_Name = "SetFileSecurityA";
#endif
typedef BOOL (WINAPI * LookupAccountSid_Proc) (
LPCTSTR lpSystemName,
PSECURITY_DESCRIPTOR pSecurityDescriptor,
DWORD nLength,
LPDWORD lpnLengthNeeded);
+typedef BOOL (WINAPI *SetFileSecurity_Proc) (
+ LPCTSTR lpFileName,
+ SECURITY_INFORMATION SecurityInformation,
+ PSECURITY_DESCRIPTOR pSecurityDescriptor);
typedef BOOL (WINAPI * GetSecurityDescriptorOwner_Proc) (
PSECURITY_DESCRIPTOR pSecurityDescriptor,
PSID *pOwner,
PSECURITY_DESCRIPTOR pSecurityDescriptor,
PSID *pGroup,
LPBOOL lpbGroupDefaulted);
+typedef BOOL (WINAPI *GetSecurityDescriptorDacl_Proc) (
+ PSECURITY_DESCRIPTOR pSecurityDescriptor,
+ LPBOOL lpbDaclPresent,
+ PACL *pDacl,
+ LPBOOL lpbDaclDefaulted);
typedef BOOL (WINAPI * IsValidSid_Proc) (
PSID sid);
typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_Proc) (
DWORD cb);
typedef BOOL (WINAPI * GetProcessWorkingSetSize_Proc) (
HANDLE hProcess,
- DWORD * lpMinimumWorkingSetSize,
- DWORD * lpMaximumWorkingSetSize);
+ PSIZE_T lpMinimumWorkingSetSize,
+ PSIZE_T lpMaximumWorkingSetSize);
typedef BOOL (WINAPI * GlobalMemoryStatus_Proc) (
LPMEMORYSTATUS lpBuffer);
typedef BOOL (WINAPI * GlobalMemoryStatusEx_Proc) (
LPTSTR lpSymlinkFileName,
LPTSTR lpTargetFileName,
DWORD dwFlags);
+typedef BOOL (WINAPI *ConvertStringSecurityDescriptorToSecurityDescriptor_Proc) (
+ LPCTSTR StringSecurityDescriptor,
+ DWORD StringSDRevision,
+ PSECURITY_DESCRIPTOR *SecurityDescriptor,
+ PULONG SecurityDescriptorSize);
+typedef BOOL (WINAPI *ConvertSecurityDescriptorToStringSecurityDescriptor_Proc) (
+ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ DWORD RequestedStringSDRevision,
+ SECURITY_INFORMATION SecurityInformation,
+ LPTSTR *StringSecurityDescriptor,
+ PULONG StringSecurityDescriptorLen);
+typedef BOOL (WINAPI *IsValidSecurityDescriptor_Proc) (PSECURITY_DESCRIPTOR);
/* ** A utility function ** */
static BOOL
HMODULE hm_advapi32 = NULL;
if (is_windows_9x () == TRUE)
{
+ errno = ENOTSUP;
return FALSE;
}
if (g_b_init_get_file_security == 0)
}
if (s_pfn_Get_File_Security == NULL)
{
+ errno = ENOTSUP;
return FALSE;
}
return (s_pfn_Get_File_Security (lpFileName, RequestedInformation,
lpnLengthNeeded));
}
+static BOOL WINAPI
+set_file_security (LPCTSTR lpFileName,
+ SECURITY_INFORMATION SecurityInformation,
+ PSECURITY_DESCRIPTOR pSecurityDescriptor)
+{
+ static SetFileSecurity_Proc s_pfn_Set_File_Security = NULL;
+ HMODULE hm_advapi32 = NULL;
+ if (is_windows_9x () == TRUE)
+ {
+ errno = ENOTSUP;
+ return FALSE;
+ }
+ if (g_b_init_set_file_security == 0)
+ {
+ g_b_init_set_file_security = 1;
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ s_pfn_Set_File_Security =
+ (SetFileSecurity_Proc) GetProcAddress (
+ hm_advapi32, SetFileSecurity_Name);
+ }
+ if (s_pfn_Set_File_Security == NULL)
+ {
+ errno = ENOTSUP;
+ return FALSE;
+ }
+ return (s_pfn_Set_File_Security (lpFileName, SecurityInformation,
+ pSecurityDescriptor));
+}
+
static BOOL WINAPI
get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
PSID *pOwner,
HMODULE hm_advapi32 = NULL;
if (is_windows_9x () == TRUE)
{
+ errno = ENOTSUP;
return FALSE;
}
if (g_b_init_get_security_descriptor_owner == 0)
}
if (s_pfn_Get_Security_Descriptor_Owner == NULL)
{
+ errno = ENOTSUP;
return FALSE;
}
return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor, pOwner,
HMODULE hm_advapi32 = NULL;
if (is_windows_9x () == TRUE)
{
+ errno = ENOTSUP;
return FALSE;
}
if (g_b_init_get_security_descriptor_group == 0)
}
if (s_pfn_Get_Security_Descriptor_Group == NULL)
{
+ errno = ENOTSUP;
return FALSE;
}
return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor, pGroup,
lpbGroupDefaulted));
}
+static BOOL WINAPI
+get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor,
+ LPBOOL lpbDaclPresent,
+ PACL *pDacl,
+ LPBOOL lpbDaclDefaulted)
+{
+ static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl = NULL;
+ HMODULE hm_advapi32 = NULL;
+ if (is_windows_9x () == TRUE)
+ {
+ errno = ENOTSUP;
+ return FALSE;
+ }
+ if (g_b_init_get_security_descriptor_dacl == 0)
+ {
+ g_b_init_get_security_descriptor_dacl = 1;
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ s_pfn_Get_Security_Descriptor_Dacl =
+ (GetSecurityDescriptorDacl_Proc) GetProcAddress (
+ hm_advapi32, "GetSecurityDescriptorDacl");
+ }
+ if (s_pfn_Get_Security_Descriptor_Dacl == NULL)
+ {
+ errno = ENOTSUP;
+ return FALSE;
+ }
+ return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor,
+ lpbDaclPresent, pDacl,
+ lpbDaclDefaulted));
+}
+
static BOOL WINAPI
is_valid_sid (PSID sid)
{
}
return retval;
}
+
+static BOOL WINAPI
+is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor)
+{
+ static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc = NULL;
+
+ if (is_windows_9x () == TRUE)
+ {
+ errno = ENOTSUP;
+ return FALSE;
+ }
+
+ if (g_b_init_is_valid_security_descriptor == 0)
+ {
+ g_b_init_is_valid_security_descriptor = 1;
+ s_pfn_Is_Valid_Security_Descriptor_Proc =
+ (IsValidSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
+ "IsValidSecurityDescriptor");
+ }
+ if (s_pfn_Is_Valid_Security_Descriptor_Proc == NULL)
+ {
+ errno = ENOTSUP;
+ return FALSE;
+ }
+
+ return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor);
+}
+
+static BOOL WINAPI
+convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor,
+ DWORD RequestedStringSDRevision,
+ SECURITY_INFORMATION SecurityInformation,
+ LPTSTR *StringSecurityDescriptor,
+ PULONG StringSecurityDescriptorLen)
+{
+ static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL = NULL;
+ BOOL retval;
+
+ if (is_windows_9x () == TRUE)
+ {
+ errno = ENOTSUP;
+ return FALSE;
+ }
+
+ if (g_b_init_convert_sd_to_sddl == 0)
+ {
+ g_b_init_convert_sd_to_sddl = 1;
+#ifdef _UNICODE
+ s_pfn_Convert_SD_To_SDDL =
+ (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
+ "ConvertSecurityDescriptorToStringSecurityDescriptorW");
+#else
+ s_pfn_Convert_SD_To_SDDL =
+ (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
+ "ConvertSecurityDescriptorToStringSecurityDescriptorA");
+#endif
+ }
+ if (s_pfn_Convert_SD_To_SDDL == NULL)
+ {
+ errno = ENOTSUP;
+ return FALSE;
+ }
+
+ retval = s_pfn_Convert_SD_To_SDDL (SecurityDescriptor,
+ RequestedStringSDRevision,
+ SecurityInformation,
+ StringSecurityDescriptor,
+ StringSecurityDescriptorLen);
+
+ return retval;
+}
+
+static BOOL WINAPI
+convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor,
+ DWORD StringSDRevision,
+ PSECURITY_DESCRIPTOR *SecurityDescriptor,
+ PULONG SecurityDescriptorSize)
+{
+ static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD = NULL;
+ BOOL retval;
+
+ if (is_windows_9x () == TRUE)
+ {
+ errno = ENOTSUP;
+ return FALSE;
+ }
+
+ if (g_b_init_convert_sddl_to_sd == 0)
+ {
+ g_b_init_convert_sddl_to_sd = 1;
+#ifdef _UNICODE
+ s_pfn_Convert_SDDL_To_SD =
+ (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
+ "ConvertStringSecurityDescriptorToSecurityDescriptorW");
+#else
+ s_pfn_Convert_SDDL_To_SD =
+ (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
+ "ConvertStringSecurityDescriptorToSecurityDescriptorA");
+#endif
+ }
+ if (s_pfn_Convert_SDDL_To_SD == NULL)
+ {
+ errno = ENOTSUP;
+ return FALSE;
+ }
+
+ retval = s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor,
+ StringSDRevision,
+ SecurityDescriptor,
+ SecurityDescriptorSize);
+
+ return retval;
+}
+
\f
/* Return 1 if P is a valid pointer to an object of size SIZE. Return
/* Get the current working directory. */
char *
-getwd (char *dir)
+getcwd (char *dir, int dirsize)
{
+ if (!dirsize)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+ if (dirsize <= strlen (startup_dir))
+ {
+ errno = ERANGE;
+ return NULL;
+ }
#if 0
if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
return dir;
return 1;
}
+/* Emulate the Posix unsetenv. */
+int
+unsetenv (const char *name)
+{
+ char *var;
+ size_t name_len;
+ int retval;
+
+ if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ name_len = strlen (name);
+ /* MS docs says an environment variable cannot be longer than 32K. */
+ if (name_len > 32767)
+ {
+ errno = ENOMEM;
+ return 0;
+ }
+ /* It is safe to use 'alloca' with 32K size, since the stack is at
+ least 2MB, and we set it to 8MB in the link command line. */
+ var = alloca (name_len + 2);
+ var[name_len++] = '=';
+ var[name_len] = '\0';
+ return _putenv (var);
+}
+
+/* MS _putenv doesn't support removing a variable when the argument
+ does not include the '=' character, so we fix that here. */
+int
+sys_putenv (char *str)
+{
+ const char *const name_end = strchr (str, '=');
+
+ if (name_end == NULL)
+ {
+ /* Remove the variable from the environment. */
+ return unsetenv (str);
+ }
+
+ return _putenv (str);
+}
+
#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
LPBYTE
memcpy (*envp, "COMSPEC=", 8);
}
- /* Remember the initial working directory for getwd. */
+ /* Remember the initial working directory for getcwd. */
/* FIXME: Do we need to resolve possible symlinks in startup_dir?
Does it matter anywhere in Emacs? */
if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
and readdir. We can't use the procedures supplied in sysdep.c,
so we provide them here. */
-struct direct dir_static; /* simulated directory contents */
+struct dirent dir_static; /* simulated directory contents */
static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
static int dir_is_fat;
static char dir_pathname[MAXPATHLEN+1];
xfree ((char *) dirp);
}
-struct direct *
+struct dirent *
readdir (DIR *dirp)
{
int downcase = !NILP (Vw32_downcase_file_names);
downcase = 1; /* 8+3 aliases are returned in all caps */
}
dir_static.d_namlen = strlen (dir_static.d_name);
- dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
+ dir_static.d_reclen = sizeof (struct dirent) - MAXNAMLEN + 3 +
dir_static.d_namlen - dir_static.d_namlen % 4;
/* If the file name in cFileName[] includes `?' characters, it means
#define GID 2
static int
-get_name_and_id (PSECURITY_DESCRIPTOR psd, const char *fname,
- unsigned *id, char *nm, int what)
+get_name_and_id (PSECURITY_DESCRIPTOR psd, unsigned *id, char *nm, int what)
{
PSID sid = NULL;
char machine[MAX_COMPUTERNAME_LENGTH+1];
DWORD name_len = sizeof (name);
char domain[1024];
DWORD domain_len = sizeof (domain);
- char *mp = NULL;
int use_dflt = 0;
int result;
use_dflt = 1;
else if (!w32_cached_id (sid, id, nm))
{
- /* If FNAME is a UNC, we need to lookup account on the
- specified machine. */
- if (IS_DIRECTORY_SEP (fname[0]) && IS_DIRECTORY_SEP (fname[1])
- && fname[2] != '\0')
- {
- const char *s;
- char *p;
-
- for (s = fname + 2, p = machine;
- *s && !IS_DIRECTORY_SEP (*s); s++, p++)
- *p = *s;
- *p = '\0';
- mp = machine;
- }
-
- if (!lookup_account_sid (mp, sid, name, &name_len,
+ if (!lookup_account_sid (NULL, sid, name, &name_len,
domain, &domain_len, &ignore)
|| name_len > UNLEN+1)
use_dflt = 1;
}
static void
-get_file_owner_and_group (PSECURITY_DESCRIPTOR psd,
- const char *fname,
- struct stat *st)
+get_file_owner_and_group (PSECURITY_DESCRIPTOR psd, struct stat *st)
{
int dflt_usr = 0, dflt_grp = 0;
}
else
{
- if (get_name_and_id (psd, fname, &st->st_uid, st->st_uname, UID))
+ if (get_name_and_id (psd, &st->st_uid, st->st_uname, UID))
dflt_usr = 1;
- if (get_name_and_id (psd, fname, &st->st_gid, st->st_gname, GID))
+ if (get_name_and_id (psd, &st->st_gid, st->st_gname, GID))
dflt_grp = 1;
}
/* Consider files to belong to current user/group, if we cannot get
return !(devtype == DRIVE_FIXED || devtype == DRIVE_RAMDISK);
}
+/* If this is non-zero, the caller wants accurate information about
+ file's owner and group, which could be expensive to get. */
+int w32_stat_get_owner_group;
+
/* MSVC stat function can't cope with UNC names and has other bugs, so
replace it with our own. This also allows us to calculate consistent
inode values and owner/group without hacks in the main Emacs code. */
/* We produce the fallback owner and group data, based on the
current user that runs Emacs, in the following cases:
+ . caller didn't request owner and group info
. this is Windows 9X
. getting security by handle failed, and we need to produce
information for the target of a symlink (this is better
If getting security by handle fails, and we don't need to
resolve symlinks, we try getting security by name. */
- if (is_windows_9x () != TRUE)
- psd = get_file_security_desc_by_handle (fh);
- if (psd)
- {
- get_file_owner_and_group (psd, name, buf);
- LocalFree (psd);
- }
- else if (is_windows_9x () == TRUE)
- get_file_owner_and_group (NULL, name, buf);
- else if (!(is_a_symlink && follow_symlinks))
+ if (!w32_stat_get_owner_group || is_windows_9x () == TRUE)
+ get_file_owner_and_group (NULL, buf);
+ else
{
- psd = get_file_security_desc_by_name (name);
- get_file_owner_and_group (psd, name, buf);
- xfree (psd);
+ psd = get_file_security_desc_by_handle (fh);
+ if (psd)
+ {
+ get_file_owner_and_group (psd, buf);
+ LocalFree (psd);
+ }
+ else if (!(is_a_symlink && follow_symlinks))
+ {
+ psd = get_file_security_desc_by_name (name);
+ get_file_owner_and_group (psd, buf);
+ xfree (psd);
+ }
+ else
+ get_file_owner_and_group (NULL, buf);
}
- else
- get_file_owner_and_group (NULL, name, buf);
CloseHandle (fh);
}
else
else
buf->st_mode = S_IFREG;
- get_file_owner_and_group (NULL, name, buf);
+ get_file_owner_and_group (NULL, buf);
}
#if 0
errno = EINVAL;
else
{
- /* Copy the link target name, in wide characters, fro
+ /* Copy the link target name, in wide characters, from
reparse_data, then convert it to multibyte encoding in
the current locale's codepage. */
WCHAR *lwname;
return target;
}
+\f
+/* Posix ACL emulation. */
+
+int
+acl_valid (acl_t acl)
+{
+ return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR)acl) ? 0 : -1;
+}
+
+char *
+acl_to_text (acl_t acl, ssize_t *size)
+{
+ LPTSTR str_acl;
+ SECURITY_INFORMATION flags =
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION;
+ char *retval = NULL;
+ ssize_t local_size;
+ int e = errno;
+
+ errno = 0;
+
+ if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR)acl, SDDL_REVISION_1, flags, &str_acl, &local_size))
+ {
+ errno = e;
+ /* We don't want to mix heaps, so we duplicate the string in our
+ heap and free the one allocated by the API. */
+ retval = xstrdup (str_acl);
+ if (size)
+ *size = local_size;
+ LocalFree (str_acl);
+ }
+ else if (errno != ENOTSUP)
+ errno = EINVAL;
+
+ return retval;
+}
+
+acl_t
+acl_from_text (const char *acl_str)
+{
+ PSECURITY_DESCRIPTOR psd, retval = NULL;
+ ULONG sd_size;
+ int e = errno;
+
+ errno = 0;
+
+ if (convert_sddl_to_sd (acl_str, SDDL_REVISION_1, &psd, &sd_size))
+ {
+ errno = e;
+ retval = xmalloc (sd_size);
+ memcpy (retval, psd, sd_size);
+ LocalFree (psd);
+ }
+ else if (errno != ENOTSUP)
+ errno = EINVAL;
+
+ return retval;
+}
+
+int
+acl_free (void *ptr)
+{
+ xfree (ptr);
+ return 0;
+}
+
+acl_t
+acl_get_file (const char *fname, acl_type_t type)
+{
+ PSECURITY_DESCRIPTOR psd = NULL;
+ const char *filename;
+
+ if (type == ACL_TYPE_ACCESS)
+ {
+ DWORD sd_len, err;
+ SECURITY_INFORMATION si =
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION ;
+ int e = errno;
+
+ filename = map_w32_filename (fname, NULL);
+ if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
+ fname = chase_symlinks (filename);
+ else
+ fname = filename;
+
+ errno = 0;
+ if (!get_file_security (fname, si, psd, 0, &sd_len)
+ && errno != ENOTSUP)
+ {
+ err = GetLastError ();
+ if (err == ERROR_INSUFFICIENT_BUFFER)
+ {
+ psd = xmalloc (sd_len);
+ if (!get_file_security (fname, si, psd, sd_len, &sd_len))
+ {
+ xfree (psd);
+ errno = EIO;
+ psd = NULL;
+ }
+ }
+ else if (err == ERROR_FILE_NOT_FOUND
+ || err == ERROR_PATH_NOT_FOUND)
+ errno = ENOENT;
+ else
+ errno = EIO;
+ }
+ else if (!errno)
+ errno = e;
+ }
+ else if (type != ACL_TYPE_DEFAULT)
+ errno = EINVAL;
+
+ return psd;
+}
+
+int
+acl_set_file (const char *fname, acl_type_t type, acl_t acl)
+{
+ TOKEN_PRIVILEGES old1, old2;
+ DWORD err;
+ BOOL res;
+ int st = 0, retval = -1;
+ SECURITY_INFORMATION flags = 0;
+ PSID psid;
+ PACL pacl;
+ BOOL dflt;
+ BOOL dacl_present;
+ int e;
+ const char *filename;
+
+ if (acl_valid (acl) != 0
+ || (type != ACL_TYPE_DEFAULT && type != ACL_TYPE_ACCESS))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (type == ACL_TYPE_DEFAULT)
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ filename = map_w32_filename (fname, NULL);
+ if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
+ fname = chase_symlinks (filename);
+ else
+ fname = filename;
+
+ if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR)acl, &psid, &dflt)
+ && psid)
+ flags |= OWNER_SECURITY_INFORMATION;
+ if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR)acl, &psid, &dflt)
+ && psid)
+ flags |= GROUP_SECURITY_INFORMATION;
+ if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR)acl, &dacl_present,
+ &pacl, &dflt)
+ && dacl_present)
+ flags |= DACL_SECURITY_INFORMATION;
+ if (!flags)
+ return 0;
+
+ /* According to KB-245153, setting the owner will succeed if either:
+ (1) the caller is the user who will be the new owner, and has the
+ SE_TAKE_OWNERSHIP privilege, or
+ (2) the caller has the SE_RESTORE privilege, in which case she can
+ set any valid user or group as the owner
+
+ We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
+ privileges, and disregard any failures in obtaining them. If
+ these privileges cannot be obtained, and do not already exist in
+ the calling thread's security token, this function could fail
+ with EPERM. */
+ if (enable_privilege (SE_TAKE_OWNERSHIP_NAME, TRUE, &old1))
+ st++;
+ if (enable_privilege (SE_RESTORE_NAME, TRUE, &old2))
+ st++;
+
+ e = errno;
+ errno = 0;
+ set_file_security ((char *)fname, flags, (PSECURITY_DESCRIPTOR)acl);
+ err = GetLastError ();
+ if (st)
+ {
+ if (st >= 2)
+ restore_privilege (&old2);
+ restore_privilege (&old1);
+ revert_to_self ();
+ }
+
+ if (errno == ENOTSUP)
+ ;
+ else if (err == ERROR_SUCCESS)
+ {
+ retval = 0;
+ errno = e;
+ }
+ else if (err == ERROR_INVALID_OWNER || err == ERROR_NOT_ALL_ASSIGNED)
+ {
+ /* Maybe the requested ACL and the one the file already has are
+ identical, in which case we can silently ignore the
+ failure. (And no, Windows doesn't.) */
+ acl_t current_acl = acl_get_file (fname, ACL_TYPE_ACCESS);
+
+ errno = EPERM;
+ if (current_acl)
+ {
+ char *acl_from = acl_to_text (current_acl, NULL);
+ char *acl_to = acl_to_text (acl, NULL);
+
+ if (acl_from && acl_to && xstrcasecmp (acl_from, acl_to) == 0)
+ {
+ retval = 0;
+ errno = e;
+ }
+ if (acl_from)
+ acl_free (acl_from);
+ if (acl_to)
+ acl_free (acl_to);
+ acl_free (current_acl);
+ }
+ }
+ else if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
+ errno = ENOENT;
+
+ return retval;
+}
+
+\f
/* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
have a fixed max size for file names, so we don't need the kind of
alloc/malloc/realloc dance the gnulib version does. We also don't
static BOOL WINAPI
get_process_working_set_size (HANDLE h_proc,
- DWORD *minrss,
- DWORD *maxrss)
+ PSIZE_T minrss,
+ PSIZE_T maxrss)
{
static GetProcessWorkingSetSize_Proc
s_pfn_Get_Process_Working_Set_Size = NULL;
unsigned egid;
PROCESS_MEMORY_COUNTERS mem;
PROCESS_MEMORY_COUNTERS_EX mem_ex;
- DWORD minrss, maxrss;
+ SIZE_T minrss, maxrss;
MEMORYSTATUS memst;
MEMORY_STATUS_EX memstex;
double totphys = 0.0;
&& get_process_memory_info (h_proc, (PROCESS_MEMORY_COUNTERS *)&mem_ex,
sizeof (mem_ex)))
{
- DWORD rss = mem_ex.WorkingSetSize / 1024;
+ SIZE_T rss = mem_ex.WorkingSetSize / 1024;
attrs = Fcons (Fcons (Qmajflt,
make_fixnum_or_float (mem_ex.PageFaultCount)),
else if (h_proc
&& get_process_memory_info (h_proc, &mem, sizeof (mem)))
{
- DWORD rss = mem_ex.WorkingSetSize / 1024;
+ SIZE_T rss = mem_ex.WorkingSetSize / 1024;
attrs = Fcons (Fcons (Qmajflt,
make_fixnum_or_float (mem.PageFaultCount)),
winsock_inuse--; /* count open sockets */
}
- delete_child (cp);
+ /* If the process handle is NULL, it's either a socket
+ or serial connection, or a subprocess that was
+ already reaped by reap_subprocess, but whose
+ resources were not yet freed, because its output was
+ not fully read yet by the time it was reaped. (This
+ usually happens with async subprocesses whose output
+ is being read by Emacs.) Otherwise, this process was
+ not reaped yet, so we set its FD to a negative value
+ to make sure sys_select will eventually get to
+ calling the SIGCHLD handler for it, which will then
+ invoke waitpid and reap_subprocess. */
+ if (cp->procinfo.hProcess == NULL)
+ delete_child (cp);
+ else
+ cp->fd = -1;
}
}
}
}
/* Function to do blocking read of one byte, needed to implement
- select. It is only allowed on sockets and pipes. */
+ select. It is only allowed on communication ports, sockets, or
+ pipes. */
int
_sys_read_ahead (int fd)
{
g_b_init_get_native_system_info = 0;
g_b_init_get_system_times = 0;
g_b_init_create_symbolic_link = 0;
+ g_b_init_get_security_descriptor_dacl = 0;
+ g_b_init_convert_sd_to_sddl = 0;
+ g_b_init_convert_sddl_to_sd = 0;
+ g_b_init_is_valid_security_descriptor = 0;
+ g_b_init_set_file_security = 0;
num_of_processors = 0;
/* The following sets a handler for shutdown notifications for
console apps. This actually applies to Emacs in both console and
/* "None" is the default group name on standalone workstations. */
strcpy (dflt_group_name, "None");
+
+ /* Reset, in case it has some value inherited from dump time. */
+ w32_stat_get_owner_group = 0;
}
/* For make-serial-process */