Use futimes() instead of utime() to implement SetFileTime, so that it
can be done on the client side.
This commit is contained in:
parent
dd46d6df9e
commit
a1fe8b4f24
|
@ -15970,6 +15970,7 @@ fi
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for ac_func in \
|
||||
|
@ -15988,6 +15989,7 @@ for ac_func in \
|
|||
fpclass \
|
||||
ftruncate \
|
||||
ftruncate64 \
|
||||
futimes \
|
||||
getnetbyaddr \
|
||||
getnetbyname \
|
||||
getopt_long \
|
||||
|
|
|
@ -1027,6 +1027,7 @@ AC_CHECK_FUNCS(\
|
|||
fpclass \
|
||||
ftruncate \
|
||||
ftruncate64 \
|
||||
futimes \
|
||||
getnetbyaddr \
|
||||
getnetbyname \
|
||||
getopt_long \
|
||||
|
|
66
files/file.c
66
files/file.c
|
@ -83,6 +83,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(file);
|
|||
|
||||
#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
|
||||
|
||||
#define SECSPERDAY 86400
|
||||
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
|
||||
|
||||
mode_t FILE_umask;
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -1787,26 +1790,57 @@ BOOL WINAPI CopyFileExA(LPCSTR sourceFilename, LPCSTR destFilename,
|
|||
* SetFileTime (KERNEL32.@)
|
||||
*/
|
||||
BOOL WINAPI SetFileTime( HANDLE hFile,
|
||||
const FILETIME *lpCreationTime,
|
||||
const FILETIME *lpLastAccessTime,
|
||||
const FILETIME *lpLastWriteTime )
|
||||
const FILETIME *ctime,
|
||||
const FILETIME *atime,
|
||||
const FILETIME *mtime )
|
||||
{
|
||||
BOOL ret;
|
||||
SERVER_START_REQ( set_file_time )
|
||||
#ifdef HAVE_FUTIMES
|
||||
BOOL ret = FALSE;
|
||||
NTSTATUS status;
|
||||
int fd;
|
||||
ULONGLONG sec, nsec;
|
||||
|
||||
if (!(status = wine_server_handle_to_fd( hFile, GENERIC_WRITE, &fd, NULL, NULL )))
|
||||
{
|
||||
req->handle = hFile;
|
||||
if (lpLastAccessTime)
|
||||
RtlTimeToSecondsSince1970( (PLARGE_INTEGER) lpLastAccessTime, (DWORD *)&req->access_time );
|
||||
else
|
||||
req->access_time = 0; /* FIXME */
|
||||
if (lpLastWriteTime)
|
||||
RtlTimeToSecondsSince1970( (PLARGE_INTEGER) lpLastWriteTime, (DWORD *)&req->write_time );
|
||||
else
|
||||
req->write_time = 0; /* FIXME */
|
||||
ret = !wine_server_call_err( req );
|
||||
struct timeval tv[2];
|
||||
|
||||
if (!atime || !mtime)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
tv[0].tv_sec = tv[0].tv_usec = 0;
|
||||
tv[1].tv_sec = tv[1].tv_usec = 0;
|
||||
if (!fstat( fd, &st ))
|
||||
{
|
||||
tv[0].tv_sec = st.st_atime;
|
||||
tv[1].tv_sec = st.st_mtime;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
if (atime)
|
||||
{
|
||||
sec = ((ULONGLONG)atime->dwHighDateTime << 32) | atime->dwLowDateTime;
|
||||
sec = RtlLargeIntegerDivide( sec, 10000000, &nsec );
|
||||
tv[0].tv_sec = sec - SECS_1601_TO_1970;
|
||||
tv[0].tv_usec = (UINT)nsec / 10;
|
||||
}
|
||||
if (mtime)
|
||||
{
|
||||
sec = ((ULONGLONG)mtime->dwHighDateTime << 32) | mtime->dwLowDateTime;
|
||||
sec = RtlLargeIntegerDivide( sec, 10000000, &nsec );
|
||||
tv[0].tv_sec = sec - SECS_1601_TO_1970;
|
||||
tv[0].tv_usec = (UINT)nsec / 10;
|
||||
}
|
||||
|
||||
if (!futimes( fd, tv )) ret = TRUE;
|
||||
else FILE_SetDosError();
|
||||
wine_server_release_fd( hFile, fd );
|
||||
}
|
||||
else SetLastError( RtlNtStatusToDosError(status) );
|
||||
return ret;
|
||||
#else
|
||||
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
|
||||
return FALSE;
|
||||
#endif /* HAVE_FUTIMES */
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -134,6 +134,9 @@
|
|||
/* Define to 1 if you have the `ftruncate64' function. */
|
||||
#undef HAVE_FTRUNCATE64
|
||||
|
||||
/* Define to 1 if you have the `futimes' function. */
|
||||
#undef HAVE_FUTIMES
|
||||
|
||||
/* Define to 1 if you have the `getbkgd' function. */
|
||||
#undef HAVE_GETBKGD
|
||||
|
||||
|
|
|
@ -834,20 +834,6 @@ struct truncate_file_reply
|
|||
|
||||
|
||||
|
||||
struct set_file_time_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t handle;
|
||||
time_t access_time;
|
||||
time_t write_time;
|
||||
};
|
||||
struct set_file_time_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct flush_file_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -3197,7 +3183,6 @@ enum request
|
|||
REQ_get_handle_fd,
|
||||
REQ_set_file_pointer,
|
||||
REQ_truncate_file,
|
||||
REQ_set_file_time,
|
||||
REQ_flush_file,
|
||||
REQ_get_file_info,
|
||||
REQ_lock_file,
|
||||
|
@ -3384,7 +3369,6 @@ union generic_request
|
|||
struct get_handle_fd_request get_handle_fd_request;
|
||||
struct set_file_pointer_request set_file_pointer_request;
|
||||
struct truncate_file_request truncate_file_request;
|
||||
struct set_file_time_request set_file_time_request;
|
||||
struct flush_file_request flush_file_request;
|
||||
struct get_file_info_request get_file_info_request;
|
||||
struct lock_file_request lock_file_request;
|
||||
|
@ -3569,7 +3553,6 @@ union generic_reply
|
|||
struct get_handle_fd_reply get_handle_fd_reply;
|
||||
struct set_file_pointer_reply set_file_pointer_reply;
|
||||
struct truncate_file_reply truncate_file_reply;
|
||||
struct set_file_time_reply set_file_time_reply;
|
||||
struct flush_file_reply flush_file_reply;
|
||||
struct get_file_info_reply get_file_info_reply;
|
||||
struct lock_file_reply lock_file_reply;
|
||||
|
@ -3710,6 +3693,6 @@ union generic_reply
|
|||
struct set_global_windows_reply set_global_windows_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 135
|
||||
#define SERVER_PROTOCOL_VERSION 136
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -573,37 +573,6 @@ int grow_file( struct file *file, int size_high, int size_low )
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int set_file_time( obj_handle_t handle, time_t access_time, time_t write_time )
|
||||
{
|
||||
struct file *file;
|
||||
struct utimbuf utimbuf;
|
||||
|
||||
if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
|
||||
return 0;
|
||||
if (!file->name)
|
||||
{
|
||||
set_error( STATUS_INVALID_HANDLE );
|
||||
release_object( file );
|
||||
return 0;
|
||||
}
|
||||
if (!access_time || !write_time)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat( file->name, &st ) == -1) goto error;
|
||||
if (!access_time) access_time = st.st_atime;
|
||||
if (!write_time) write_time = st.st_mtime;
|
||||
}
|
||||
utimbuf.actime = access_time;
|
||||
utimbuf.modtime = write_time;
|
||||
if (utime( file->name, &utimbuf ) == -1) goto error;
|
||||
release_object( file );
|
||||
return 1;
|
||||
error:
|
||||
file_set_error();
|
||||
release_object( file );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* create a file */
|
||||
DECL_HANDLER(create_file)
|
||||
{
|
||||
|
@ -659,12 +628,6 @@ DECL_HANDLER(truncate_file)
|
|||
}
|
||||
}
|
||||
|
||||
/* set a file access and modification times */
|
||||
DECL_HANDLER(set_file_time)
|
||||
{
|
||||
set_file_time( req->handle, req->access_time, req->write_time );
|
||||
}
|
||||
|
||||
/* lock a region of a file */
|
||||
DECL_HANDLER(lock_file)
|
||||
{
|
||||
|
|
|
@ -633,14 +633,6 @@ enum fd_type
|
|||
@END
|
||||
|
||||
|
||||
/* Set a file access and modification times */
|
||||
@REQ(set_file_time)
|
||||
obj_handle_t handle; /* handle to the file */
|
||||
time_t access_time; /* last access time */
|
||||
time_t write_time; /* last write time */
|
||||
@END
|
||||
|
||||
|
||||
/* Flush a file buffers */
|
||||
@REQ(flush_file)
|
||||
obj_handle_t handle; /* handle to the file */
|
||||
|
|
|
@ -144,7 +144,6 @@ DECL_HANDLER(alloc_file_handle);
|
|||
DECL_HANDLER(get_handle_fd);
|
||||
DECL_HANDLER(set_file_pointer);
|
||||
DECL_HANDLER(truncate_file);
|
||||
DECL_HANDLER(set_file_time);
|
||||
DECL_HANDLER(flush_file);
|
||||
DECL_HANDLER(get_file_info);
|
||||
DECL_HANDLER(lock_file);
|
||||
|
@ -330,7 +329,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_get_handle_fd,
|
||||
(req_handler)req_set_file_pointer,
|
||||
(req_handler)req_truncate_file,
|
||||
(req_handler)req_set_file_time,
|
||||
(req_handler)req_flush_file,
|
||||
(req_handler)req_get_file_info,
|
||||
(req_handler)req_lock_file,
|
||||
|
|
|
@ -891,13 +891,6 @@ static void dump_truncate_file_request( const struct truncate_file_request *req
|
|||
fprintf( stderr, " handle=%p", req->handle );
|
||||
}
|
||||
|
||||
static void dump_set_file_time_request( const struct set_file_time_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%p,", req->handle );
|
||||
fprintf( stderr, " access_time=%ld,", (long)req->access_time );
|
||||
fprintf( stderr, " write_time=%ld", (long)req->write_time );
|
||||
}
|
||||
|
||||
static void dump_flush_file_request( const struct flush_file_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%p", req->handle );
|
||||
|
@ -2608,7 +2601,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_get_handle_fd_request,
|
||||
(dump_func)dump_set_file_pointer_request,
|
||||
(dump_func)dump_truncate_file_request,
|
||||
(dump_func)dump_set_file_time_request,
|
||||
(dump_func)dump_flush_file_request,
|
||||
(dump_func)dump_get_file_info_request,
|
||||
(dump_func)dump_lock_file_request,
|
||||
|
@ -2791,7 +2783,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_get_handle_fd_reply,
|
||||
(dump_func)dump_set_file_pointer_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_flush_file_reply,
|
||||
(dump_func)dump_get_file_info_reply,
|
||||
(dump_func)dump_lock_file_reply,
|
||||
|
@ -2974,7 +2965,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"get_handle_fd",
|
||||
"set_file_pointer",
|
||||
"truncate_file",
|
||||
"set_file_time",
|
||||
"flush_file",
|
||||
"get_file_info",
|
||||
"lock_file",
|
||||
|
|
Loading…
Reference in New Issue