diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 669c5c9e7..df7cf3eff 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,38 @@ +2004-04-16 Corinna Vinschen + + * autoload.cc (NtCreateFile): Add. + * dir.cc (mkdir): Change set_file_attribute call to indicate that + NT security isn't used. + * fhandler.cc (fhandler_base::open_9x): New method, created from + fhandler_base::open. + (fhandler_base::open): Rearrange to use NtCreateFile instead of + CreateFile. + * fhandler.h (enum query_state): Redefine query_null_access to + query_stat_control. query_null_access isn't allowed in NtCreateFile. + (fhandler_base::open_9x): Declare. + * fhandler_disk_file.cc (fhandler_base::fstat_fs): Use + query_stat_control first, query_read_control if that fails. + (fhandler_disk_file::fchmod): Call enable_restore_privilege before + trying to open for query_write_control. Don't fall back to + opening for query_read_control. + (fhandler_disk_file::fchown): Ditto. + (fhandler_disk_file::facl): Only request restore privilege and query + access necessary for given cmd. + * fhandler_raw.cc (fhandler_dev_raw::open): Call fhandler_base::open + instead of opening device here. + * ntdll.h (NtCreateFile): Declare. + * path.cc (symlink_worker): Change set_file_attribute call to indicate + that NT security isn't used. + * sec_acl.cc (getacl): Fix bracketing. + * sec_helper.cc (enable_restore_privilege): New function. + * security.cc (str2buf2uni_cat): New function. + (write_sd): Don't request restore permission here. + * security.h (set_process_privileges): Drop stale declaration. + (str2buf2uni): Declare. + (str2buf2uni_cat): Declare. + (enable_restore_privilege): Declare. + * syscalls.cc (fchown32): Return immediate success on 9x. + 2004-04-15 Christopher Faylor * autoload.cc (dll_chain1): Rename to dll_chain. Remove old dll_chain diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 7e9e71536..bccc3ad72 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -375,6 +375,7 @@ LoadDLLfunc (NetUserGetGroups, 28, netapi32) LoadDLLfunc (NetUserGetInfo, 16, netapi32) LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32) +LoadDLLfuncEx (NtCreateFile, 44, ntdll, 1) LoadDLLfuncEx (NtCreateToken, 52, ntdll, 1) LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1) LoadDLLfuncEx (NtOpenFile, 24, ntdll, 1) diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc index 4fc1932da..1bb7f0013 100644 --- a/winsup/cygwin/dir.cc +++ b/winsup/cygwin/dir.cc @@ -284,7 +284,7 @@ mkdir (const char *dir, mode_t mode) if (CreateDirectoryA (real_dir.get_win32 (), &sa)) { if (!allow_ntsec && allow_ntea) - set_file_attribute (real_dir.has_acls (), NULL, real_dir.get_win32 (), + set_file_attribute (false, NULL, real_dir.get_win32 (), S_IFDIR | ((mode & 07777) & ~cygheap->umask)); #ifdef HIDDEN_DOT_FILES char *c = strrchr (real_dir.get_win32 (), '\\'); diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index af9d63313..f1dfed8c4 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -28,6 +28,8 @@ details. */ #include #include #include +#include +#include "ntdll.h" static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ @@ -425,7 +427,7 @@ done: /* Open system call handler function. */ int -fhandler_base::open (int flags, mode_t mode) +fhandler_base::open_9x (int flags, mode_t mode) { int res = 0; HANDLE x; @@ -435,7 +437,7 @@ fhandler_base::open (int flags, mode_t mode) SECURITY_ATTRIBUTES sa = sec_none; security_descriptor sd; - syscall_printf ("(%s, %p) query_open %d", get_win32_name (), flags, query_open ()); + syscall_printf ("(%s, %p)", get_win32_name (), flags); if (get_win32_name () == NULL) { @@ -443,34 +445,12 @@ fhandler_base::open (int flags, mode_t mode) goto done; } - switch (query_open ()) - { - case query_null_access: - access = 0; - break; - case query_read_control: - access = READ_CONTROL; - break; - case query_write_control: - access = READ_CONTROL | WRITE_OWNER | WRITE_DAC; - break; - default: - if (get_major () == DEV_TAPE_MAJOR) - access = GENERIC_READ | GENERIC_WRITE; - else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) - access = GENERIC_READ; - else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) - access = GENERIC_WRITE; - else - access = GENERIC_READ | GENERIC_WRITE; - break; - } - - /* Allow reliable lseek on disk devices. */ - if (get_major () == DEV_FLOPPY_MAJOR) - access |= GENERIC_READ; - - /* FIXME: O_EXCL handling? */ + if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) + access = GENERIC_READ; + else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) + access = GENERIC_WRITE; + else + access = GENERIC_READ | GENERIC_WRITE; if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY)) { @@ -508,16 +488,6 @@ fhandler_base::open (int flags, mode_t mode) } #endif - /* CreateFile() with dwDesiredAccess == 0 when called on remote - share returns some handle, even if file doesn't exist. This code - works around this bug. */ - if (query_open () && isremote () && - creation_distribution == OPEN_EXISTING && !pc.exists ()) - { - set_errno (ENOENT); - goto done; - } - /* If mode has no write bits set, we set the R/O attribute. */ if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH))) file_attributes |= FILE_ATTRIBUTE_READONLY; @@ -564,6 +534,162 @@ done: return res; } +/* Open system call handler function. */ +int +fhandler_base::open (int flags, mode_t mode) +{ + if (!wincap.is_winnt ()) + return fhandler_base::open_9x (flags, mode); + + int res = 0; + HANDLE x; + ULONG file_attributes = 0; + ULONG shared = wincap.shared (); + ULONG create_disposition; + ULONG create_options; + SECURITY_ATTRIBUTES sa = sec_none; + security_descriptor sd; + UNICODE_STRING upath; + WCHAR wpath[CYG_MAX_PATH + 10]; + OBJECT_ATTRIBUTES attr; + IO_STATUS_BLOCK io; + NTSTATUS status; + + syscall_printf ("(%s, %p)", get_win32_name (), flags); + if (get_win32_name () == NULL) + { + set_errno (ENOENT); + goto done; + } + if (get_win32_name ()[0] == '\\') + { + if (get_win32_name ()[1] == '\\') + { + str2buf2uni (upath, wpath, "\\??\\UNC"); + str2buf2uni_cat (upath, get_win32_name () + 1); + } + else + str2buf2uni (upath, wpath, get_win32_name ()); + } + else + { + str2buf2uni (upath, wpath, "\\??\\"); + str2buf2uni_cat (upath, get_win32_name ()); + } + InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE | OBJ_INHERIT, + sa.lpSecurityDescriptor, NULL); + + switch (query_open ()) + { + case query_read_control: + access = READ_CONTROL; + create_options = FILE_OPEN_FOR_BACKUP_INTENT; + break; + case query_stat_control: + access = READ_CONTROL | FILE_READ_ATTRIBUTES; + create_options = FILE_OPEN_FOR_BACKUP_INTENT; + break; + case query_write_control: + access = READ_CONTROL | WRITE_OWNER | WRITE_DAC; + create_options = FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY; + break; + default: + create_options = 0; + if (get_major () == DEV_TAPE_MAJOR && (flags & O_TEXT)) + { + /* O_TEXT is used to indicate write-through on tape devices */ + create_options |= FILE_WRITE_THROUGH; + flags &= ~O_TEXT; + } + if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) + access = GENERIC_READ; + else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) + access = GENERIC_WRITE; + else + access = GENERIC_READ | GENERIC_WRITE; + /* Allow reliable lseek on disk devices. */ + if (get_major () == DEV_FLOPPY_MAJOR) + access |= GENERIC_READ; + else if (get_major () != DEV_SERIAL_MAJOR) + { + create_options |= FILE_SYNCHRONOUS_IO_NONALERT; + access |= SYNCHRONIZE; + } + break; + } + + if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY)) + { + if (flags & O_CREAT) + create_disposition = FILE_SUPERSEDE; + else + create_disposition = FILE_OVERWRITE; + } + else if (flags & O_CREAT) + create_disposition = FILE_OPEN_IF; + else + create_disposition = FILE_OPEN; + + if ((flags & O_EXCL) && (flags & O_CREAT)) + create_disposition = FILE_CREATE; + + if (flags & O_APPEND) + append_mode (true); + + if (flags & O_CREAT && get_device () == FH_FS) + { + file_attributes = FILE_ATTRIBUTE_NORMAL; + /* If mode has no write bits set, we set the R/O attribute. */ + if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH))) + file_attributes |= FILE_ATTRIBUTE_READONLY; +#ifdef HIDDEN_DOT_FILES + char *c = strrchr (get_win32_name (), '\\'); + if ((c && c[1] == '.') || *get_win32_name () == '.') + file_attributes |= FILE_ATTRIBUTE_HIDDEN; +#endif + /* If the file should actually be created and ntsec is on, + set files attributes. */ + if (allow_ntsec && has_acls ()) + { + set_security_attribute (mode, &sa, sd); + attr.SecurityDescriptor = sa.lpSecurityDescriptor; + } + } + + status = NtCreateFile (&x, access, &attr, &io, NULL, file_attributes, shared, + create_disposition, create_options, NULL, 0); + if (!NT_SUCCESS (status)) + { + if (!wincap.can_open_directories () && pc.isdir ()) + { + if (flags & (O_CREAT | O_EXCL) == (O_CREAT | O_EXCL)) + set_errno (EEXIST); + else if (flags & (O_WRONLY | O_RDWR)) + set_errno (EISDIR); + else + nohandle (true); + } + __seterrno_from_win_error (RtlNtStatusToDosError (status)); + if (!nohandle ()) + goto done; + } + + syscall_printf ("%x = NtCreateFile " + "(%p, %x, %s, io, NULL, %x, %x, %x, %x, NULL, 0)", + status, x, access, get_win32_name (), file_attributes, shared, + create_disposition, create_options); + + set_io_handle (x); + set_flags (flags, pc.binmode ()); + + res = 1; + set_open_status (); +done: + syscall_printf ("%d = fhandler_base::open (%s, %p)", res, get_win32_name (), + flags); + return res; +} + /* states: open buffer in binary mode? Just do the read. diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 3e27b7b8f..17f3ade02 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -63,8 +63,8 @@ enum bg_check_types enum query_state { no_query = 0, - query_null_access = 1, - query_read_control = 2, + query_read_control = 1, + query_stat_control = 2, query_write_control = 3 }; @@ -226,6 +226,7 @@ class fhandler_base void fork_fixup (HANDLE parent, HANDLE &h, const char *name); virtual bool need_fixup_before () const {return false;} + int open_9x (int flags, mode_t mode = 0); virtual int open (int flags, mode_t mode = 0); int open_fs (int flags, mode_t mode = 0); virtual int close (); diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 9b1d769c8..fcc4417e3 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -174,16 +174,16 @@ fhandler_base::fstat_fs (struct __stat64 *buf) then just do a "query open" as it is apparently much faster. */ if (pc.exec_state () != dont_know_if_executable) { - query_open (query_read_control); if (pc.fs_is_fat () && !strpbrk (get_win32_name (), "?*|<>")) return fstat_by_name (buf); + query_open (query_stat_control); } if (!(oret = open_fs (open_flags, 0)) && get_errno () == EACCES) { /* If we couldn't open the file, try a query open with no permissions. This allows us to determine *some* things about the file, at least. */ pc.set_exec (0); - query_open (query_null_access); + query_open (query_read_control); oret = open_fs (open_flags, 0); } @@ -378,15 +378,15 @@ fhandler_disk_file::fchmod (mode_t mode) if (pc.is_fs_special ()) return chmod_device (pc, mode); - if (!get_io_handle ()) + if (wincap.has_security ()) { - query_open (query_write_control); - if (!(oret = open_fs (O_BINARY, 0))) - { - query_open (query_read_control); + enable_restore_privilege (); + if (!get_io_handle ()) + { + query_open (query_write_control); if (!(oret = open_fs (O_BINARY, 0))) return -1; - } + } } if (!allow_ntsec && allow_ntea) /* Not necessary when manipulating SD. */ @@ -423,15 +423,13 @@ int __stdcall fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid) { int oret = 0; + + enable_restore_privilege (); if (!get_io_handle ()) { query_open (query_write_control); if (!(oret = open_fs (O_BINARY, 0))) - { - query_open (query_read_control); - if (!(oret = open_fs (O_BINARY, 0))) - return -1; - } + return -1; } mode_t attrib = 0; @@ -460,17 +458,6 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp) int res = -1; int oret = 0; - if (!get_io_handle ()) - { - query_open (query_write_control); - if (!(oret = open_fs (O_BINARY, 0))) - { - query_open (query_read_control); - if (!(oret = open_fs (O_BINARY, 0))) - return -1; - } - } - if (!pc.has_acls () || !allow_ntsec) { switch (cmd) @@ -485,30 +472,50 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp) set_errno(EFAULT); else if (nentries < MIN_ACL_ENTRIES) set_errno (ENOSPC); - else if (!fstat_by_handle (&st)) + else { - aclbufp[0].a_type = USER_OBJ; - aclbufp[0].a_id = st.st_uid; - aclbufp[0].a_perm = (st.st_mode & S_IRWXU) >> 6; - aclbufp[1].a_type = GROUP_OBJ; - aclbufp[1].a_id = st.st_gid; - aclbufp[1].a_perm = (st.st_mode & S_IRWXG) >> 3; - aclbufp[2].a_type = OTHER_OBJ; - aclbufp[2].a_id = ILLEGAL_GID; - aclbufp[2].a_perm = st.st_mode & S_IRWXO; - aclbufp[3].a_type = CLASS_OBJ; - aclbufp[3].a_id = ILLEGAL_GID; - aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO; - res = MIN_ACL_ENTRIES; + if (!get_io_handle ()) + { + query_open (query_read_control); + if (!(oret = open_fs (O_BINARY, 0))) + return -1; + } + if (!fstat_by_handle (&st)) + { + aclbufp[0].a_type = USER_OBJ; + aclbufp[0].a_id = st.st_uid; + aclbufp[0].a_perm = (st.st_mode & S_IRWXU) >> 6; + aclbufp[1].a_type = GROUP_OBJ; + aclbufp[1].a_id = st.st_gid; + aclbufp[1].a_perm = (st.st_mode & S_IRWXG) >> 3; + aclbufp[2].a_type = OTHER_OBJ; + aclbufp[2].a_id = ILLEGAL_GID; + aclbufp[2].a_perm = st.st_mode & S_IRWXO; + aclbufp[3].a_type = CLASS_OBJ; + aclbufp[3].a_id = ILLEGAL_GID; + aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO; + res = MIN_ACL_ENTRIES; + } } break; case GETACLCNT: res = MIN_ACL_ENTRIES; break; + default: + set_errno (EINVAL); + break; } } else { + if (cmd == SETACL) + enable_restore_privilege (); + if (!get_io_handle ()) + { + query_open (cmd == SETACL ? query_write_control : query_read_control); + if (!(oret = open_fs (O_BINARY, 0))) + return -1; + } switch (cmd) { case SETACL: diff --git a/winsup/cygwin/fhandler_raw.cc b/winsup/cygwin/fhandler_raw.cc index 5a05e704f..4fafe20cf 100644 --- a/winsup/cygwin/fhandler_raw.cc +++ b/winsup/cygwin/fhandler_raw.cc @@ -144,41 +144,16 @@ fhandler_dev_raw::open (int flags, mode_t) flags &= ~(O_CREAT | O_TRUNC); flags |= O_BINARY; - DWORD access = GENERIC_READ | SYNCHRONIZE; if (get_major () == DEV_TAPE_MAJOR || (flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY || (flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDWR) - access |= GENERIC_WRITE; + flags = ((flags & ~(O_WRONLY | O_RDWR)) | O_RDWR); - extern void str2buf2uni (UNICODE_STRING &, WCHAR *, const char *); - UNICODE_STRING dev; - WCHAR devname[CYG_MAX_PATH + 1]; - str2buf2uni (dev, devname, get_win32_name ()); - OBJECT_ATTRIBUTES attr; - ULONG options = FILE_SYNCHRONOUS_IO_NONALERT; - /* The O_TEXT flag is used to indicate write-through on tape devices */ - if (get_major () == DEV_TAPE_MAJOR && (flags & O_TEXT)) - options |= FILE_WRITE_THROUGH; - flags &= ~O_TEXT; - InitializeObjectAttributes (&attr, &dev, OBJ_CASE_INSENSITIVE, NULL, NULL); - - HANDLE h; - IO_STATUS_BLOCK io; - NTSTATUS status = NtOpenFile (&h, access, &attr, &io, 0 /* excl. access */, - options); - if (!NT_SUCCESS (status)) - { - __seterrno_from_win_error (RtlNtStatusToDosError (status)); - return 0; - } - - set_io_handle (h); - set_flags ((flags & ~O_TEXT) | O_BINARY); - - if (devbufsiz > 1L) + int res = fhandler_base::open (flags, 0); + if (res && devbufsiz > 1L) devbuf = new char [devbufsiz]; - return 1; + return res; } int diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index 2ecedcf01..0fb7c0e5a 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -389,6 +389,9 @@ typedef struct _OBJECT_NAME_INFORMATION standard Win32 header. */ extern "C" { + NTSTATUS NTAPI NtCreateFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, + PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, + ULONG, ULONG, PVOID, ULONG); NTSTATUS NTAPI NtCreateToken (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, TOKEN_TYPE, PLUID, PLARGE_INTEGER, PTOKEN_USER, PTOKEN_GROUPS, PTOKEN_PRIVILEGES, PTOKEN_OWNER, diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 1b4000fe7..a99198bd6 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2648,8 +2648,7 @@ symlink_worker (const char *topath, const char *frompath, bool use_winsym, { CloseHandle (h); if (!allow_ntsec && allow_ntea) - set_file_attribute (win32_path.has_acls (), NULL, - win32_path.get_win32 (), + set_file_attribute (false, NULL, win32_path.get_win32 (), S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO); DWORD attr = use_winsym ? FILE_ATTRIBUTE_READONLY diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc index 0e20a9fc5..268f378db 100644 --- a/winsup/cygwin/sec_acl.cc +++ b/winsup/cygwin/sec_acl.cc @@ -261,7 +261,7 @@ getacl (HANDLE handle, const char *file, DWORD attr, int nentries, { security_descriptor sd; - if (!handle || get_nt_object_security (handle, SE_FILE_OBJECT, sd) + if ((!handle || get_nt_object_security (handle, SE_FILE_OBJECT, sd)) && read_sd (file, sd) <= 0) { debug_printf ("read_sd %E"); diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc index 0c44c6f7c..b97dcd028 100644 --- a/winsup/cygwin/sec_helper.cc +++ b/winsup/cygwin/sec_helper.cc @@ -375,6 +375,20 @@ out: return ret; } +/* Helper function to set the SE_RESTORE_NAME privilege once. */ +void +enable_restore_privilege () +{ + static int NO_COPY saved_res; + bool issetuid = cygheap->user.issetuid (); + if (!saved_res || issetuid) + { + int res = 2 + set_process_privilege (SE_RESTORE_NAME, true, issetuid); + if (!issetuid) + saved_res = res; + } +} + /* * Function to return a common SECURITY_DESCRIPTOR * that * allows all access. diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 239505128..29dd0a056 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -165,6 +165,16 @@ str2buf2uni (UNICODE_STRING &tgt, WCHAR *buf, const char *srcstr) sys_mbstowcs (buf, srcstr, tgt.MaximumLength); } +void +str2buf2uni_cat (UNICODE_STRING &tgt, const char *srcstr) +{ + DWORD len = strlen (srcstr) * sizeof (WCHAR); + sys_mbstowcs (tgt.Buffer + tgt.Length / sizeof (WCHAR), srcstr, + len + tgt.MaximumLength); + tgt.Length += len; + tgt.MaximumLength += len; +} + #if 0 /* unused */ static void lsa2wchar (WCHAR *tgt, LSA_UNICODE_STRING &src, int size) @@ -1119,38 +1129,9 @@ read_sd (const char *file, security_descriptor &sd) LONG write_sd (HANDLE fh, const char *file, security_descriptor &sd) { - /* Try turning privilege on, may not have WRITE_OWNER or WRITE_DAC access. - Must have privilege to set different owner, else BackupWrite misbehaves */ - static int NO_COPY saved_res; /* 0: never, 1: failed, 2 & 3: OK */ - int res; - if (!saved_res || cygheap->user.issetuid ()) - { - res = 2 + set_process_privilege (SE_RESTORE_NAME, true, - cygheap->user.issetuid ()); - if (!cygheap->user.issetuid ()) - saved_res = res; - } - else - res = saved_res; - if (res == 1) - { - BOOL dummy; - cygpsid owner; - - if (!GetSecurityDescriptorOwner (sd, (PSID *) &owner, &dummy)) - { - __seterrno (); - return -1; - } - if (owner != cygheap->user.sid ()) - { - set_errno (EPERM); - return -1; - } - } NTSTATUS ret = STATUS_SUCCESS; int retry = 0; - res = -1; + int res = -1; for (; retry < 2; ++retry) { if (retry && (fh = CreateFile (file, WRITE_OWNER | WRITE_DAC, diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index df78775e5..b0bc6e414 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -248,7 +248,6 @@ extern bool allow_ntsec; extern bool allow_smbntsec; /* File manipulation */ -int __stdcall set_process_privileges (); int __stdcall get_file_attribute (int, HANDLE, const char *, mode_t *, __uid32_t * = NULL, __gid32_t * = NULL); int __stdcall set_file_attribute (bool, HANDLE, const char *, int); @@ -275,6 +274,10 @@ extern "C" int acl32 (const char *, int, int, __acl32 *); int getacl (HANDLE, const char *, DWORD, int, __acl32 *); int setacl (HANDLE, const char *, int, __acl32 *); +struct _UNICODE_STRING; +void __stdcall str2buf2uni (_UNICODE_STRING &, WCHAR *, const char *) __attribute__ ((regparm (3))); +void __stdcall str2buf2uni_cat (_UNICODE_STRING &, const char *) __attribute__ ((regparm (2))); + /* Try a subauthentication. */ HANDLE subauth (struct passwd *pw); /* Try creating a token directly. */ @@ -289,6 +292,7 @@ bool get_logon_server (const char * domain, char * server, WCHAR *wserver = NULL /* sec_helper.cc: Security helper functions. */ int set_process_privilege (const char *privilege, bool enable = true, bool use_thread = false); +void enable_restore_privilege (void); /* shared.cc: */ /* Retrieve a security descriptor that allows all access */ diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 659f33185..d89b86484 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -872,6 +872,9 @@ lchown (const char * name, __uid16_t uid, __gid16_t gid) extern "C" int fchown32 (int fd, __uid32_t uid, __gid32_t gid) { + if (!wincap.has_security ()) // real chown only works on NT + return 0; // return zero (and do nothing) under Windows 9x + cygheap_fdget cfd (fd); if (cfd < 0) {