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 \
|
for ac_func in \
|
||||||
|
@ -15988,6 +15989,7 @@ for ac_func in \
|
||||||
fpclass \
|
fpclass \
|
||||||
ftruncate \
|
ftruncate \
|
||||||
ftruncate64 \
|
ftruncate64 \
|
||||||
|
futimes \
|
||||||
getnetbyaddr \
|
getnetbyaddr \
|
||||||
getnetbyname \
|
getnetbyname \
|
||||||
getopt_long \
|
getopt_long \
|
||||||
|
|
|
@ -1027,6 +1027,7 @@ AC_CHECK_FUNCS(\
|
||||||
fpclass \
|
fpclass \
|
||||||
ftruncate \
|
ftruncate \
|
||||||
ftruncate64 \
|
ftruncate64 \
|
||||||
|
futimes \
|
||||||
getnetbyaddr \
|
getnetbyaddr \
|
||||||
getnetbyname \
|
getnetbyname \
|
||||||
getopt_long \
|
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 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;
|
mode_t FILE_umask;
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -1787,26 +1790,57 @@ BOOL WINAPI CopyFileExA(LPCSTR sourceFilename, LPCSTR destFilename,
|
||||||
* SetFileTime (KERNEL32.@)
|
* SetFileTime (KERNEL32.@)
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI SetFileTime( HANDLE hFile,
|
BOOL WINAPI SetFileTime( HANDLE hFile,
|
||||||
const FILETIME *lpCreationTime,
|
const FILETIME *ctime,
|
||||||
const FILETIME *lpLastAccessTime,
|
const FILETIME *atime,
|
||||||
const FILETIME *lpLastWriteTime )
|
const FILETIME *mtime )
|
||||||
{
|
{
|
||||||
BOOL ret;
|
#ifdef HAVE_FUTIMES
|
||||||
SERVER_START_REQ( set_file_time )
|
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;
|
struct timeval tv[2];
|
||||||
if (lpLastAccessTime)
|
|
||||||
RtlTimeToSecondsSince1970( (PLARGE_INTEGER) lpLastAccessTime, (DWORD *)&req->access_time );
|
if (!atime || !mtime)
|
||||||
else
|
{
|
||||||
req->access_time = 0; /* FIXME */
|
struct stat st;
|
||||||
if (lpLastWriteTime)
|
|
||||||
RtlTimeToSecondsSince1970( (PLARGE_INTEGER) lpLastWriteTime, (DWORD *)&req->write_time );
|
tv[0].tv_sec = tv[0].tv_usec = 0;
|
||||||
else
|
tv[1].tv_sec = tv[1].tv_usec = 0;
|
||||||
req->write_time = 0; /* FIXME */
|
if (!fstat( fd, &st ))
|
||||||
ret = !wine_server_call_err( req );
|
{
|
||||||
|
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;
|
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. */
|
/* Define to 1 if you have the `ftruncate64' function. */
|
||||||
#undef HAVE_FTRUNCATE64
|
#undef HAVE_FTRUNCATE64
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `futimes' function. */
|
||||||
|
#undef HAVE_FUTIMES
|
||||||
|
|
||||||
/* Define to 1 if you have the `getbkgd' function. */
|
/* Define to 1 if you have the `getbkgd' function. */
|
||||||
#undef HAVE_GETBKGD
|
#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 flush_file_request
|
||||||
{
|
{
|
||||||
struct request_header __header;
|
struct request_header __header;
|
||||||
|
@ -3197,7 +3183,6 @@ enum request
|
||||||
REQ_get_handle_fd,
|
REQ_get_handle_fd,
|
||||||
REQ_set_file_pointer,
|
REQ_set_file_pointer,
|
||||||
REQ_truncate_file,
|
REQ_truncate_file,
|
||||||
REQ_set_file_time,
|
|
||||||
REQ_flush_file,
|
REQ_flush_file,
|
||||||
REQ_get_file_info,
|
REQ_get_file_info,
|
||||||
REQ_lock_file,
|
REQ_lock_file,
|
||||||
|
@ -3384,7 +3369,6 @@ union generic_request
|
||||||
struct get_handle_fd_request get_handle_fd_request;
|
struct get_handle_fd_request get_handle_fd_request;
|
||||||
struct set_file_pointer_request set_file_pointer_request;
|
struct set_file_pointer_request set_file_pointer_request;
|
||||||
struct truncate_file_request truncate_file_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 flush_file_request flush_file_request;
|
||||||
struct get_file_info_request get_file_info_request;
|
struct get_file_info_request get_file_info_request;
|
||||||
struct lock_file_request lock_file_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 get_handle_fd_reply get_handle_fd_reply;
|
||||||
struct set_file_pointer_reply set_file_pointer_reply;
|
struct set_file_pointer_reply set_file_pointer_reply;
|
||||||
struct truncate_file_reply truncate_file_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 flush_file_reply flush_file_reply;
|
||||||
struct get_file_info_reply get_file_info_reply;
|
struct get_file_info_reply get_file_info_reply;
|
||||||
struct lock_file_reply lock_file_reply;
|
struct lock_file_reply lock_file_reply;
|
||||||
|
@ -3710,6 +3693,6 @@ union generic_reply
|
||||||
struct set_global_windows_reply set_global_windows_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 */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -573,37 +573,6 @@ int grow_file( struct file *file, int size_high, int size_low )
|
||||||
return ret;
|
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 */
|
/* create a file */
|
||||||
DECL_HANDLER(create_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 */
|
/* lock a region of a file */
|
||||||
DECL_HANDLER(lock_file)
|
DECL_HANDLER(lock_file)
|
||||||
{
|
{
|
||||||
|
|
|
@ -633,14 +633,6 @@ enum fd_type
|
||||||
@END
|
@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 */
|
/* Flush a file buffers */
|
||||||
@REQ(flush_file)
|
@REQ(flush_file)
|
||||||
obj_handle_t handle; /* handle to the 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(get_handle_fd);
|
||||||
DECL_HANDLER(set_file_pointer);
|
DECL_HANDLER(set_file_pointer);
|
||||||
DECL_HANDLER(truncate_file);
|
DECL_HANDLER(truncate_file);
|
||||||
DECL_HANDLER(set_file_time);
|
|
||||||
DECL_HANDLER(flush_file);
|
DECL_HANDLER(flush_file);
|
||||||
DECL_HANDLER(get_file_info);
|
DECL_HANDLER(get_file_info);
|
||||||
DECL_HANDLER(lock_file);
|
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_get_handle_fd,
|
||||||
(req_handler)req_set_file_pointer,
|
(req_handler)req_set_file_pointer,
|
||||||
(req_handler)req_truncate_file,
|
(req_handler)req_truncate_file,
|
||||||
(req_handler)req_set_file_time,
|
|
||||||
(req_handler)req_flush_file,
|
(req_handler)req_flush_file,
|
||||||
(req_handler)req_get_file_info,
|
(req_handler)req_get_file_info,
|
||||||
(req_handler)req_lock_file,
|
(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 );
|
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 )
|
static void dump_flush_file_request( const struct flush_file_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " handle=%p", req->handle );
|
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_get_handle_fd_request,
|
||||||
(dump_func)dump_set_file_pointer_request,
|
(dump_func)dump_set_file_pointer_request,
|
||||||
(dump_func)dump_truncate_file_request,
|
(dump_func)dump_truncate_file_request,
|
||||||
(dump_func)dump_set_file_time_request,
|
|
||||||
(dump_func)dump_flush_file_request,
|
(dump_func)dump_flush_file_request,
|
||||||
(dump_func)dump_get_file_info_request,
|
(dump_func)dump_get_file_info_request,
|
||||||
(dump_func)dump_lock_file_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_get_handle_fd_reply,
|
||||||
(dump_func)dump_set_file_pointer_reply,
|
(dump_func)dump_set_file_pointer_reply,
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
(dump_func)0,
|
|
||||||
(dump_func)dump_flush_file_reply,
|
(dump_func)dump_flush_file_reply,
|
||||||
(dump_func)dump_get_file_info_reply,
|
(dump_func)dump_get_file_info_reply,
|
||||||
(dump_func)dump_lock_file_reply,
|
(dump_func)dump_lock_file_reply,
|
||||||
|
@ -2974,7 +2965,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||||
"get_handle_fd",
|
"get_handle_fd",
|
||||||
"set_file_pointer",
|
"set_file_pointer",
|
||||||
"truncate_file",
|
"truncate_file",
|
||||||
"set_file_time",
|
|
||||||
"flush_file",
|
"flush_file",
|
||||||
"get_file_info",
|
"get_file_info",
|
||||||
"lock_file",
|
"lock_file",
|
||||||
|
|
Loading…
Reference in New Issue