From: Qian Hong qhong@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/unix/file.c | 23 +++++----------------- server/fd.c | 43 ++++++++++++++++++++++++++++++++++++++++++ server/protocol.def | 7 +++++++ 3 files changed, 55 insertions(+), 18 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 21f5d10f3f8..1a57a112a59 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -4360,28 +4360,15 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, case FileEndOfFileInformation: if (len >= sizeof(FILE_END_OF_FILE_INFORMATION)) { - struct stat st; const FILE_END_OF_FILE_INFORMATION *info = ptr;
- if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) - return io->u.Status; - - /* first try normal truncate */ - if (ftruncate( fd, (off_t)info->EndOfFile.QuadPart ) != -1) break; - - /* now check for the need to extend the file */ - if (fstat( fd, &st ) != -1 && (off_t)info->EndOfFile.QuadPart > st.st_size) + SERVER_START_REQ( set_fd_eof_info ) { - static const char zero; - - /* extend the file one byte beyond the requested size and then truncate it */ - /* this should work around ftruncate implementations that can't extend files */ - if (pwrite( fd, &zero, 1, (off_t)info->EndOfFile.QuadPart ) != -1 && - ftruncate( fd, (off_t)info->EndOfFile.QuadPart ) != -1) break; + req->handle = wine_server_obj_handle( handle ); + req->eof = info->EndOfFile.QuadPart; + io->u.Status = wine_server_call( req ); } - io->u.Status = errno_to_status( errno ); - - if (needs_close) close( fd ); + SERVER_END_REQ; } else io->u.Status = STATUS_INVALID_PARAMETER_3; break; diff --git a/server/fd.c b/server/fd.c index e326354d127..fe97ca01c98 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2630,6 +2630,38 @@ failed: free( name ); }
+static void set_fd_eof( struct fd *fd, file_pos_t eof ) +{ + static const char zero; + struct stat st; + + if (!fd->inode) + { + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + return; + } + + if (fd->unix_fd == -1) + { + set_error( fd->no_fd_status ); + return; + } + + /* first try normal truncate */ + if (ftruncate( fd->unix_fd, eof ) != -1) return; + + /* now check for the need to extend the file */ + if (fstat( fd->unix_fd, &st ) != -1 && eof > st.st_size) + { + /* extend the file one byte beyond the requested size and then truncate it */ + /* this should work around ftruncate implementations that can't extend files */ + if (pwrite( fd->unix_fd, &zero, 1, eof ) != -1 && + ftruncate( fd->unix_fd, eof) != -1) return; + } + + file_set_error(); +} + struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key ) { *p_key = fd->comp_key; @@ -2922,3 +2954,14 @@ DECL_HANDLER(set_fd_name_info) } if (root_fd) release_object( root_fd ); } + +/* set fd eof information */ +DECL_HANDLER(set_fd_eof_info) +{ + struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 ); + if (fd) + { + set_fd_eof( fd, req->eof ); + release_object( fd ); + } +} diff --git a/server/protocol.def b/server/protocol.def index 6a11dfac77d..6a92a4f8e74 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3534,6 +3534,13 @@ struct handle_info @END
+/* set fd eof information */ +@REQ(set_fd_eof_info) + obj_handle_t handle; /* handle to a file or directory */ + file_pos_t eof; /* offset of eof of file */ +@END + + /* Retrieve layered info for a window */ @REQ(get_window_layered_info) user_handle_t handle; /* handle to the window */