ObjFW  Diff

Differences From Artifact [d9639e50f4]:

  • File src/OFFileIRIHandler.m — part of check-in [c615b62ed8] at 2024-04-16 23:50:40 on branch trunk — Don't use readdir_r

    readdir_r can easily lead to stack overflows if the path is longer than
    the space reserved for d_name in dirent. While some OSes use a length of
    MAXNAMLEN + 1, others use just 1. This could be worked around by always
    allocating a buffer of sizeof(struct dirent) + MAXNAMLEN (which would
    work only in case MAXNAMLEN is actually the longest readdir_r can
    return), but is probably not worth the risk, especially as glibc has
    entirely deprecated readdir_r and it is expected to be removed from
    POSIX. (user: js, size: 50258) [annotate] [blame] [check-ins using] [more...]

To Artifact [ae11241b71]:


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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_WINDOWS
# include <utime.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
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 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 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
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 = 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))
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
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)
	if (_wutime64FuncPtr != NULL) {
		struct __utimbuf64 times = {
			.actime =
			    (__time64_t)lastAccessDate.timeIntervalSince1970,
			.modtime =
			    (__time64_t)modificationDate.timeIntervalSince1970
		};
	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 (_wutime64FuncPtr([path UTF16String], &times) != 0) {
			int errNo = errno;

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

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

			@throw [OFSetItemAttributesFailedException
			    exceptionWithIRI: IRI
				  attributes: attributes
			     failedAttribute: attributeKey
				       errNo: errNo];
		}
		@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);

	CloseHandle(handle);
		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;