ObjFW  Check-in [7eb995ad11]

Overview
Comment:Don't use _wutime64 on Windows

It seems to be buggy in some MinGW distributions and doesn't handle DST
correctly.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 7eb995ad117084321e97f78ee306a3a189f7461cb8ed17c0cc7d08b749d2cbe2
User & Date: js on 2024-04-21 11:16:37
Other Links: manifest | tags
Context
2024-04-21
19:15
Use RtlGenRandom on Windows if available check-in: 2bcb2bd40f user: js tags: trunk
11:16
Don't use _wutime64 on Windows check-in: 7eb995ad11 user: js tags: trunk
2024-04-20
17:50
Update ChangeLog for 1.1.2 check-in: dca251a2b9 user: js tags: trunk
Changes

Modified src/OFFileIRIHandler.m from [d9639e50f4] to [ae11241b71].

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#endif
#if defined(OF_FREEBSD) || defined(OF_NETBSD)
# include <sys/extattr.h>
#endif
#ifdef OF_HAIKU
# include <kernel/fs_attr.h>
#endif
#ifdef OF_WINDOWS
# include <utime.h>
#endif
#ifdef OF_DJGPP
# include <syslimits.h>
#endif

#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif







<
<
<







41
42
43
44
45
46
47



48
49
50
51
52
53
54
#endif
#if defined(OF_FREEBSD) || defined(OF_NETBSD)
# include <sys/extattr.h>
#endif
#ifdef OF_HAIKU
# include <kernel/fs_attr.h>
#endif



#ifdef OF_DJGPP
# include <syslimits.h>
#endif

#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171













172
173
174
175
176
177
178
releaseReaddirMutex(void)
{
	[readdirMutex release];
}
#endif

#ifdef OF_WINDOWS
static int (*_wutime64FuncPtr)(const wchar_t *, struct __utimbuf64 *);
static WINAPI BOOLEAN (*createSymbolicLinkWFuncPtr)(LPCWSTR, LPCWSTR, DWORD);
static WINAPI BOOLEAN (*createHardLinkWFuncPtr)(LPCWSTR, LPCWSTR,
    LPSECURITY_ATTRIBUTES);
#endif

#ifdef OF_FREEBSD
static const char *namespaces[] = EXTATTR_NAMESPACE_NAMES;
static int numNamespaces = sizeof(namespaces) / sizeof(*namespaces);
#endif

#ifdef OF_WINDOWS
static OFTimeInterval
filetimeToTimeInterval(const FILETIME *filetime)
{
	return (double)((int64_t)filetime->dwHighDateTime << 32 |
	    filetime->dwLowDateTime) / 10000000.0 - 11644473600.0;
}














static int
lastError(void)
{
	switch (GetLastError()) {
	case ERROR_FILE_NOT_FOUND:
	case ERROR_PATH_NOT_FOUND:







<

















>
>
>
>
>
>
>
>
>
>
>
>
>







144
145
146
147
148
149
150

151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
releaseReaddirMutex(void)
{
	[readdirMutex release];
}
#endif

#ifdef OF_WINDOWS

static WINAPI BOOLEAN (*createSymbolicLinkWFuncPtr)(LPCWSTR, LPCWSTR, DWORD);
static WINAPI BOOLEAN (*createHardLinkWFuncPtr)(LPCWSTR, LPCWSTR,
    LPSECURITY_ATTRIBUTES);
#endif

#ifdef OF_FREEBSD
static const char *namespaces[] = EXTATTR_NAMESPACE_NAMES;
static int numNamespaces = sizeof(namespaces) / sizeof(*namespaces);
#endif

#ifdef OF_WINDOWS
static OFTimeInterval
filetimeToTimeInterval(const FILETIME *filetime)
{
	return (double)((int64_t)filetime->dwHighDateTime << 32 |
	    filetime->dwLowDateTime) / 10000000.0 - 11644473600.0;
}

static FILETIME
timeIntervalToFiletime(OFTimeInterval timeInterval)
{
	uint64_t timestamp =
	    (uint64_t)((timeInterval + 11644473600.0) * 10000000.0);
	FILETIME filetime = {
		.dwHighDateTime = timestamp >> 32,
		.dwLowDateTime = timestamp & 0xFFFFFFFF
	};

	return filetime;
}

static int
lastError(void)
{
	switch (GetLastError()) {
	case ERROR_FILE_NOT_FOUND:
	case ERROR_PATH_NOT_FOUND:
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
#endif
#if defined(OF_HAVE_THREADS) && !defined(__GLIBC__) && !defined(OF_WINDOWS)
	readdirMutex = [[OFMutex alloc] init];
	atexit(releaseReaddirMutex);
#endif

#ifdef OF_WINDOWS
	if ((module = GetModuleHandle("msvcrt.dll")) != NULL)
		_wutime64FuncPtr = (int (*)(const wchar_t *,
		    struct __utimbuf64 *))GetProcAddress(module, "_wutime64");

	if ((module = GetModuleHandleA("kernel32.dll")) != NULL) {
		createSymbolicLinkWFuncPtr =
		    (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR, DWORD))
		    GetProcAddress(module, "CreateSymbolicLinkW");
		createHardLinkWFuncPtr =
		    (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR,
		    LPSECURITY_ATTRIBUTES))







<
<
<
<







786
787
788
789
790
791
792




793
794
795
796
797
798
799
#endif
#if defined(OF_HAVE_THREADS) && !defined(__GLIBC__) && !defined(OF_WINDOWS)
	readdirMutex = [[OFMutex alloc] init];
	atexit(releaseReaddirMutex);
#endif

#ifdef OF_WINDOWS




	if ((module = GetModuleHandleA("kernel32.dll")) != NULL) {
		createSymbolicLinkWFuncPtr =
		    (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR, DWORD))
		    GetProcAddress(module, "CreateSymbolicLinkW");
		createHardLinkWFuncPtr =
		    (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR,
		    LPSECURITY_ATTRIBUTES))
895
896
897
898
899
900
901
902
903
904
905
906
907

908









909






910

911
912
913
914

915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956

	if (lastAccessDate == nil)
		lastAccessDate = modificationDate;
	if (modificationDate == nil)
		modificationDate = lastAccessDate;

#if defined(OF_WINDOWS)
	if (_wutime64FuncPtr != NULL) {
		struct __utimbuf64 times = {
			.actime =
			    (__time64_t)lastAccessDate.timeIntervalSince1970,
			.modtime =
			    (__time64_t)modificationDate.timeIntervalSince1970

		};
















		if (_wutime64FuncPtr([path UTF16String], &times) != 0) {

			int errNo = errno;

			if (errNo == EACCES && [self directoryExistsAtIRI: IRI])
				errNo = EISDIR;


			@throw [OFSetItemAttributesFailedException
			    exceptionWithIRI: IRI
				  attributes: attributes
			     failedAttribute: attributeKey
				       errNo: errNo];
		}
	} else {
		struct _utimbuf times = {
			.actime = (time_t)lastAccessDate.timeIntervalSince1970,
			.modtime =
			    (time_t)modificationDate.timeIntervalSince1970
		};
		int status;

		if ([OFSystemInfo isWindowsNT])
			status = _wutime([path UTF16String], &times);
		else
			status = _utime(
			    [path cStringWithEncoding: [OFLocale encoding]],
			    &times);

		if (status != 0) {
			int errNo = errno;

			if (errNo == EACCES && [self directoryExistsAtIRI: IRI])
				errNo = EISDIR;

			@throw [OFSetItemAttributesFailedException
			    exceptionWithIRI: IRI
				  attributes: attributes
			     failedAttribute: attributeKey
				       errNo: errNo];
		}
	}
#elif defined(OF_AMIGAOS)
	/* AmigaOS does not support access time. */
	OFTimeInterval modificationTime =
	    modificationDate.timeIntervalSince1970;
	struct Locale *locale;
	struct DateStamp date;








<
<
|
|
|
|
>
|
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
|
>
|

<
<
>

|
|
|
|
|
|
<
<
<
<
<
<
<

<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<







900
901
902
903
904
905
906


907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932


933
934
935
936
937
938
939
940







941






942













943
944
945
946
947
948
949

	if (lastAccessDate == nil)
		lastAccessDate = modificationDate;
	if (modificationDate == nil)
		modificationDate = lastAccessDate;

#if defined(OF_WINDOWS)


	FILETIME accessTime = timeIntervalToFiletime(
	    lastAccessDate.timeIntervalSince1970);
	FILETIME modificationTime = timeIntervalToFiletime(
	    modificationDate.timeIntervalSince1970);
	HANDLE handle;

	if ([OFSystemInfo isWindowsNT])
		handle = CreateFileW(path.UTF16String, FILE_WRITE_ATTRIBUTES,
		    FILE_SHARE_READ, NULL, OPEN_EXISTING,
		    FILE_ATTRIBUTE_NORMAL, NULL);
	else
		handle = CreateFileA(
		    [path cStringWithEncoding: [OFLocale encoding]],
		    FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ, NULL,
		    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	if (handle == NULL)
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: lastError()];

	if (!SetFileTime(handle, NULL, &accessTime, &modificationTime)) {
		int errNo = lastError();



		CloseHandle(handle);

		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: errNo];
	}














	CloseHandle(handle);













#elif defined(OF_AMIGAOS)
	/* AmigaOS does not support access time. */
	OFTimeInterval modificationTime =
	    modificationDate.timeIntervalSince1970;
	struct Locale *locale;
	struct DateStamp date;