* 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.
This commit is contained in:
Corinna Vinschen
2004-04-16 21:22:13 +00:00
parent e2c248c18b
commit e859706578
14 changed files with 293 additions and 144 deletions

View File

@ -28,6 +28,8 @@ details. */
#include <assert.h>
#include <limits.h>
#include <winioctl.h>
#include <ntdef.h>
#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.