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], ×) != 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], ×);
else
status = _utime(
[path cStringWithEncoding: [OFLocale encoding]],
×);
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;
|