From: Eric Pouech eric.pouech@gmail.com
Signed-off-by: Eric Pouech eric.pouech@gmail.com --- dlls/ntdll/tests/file.c | 8 -------- server/fd.c | 42 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 837fd0adecc..ba6e8564968 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -3152,7 +3152,6 @@ static void test_file_disposition_information(void) ok( fileDeleted, "File should have been deleted\n" ); res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation); ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); - todo_wine ok(fsi.DeletePending, "Handle should be marked for deletion\n"); res = nt_get_file_attrs( buffer, &fdi2 ); todo_wine @@ -3209,7 +3208,6 @@ static void test_file_disposition_information(void) ok( fileDeleted, "Directory should have been deleted\n" ); res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation); ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); - todo_wine ok(fsi.DeletePending, "Handle should be marked for deletion\n"); res = nt_get_file_attrs( buffer, &fdi2 ); todo_wine @@ -3429,19 +3427,16 @@ static void test_file_disposition_information(void) ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); res = NtQueryInformationFile(handle2, &io, &fsi, sizeof(fsi), FileStandardInformation); ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); - todo_wine ok(fsi.DeletePending, "Handle should be marked for deletion\n"); fdi.DoDeleteFile = FALSE; res = NtSetInformationFile(handle2, &io, &fdi, sizeof(fdi), FileDispositionInformation); ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation); ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); - todo_wine ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n"); CloseHandle(handle); CloseHandle(handle2); res = GetFileAttributesA( buffer ); - todo_wine ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" );
/* pending delete flag is shared across handles (even after closing) */ @@ -3461,7 +3456,6 @@ static void test_file_disposition_information(void) ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); res = NtQueryInformationFile(handle2, &io, &fsi, sizeof(fsi), FileStandardInformation); ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); - todo_wine ok(fsi.DeletePending, "Handle should be marked for deletion\n"); fdi.DoDeleteFile = FALSE; res = NtSetInformationFile(handle2, &io, &fdi, sizeof(fdi), FileDispositionInformation); @@ -3469,11 +3463,9 @@ static void test_file_disposition_information(void) CloseHandle(handle2); res = NtQueryInformationFile(handle, &io, &fsi, sizeof(fsi), FileStandardInformation); ok(res == STATUS_SUCCESS, "NtQueryInformationFile failed %lx\n", res); - todo_wine ok(!fsi.DeletePending, "Handle shouldn't be marked for deletion\n"); CloseHandle(handle); res = GetFileAttributesA( buffer ); - todo_wine ok( res != INVALID_FILE_ATTRIBUTES, "expected file to exist\n" ); }
diff --git a/server/fd.c b/server/fd.c index e11a66ce625..292850682fd 100644 --- a/server/fd.c +++ b/server/fd.c @@ -162,7 +162,8 @@ struct closed_fd { struct list entry; /* entry in inode closed list */ int unix_fd; /* the unix file descriptor */ - int unlink; /* whether to unlink on close: -1 - implicit FILE_DELETE_ON_CLOSE, 1 - explicit disposition */ + int unlink; /* whether to unlink on close: bit0 - implicit FILE_DELETE_ON_CLOSE, bit1 - explicit disposition */ + /* value duplicated (=shared) across all closed_fd:s of same path */ char *unix_name; /* name to unlink on close, points to parent fd unix_name */ };
@@ -1132,6 +1133,34 @@ static void inode_close_pending( struct inode *inode, int keep_unlinks ) } }
+static unsigned int inode_propagate_unlink( struct fd *fd, unsigned or_mask, unsigned and_mask ) +{ + struct list *ptr; + unsigned int unlink = 0; + + LIST_FOR_EACH( ptr, &fd->inode->open ) + { + 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)) + { + unlink |= fd_ptr->closed->unlink; + fd_ptr->closed->unlink |= or_mask; + fd_ptr->closed->unlink &= ~and_mask; + } + } + 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)) + { + unlink |= closed_fd->unlink; + closed_fd->unlink |= or_mask; + closed_fd->unlink &= ~and_mask; + } + } + return unlink; +} + static void inode_dump( struct object *obj, int verbose ) { struct inode *inode = (struct inode *)obj; @@ -2026,7 +2055,8 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam goto error; }
- fd->closed->unlink = (options & FILE_DELETE_ON_CLOSE) ? -1 : 0; + /* get existing unlink value from open/closed fd */ + fd->closed->unlink = inode_propagate_unlink( fd, 0, 0 ); if (flags & O_TRUNC) { if (S_ISDIR(st.st_mode)) @@ -2036,6 +2066,7 @@ 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, 1, 0 ); } else /* special file */ { @@ -2542,9 +2573,10 @@ static void set_fd_disposition( struct fd *fd, int unlink ) } }
- fd->closed->unlink = unlink ? 1 : 0; - if (fd->options & FILE_DELETE_ON_CLOSE) - fd->closed->unlink = -1; + if (unlink) + inode_propagate_unlink( fd, 2, 0 ); + else + inode_propagate_unlink( fd, 0, 2 ); }
/* set new name for the fd */