From e859706578ba60d3fcc011dd0e5d77b10342ae3f Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 16 Apr 2004 21:22:13 +0000 Subject: * 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. --- winsup/cygwin/fhandler.cc | 206 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 166 insertions(+), 40 deletions(-) (limited to 'winsup/cygwin/fhandler.cc') 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. -- cgit v1.2.3