* autoload.cc (LoadDLLfuncNt): Re-invent.

(NtCreateTransaction): Define.
	(NtCommitTransaction): Define.
	(NtRollbackTransaction): Define.
	(RtlGetCurrentTransaction): Define.
	(RtlSetCurrentTransaction): Define.
	* ntdll.h (TRANSACTION_ALL_ACCESS): Define.
	(NtCreateTransaction): Declare.
	(NtCommitTransaction): Declare.
	(NtRollbackTransaction): Declare.
	(RtlGetCurrentTransaction): Declare.
	(RtlSetCurrentTransaction): Declare.
	* syscalls.cc (start_transaction): New static function to start TxF
	transaction.
	(stop_transaction): New static function to end TxF transaction.
	(rename): Call start_transaction and stop_transaction where appropriate
	on systems supporting transactions.
	* wincap.h (wincaps::has_transactions): New element.
	* wincap.cc: Implement above element throughout.
This commit is contained in:
Corinna Vinschen 2008-05-15 16:34:01 +00:00
parent 43334bd027
commit 4c153b24d9
6 changed files with 123 additions and 3 deletions

View File

@ -1,3 +1,25 @@
2008-05-15 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc (LoadDLLfuncNt): Re-invent.
(NtCreateTransaction): Define.
(NtCommitTransaction): Define.
(NtRollbackTransaction): Define.
(RtlGetCurrentTransaction): Define.
(RtlSetCurrentTransaction): Define.
* ntdll.h (TRANSACTION_ALL_ACCESS): Define.
(NtCreateTransaction): Declare.
(NtCommitTransaction): Declare.
(NtRollbackTransaction): Declare.
(RtlGetCurrentTransaction): Declare.
(RtlSetCurrentTransaction): Declare.
* syscalls.cc (start_transaction): New static function to start TxF
transaction.
(stop_transaction): New static function to end TxF transaction.
(rename): Call start_transaction and stop_transaction where appropriate
on systems supporting transactions.
* wincap.h (wincaps::has_transactions): New element.
* wincap.cc: Implement above element throughout.
2008-05-14 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (fhandler_disk_file::readdir_helper): Drop

View File

@ -311,6 +311,15 @@ LoadDLLfunc (NetLocalGroupGetMembers, 32, netapi32)
LoadDLLfunc (NetUserGetGroups, 28, netapi32)
LoadDLLfunc (NetUserGetInfo, 16, netapi32)
/* 0xc000007a == STATUS_PROCEDURE_NOT_FOUND */
#define LoadDLLfuncNt(name, n, dllname) \
LoadDLLfuncEx2(name, n, dllname, 1, 0xc000007a)
LoadDLLfuncNt (NtCommitTransaction, 8, ntdll)
LoadDLLfuncNt (NtCreateTransaction, 40, ntdll)
LoadDLLfuncNt (NtRollbackTransaction, 8, ntdll)
LoadDLLfuncNt (RtlGetCurrentTransaction, 0, ntdll)
LoadDLLfuncNt (RtlSetCurrentTransaction, 4, ntdll)
LoadDLLfuncEx (EnumProcessModules, 16, psapi, 1)
LoadDLLfuncEx (GetModuleFileNameExW, 16, psapi, 1)
LoadDLLfuncEx (GetModuleInformation, 16, psapi, 1)

View File

@ -77,6 +77,9 @@
#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080
#define FILE_DEVICE_SECURE_OPEN 0x00000100
/* Transaction access rights. */
#define TRANSACTION_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x3F)
typedef enum _FILE_INFORMATION_CLASS
{
FileDirectoryInformation = 1,
@ -855,6 +858,7 @@ extern "C"
NTSTATUS NTAPI NtAdjustPrivilegesToken (HANDLE, BOOLEAN, PTOKEN_PRIVILEGES,
ULONG, PTOKEN_PRIVILEGES, PULONG);
NTSTATUS NTAPI NtClose (HANDLE);
NTSTATUS NTAPI NtCommitTransaction (HANDLE, BOOLEAN);
NTSTATUS NTAPI NtCreateDirectoryObject (PHANDLE, ACCESS_MASK,
POBJECT_ATTRIBUTES);
NTSTATUS NTAPI NtCreateEvent (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
@ -876,6 +880,9 @@ extern "C"
PTOKEN_GROUPS, PTOKEN_PRIVILEGES, PTOKEN_OWNER,
PTOKEN_PRIMARY_GROUP, PTOKEN_DEFAULT_DACL,
PTOKEN_SOURCE);
NTSTATUS NTAPI NtCreateTransaction (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
LPGUID, HANDLE, ULONG, ULONG, ULONG,
PLARGE_INTEGER, PUNICODE_STRING);
NTSTATUS NTAPI NtFsControlFile (HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
PIO_STATUS_BLOCK, ULONG, PVOID, ULONG,
PVOID, ULONG);
@ -929,6 +936,7 @@ extern "C"
NTSTATUS NTAPI NtReadFile (HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER,
PULONG);
NTSTATUS NTAPI NtRollbackTransaction (HANDLE, BOOLEAN);
NTSTATUS NTAPI NtSetEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG);
NTSTATUS NTAPI NtSetInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG,
FILE_INFORMATION_CLASS);
@ -957,6 +965,7 @@ extern "C"
VOID NTAPI RtlFreeAnsiString (PANSI_STRING);
VOID NTAPI RtlFreeOemString (POEM_STRING);
VOID NTAPI RtlFreeUnicodeString (PUNICODE_STRING);
HANDLE NTAPI RtlGetCurrentTransaction ();
VOID NTAPI RtlInitEmptyUnicodeString (PUNICODE_STRING, PCWSTR, USHORT);
VOID NTAPI RtlInitUnicodeString (PUNICODE_STRING, PCWSTR);
NTSTATUS NTAPI RtlIntegerToUnicodeString (ULONG, ULONG, PUNICODE_STRING);
@ -968,6 +977,7 @@ extern "C"
BOOLEAN);
VOID NTAPI RtlReleasePebLock ();
VOID NTAPI RtlSecondsSince1970ToTime (ULONG, PLARGE_INTEGER);
BOOLEAN NTAPI RtlSetCurrentTransaction (HANDLE);
NTSTATUS NTAPI RtlUnicodeStringToAnsiString (PANSI_STRING, PUNICODE_STRING,
BOOLEAN);
NTSTATUS NTAPI RtlUnicodeStringToOemString (PANSI_STRING, PUNICODE_STRING,

View File

@ -1461,6 +1461,36 @@ rename_append_suffix (path_conv &pc, const char *path, size_t len,
pc.check (buf, PC_SYM_NOFOLLOW);
}
static void
start_transaction (HANDLE &old_trans, HANDLE &trans)
{
NTSTATUS status = NtCreateTransaction (&trans,
SYNCHRONIZE | TRANSACTION_ALL_ACCESS,
NULL, NULL, NULL, 0, 0, 0, NULL, NULL);
if (NT_SUCCESS (status))
{
old_trans = RtlGetCurrentTransaction ();
RtlSetCurrentTransaction (trans);
}
else
{
debug_printf ("NtCreateTransaction failed, %p", status);
old_trans = trans = NULL;
}
}
static NTSTATUS
stop_transaction (NTSTATUS status, HANDLE old_trans, HANDLE trans)
{
RtlSetCurrentTransaction (old_trans);
if (NT_SUCCESS (status))
status = NtCommitTransaction (trans, TRUE);
else
status = NtRollbackTransaction (trans, TRUE);
NtClose (trans);
return status;
}
extern "C" int
rename (const char *oldpath, const char *newpath)
{
@ -1473,6 +1503,7 @@ rename (const char *oldpath, const char *newpath)
bool equal_path;
NTSTATUS status;
HANDLE fh = NULL, nfh;
HANDLE old_trans = NULL, trans = NULL;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
ULONG size;
@ -1681,6 +1712,13 @@ rename (const char *oldpath, const char *newpath)
}
dstpc = (removepc == &newpc) ? &new2pc : &newpc;
/* Opening the file must be part of the transaction. It's not sufficient
to call only NtSetInformationFile under the transaction. Therefore we
have to start the transaction here, if necessary. */
if (wincap.has_transactions ()
&& (dstpc->isdir () || dstpc->has_attribute (FILE_ATTRIBUTE_READONLY)))
start_transaction (old_trans, trans);
/* DELETE is required to rename a file. */
status = NtOpenFile (&fh, DELETE, oldpc.get_object_attr (attr, sec_none_nih),
&io, FILE_SHARE_VALID_FLAGS,
@ -1789,9 +1827,36 @@ rename (const char *oldpath, const char *newpath)
existing file, if the permissions of the existing file aren't right.
Like directories, we have to handle this separately by removing the
destination before renaming. */
if (status == STATUS_ACCESS_DENIED && dstpc->exists () && !dstpc->isdir ()
&& NT_SUCCESS (status = unlink_nt (*dstpc)))
status = NtSetInformationFile (fh, &io, pfri, size, FileRenameInformation);
if (status == STATUS_ACCESS_DENIED && dstpc->exists () && !dstpc->isdir ())
{
if (wincap.has_transactions () && !trans)
{
start_transaction (old_trans, trans);
/* As mentioned earlier, opening the file must be part of the
transaction. Therefore we have to reopen the file here if the
transaction hasn't been started already. Unfortunately we can't
use the NT "reopen file from existing handle" feature. In that
case NtOpenFile returns STATUS_TRANSACTIONAL_CONFLICT. We *have*
to close the handle to the file first, *then* we can re-open it.
Fortunately nothing has happened yet, so the atomicity of the
rename functionality is not spoiled. */
NtClose (fh);
status = NtOpenFile (&fh, DELETE,
oldpc.get_object_attr (attr, sec_none_nih),
&io, FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT
| (oldpc.is_rep_symlink ()
? FILE_OPEN_REPARSE_POINT : 0));
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
goto out;
}
}
if (NT_SUCCESS (status = unlink_nt (*dstpc)))
status = NtSetInformationFile (fh, &io, pfri, size,
FileRenameInformation);
}
if (NT_SUCCESS (status))
{
if (removepc)
@ -1804,6 +1869,8 @@ rename (const char *oldpath, const char *newpath)
out:
if (fh)
NtClose (fh);
if (wincap.has_transactions () && trans)
stop_transaction (status, old_trans, trans);
syscall_printf ("%d = rename (%s, %s)", res, oldpath, newpath);
return res;
}

View File

@ -42,6 +42,7 @@ static NO_COPY wincaps wincap_unknown = {
has_gaa_on_link_prefix:false,
supports_all_posix_ai_flags:false,
has_restricted_stack_args:false,
has_transactions:false,
};
static NO_COPY wincaps wincap_nt4 = {
@ -72,6 +73,7 @@ static NO_COPY wincaps wincap_nt4 = {
has_gaa_on_link_prefix:false,
supports_all_posix_ai_flags:false,
has_restricted_stack_args:false,
has_transactions:false,
};
static NO_COPY wincaps wincap_nt4sp4 = {
@ -102,6 +104,7 @@ static NO_COPY wincaps wincap_nt4sp4 = {
has_gaa_on_link_prefix:false,
supports_all_posix_ai_flags:false,
has_restricted_stack_args:false,
has_transactions:false,
};
static NO_COPY wincaps wincap_2000 = {
@ -132,6 +135,7 @@ static NO_COPY wincaps wincap_2000 = {
has_gaa_on_link_prefix:false,
supports_all_posix_ai_flags:false,
has_restricted_stack_args:false,
has_transactions:false,
};
static NO_COPY wincaps wincap_2000sp4 = {
@ -162,6 +166,7 @@ static NO_COPY wincaps wincap_2000sp4 = {
has_gaa_on_link_prefix:false,
supports_all_posix_ai_flags:false,
has_restricted_stack_args:false,
has_transactions:false,
};
static NO_COPY wincaps wincap_xp = {
@ -192,6 +197,7 @@ static NO_COPY wincaps wincap_xp = {
has_gaa_on_link_prefix:false,
supports_all_posix_ai_flags:false,
has_restricted_stack_args:false,
has_transactions:false,
};
static NO_COPY wincaps wincap_xpsp1 = {
@ -222,6 +228,7 @@ static NO_COPY wincaps wincap_xpsp1 = {
has_gaa_on_link_prefix:false,
supports_all_posix_ai_flags:false,
has_restricted_stack_args:false,
has_transactions:false,
};
static NO_COPY wincaps wincap_xpsp2 = {
@ -252,6 +259,7 @@ static NO_COPY wincaps wincap_xpsp2 = {
has_gaa_on_link_prefix:false,
supports_all_posix_ai_flags:false,
has_restricted_stack_args:false,
has_transactions:false,
};
static NO_COPY wincaps wincap_2003 = {
@ -282,6 +290,7 @@ static NO_COPY wincaps wincap_2003 = {
has_gaa_on_link_prefix:false,
supports_all_posix_ai_flags:false,
has_restricted_stack_args:true,
has_transactions:false,
};
static NO_COPY wincaps wincap_vista = {
@ -312,6 +321,7 @@ static NO_COPY wincaps wincap_vista = {
has_gaa_on_link_prefix:true,
supports_all_posix_ai_flags:true,
has_restricted_stack_args:false,
has_transactions:true,
};
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));

View File

@ -40,6 +40,7 @@ struct wincaps
unsigned has_gaa_on_link_prefix : 1;
unsigned supports_all_posix_ai_flags : 1;
unsigned has_restricted_stack_args : 1;
unsigned has_transactions : 1;
};
class wincapc
@ -86,6 +87,7 @@ public:
bool IMPLEMENT (has_gaa_on_link_prefix)
bool IMPLEMENT (supports_all_posix_ai_flags)
bool IMPLEMENT (has_restricted_stack_args)
bool IMPLEMENT (has_transactions)
#undef IMPLEMENT
};