[PATCH 4/5] ntdll: Truncate files through the server.
Zebediah Figura
z.figura12 at gmail.com
Fri Jun 25 00:28:51 CDT 2021
From: Qian Hong <qhong at codeweavers.com>
Signed-off-by: Zebediah Figura <z.figura12 at 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 */
+ at REQ(set_fd_eof_info)
+ obj_handle_t handle; /* handle to a file or directory */
+ file_pos_t eof; /* offset of eof of file */
+ at END
+
+
/* Retrieve layered info for a window */
@REQ(get_window_layered_info)
user_handle_t handle; /* handle to the window */
--
2.30.2
More information about the wine-devel
mailing list