From a1fe8b4f2484ca12e4a67422c9098aa658b9abea Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sat, 27 Mar 2004 01:48:52 +0000 Subject: [PATCH] Use futimes() instead of utime() to implement SetFileTime, so that it can be done on the client side. --- configure | 2 ++ configure.ac | 1 + files/file.c | 66 +++++++++++++++++++++++++--------- include/config.h.in | 3 ++ include/wine/server_protocol.h | 19 +--------- server/file.c | 37 ------------------- server/protocol.def | 8 ----- server/request.h | 2 -- server/trace.c | 10 ------ 9 files changed, 57 insertions(+), 91 deletions(-) diff --git a/configure b/configure index 3cdaec94aff..aff6ad5c475 100755 --- a/configure +++ b/configure @@ -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 \ diff --git a/configure.ac b/configure.ac index 65bb6f7c84f..8457d067f5d 100644 --- a/configure.ac +++ b/configure.ac @@ -1027,6 +1027,7 @@ AC_CHECK_FUNCS(\ fpclass \ ftruncate \ ftruncate64 \ + futimes \ getnetbyaddr \ getnetbyname \ getopt_long \ diff --git a/files/file.c b/files/file.c index b293d67a846..39d4b2daedf 100644 --- a/files/file.c +++ b/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; + } + } + 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 */ } diff --git a/include/config.h.in b/include/config.h.in index a5964fd9886..5c63db70ba7 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -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 diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index a4ace65e34e..653f7e003a0 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -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 */ diff --git a/server/file.c b/server/file.c index 62bda2404fb..6b803f4cff1 100644 --- a/server/file.c +++ b/server/file.c @@ -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) { diff --git a/server/protocol.def b/server/protocol.def index 0ee3fdfc981..5d0f732a955 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -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 */ diff --git a/server/request.h b/server/request.h index 46a3cee93d8..5b168f7ebe2 100644 --- a/server/request.h +++ b/server/request.h @@ -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, diff --git a/server/trace.c b/server/trace.c index 0294019540e..b18ae51c473 100644 --- a/server/trace.c +++ b/server/trace.c @@ -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",