ntdll: Truncate files through the server.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
08c5e0106b
commit
4e84a553a8
|
@ -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;
|
||||
|
|
|
@ -5083,6 +5083,19 @@ struct set_fd_name_info_reply
|
|||
|
||||
|
||||
|
||||
struct set_fd_eof_info_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t handle;
|
||||
file_pos_t eof;
|
||||
};
|
||||
struct set_fd_eof_info_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct get_window_layered_info_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -5640,6 +5653,7 @@ enum request
|
|||
REQ_set_fd_completion_mode,
|
||||
REQ_set_fd_disp_info,
|
||||
REQ_set_fd_name_info,
|
||||
REQ_set_fd_eof_info,
|
||||
REQ_get_window_layered_info,
|
||||
REQ_set_window_layered_info,
|
||||
REQ_alloc_user_handle,
|
||||
|
@ -5919,6 +5933,7 @@ union generic_request
|
|||
struct set_fd_completion_mode_request set_fd_completion_mode_request;
|
||||
struct set_fd_disp_info_request set_fd_disp_info_request;
|
||||
struct set_fd_name_info_request set_fd_name_info_request;
|
||||
struct set_fd_eof_info_request set_fd_eof_info_request;
|
||||
struct get_window_layered_info_request get_window_layered_info_request;
|
||||
struct set_window_layered_info_request set_window_layered_info_request;
|
||||
struct alloc_user_handle_request alloc_user_handle_request;
|
||||
|
@ -6196,6 +6211,7 @@ union generic_reply
|
|||
struct set_fd_completion_mode_reply set_fd_completion_mode_reply;
|
||||
struct set_fd_disp_info_reply set_fd_disp_info_reply;
|
||||
struct set_fd_name_info_reply set_fd_name_info_reply;
|
||||
struct set_fd_eof_info_reply set_fd_eof_info_reply;
|
||||
struct get_window_layered_info_reply get_window_layered_info_reply;
|
||||
struct set_window_layered_info_reply set_window_layered_info_reply;
|
||||
struct alloc_user_handle_reply alloc_user_handle_reply;
|
||||
|
@ -6220,7 +6236,7 @@ union generic_reply
|
|||
|
||||
/* ### protocol_version begin ### */
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 717
|
||||
#define SERVER_PROTOCOL_VERSION 718
|
||||
|
||||
/* ### protocol_version end ### */
|
||||
|
||||
|
|
37
server/fd.c
37
server/fd.c
|
@ -2630,6 +2630,32 @@ failed:
|
|||
free( name );
|
||||
}
|
||||
|
||||
static void set_fd_eof( struct fd *fd, file_pos_t eof )
|
||||
{
|
||||
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)
|
||||
grow_file( fd->unix_fd, eof );
|
||||
else
|
||||
file_set_error();
|
||||
}
|
||||
|
||||
struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key )
|
||||
{
|
||||
*p_key = fd->comp_key;
|
||||
|
@ -2922,3 +2948,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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,6 +168,7 @@ extern int is_file_executable( const char *name );
|
|||
|
||||
struct memory_view;
|
||||
|
||||
extern int grow_file( int unix_fd, file_pos_t new_size );
|
||||
extern struct memory_view *find_mapped_view( struct process *process, client_ptr_t base );
|
||||
extern struct memory_view *get_exe_view( struct process *process );
|
||||
extern struct file *get_view_file( const struct memory_view *view, unsigned int access, unsigned int sharing );
|
||||
|
|
|
@ -241,7 +241,7 @@ static void shared_map_destroy( struct object *obj )
|
|||
}
|
||||
|
||||
/* extend a file beyond the current end of file */
|
||||
static int grow_file( int unix_fd, file_pos_t new_size )
|
||||
int grow_file( int unix_fd, file_pos_t new_size )
|
||||
{
|
||||
static const char zero;
|
||||
off_t size = new_size;
|
||||
|
|
|
@ -3535,6 +3535,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 */
|
||||
|
|
|
@ -371,6 +371,7 @@ DECL_HANDLER(add_fd_completion);
|
|||
DECL_HANDLER(set_fd_completion_mode);
|
||||
DECL_HANDLER(set_fd_disp_info);
|
||||
DECL_HANDLER(set_fd_name_info);
|
||||
DECL_HANDLER(set_fd_eof_info);
|
||||
DECL_HANDLER(get_window_layered_info);
|
||||
DECL_HANDLER(set_window_layered_info);
|
||||
DECL_HANDLER(alloc_user_handle);
|
||||
|
@ -649,6 +650,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_set_fd_completion_mode,
|
||||
(req_handler)req_set_fd_disp_info,
|
||||
(req_handler)req_set_fd_name_info,
|
||||
(req_handler)req_set_fd_eof_info,
|
||||
(req_handler)req_get_window_layered_info,
|
||||
(req_handler)req_set_window_layered_info,
|
||||
(req_handler)req_alloc_user_handle,
|
||||
|
@ -2141,6 +2143,9 @@ C_ASSERT( FIELD_OFFSET(struct set_fd_name_info_request, namelen) == 20 );
|
|||
C_ASSERT( FIELD_OFFSET(struct set_fd_name_info_request, link) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_fd_name_info_request, replace) == 28 );
|
||||
C_ASSERT( sizeof(struct set_fd_name_info_request) == 32 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_fd_eof_info_request, handle) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_fd_eof_info_request, eof) == 16 );
|
||||
C_ASSERT( sizeof(struct set_fd_eof_info_request) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_window_layered_info_request, handle) == 12 );
|
||||
C_ASSERT( sizeof(struct get_window_layered_info_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_window_layered_info_reply, color_key) == 8 );
|
||||
|
|
|
@ -4355,6 +4355,12 @@ static void dump_set_fd_name_info_request( const struct set_fd_name_info_request
|
|||
dump_varargs_string( ", filename=", cur_size );
|
||||
}
|
||||
|
||||
static void dump_set_fd_eof_info_request( const struct set_fd_eof_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
dump_uint64( ", eof=", &req->eof );
|
||||
}
|
||||
|
||||
static void dump_get_window_layered_info_request( const struct get_window_layered_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%08x", req->handle );
|
||||
|
@ -4792,6 +4798,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_set_fd_completion_mode_request,
|
||||
(dump_func)dump_set_fd_disp_info_request,
|
||||
(dump_func)dump_set_fd_name_info_request,
|
||||
(dump_func)dump_set_fd_eof_info_request,
|
||||
(dump_func)dump_get_window_layered_info_request,
|
||||
(dump_func)dump_set_window_layered_info_request,
|
||||
(dump_func)dump_alloc_user_handle_request,
|
||||
|
@ -5067,6 +5074,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(dump_func)dump_get_window_layered_info_reply,
|
||||
NULL,
|
||||
(dump_func)dump_alloc_user_handle_reply,
|
||||
|
@ -5342,6 +5350,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"set_fd_completion_mode",
|
||||
"set_fd_disp_info",
|
||||
"set_fd_name_info",
|
||||
"set_fd_eof_info",
|
||||
"get_window_layered_info",
|
||||
"set_window_layered_info",
|
||||
"alloc_user_handle",
|
||||
|
|
Loading…
Reference in New Issue