From: Joel Holdsworth joel@airwebreathe.org.uk
Both the Msys2 and Cygwin runtimes make use of FILE_DISPOSITON_POSIX_SEMANTICS in their implementations of the unlink() system call. This enables these routines to behave similarly to POSIX where are unlisted from the directory, if handles are still open.
https://github.com/msys2/msys2-runtime/blob/msys2-3.4.3/winsup/cygwin/syscal... https://www.cygwin.com/git/?p=newlib-cygwin.git;a=blob;f=winsup/cygwin/sysca...
Signed-off-by: Joel Holdsworth joel@airwebreathe.org.uk --- dlls/ntdll/tests/file.c | 1 - dlls/ntdll/unix/file.c | 2 -- server/fd.c | 36 ++++++++++++++++++++++++------------ 3 files changed, 24 insertions(+), 15 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 0da10e4a3da..40793e2db05 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -3076,7 +3076,6 @@ static void test_file_disposition_information(void) if ( res == STATUS_SUCCESS ) { fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND; - todo_wine ok( fileDeleted, "File should have been deleted\n" ); } CloseHandle( handle2 ); diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 90760588e63..b2219645478 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -4767,8 +4767,6 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, { FILE_DISPOSITION_INFORMATION_EX *info = ptr;
- if (info->Flags & FILE_DISPOSITION_POSIX_SEMANTICS) - FIXME( "FILE_DISPOSITION_POSIX_SEMANTICS not supported\n" ); if (info->Flags & FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK) FIXME( "FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK not supported\n" );
diff --git a/server/fd.c b/server/fd.c index 6ce3343fb6f..0b0e91ebfbb 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1103,10 +1103,20 @@ static void device_destroy( struct object *obj ) list_remove( &device->entry ); /* remove it from the hash table */ }
- /****************************************************************/ /* inode functions */
+static void unlink_closed_fd( struct inode *inode, struct closed_fd *fd ) +{ + /* make sure it is still the same file */ + struct stat st; + if (!stat( fd->unix_name, &st ) && st.st_dev == inode->device->dev && st.st_ino == inode->ino) + { + if (S_ISDIR(st.st_mode)) rmdir( fd->unix_name ); + else unlink( fd->unix_name ); + } +} + /* close all pending file descriptors in the closed list */ static void inode_close_pending( struct inode *inode, int keep_unlinks ) { @@ -1158,15 +1168,7 @@ static void inode_destroy( struct object *obj ) list_remove( ptr ); if (fd->unix_fd != -1) close( fd->unix_fd ); if (fd->disp_flags & FILE_DISPOSITION_DELETE) - { - /* make sure it is still the same file */ - struct stat st; - if (!stat( fd->unix_name, &st ) && st.st_dev == inode->device->dev && st.st_ino == inode->ino) - { - if (S_ISDIR(st.st_mode)) rmdir( fd->unix_name ); - else unlink( fd->unix_name ); - } - } + unlink_closed_fd( inode, fd ); free( fd->unix_name ); free( fd ); } @@ -1213,7 +1215,16 @@ static void inode_add_closed_fd( struct inode *inode, struct closed_fd *fd ) { list_add_head( &inode->closed, &fd->entry ); } - else if (fd->disp_flags & FILE_DISPOSITION_ON_CLOSE) + else if ((fd->disp_flags & FILE_DISPOSITION_DELETE) && + (fd->disp_flags & FILE_DISPOSITION_POSIX_SEMANTICS)) + { + /* close the fd and unlink it at once */ + if (fd->unix_fd != -1) close( fd->unix_fd ); + unlink_closed_fd( inode, fd ); + free( fd->unix_name ); + free( fd ); + } + else if (fd->disp_flags & FILE_DISPOSITION_DELETE) { /* close the fd but keep the structure around for unlink */ if (fd->unix_fd != -1) close( fd->unix_fd ); @@ -2532,7 +2543,8 @@ static void set_fd_disposition( struct fd *fd, unsigned int flags ) if (flags & FILE_DISPOSITION_ON_CLOSE) fd->options &= ~FILE_DELETE_ON_CLOSE;
- fd->closed->disp_flags = (flags & FILE_DISPOSITION_DELETE) | + fd->closed->disp_flags = + (flags & (FILE_DISPOSITION_DELETE | FILE_DISPOSITION_POSIX_SEMANTICS)) | ((fd->options & FILE_DELETE_ON_CLOSE) ? FILE_DISPOSITION_DELETE : 0); }