Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2008-05-15 20:34:01 +0400
committerCorinna Vinschen <corinna@vinschen.de>2008-05-15 20:34:01 +0400
commit4c153b24d98b49d34a17a0ba91dd959e7b9d6dc7 (patch)
tree07178ce3c1abad0f7c1f8d8b8ee5c21d35f2c4bd /winsup
parent43334bd027aed0c02a9f6fb71f995cdcd4cfc733 (diff)
* 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.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog22
-rw-r--r--winsup/cygwin/autoload.cc9
-rw-r--r--winsup/cygwin/ntdll.h10
-rw-r--r--winsup/cygwin/syscalls.cc73
-rw-r--r--winsup/cygwin/wincap.cc10
-rw-r--r--winsup/cygwin/wincap.h2
6 files changed, 123 insertions, 3 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 44b94cbc1..4bc83a643 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 7f9dbe992..f9f02f289 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -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)
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index bf901eaaa..cc2f95f77 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -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,
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index b323da203..af3d0ad17 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -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;
}
diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc
index 4ce3ca1ce..cf44dcc79 100644
--- a/winsup/cygwin/wincap.cc
+++ b/winsup/cygwin/wincap.cc
@@ -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));
diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h
index b1b8a3c72..2035ecc5a 100644
--- a/winsup/cygwin/wincap.h
+++ b/winsup/cygwin/wincap.h
@@ -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
};