From: Eric Pouech eric.pouech@gmail.com
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/ntdll/tests/file.c | 6 ------ server/fd.c | 30 +++++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index b3b6cb79bcf..7d7de7d1a32 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -3021,7 +3021,6 @@ static void test_file_disposition_information(void) ok( res == STATUS_DELETE_PENDING, "got %#lx\n", res ); /* can't open the deleted file */ handle3 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); - todo_wine ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" ); if (handle3 != INVALID_HANDLE_VALUE) CloseHandle( handle3 ); @@ -3158,9 +3157,7 @@ static void test_file_disposition_information(void) ok( res == STATUS_OBJECT_NAME_NOT_FOUND || broken(res == STATUS_DELETE_PENDING), "got %#lx\n", res ); /* can't open the deleted file */ handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); - todo_wine ok( handle2 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" ); - todo_wine ok( GetLastError() == ERROR_FILE_NOT_FOUND || broken(GetLastError() == ERROR_ACCESS_DENIED), "got %lu\n", GetLastError()); if (handle2 != INVALID_HANDLE_VALUE) CloseHandle( handle2); @@ -3214,9 +3211,7 @@ static void test_file_disposition_information(void) ok( res == STATUS_OBJECT_NAME_NOT_FOUND || broken(res == STATUS_DELETE_PENDING), "got %#lx\n", res ); /* can't open the deleted directory */ handle2 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); - todo_wine ok( handle2 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" ); - todo_wine ok(GetLastError() == ERROR_FILE_NOT_FOUND || broken(GetLastError() == ERROR_ACCESS_DENIED), "got %lu\n", GetLastError()); if (handle2 != INVALID_HANDLE_VALUE) CloseHandle( handle2 ); CloseHandle( handle ); @@ -3239,7 +3234,6 @@ static void test_file_disposition_information(void) ok( res == STATUS_DELETE_PENDING, "got %#lx\n", res ); /* can't open the deleted directory */ handle3 = CreateFileA(buffer, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); - todo_wine ok( handle3 == INVALID_HANDLE_VALUE, "CreateFile should fail\n" ); if (handle3 != INVALID_HANDLE_VALUE) CloseHandle( handle3 ); diff --git a/server/fd.c b/server/fd.c index 6db2da6764f..6263d39c119 100644 --- a/server/fd.c +++ b/server/fd.c @@ -157,7 +157,8 @@ static inline int epoll_wait( int epfd, struct epoll_event *events, int maxevent
/* file descriptor object */
-#define UNLINK_OPENED_WITH_DELETE_ON_CLOSE 1u /* shared across all fd with same name */ +#define UNLINK_OPENED_WITH_DELETE_ON_CLOSE 1u /* only on fd opened with delete-on-close flag */ +#define UNLINK_PROPAGATED_DELETE_ON_CLOSE 2u /* shared across all fd with same name */ #define UNLINK_DISPOSITION 4u /* shared across all fd with same name */
@@ -1160,7 +1161,7 @@ static void inode_propagate_unlink( struct fd *fd, unsigned or_mask, unsigned an } }
-static void inode_init_closed_unlink( struct fd *fd ) +static BOOL inode_init_closed_unlink( struct fd *fd ) { struct list *ptr;
@@ -1169,10 +1170,21 @@ static void inode_init_closed_unlink( struct fd *fd ) struct fd *fd_ptr = LIST_ENTRY( ptr, struct fd, inode_entry ); if (fd_ptr->unix_name && fd->unix_name && !strcmp(fd_ptr->unix_name, fd->unix_name)) { + if (fd_ptr->closed->unlink & UNLINK_DISPOSITION) return FALSE; if (fd_ptr->closed->unlink & UNLINK_OPENED_WITH_DELETE_ON_CLOSE) - fd->closed->unlink |= UNLINK_OPENED_WITH_DELETE_ON_CLOSE; + fd->closed->unlink |= UNLINK_PROPAGATED_DELETE_ON_CLOSE; } } + LIST_FOR_EACH( ptr, &fd->inode->closed ) + { + struct closed_fd *closed_fd = LIST_ENTRY( ptr, struct closed_fd, entry ); + if (closed_fd->unix_name && fd->unix_name && !strcmp(closed_fd->unix_name, fd->unix_name)) + { + if (closed_fd->unlink & (UNLINK_OPENED_WITH_DELETE_ON_CLOSE | UNLINK_DISPOSITION)) + return FALSE; + } + } + return TRUE; }
static void inode_dump( struct object *obj, int verbose ) @@ -2069,7 +2081,11 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam goto error; }
- inode_init_closed_unlink( fd ); + if (!inode_init_closed_unlink( fd )) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + goto error; + } if (flags & O_TRUNC) { if (S_ISDIR(st.st_mode)) @@ -2079,7 +2095,11 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam } ftruncate( fd->unix_fd, 0 ); } - if (options & FILE_DELETE_ON_CLOSE) inode_propagate_unlink( fd, UNLINK_OPENED_WITH_DELETE_ON_CLOSE, 0 ); + if (options & FILE_DELETE_ON_CLOSE) + { + inode_propagate_unlink( fd, UNLINK_PROPAGATED_DELETE_ON_CLOSE, 0 ); + fd->closed->unlink = UNLINK_OPENED_WITH_DELETE_ON_CLOSE; + } } else /* special file */ {