Commit a1fe8b4f authored by Alexandre Julliard's avatar Alexandre Julliard

Use futimes() instead of utime() to implement SetFileTime, so that it

can be done on the client side.
parent dd46d6df
......@@ -15972,6 +15972,7 @@ fi
for ac_func in \
_lwp_create \
_lwp_self \
......@@ -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 \
......
......@@ -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;
}
}
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 );
}
SERVER_END_REQ;
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",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment