Index: src/OFFileURLHandler.m ================================================================== --- src/OFFileURLHandler.m +++ src/OFFileURLHandler.m @@ -22,12 +22,17 @@ #ifdef HAVE_DIRENT_H # include #endif #include "unistd_wrapper.h" +#import "platform.h" #ifdef HAVE_SYS_STAT_H # include +#endif +#include +#ifdef OF_WINDOWS +# include #endif #ifdef HAVE_PWD_H # include #endif @@ -107,10 +112,11 @@ #if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS) && !defined(OF_WINDOWS) static OFMutex *readdirMutex; #endif #ifdef OF_WINDOWS +static int (*func__wutime64)(const wchar_t *, struct __utimbuf64 *); static WINAPI BOOLEAN (*func_CreateSymbolicLinkW)(LPCWSTR, LPCWSTR, DWORD); static WINAPI BOOLEAN (*func_CreateHardLinkW)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES); #endif @@ -511,10 +517,14 @@ #if !defined(HAVE_READDIR_R) && !defined(OF_WINDOWS) && defined(OF_HAVE_THREADS) readdirMutex = [[OFMutex alloc] init]; #endif #ifdef OF_WINDOWS + if ((module = LoadLibrary("msvcrt.dll")) != NULL) + func__wutime64 = (int (*)(const wchar_t *, + struct __utimbuf64 *))GetProcAddress(module, "_wutime64"); + if ((module = LoadLibrary("kernel32.dll")) != NULL) { func_CreateSymbolicLinkW = (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR, DWORD)) GetProcAddress(module, "CreateSymbolicLinkW"); func_CreateHardLinkW = @@ -595,10 +605,69 @@ objc_autoreleasePoolPop(pool); return ret; } + +- (void)of_setModificationDate: (OFDate *)date + ofItemAtURL: (OFURL *)URL + attributes: (of_file_attributes_t)attributes +{ + of_time_interval_t timeInterval = date.timeIntervalSince1970; + OFString *path = URL.fileSystemRepresentation; +#ifdef OF_WINDOWS + if (func__wutime64 != NULL) { + struct __utimbuf64 times = { + (__time64_t)timeInterval, + (__time64_t)timeInterval + }; + + if (func__wutime64([path UTF16String], ×) != 0) { + of_file_attribute_key_t failedAttribute = + of_file_attribute_key_modification_date; + + @throw [OFSetItemAttributesFailedException + exceptionWithURL: URL + attributes: attributes + failedAttribute: failedAttribute + errNo: errno]; + } + } else { + struct _utimbuf times = { + (time_t)timeInterval, + (time_t)timeInterval + }; + + if (_wutime([path UTF16String], ×) != 0) { + of_file_attribute_key_t failedAttribute = + of_file_attribute_key_modification_date; + + @throw [OFSetItemAttributesFailedException + exceptionWithURL: URL + attributes: attributes + failedAttribute: failedAttribute + errNo: errno]; + } + } +#else + struct timeval times[2] = { + { + .tv_sec = (time_t)timeInterval, + .tv_usec = + (int)((timeInterval - times[0].tv_sec) * 1000) + }, + times[0] + }; + + if (utimes([path cStringWithEncoding: [OFLocale encoding]], times) != 0) + @throw [OFSetItemAttributesFailedException + exceptionWithURL: URL + attributes: attributes + failedAttribute: of_file_attribute_key_modification_date + errNo: errno]; +#endif +} - (void)of_setPOSIXPermissions: (OFNumber *)permissions ofItemAtURL: (OFURL *)URL attributes: (of_file_attributes_t)attributes { @@ -709,11 +778,15 @@ keyEnumerator = [attributes keyEnumerator]; objectEnumerator = [attributes objectEnumerator]; while ((key = [keyEnumerator nextObject]) != nil && (object = [objectEnumerator nextObject]) != nil) { - if ([key isEqual: of_file_attribute_key_posix_permissions]) + if ([key isEqual: of_file_attribute_key_modification_date]) + [self of_setModificationDate: object + ofItemAtURL: URL + attributes: attributes]; + else if ([key isEqual: of_file_attribute_key_posix_permissions]) [self of_setPOSIXPermissions: object ofItemAtURL: URL attributes: attributes]; else if ([key isEqual: of_file_attribute_key_owner]) [self of_setOwner: object