ObjFW  Check-in [a58aa8e069]

Overview
Comment:Merge trunk into branch "amiga-library"
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | amiga-library
Files: files | file ages | folders
SHA3-256: a58aa8e0695c818074fa4cde9436e7121ed9655b67d01cb8b6fd4e2b3ae4c3c5
User & Date: js on 2020-12-22 21:42:02
Other Links: branch diff | manifest | tags
Context
2020-12-23
03:03
Merge trunk into branch "amiga-library" check-in: 8f56a02f49 user: js tags: amiga-library
2020-12-22
21:42
Merge trunk into branch "amiga-library" check-in: a58aa8e069 user: js tags: amiga-library
20:15
Fix files accidentally being executable check-in: 55fdd76bb7 user: js tags: trunk
2020-12-20
22:51
Make linklib compile for MorphOS check-in: 6dac4586ab user: js tags: amiga-library
Changes

Modified src/OFDNSResolverSettings.m from [7c81772fe9] to [d77fb49b97].

44
45
46
47
48
49
50






51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100








101











































































102
103
104
105
106
107
108

#ifdef OF_NINTENDO_3DS
/* Newer versions of libctru started using id as a parameter name. */
# define id id_3ds
# include <3ds.h>
# undef id
#endif







#import "socket_helpers.h"

#if defined(OF_HAIKU)
# define HOSTS_PATH @"/system/settings/network/hosts"
# define RESOLV_CONF_PATH @"/system/settings/network/resolv.conf"
#elif defined(OF_MORPHOS)
# define HOSTS_PATH @"ENV:sys/net/hosts"
# define RESOLV_CONF_PATH @"ENV:sys/net/resolv.conf"
#elif defined(OF_AMIGAOS4)
# define HOSTS_PATH @"DEVS:Internet/hosts"
#elif defined(OF_AMIGAOS)
# define HOSTS_PATH @"AmiTCP:db/hosts"
# define RESOLV_CONF_PATH @"AmiTCP:db/resolv.conf"
#else
# define HOSTS_PATH @"/etc/hosts"
# define RESOLV_CONF_PATH @"/etc/resolv.conf"
#endif

#ifndef OF_WII
static OFString *
domainFromHostname(void)
{
	char hostname[256];
	OFString *domain, *ret;

	if (gethostname(hostname, 256) != 0)
		return nil;

	domain = [OFString stringWithCString: hostname
				    encoding: [OFLocale encoding]];

	@try {
		of_socket_address_parse_ip(domain, 0);

		/*
		 * If we are still here, the host name is a valid IP address.
		 * We can't use that as local domain.
		 */
		return nil;
	} @catch (OFInvalidFormatException *e) {
		/* Not an IP address -> we can use it if it contains a dot. */
		size_t pos = [domain rangeOfString: @"."].location;

		if (pos == OF_NOT_FOUND)
			return nil;

		ret = [domain substringFromIndex: pos + 1];
	}









	return ret;











































































}
#endif

@implementation OFDNSResolverSettings
- (void)dealloc
{
	[_staticHosts release];







>
>
>
>
>
>






<
<
<










<

|

|
<
<
<


<
<
<

|








|




|

|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62



63
64
65
66
67
68
69
70
71
72

73
74
75
76



77
78



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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

#ifdef OF_NINTENDO_3DS
/* Newer versions of libctru started using id as a parameter name. */
# define id id_3ds
# include <3ds.h>
# undef id
#endif

#ifdef OF_MORPHOS
# include <proto/rexxsyslib.h>
# include <rexx/errors.h>
# include <rexx/storage.h>
#endif

#import "socket_helpers.h"

#if defined(OF_HAIKU)
# define HOSTS_PATH @"/system/settings/network/hosts"
# define RESOLV_CONF_PATH @"/system/settings/network/resolv.conf"



#elif defined(OF_AMIGAOS4)
# define HOSTS_PATH @"DEVS:Internet/hosts"
#elif defined(OF_AMIGAOS)
# define HOSTS_PATH @"AmiTCP:db/hosts"
# define RESOLV_CONF_PATH @"AmiTCP:db/resolv.conf"
#else
# define HOSTS_PATH @"/etc/hosts"
# define RESOLV_CONF_PATH @"/etc/resolv.conf"
#endif


static OFString *
domainFromHostname(OFString *hostname)
{
	if (hostname == nil)



		return nil;




	@try {
		of_socket_address_parse_ip(hostname, 0);

		/*
		 * If we are still here, the host name is a valid IP address.
		 * We can't use that as local domain.
		 */
		return nil;
	} @catch (OFInvalidFormatException *e) {
		/* Not an IP address -> we can use it if it contains a dot. */
		size_t pos = [hostname rangeOfString: @"."].location;

		if (pos == OF_NOT_FOUND)
			return nil;

		return [hostname substringFromIndex: pos + 1];
	}
}

#if !defined(OF_WII) && !defined(OF_MORPHOS)
static OFString *
obtainHostname(void)
{
	char hostname[256];

	if (gethostname(hostname, 256) != 0)
		return nil;

	return [OFString stringWithCString: hostname
				  encoding: [OFLocale encoding]];
}
#endif

#ifdef OF_MORPHOS
static OFString *
arexxCommand(const char *port, const char *command)
{
	struct Library *RexxSysBase;
	struct MsgPort *replyPort = NULL;
	struct RexxMsg *msg = NULL;

	if ((RexxSysBase = OpenLibrary("rexxsyslib.library", 36)) == NULL)
		return nil;

	@try {
		struct MsgPort *rexxPort;

		if ((replyPort = CreateMsgPort()) == NULL)
			return nil;

		if ((msg = CreateRexxMsg(replyPort, NULL, port)) == NULL)
			return nil;

		msg->rm_Action = RXCOMM | RXFF_RESULT;

		if ((msg->rm_Args[0] = (char *)CreateArgstring(
		    command, strlen(command))) == NULL)
			return nil;

		Forbid();

		if ((rexxPort = FindPort(port)) == NULL) {
			Permit();
			return nil;
		}

		PutMsg(rexxPort, &msg->rm_Node);
		Permit();
		WaitPort(replyPort);
		GetMsg(replyPort);

		if (msg->rm_Result1 != RC_OK || msg->rm_Result2 == 0)
			return nil;

		return [OFString stringWithCString: (char *)msg->rm_Result2
					  encoding: [OFLocale encoding]];
	} @finally {
		if (msg != NULL) {
			if (msg->rm_Args[0] != NULL)
				DeleteArgstring(msg->rm_Args[0]);
			if (msg->rm_Result2 != 0)
				DeleteArgstring((char *)msg->rm_Result2);

			DeleteRexxMsg(msg);
		}

		if (replyPort != NULL)
			DeleteMsgPort(replyPort);

		CloseLibrary(RexxSysBase);
	}
}

static OFArray OF_GENERIC(OFString *) *
parseNetStackArray(OFString *string)
{
	if (![string hasPrefix: @"["] || ![string hasSuffix: @"]"])
		return nil;

	string = [string substringWithRange: of_range(1, string.length - 2)];

	return [string componentsSeparatedByString: @"|"];
}
#endif

@implementation OFDNSResolverSettings
- (void)dealloc
{
	[_staticHosts release];
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#ifndef OF_NINTENDO_3DS
	_configReloadInterval = 2;
#else
	_configReloadInterval = 0;
#endif
}

#if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_3DS)
- (void)parseHosts: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFCharacterSet *whitespaceCharacterSet =
	    [OFCharacterSet whitespaceCharacterSet];
	OFMutableDictionary *staticHosts;
	OFFile *file;
	OFString *line;
	OFEnumerator *enumerator;
	OFMutableArray *addresses;

	@try {
		file = [OFFile fileWithPath: path
				       mode: @"r"];
	} @catch (OFOpenItemFailedException *e) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	staticHosts = [OFMutableDictionary dictionary];

	while ((line = [file readLine]) != nil) {
		void *pool2 = objc_autoreleasePoolPush();
		OFArray *components, *hosts;
		size_t pos;
		OFString *address;

		pos = [line rangeOfString: @"#"].location;
		if (pos != OF_NOT_FOUND)
			line = [line substringToIndex: pos];

		components = [line
		    componentsSeparatedByCharactersInSet: whitespaceCharacterSet
						 options: OF_STRING_SKIP_EMPTY];

		if (components.count < 2) {
			objc_autoreleasePoolPop(pool2);
			continue;
		}

		address = components.firstObject;
		hosts = [components objectsInRange:
		    of_range(1, components.count - 1)];

		for (OFString *host in hosts) {

			addresses = [staticHosts objectForKey: host];

			if (addresses == nil) {
				addresses = [OFMutableArray array];
				[staticHosts setObject: addresses
						forKey: host];
			}

			[addresses addObject: address];
		}

		objc_autoreleasePoolPop(pool2);
	}

	enumerator = [staticHosts objectEnumerator];
	while ((addresses = [enumerator nextObject]) != nil)
		[addresses makeImmutable];

	[staticHosts makeImmutable];

	[_staticHosts release];
	_staticHosts = [staticHosts copy];

	objc_autoreleasePoolPop(pool);
}

# if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4)
- (void)parseResolvConfOption: (OFString *)option







|








<
<












<












|
<

<






>
|









|
<
<
<
|
<



<
<







238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253


254
255
256
257
258
259
260
261
262
263
264
265

266
267
268
269
270
271
272
273
274
275
276
277
278

279

280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297



298

299
300
301


302
303
304
305
306
307
308
#ifndef OF_NINTENDO_3DS
	_configReloadInterval = 2;
#else
	_configReloadInterval = 0;
#endif
}

#if defined(OF_HAVE_FILES) && !defined(OF_MORPHOS) && !defined(OF_NINTENDO_3DS)
- (void)parseHosts: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFCharacterSet *whitespaceCharacterSet =
	    [OFCharacterSet whitespaceCharacterSet];
	OFMutableDictionary *staticHosts;
	OFFile *file;
	OFString *line;



	@try {
		file = [OFFile fileWithPath: path
				       mode: @"r"];
	} @catch (OFOpenItemFailedException *e) {
		objc_autoreleasePoolPop(pool);
		return;
	}

	staticHosts = [OFMutableDictionary dictionary];

	while ((line = [file readLine]) != nil) {

		OFArray *components, *hosts;
		size_t pos;
		OFString *address;

		pos = [line rangeOfString: @"#"].location;
		if (pos != OF_NOT_FOUND)
			line = [line substringToIndex: pos];

		components = [line
		    componentsSeparatedByCharactersInSet: whitespaceCharacterSet
						 options: OF_STRING_SKIP_EMPTY];

		if (components.count < 2)

			continue;


		address = components.firstObject;
		hosts = [components objectsInRange:
		    of_range(1, components.count - 1)];

		for (OFString *host in hosts) {
			OFMutableArray *addresses =
			    [staticHosts objectForKey: host];

			if (addresses == nil) {
				addresses = [OFMutableArray array];
				[staticHosts setObject: addresses
						forKey: host];
			}

			[addresses addObject: address];
		}
	}



	for (OFMutableArray *addresses in [staticHosts objectEnumerator])

		[addresses makeImmutable];

	[staticHosts makeImmutable];


	_staticHosts = [staticHosts copy];

	objc_autoreleasePoolPop(pool);
}

# if !defined(OF_WINDOWS) && !defined(OF_AMIGAOS4)
- (void)parseResolvConfOption: (OFString *)option
384
385
386
387
388
389
390



















































391
392
393
394
395
396
397

	if (fixedInfo->DomainName[0] != '\0')
		_localDomain = [[OFString alloc]
		    initWithCString: fixedInfo->DomainName
			   encoding: encoding];
}
#endif




















































#ifdef OF_AMIGAOS4
- (void)obtainAmigaOS4SystemConfig
{
	OFMutableArray *nameServers = [OFMutableArray array];
	of_string_encoding_t encoding = [OFLocale encoding];
	struct List *nameServerList = ObtainDomainNameServerList();







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







453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517

	if (fixedInfo->DomainName[0] != '\0')
		_localDomain = [[OFString alloc]
		    initWithCString: fixedInfo->DomainName
			   encoding: encoding];
}
#endif

#ifdef OF_MORPHOS
- (void)obtainMorphOSSystemConfig
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableDictionary *staticHosts;

	_nameServers = [parseNetStackArray(arexxCommand("NETSTACK",
	    "QUERY NAMESERVERS")) copy];
	_localDomain = [domainFromHostname(arexxCommand("NETSTACK",
	    "QUERY HOSTNAME")) copy];
	_searchDomains = [parseNetStackArray(arexxCommand("NETSTACK",
	    "QUERY DOMAINS")) copy];

	staticHosts = [OFMutableDictionary dictionary];

	for (OFString *entry in parseNetStackArray(arexxCommand("NETSTACK",
	    "QUERY HOSTS"))) {
		OFArray *components = [entry componentsSeparatedByString: @" "];
		OFString *address;
		OFArray *hosts;

		if (components.count < 2)
			continue;

		address = components.firstObject;
		hosts = [components objectsInRange:
		    of_range(1, components.count - 1)];

		for (OFString *host in hosts) {
			OFMutableArray *addresses =
			    [staticHosts objectForKey: host];

			if (addresses == nil) {
				addresses = [OFMutableArray array];
				[staticHosts setObject: addresses
						forKey: host];
			}

			[addresses addObject: address];
		}
	}
	for (OFMutableArray *addresses in [staticHosts objectEnumerator])
		[addresses makeImmutable];

	[staticHosts makeImmutable];
	_staticHosts = [staticHosts copy];

	objc_autoreleasePoolPop(pool);
}
#endif

#ifdef OF_AMIGAOS4
- (void)obtainAmigaOS4SystemConfig
{
	OFMutableArray *nameServers = [OFMutableArray array];
	of_string_encoding_t encoding = [OFLocale encoding];
	struct List *nameServerList = ObtainDomainNameServerList();
506
507
508
509
510
511
512


513
514
515
516
517
518
519
	    stringByExpandingWindowsEnvironmentStrings];

	if (path != nil)
		[self parseHosts: path];
# endif

	[self obtainWindowsSystemConfig];


#elif defined(OF_AMIGAOS4)
	[self parseHosts: HOSTS_PATH];
	[self obtainAmigaOS4SystemConfig];
#elif defined(OF_NINTENDO_3DS)
	[self obtainNintendo3DSSytemConfig];
#elif defined(OF_HAVE_FILES)
	[self parseHosts: HOSTS_PATH];







>
>







626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
	    stringByExpandingWindowsEnvironmentStrings];

	if (path != nil)
		[self parseHosts: path];
# endif

	[self obtainWindowsSystemConfig];
#elif defined(OF_MORPHOS)
	[self obtainMorphOSSystemConfig];
#elif defined(OF_AMIGAOS4)
	[self parseHosts: HOSTS_PATH];
	[self obtainAmigaOS4SystemConfig];
#elif defined(OF_NINTENDO_3DS)
	[self obtainNintendo3DSSytemConfig];
#elif defined(OF_HAVE_FILES)
	[self parseHosts: HOSTS_PATH];
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
#ifdef OF_HAVE_IPV6
		_nameServers = [[OFArray alloc]
		    initWithObjects: @"127.0.0.1", @"::1", nil];
#else
		_nameServers = [[OFArray alloc] initWithObject: @"127.0.0.1"];
#endif

#ifndef OF_WII
	if (_localDomain == nil)
		_localDomain = [domainFromHostname() copy];
#endif

	if (_searchDomains == nil) {
		if (_localDomain != nil)
			_searchDomains = [[OFArray alloc]
			    initWithObject: _localDomain];
		else
			_searchDomains = [[OFArray alloc] init];
	}

	objc_autoreleasePoolPop(pool);
}
@end







|

|













659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
#ifdef OF_HAVE_IPV6
		_nameServers = [[OFArray alloc]
		    initWithObjects: @"127.0.0.1", @"::1", nil];
#else
		_nameServers = [[OFArray alloc] initWithObject: @"127.0.0.1"];
#endif

#if !defined(OF_WII) && !defined(OF_MORPHOS)
	if (_localDomain == nil)
		_localDomain = [domainFromHostname(obtainHostname()) copy];
#endif

	if (_searchDomains == nil) {
		if (_localDomain != nil)
			_searchDomains = [[OFArray alloc]
			    initWithObject: _localDomain];
		else
			_searchDomains = [[OFArray alloc] init];
	}

	objc_autoreleasePoolPop(pool);
}
@end

Modified src/OFDate.m from [2f04475c25] to [d8bff9d62d].

106
107
108
109
110
111
112






113
114
115
116
117
118
119

	return seconds;
}

#if (!defined(HAVE_GMTIME_R) || !defined(HAVE_LOCALTIME_R)) && \
    defined(OF_HAVE_THREADS)
static OFMutex *mutex;






#endif

#ifdef OF_WINDOWS
static __time64_t (*func__mktime64)(struct tm *);
#endif

#ifdef HAVE_GMTIME_R







>
>
>
>
>
>







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

	return seconds;
}

#if (!defined(HAVE_GMTIME_R) || !defined(HAVE_LOCALTIME_R)) && \
    defined(OF_HAVE_THREADS)
static OFMutex *mutex;

static void
releaseMutex(void)
{
	[mutex release];
}
#endif

#ifdef OF_WINDOWS
static __time64_t (*func__mktime64)(struct tm *);
#endif

#ifdef HAVE_GMTIME_R
342
343
344
345
346
347
348

349
350
351
352
353
354
355
		return;

	placeholder.isa = [OFDatePlaceholder class];

#if (!defined(HAVE_GMTIME_R) || !defined(HAVE_LOCALTIME_R)) && \
    defined(OF_HAVE_THREADS)
	mutex = [[OFMutex alloc] init];

#endif

#ifdef OF_WINDOWS
	if ((module = LoadLibrary("msvcrt.dll")) != NULL)
		func__mktime64 = (__time64_t (*)(struct tm *))
		    GetProcAddress(module, "_mktime64");
#endif







>







348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
		return;

	placeholder.isa = [OFDatePlaceholder class];

#if (!defined(HAVE_GMTIME_R) || !defined(HAVE_LOCALTIME_R)) && \
    defined(OF_HAVE_THREADS)
	mutex = [[OFMutex alloc] init];
	atexit(releaseMutex);
#endif

#ifdef OF_WINDOWS
	if ((module = LoadLibrary("msvcrt.dll")) != NULL)
		func__mktime64 = (__time64_t (*)(struct tm *))
		    GetProcAddress(module, "_mktime64");
#endif

Modified src/OFFileURLHandler.m from [529682cb40] to [7c47454fd6].

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# include <proto/dos.h>
# include <proto/locale.h>
# ifdef OF_AMIGAOS4
#  define DeleteFile(path) Delete(path)
# endif
#endif

#if defined(OF_WINDOWS) || (defined(OF_AMIGAOS) && !defined(OF_MORPHOS))
typedef struct {
	of_offset_t st_size;
	unsigned int st_mode;
	of_time_interval_t st_atime, st_mtime, st_ctime;
# ifdef OF_WINDOWS
#  define HAVE_STRUCT_STAT_ST_BIRTHTIME
	of_time_interval_t st_birthtime;







|







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# include <proto/dos.h>
# include <proto/locale.h>
# ifdef OF_AMIGAOS4
#  define DeleteFile(path) Delete(path)
# endif
#endif

#if defined(OF_WINDOWS) || defined(OF_AMIGAOS)
typedef struct {
	of_offset_t st_size;
	unsigned int st_mode;
	of_time_interval_t st_atime, st_mtime, st_ctime;
# ifdef OF_WINDOWS
#  define HAVE_STRUCT_STAT_ST_BIRTHTIME
	of_time_interval_t st_birthtime;
105
106
107
108
109
110
111






112
113
114






115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282

283
284
285
286
287

288
289
290
291
292
293
294
295


296
297
298
299
300




301
302
303
304
305
306
307
#ifdef OF_WINDOWS
# define S_IFLNK 0x10000
# define S_ISLNK(mode) (mode & S_IFLNK)
#endif

#if defined(OF_FILE_MANAGER_SUPPORTS_OWNER) && defined(OF_HAVE_THREADS)
static OFMutex *passwdMutex;






#endif
#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

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

static void
setErrno(void)
{
	switch (GetLastError()) {
	case ERROR_FILE_NOT_FOUND:
	case ERROR_PATH_NOT_FOUND:
	case ERROR_NO_MORE_FILES:
		errno = ENOENT;
		return;
	case ERROR_ACCESS_DENIED:
		errno = EACCES;
		return;
	case ERROR_DIRECTORY:
		errno = ENOTDIR;
		return;
	case ERROR_NOT_READY:
		errno = EBUSY;

		return;
	}

	errno = 0;
}
#endif

#ifdef OF_AMIGAOS
static void
setErrno(void)
{
	switch (IoErr()) {
	case ERROR_DELETE_PROTECTED:
	case ERROR_READ_PROTECTED:
	case ERROR_WRITE_PROTECTED:
		errno = EACCES;
		break;
	case ERROR_DISK_NOT_VALIDATED:
	case ERROR_OBJECT_IN_USE:
		errno = EBUSY;
		break;
	case ERROR_OBJECT_EXISTS:
		errno = EEXIST;
		break;
	case ERROR_DIR_NOT_FOUND:
	case ERROR_NO_MORE_ENTRIES:
	case ERROR_OBJECT_NOT_FOUND:
		errno = ENOENT;
		break;
	case ERROR_NO_FREE_STORE:
		errno = ENOMEM;
		break;
	case ERROR_DISK_FULL:
		errno = ENOSPC;
		break;
	case ERROR_DIRECTORY_NOT_EMPTY:
		errno = ENOTEMPTY;
		break;
	case ERROR_DISK_WRITE_PROTECTED:
		errno = EROFS;
		break;
	case ERROR_RENAME_ACROSS_DEVICES:
		errno = EXDEV;
		break;
	default:
		errno = 0;
		break;
	}
}
#endif

static int
of_stat(OFString *path, of_stat_t *buffer)
{
#if defined(OF_WINDOWS)
	WIN32_FILE_ATTRIBUTE_DATA data;
	bool success;

	if ([OFSystemInfo isWindowsNT])
		success = GetFileAttributesExW(path.UTF16String,
		    GetFileExInfoStandard, &data);
	else
		success = GetFileAttributesExA(
		    [path cStringWithEncoding: [OFLocale encoding]],
		    GetFileExInfoStandard, &data);

	if (!success) {
		setErrno();
		return -1;
	}

	buffer->st_size = (uint64_t)data.nFileSizeHigh << 32 |
	    data.nFileSizeLow;

	if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		buffer->st_mode = S_IFDIR;
	else if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
		/*
		 * No need to use A functions in this branch: This is only
		 * available on NTFS (and hence Windows NT) anyway.
		 */
		WIN32_FIND_DATAW findData;
		HANDLE findHandle;

		if ((findHandle = FindFirstFileW(path.UTF16String,
		    &findData)) == INVALID_HANDLE_VALUE) {
			setErrno();
			return -1;
		}

		@try {
			if (!(findData.dwFileAttributes &
			    FILE_ATTRIBUTE_REPARSE_POINT)) {
				/* Race? Indicate to try again. */
				errno = EAGAIN;
				return -1;
			}

			buffer->st_mode =
			    (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK
			    ? S_IFLNK : S_IFREG);
		} @finally {
			FindClose(findHandle);
		}
	} else
		buffer->st_mode = S_IFREG;

	buffer->st_mode |= (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY
	    ? (S_IRUSR | S_IXUSR) : (S_IRUSR | S_IWUSR | S_IXUSR));

	buffer->st_atime = filetimeToTimeInterval(&data.ftLastAccessTime);
	buffer->st_mtime = filetimeToTimeInterval(&data.ftLastWriteTime);
	buffer->st_ctime = buffer->st_birthtime =
	    filetimeToTimeInterval(&data.ftCreationTime);
	buffer->fileAttributes = data.dwFileAttributes;

	return 0;
#elif defined(OF_AMIGAOS) && !defined(OF_MORPHOS)
	BPTR lock;
# ifdef OF_AMIGAOS4
	struct ExamineData *ed;
# else
	struct FileInfoBlock fib;
# endif
	of_time_interval_t timeInterval;
	struct Locale *locale;
	struct DateStamp *date;

	if ((lock = Lock([path cStringWithEncoding: [OFLocale encoding]],
	    SHARED_LOCK)) == 0) {
		setErrno();
		return -1;
	}


# ifdef OF_AMIGAOS4
	if ((ed = ExamineObjectTags(EX_FileLockInput, lock, TAG_END)) == NULL) {
# else
	if (!Examine(lock, &fib)) {
# endif

		UnLock(lock);

		errno = 0;
		return -1;
	}

	UnLock(lock);



# ifdef OF_AMIGAOS4
	buffer->st_size = ed->FileSize;
	buffer->st_mode = (EXD_IS_DIRECTORY(ed) ? S_IFDIR : S_IFREG);
# else
	buffer->st_size = fib.fib_Size;




	buffer->st_mode = (fib.fib_DirEntryType > 0 ? S_IFDIR : S_IFREG);
# endif

	timeInterval = 252460800;	/* 1978-01-01 */

	locale = OpenLocale(NULL);
	/*







>
>
>
>
>
>



>
>
>
>
>
>

















|
|





<
|

<
|

<
|

|
>
|

<
<




|
|





|
<


|
<

|
<



|
<

|
<

|
<

|
<

|
<

|
<

<
|



















|
<
|
<















|
<
|
<



|

<
|
<




















|











|
<
|
|
|
>
|




>

<
<
|




>
>
|

<


>
>
>
>







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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

188
189

190
191

192

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

214

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230

231

232
233
234
235
236

237

238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278
279
280
281


282
283
284
285
286
287
288
289
290

291
292
293
294
295
296
297
298
299
300
301
302
303
#ifdef OF_WINDOWS
# define S_IFLNK 0x10000
# define S_ISLNK(mode) (mode & S_IFLNK)
#endif

#if defined(OF_FILE_MANAGER_SUPPORTS_OWNER) && defined(OF_HAVE_THREADS)
static OFMutex *passwdMutex;

static void
releasePasswdMutex(void)
{
	[passwdMutex release];
}
#endif
#if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS) && !defined(OF_WINDOWS)
static OFMutex *readdirMutex;

static void
releaseReaddirMutex(void)
{
	[readdirMutex release];
}
#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

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

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

		return ENOENT;
	case ERROR_ACCESS_DENIED:

		return EACCES;
	case ERROR_DIRECTORY:

		return ENOTDIR;
	case ERROR_NOT_READY:
		return EBUSY;
	default:
		return EIO;
	}


}
#endif

#ifdef OF_AMIGAOS
static int
retrieveError(void)
{
	switch (IoErr()) {
	case ERROR_DELETE_PROTECTED:
	case ERROR_READ_PROTECTED:
	case ERROR_WRITE_PROTECTED:
		return EACCES;

	case ERROR_DISK_NOT_VALIDATED:
	case ERROR_OBJECT_IN_USE:
		return EBUSY;

	case ERROR_OBJECT_EXISTS:
		return EEXIST;

	case ERROR_DIR_NOT_FOUND:
	case ERROR_NO_MORE_ENTRIES:
	case ERROR_OBJECT_NOT_FOUND:
		return ENOENT;

	case ERROR_NO_FREE_STORE:
		return ENOMEM;

	case ERROR_DISK_FULL:
		return ENOSPC;

	case ERROR_DIRECTORY_NOT_EMPTY:
		return ENOTEMPTY;

	case ERROR_DISK_WRITE_PROTECTED:
		return EROFS;

	case ERROR_RENAME_ACROSS_DEVICES:
		return EXDEV;

	default:

		return EIO;
	}
}
#endif

static int
of_stat(OFString *path, of_stat_t *buffer)
{
#if defined(OF_WINDOWS)
	WIN32_FILE_ATTRIBUTE_DATA data;
	bool success;

	if ([OFSystemInfo isWindowsNT])
		success = GetFileAttributesExW(path.UTF16String,
		    GetFileExInfoStandard, &data);
	else
		success = GetFileAttributesExA(
		    [path cStringWithEncoding: [OFLocale encoding]],
		    GetFileExInfoStandard, &data);

	if (!success)

		return retrieveError();


	buffer->st_size = (uint64_t)data.nFileSizeHigh << 32 |
	    data.nFileSizeLow;

	if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		buffer->st_mode = S_IFDIR;
	else if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
		/*
		 * No need to use A functions in this branch: This is only
		 * available on NTFS (and hence Windows NT) anyway.
		 */
		WIN32_FIND_DATAW findData;
		HANDLE findHandle;

		if ((findHandle = FindFirstFileW(path.UTF16String,
		    &findData)) == INVALID_HANDLE_VALUE)

			return retrieveError();


		@try {
			if (!(findData.dwFileAttributes &
			    FILE_ATTRIBUTE_REPARSE_POINT))
				/* Race? Indicate to try again. */

				return EAGAIN;


			buffer->st_mode =
			    (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK
			    ? S_IFLNK : S_IFREG);
		} @finally {
			FindClose(findHandle);
		}
	} else
		buffer->st_mode = S_IFREG;

	buffer->st_mode |= (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY
	    ? (S_IRUSR | S_IXUSR) : (S_IRUSR | S_IWUSR | S_IXUSR));

	buffer->st_atime = filetimeToTimeInterval(&data.ftLastAccessTime);
	buffer->st_mtime = filetimeToTimeInterval(&data.ftLastWriteTime);
	buffer->st_ctime = buffer->st_birthtime =
	    filetimeToTimeInterval(&data.ftCreationTime);
	buffer->fileAttributes = data.dwFileAttributes;

	return 0;
#elif defined(OF_AMIGAOS)
	BPTR lock;
# ifdef OF_AMIGAOS4
	struct ExamineData *ed;
# else
	struct FileInfoBlock fib;
# endif
	of_time_interval_t timeInterval;
	struct Locale *locale;
	struct DateStamp *date;

	if ((lock = Lock([path cStringWithEncoding: [OFLocale encoding]],
	    SHARED_LOCK)) == 0)

		return retrieveError();

# if defined(OF_MORPHOS)
	if (!Examine64(lock, &fib, TAG_DONE)) {
# elif defined(OF_AMIGAOS4)
	if ((ed = ExamineObjectTags(EX_FileLockInput, lock, TAG_END)) == NULL) {
# else
	if (!Examine(lock, &fib)) {
# endif
		int error = retrieveError();
		UnLock(lock);


		return error;
	}

	UnLock(lock);

# if defined(OF_MORPHOS)
	buffer->st_size = fib.fib_Size64;
# elif defined(OF_AMIGAOS4)
	buffer->st_size = ed->FileSize;

# else
	buffer->st_size = fib.fib_Size;
# endif
# ifdef OF_AMIGAOS4
	buffer->st_mode = (EXD_IS_DIRECTORY(ed) ? S_IFDIR : S_IFREG);
# else
	buffer->st_mode = (fib.fib_DirEntryType > 0 ? S_IFDIR : S_IFREG);
# endif

	timeInterval = 252460800;	/* 1978-01-01 */

	locale = OpenLocale(NULL);
	/*
325
326
327
328
329
330
331
332




333
334



335
336
337
338
339
340
341
342
343
344


345
346

347


348
349
350
351
352
353
354

# ifdef OF_AMIGAOS4
	FreeDosObject(DOS_EXAMINEDATA, ed);
# endif

	return 0;
#elif defined(HAVE_STAT64)
	return stat64([path cStringWithEncoding: [OFLocale encoding]], buffer);




#else
	return stat([path cStringWithEncoding: [OFLocale encoding]], buffer);



#endif
}

static int
of_lstat(OFString *path, of_stat_t *buffer)
{
#if defined(HAVE_LSTAT) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS) && \
    !defined(OF_NINTENDO_3DS) && !defined(OF_WII)
# ifdef HAVE_LSTAT64
	return lstat64([path cStringWithEncoding: [OFLocale encoding]], buffer);


# else
	return lstat([path cStringWithEncoding: [OFLocale encoding]], buffer);

# endif


#else
	return of_stat(path, buffer);
#endif
}

static void
setTypeAttribute(of_mutable_file_attributes_t attributes, of_stat_t *s)







|
>
>
>
>

|
>
>
>









|
>
>

|
>

>
>







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362

# ifdef OF_AMIGAOS4
	FreeDosObject(DOS_EXAMINEDATA, ed);
# endif

	return 0;
#elif defined(HAVE_STAT64)
	if (stat64([path cStringWithEncoding: [OFLocale encoding]],
	    buffer) != 0)
		return errno;

	return 0;
#else
	if (stat([path cStringWithEncoding: [OFLocale encoding]], buffer) != 0)
		return errno;

	return 0;
#endif
}

static int
of_lstat(OFString *path, of_stat_t *buffer)
{
#if defined(HAVE_LSTAT) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS) && \
    !defined(OF_NINTENDO_3DS) && !defined(OF_WII)
# ifdef HAVE_LSTAT64
	if (lstat64([path cStringWithEncoding: [OFLocale encoding]],
	    buffer) != 0)
		return errno;
# else
	if (lstat([path cStringWithEncoding: [OFLocale encoding]], buffer) != 0)
		return errno;
# endif

	return 0;
#else
	return of_stat(path, buffer);
#endif
}

static void
setTypeAttribute(of_mutable_file_attributes_t attributes, of_stat_t *s)
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
		return;

	if ((handle = CreateFileW(path.UTF16String, 0, (FILE_SHARE_READ |
	    FILE_SHARE_WRITE), NULL, OPEN_EXISTING,
	    FILE_FLAG_OPEN_REPARSE_POINT, NULL)) == INVALID_HANDLE_VALUE)
		@throw [OFRetrieveItemAttributesFailedException
		    exceptionWithURL: URL
			       errNo: 0];

	@try {
		union {
			char bytes[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
			REPARSE_DATA_BUFFER data;
		} buffer;
		DWORD size;
		wchar_t *tmp;
		of_file_attribute_key_t key;

		if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0,
		    buffer.bytes, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &size,
		    NULL))
			@throw [OFRetrieveItemAttributesFailedException
			    exceptionWithURL: URL
				       errNo: 0];

		if (buffer.data.ReparseTag != IO_REPARSE_TAG_SYMLINK)
			@throw [OFRetrieveItemAttributesFailedException
			    exceptionWithURL: URL
				       errNo: 0];

#  define slrb buffer.data.SymbolicLinkReparseBuffer
		tmp = slrb.PathBuffer +
		    (slrb.SubstituteNameOffset / sizeof(wchar_t));

		destination = [OFString
		    stringWithUTF16String: tmp







|















|




|







493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
		return;

	if ((handle = CreateFileW(path.UTF16String, 0, (FILE_SHARE_READ |
	    FILE_SHARE_WRITE), NULL, OPEN_EXISTING,
	    FILE_FLAG_OPEN_REPARSE_POINT, NULL)) == INVALID_HANDLE_VALUE)
		@throw [OFRetrieveItemAttributesFailedException
		    exceptionWithURL: URL
			       errNo: retrieveError()];

	@try {
		union {
			char bytes[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
			REPARSE_DATA_BUFFER data;
		} buffer;
		DWORD size;
		wchar_t *tmp;
		of_file_attribute_key_t key;

		if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0,
		    buffer.bytes, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &size,
		    NULL))
			@throw [OFRetrieveItemAttributesFailedException
			    exceptionWithURL: URL
				       errNo: retrieveError()];

		if (buffer.data.ReparseTag != IO_REPARSE_TAG_SYMLINK)
			@throw [OFRetrieveItemAttributesFailedException
			    exceptionWithURL: URL
				       errNo: retrieveError()];

#  define slrb buffer.data.SymbolicLinkReparseBuffer
		tmp = slrb.PathBuffer +
		    (slrb.SubstituteNameOffset / sizeof(wchar_t));

		destination = [OFString
		    stringWithUTF16String: tmp
542
543
544
545
546
547
548

549
550
551

552
553
554
555
556
557
558
#endif

	if (self != [OFFileURLHandler class])
		return;

#if defined(OF_FILE_MANAGER_SUPPORTS_OWNER) && defined(OF_HAVE_THREADS)
	passwdMutex = [[OFMutex alloc] init];

#endif
#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");








>



>







550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
#endif

	if (self != [OFFileURLHandler class])
		return;

#if defined(OF_FILE_MANAGER_SUPPORTS_OWNER) && defined(OF_HAVE_THREADS)
	passwdMutex = [[OFMutex alloc] init];
	atexit(releasePasswdMutex);
#endif
#if !defined(HAVE_READDIR_R) && !defined(OF_WINDOWS) && defined(OF_HAVE_THREADS)
	readdirMutex = [[OFMutex alloc] init];
	atexit(releaseReaddirMutex);
#endif

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

574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
	[OFFile class];
}

+ (bool)of_directoryExistsAtPath: (OFString *)path
{
	of_stat_t s;

	if (of_stat(path, &s) == -1)
		return false;

	return S_ISDIR(s.st_mode);
}

- (OFStream *)openItemAtURL: (OFURL *)URL
		       mode: (OFString *)mode







|







584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
	[OFFile class];
}

+ (bool)of_directoryExistsAtPath: (OFString *)path
{
	of_stat_t s;

	if (of_stat(path, &s) != 0)
		return false;

	return S_ISDIR(s.st_mode);
}

- (OFStream *)openItemAtURL: (OFURL *)URL
		       mode: (OFString *)mode
598
599
600
601
602
603
604

605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
}

- (of_file_attributes_t)attributesOfItemAtURL: (OFURL *)URL
{
	of_mutable_file_attributes_t ret = [OFMutableDictionary dictionary];
	void *pool = objc_autoreleasePoolPush();
	OFString *path;

	of_stat_t s;

	if (URL == nil)
		@throw [OFInvalidArgumentException exception];

	if (![[URL scheme] isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URL.fileSystemRepresentation;

	if (of_lstat(path, &s) == -1)
		@throw [OFRetrieveItemAttributesFailedException
		    exceptionWithURL: URL
			       errNo: errno];

	if (s.st_size < 0)
		@throw [OFOutOfRangeException exception];

	[ret setObject: [NSNumber numberWithUnsignedLongLong: s.st_size]
		forKey: of_file_attribute_key_size];








>










|


|







608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
}

- (of_file_attributes_t)attributesOfItemAtURL: (OFURL *)URL
{
	of_mutable_file_attributes_t ret = [OFMutableDictionary dictionary];
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	int error;
	of_stat_t s;

	if (URL == nil)
		@throw [OFInvalidArgumentException exception];

	if (![[URL scheme] isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URL.fileSystemRepresentation;

	if ((error = of_lstat(path, &s)) != 0)
		@throw [OFRetrieveItemAttributesFailedException
		    exceptionWithURL: URL
			       errNo: error];

	if (s.st_size < 0)
		@throw [OFOutOfRangeException exception];

	[ret setObject: [NSNumber numberWithUnsignedLongLong: s.st_size]
		forKey: of_file_attribute_key_size];

716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742

	date.ds_Days = modificationTime / 86400;
	date.ds_Minute = ((LONG)modificationTime % 86400) / 60;
	date.ds_Tick = fmod(modificationTime, 60) * TICKS_PER_SECOND;

# ifdef OF_AMIGAOS4
	if (!SetDate([path cStringWithEncoding: [OFLocale encoding]],
	    &date) != 0) {
# else
	if (!SetFileDate([path cStringWithEncoding: [OFLocale encoding]],
	    &date) != 0) {
# endif
		setErrno();

		@throw [OFSetItemAttributesFailedException
		    exceptionWithURL: URL
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: errno];
	}
#else
	of_time_interval_t lastAccessTime =
	    lastAccessDate.timeIntervalSince1970;
	of_time_interval_t modificationTime =
	    modificationDate.timeIntervalSince1970;
	struct timeval times[2] = {
		{







|


|

<
<




|
<







727
728
729
730
731
732
733
734
735
736
737
738


739
740
741
742
743

744
745
746
747
748
749
750

	date.ds_Days = modificationTime / 86400;
	date.ds_Minute = ((LONG)modificationTime % 86400) / 60;
	date.ds_Tick = fmod(modificationTime, 60) * TICKS_PER_SECOND;

# ifdef OF_AMIGAOS4
	if (!SetDate([path cStringWithEncoding: [OFLocale encoding]],
	    &date) != 0)
# else
	if (!SetFileDate([path cStringWithEncoding: [OFLocale encoding]],
	    &date) != 0)
# endif


		@throw [OFSetItemAttributesFailedException
		    exceptionWithURL: URL
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: retrieveError()];

#else
	of_time_interval_t lastAccessTime =
	    lastAccessDate.timeIntervalSince1970;
	of_time_interval_t modificationTime =
	    modificationDate.timeIntervalSince1970;
	struct timeval times[2] = {
		{
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935

	if (URL == nil)
		@throw [OFInvalidArgumentException exception];

	if (![URL.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	if (of_stat(URL.fileSystemRepresentation, &s) == -1) {
		objc_autoreleasePoolPop(pool);
		return false;
	}

	ret = S_ISREG(s.st_mode);

	objc_autoreleasePoolPop(pool);







|







929
930
931
932
933
934
935
936
937
938
939
940
941
942
943

	if (URL == nil)
		@throw [OFInvalidArgumentException exception];

	if (![URL.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	if (of_stat(URL.fileSystemRepresentation, &s) != 0) {
		objc_autoreleasePoolPop(pool);
		return false;
	}

	ret = S_ISREG(s.st_mode);

	objc_autoreleasePoolPop(pool);
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959

	if (URL == nil)
		@throw [OFInvalidArgumentException exception];

	if (![URL.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	if (of_stat(URL.fileSystemRepresentation, &s) == -1) {
		objc_autoreleasePoolPop(pool);
		return false;
	}

	ret = S_ISDIR(s.st_mode);

	objc_autoreleasePoolPop(pool);







|







953
954
955
956
957
958
959
960
961
962
963
964
965
966
967

	if (URL == nil)
		@throw [OFInvalidArgumentException exception];

	if (![URL.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	if (of_stat(URL.fileSystemRepresentation, &s) != 0) {
		objc_autoreleasePoolPop(pool);
		return false;
	}

	ret = S_ISDIR(s.st_mode);

	objc_autoreleasePoolPop(pool);
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
		@throw [OFCreateDirectoryFailedException
		    exceptionWithURL: URL
			       errNo: errno];
#elif defined(OF_AMIGAOS)
	BPTR lock;

	if ((lock = CreateDir(
	    [path cStringWithEncoding: [OFLocale encoding]])) == 0) {
		setErrno();

		@throw [OFCreateDirectoryFailedException
		    exceptionWithURL: URL
			       errNo: errno];
	}

	UnLock(lock);
#else
	if (mkdir([path cStringWithEncoding: [OFLocale encoding]], 0777) != 0)
		@throw [OFCreateDirectoryFailedException
		    exceptionWithURL: URL
			       errNo: errno];







|
<
<


|
<







995
996
997
998
999
1000
1001
1002


1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
		@throw [OFCreateDirectoryFailedException
		    exceptionWithURL: URL
			       errNo: errno];
#elif defined(OF_AMIGAOS)
	BPTR lock;

	if ((lock = CreateDir(
	    [path cStringWithEncoding: [OFLocale encoding]])) == 0)


		@throw [OFCreateDirectoryFailedException
		    exceptionWithURL: URL
			       errNo: retrieveError()];


	UnLock(lock);
#else
	if (mkdir([path cStringWithEncoding: [OFLocale encoding]], 0777) != 0)
		@throw [OFCreateDirectoryFailedException
		    exceptionWithURL: URL
			       errNo: errno];
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053

	path = [path stringByAppendingString: @"\\*"];

	if ([OFSystemInfo isWindowsNT]) {
		WIN32_FIND_DATAW fd;

		if ((handle = FindFirstFileW(path.UTF16String,
		    &fd)) == INVALID_HANDLE_VALUE) {
			int errNo = 0;

			if (GetLastError() == ERROR_FILE_NOT_FOUND)
				errNo = ENOENT;

			@throw [OFOpenItemFailedException
			    exceptionWithURL: URL
					mode: nil
				       errNo: errNo];
		}

		@try {
			do {
				OFString *file;

				if (wcscmp(fd.cFileName, L".") == 0 ||
				    wcscmp(fd.cFileName, L"..") == 0)







|
<
<
<
<
<



|
<







1034
1035
1036
1037
1038
1039
1040
1041





1042
1043
1044
1045

1046
1047
1048
1049
1050
1051
1052

	path = [path stringByAppendingString: @"\\*"];

	if ([OFSystemInfo isWindowsNT]) {
		WIN32_FIND_DATAW fd;

		if ((handle = FindFirstFileW(path.UTF16String,
		    &fd)) == INVALID_HANDLE_VALUE)





			@throw [OFOpenItemFailedException
			    exceptionWithURL: URL
					mode: nil
				       errNo: retrieveError()];


		@try {
			do {
				OFString *file;

				if (wcscmp(fd.cFileName, L".") == 0 ||
				    wcscmp(fd.cFileName, L"..") == 0)
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
				}
			} while (FindNextFileW(handle, &fd));

			if (GetLastError() != ERROR_NO_MORE_FILES)
				@throw [OFReadFailedException
				    exceptionWithObject: self
					requestedLength: 0
						  errNo: EIO];
		} @finally {
			FindClose(handle);
		}
	} else {
		of_string_encoding_t encoding = [OFLocale encoding];
		WIN32_FIND_DATA fd;

		if ((handle = FindFirstFileA(
		    [path cStringWithEncoding: encoding], &fd)) ==
		    INVALID_HANDLE_VALUE) {
			int errNo = 0;

			if (GetLastError() == ERROR_FILE_NOT_FOUND)
				errNo = ENOENT;

			@throw [OFOpenItemFailedException
			    exceptionWithURL: URL
					mode: nil
				       errNo: errNo];
		}

		@try {
			do {
				OFString *file;

				if (strcmp(fd.cFileName, ".") == 0 ||
				    strcmp(fd.cFileName, "..") == 0)







|









|
<
<
<
<
<



|
<







1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078





1079
1080
1081
1082

1083
1084
1085
1086
1087
1088
1089
				}
			} while (FindNextFileW(handle, &fd));

			if (GetLastError() != ERROR_NO_MORE_FILES)
				@throw [OFReadFailedException
				    exceptionWithObject: self
					requestedLength: 0
						  errNo: retrieveError()];
		} @finally {
			FindClose(handle);
		}
	} else {
		of_string_encoding_t encoding = [OFLocale encoding];
		WIN32_FIND_DATA fd;

		if ((handle = FindFirstFileA(
		    [path cStringWithEncoding: encoding], &fd)) ==
		    INVALID_HANDLE_VALUE)





			@throw [OFOpenItemFailedException
			    exceptionWithURL: URL
					mode: nil
				       errNo: retrieveError()];


		@try {
			do {
				OFString *file;

				if (strcmp(fd.cFileName, ".") == 0 ||
				    strcmp(fd.cFileName, "..") == 0)
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126

1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
				}
			} while (FindNextFileA(handle, &fd));

			if (GetLastError() != ERROR_NO_MORE_FILES)
				@throw [OFReadFailedException
				    exceptionWithObject: self
					requestedLength: 0
						  errNo: EIO];
		} @finally {
			FindClose(handle);
		}
	}
#elif defined(OF_AMIGAOS)
	of_string_encoding_t encoding = [OFLocale encoding];
	BPTR lock;

	if ((lock = Lock([path cStringWithEncoding: encoding],
	    SHARED_LOCK)) == 0) {
		setErrno();

		@throw [OFOpenItemFailedException exceptionWithURL: URL

							      mode: nil
							     errNo: errno];
	}

	@try {
# ifdef OF_AMIGAOS4
		struct ExamineData *ed;
		APTR context;

		if ((context = ObtainDirContextTags(EX_FileLockInput, lock,
		    EX_DoCurrentDir, TRUE, EX_DataFields, EXF_NAME,
		    TAG_END)) == NULL)
			@throw [OFOpenItemFailedException
			    exceptionWithURL: URL
					mode: nil
				       errNo: 0];

		@try {
			while ((ed = ExamineDir(context)) != NULL) {
				OFString *file = [[OFString alloc]
				    initWithCString: ed->Name
					   encoding: encoding];








|









|
<
<
|
>
|
|
<












|







1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116


1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
				}
			} while (FindNextFileA(handle, &fd));

			if (GetLastError() != ERROR_NO_MORE_FILES)
				@throw [OFReadFailedException
				    exceptionWithObject: self
					requestedLength: 0
						  errNo: retrieveError()];
		} @finally {
			FindClose(handle);
		}
	}
#elif defined(OF_AMIGAOS)
	of_string_encoding_t encoding = [OFLocale encoding];
	BPTR lock;

	if ((lock = Lock([path cStringWithEncoding: encoding],
	    SHARED_LOCK)) == 0)


		@throw [OFOpenItemFailedException
		    exceptionWithURL: URL
				mode: nil
			       errNo: retrieveError()];


	@try {
# ifdef OF_AMIGAOS4
		struct ExamineData *ed;
		APTR context;

		if ((context = ObtainDirContextTags(EX_FileLockInput, lock,
		    EX_DoCurrentDir, TRUE, EX_DataFields, EXF_NAME,
		    TAG_END)) == NULL)
			@throw [OFOpenItemFailedException
			    exceptionWithURL: URL
					mode: nil
				       errNo: retrieveError()];

		@try {
			while ((ed = ExamineDir(context)) != NULL) {
				OFString *file = [[OFString alloc]
				    initWithCString: ed->Name
					   encoding: encoding];

1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
# else
		struct FileInfoBlock fib;

		if (!Examine(lock, &fib))
			@throw [OFOpenItemFailedException
			    exceptionWithURL: URL
					mode: nil
				       errNo: 0];

		while (ExNext(lock, &fib)) {
			OFString *file = [[OFString alloc]
			    initWithCString: fib.fib_FileName
				   encoding: encoding];

			@try {
				[files addObject: file];
			} @finally {
				[file release];
			}
		}
# endif

		if (IoErr() != ERROR_NO_MORE_ENTRIES)
			@throw [OFReadFailedException
			    exceptionWithObject: self
				requestedLength: 0
					  errNo: EIO];
	} @finally {
		UnLock(lock);
	}
#else
	of_string_encoding_t encoding = [OFLocale encoding];
	DIR *dir;








|


















|







1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
# else
		struct FileInfoBlock fib;

		if (!Examine(lock, &fib))
			@throw [OFOpenItemFailedException
			    exceptionWithURL: URL
					mode: nil
				       errNo: retrieveError()];

		while (ExNext(lock, &fib)) {
			OFString *file = [[OFString alloc]
			    initWithCString: fib.fib_FileName
				   encoding: encoding];

			@try {
				[files addObject: file];
			} @finally {
				[file release];
			}
		}
# endif

		if (IoErr() != ERROR_NO_MORE_ENTRIES)
			@throw [OFReadFailedException
			    exceptionWithObject: self
				requestedLength: 0
					  errNo: retrieveError()];
	} @finally {
		UnLock(lock);
	}
#else
	of_string_encoding_t encoding = [OFLocale encoding];
	DIR *dir;

1261
1262
1263
1264
1265
1266
1267

1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
	return files;
}

- (void)removeItemAtURL: (OFURL *)URL
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;

	of_stat_t s;

	if (URL == nil)
		@throw [OFInvalidArgumentException exception];

	if (![URL.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URL.fileSystemRepresentation;

	if (of_lstat(path, &s) != 0)
		@throw [OFRemoveItemFailedException exceptionWithURL: URL
							       errNo: errno];

	if (S_ISDIR(s.st_mode)) {
		OFArray *contents;

		@try {
			contents = [self contentsOfDirectoryAtURL: URL];
		} @catch (id e) {







>










|

|







1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
	return files;
}

- (void)removeItemAtURL: (OFURL *)URL
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	int error;
	of_stat_t s;

	if (URL == nil)
		@throw [OFInvalidArgumentException exception];

	if (![URL.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	path = URL.fileSystemRepresentation;

	if ((error = of_lstat(path, &s)) != 0)
		@throw [OFRemoveItemFailedException exceptionWithURL: URL
							       errNo: error];

	if (S_ISDIR(s.st_mode)) {
		OFArray *contents;

		@try {
			contents = [self contentsOfDirectoryAtURL: URL];
		} @catch (id e) {
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349

1350
1351
1352
1353
1354
1355
1356
1357
1358
			@throw [OFRemoveItemFailedException
			    exceptionWithURL: URL
				       errNo: errno];
#endif
	}

#ifdef OF_AMIGAOS
	if (!DeleteFile([path cStringWithEncoding: [OFLocale encoding]])) {
		setErrno();

		@throw [OFRemoveItemFailedException exceptionWithURL: URL

							       errNo: errno];
	}
#endif

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS
- (void)linkItemAtURL: (OFURL *)source







|
<
<
|
>
|
<







1331
1332
1333
1334
1335
1336
1337
1338


1339
1340
1341

1342
1343
1344
1345
1346
1347
1348
			@throw [OFRemoveItemFailedException
			    exceptionWithURL: URL
				       errNo: errno];
#endif
	}

#ifdef OF_AMIGAOS
	if (!DeleteFile([path cStringWithEncoding: [OFLocale encoding]]))


		@throw [OFRemoveItemFailedException
		    exceptionWithURL: URL
			       errNo: retrieveError()];

#endif

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS
- (void)linkItemAtURL: (OFURL *)source
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
								 object: self];

	if (!func_CreateHardLinkW(destinationPath.UTF16String,
	    sourcePath.UTF16String, NULL))
		@throw [OFLinkFailedException
		    exceptionWithSourceURL: source
			    destinationURL: destination
				     errNo: 0];
# endif

	objc_autoreleasePoolPop(pool);
}
#endif

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS







|







1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
								 object: self];

	if (!func_CreateHardLinkW(destinationPath.UTF16String,
	    sourcePath.UTF16String, NULL))
		@throw [OFLinkFailedException
		    exceptionWithSourceURL: source
			    destinationURL: destination
				     errNo: retrieveError()];
# endif

	objc_autoreleasePoolPop(pool);
}
#endif

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	if (!func_CreateSymbolicLinkW(path.UTF16String, target.UTF16String, 0))
		@throw [OFCreateSymbolicLinkFailedException
		    exceptionWithURL: URL
			      target: target
			       errNo: 0];
# endif

	objc_autoreleasePoolPop(pool);
}
#endif

- (bool)moveItemAtURL: (OFURL *)source







|







1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

	if (!func_CreateSymbolicLinkW(path.UTF16String, target.UTF16String, 0))
		@throw [OFCreateSymbolicLinkFailedException
		    exceptionWithURL: URL
			      target: target
			       errNo: retrieveError()];
# endif

	objc_autoreleasePoolPop(pool);
}
#endif

- (bool)moveItemAtURL: (OFURL *)source
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477

#ifdef OF_AMIGAOS
	of_string_encoding_t encoding = [OFLocale encoding];

	if (!Rename([source.fileSystemRepresentation
	    cStringWithEncoding: encoding],
	    [destination.fileSystemRepresentation
	    cStringWithEncoding: encoding])) {
		setErrno();

		@throw [OFMoveItemFailedException
		    exceptionWithSourceURL: source
			    destinationURL: destination
				     errNo: errno];
	}
#else
	int status;

# ifdef OF_WINDOWS
	if ([OFSystemInfo isWindowsNT])
		status = _wrename(source.fileSystemRepresentation.UTF16String,
		    destination.fileSystemRepresentation.UTF16String);







|
<
<



|
<







1446
1447
1448
1449
1450
1451
1452
1453


1454
1455
1456
1457

1458
1459
1460
1461
1462
1463
1464

#ifdef OF_AMIGAOS
	of_string_encoding_t encoding = [OFLocale encoding];

	if (!Rename([source.fileSystemRepresentation
	    cStringWithEncoding: encoding],
	    [destination.fileSystemRepresentation
	    cStringWithEncoding: encoding]))


		@throw [OFMoveItemFailedException
		    exceptionWithSourceURL: source
			    destinationURL: destination
				     errNo: retrieveError()];

#else
	int status;

# ifdef OF_WINDOWS
	if ([OFSystemInfo isWindowsNT])
		status = _wrename(source.fileSystemRepresentation.UTF16String,
		    destination.fileSystemRepresentation.UTF16String);

Modified src/OFString.m from [77195aa3b1] to [0e8c3a02df].

2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254







2255
2256
2257
2258
2259
2260
2261
					 options: 0];
}

- (OFArray *)componentsSeparatedByString: (OFString *)delimiter
				 options: (int)options
{
	void *pool;
	OFMutableArray *array = [OFMutableArray array];
	const of_unichar_t *characters, *delimiterCharacters;
	bool skipEmpty = (options & OF_STRING_SKIP_EMPTY);
	size_t length = self.length;
	size_t delimiterLength = delimiter.length;
	size_t last;
	OFString *component;








	pool = objc_autoreleasePoolPush();

	characters = self.characters;
	delimiterCharacters = delimiter.characters;

	if (delimiterLength > length) {
		[array addObject: [[self copy] autorelease]];







|







>
>
>
>
>
>
>







2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
					 options: 0];
}

- (OFArray *)componentsSeparatedByString: (OFString *)delimiter
				 options: (int)options
{
	void *pool;
	OFMutableArray *array;
	const of_unichar_t *characters, *delimiterCharacters;
	bool skipEmpty = (options & OF_STRING_SKIP_EMPTY);
	size_t length = self.length;
	size_t delimiterLength = delimiter.length;
	size_t last;
	OFString *component;

	if (delimiter == nil)
		@throw [OFInvalidArgumentException exception];

	if (delimiter.length == 0)
		return [OFArray arrayWithObject: self];

	array = [OFMutableArray array];
	pool = objc_autoreleasePoolPush();

	characters = self.characters;
	delimiterCharacters = delimiter.characters;

	if (delimiterLength > length) {
		[array addObject: [[self copy] autorelease]];
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351


2352




2353
2354
2355






2356
2357




2358



2359


2360









2361



2362

2363









2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386

2387


2388
2389
2390



2391
2392
2393
2394




2395



2396


2397









2398



2399

2400







2401
2402
2403
2404
2405
2406
2407
	return [self longLongValueWithBase: 10];
}

- (long long)longLongValueWithBase: (int)base
{
	void *pool = objc_autoreleasePoolPush();
	const char *UTF8String = self.UTF8String;
	char *endPointer = NULL;
	long long value;



	errno = 0;




	value = strtoll(UTF8String, &endPointer, base);

	if ((value == LLONG_MIN || value == LLONG_MAX) && errno == ERANGE)






		@throw [OFOutOfRangeException exception];





	/* Check if there are any invalid chars left */



	if (endPointer != NULL)


		for (; *endPointer != '\0'; endPointer++)









			/* Use isspace since strtoll uses the same. */



			if (!isspace((unsigned char)*endPointer))

				@throw [OFInvalidFormatException exception];










	objc_autoreleasePoolPop(pool);

	return value;
}

- (unsigned long long)unsignedLongLongValue
{
	return [self unsignedLongLongValueWithBase: 10];
}

- (unsigned long long)unsignedLongLongValueWithBase: (int)base
{
	void *pool = objc_autoreleasePoolPush();
	const char *UTF8String = self.UTF8String;
	char *endPointer = NULL;
	unsigned long long value;

	/* Use isspace since strtoull uses the same. */
	while (isspace((unsigned char)*UTF8String))
		UTF8String++;

	if (*UTF8String == '-')

		@throw [OFInvalidFormatException exception];



	errno = 0;
	value = strtoull(UTF8String, &endPointer, base);




	if (value == ULLONG_MAX && errno == ERANGE)
		@throw [OFOutOfRangeException exception];





	/* Check if there are any invalid chars left */



	if (endPointer != NULL)


		for (; *endPointer != '\0'; endPointer++)









			/* Use isspace since strtoull uses the same. */



			if (!isspace((unsigned char)*endPointer))

				@throw [OFInvalidFormatException exception];








	objc_autoreleasePoolPop(pool);

	return value;
}

- (float)floatValue







|
|

>
>
|
>
>
>
>
|
|
|
>
>
>
>
>
>
|

>
>
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>















<
|

<
|


|
>

>
>
|
|
|
>
>
>

|
|

>
>
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
|
>
>
>
>
>
>
>







2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428

2429
2430

2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
	return [self longLongValueWithBase: 10];
}

- (long long)longLongValueWithBase: (int)base
{
	void *pool = objc_autoreleasePoolPush();
	const char *UTF8String = self.UTF8String;
	bool negative = false;
	long long value = 0;

	while (of_ascii_isspace(*UTF8String))
		UTF8String++;

	switch (*UTF8String) {
	case '-':
		negative = true;
	case '+':
		UTF8String++;
	}

	if (UTF8String[0] == '0') {
		if (UTF8String[1] == 'x') {
			if (base == 0)
				base = 16;

			if (base != 16 || UTF8String[2] == '\0')
				@throw [OFInvalidFormatException exception];

			UTF8String += 2;
		} else {
			if (base == 0)
				base = 8;

			UTF8String++;
		}
	}

	while (*UTF8String != '\0') {
		unsigned char c = of_ascii_toupper(*UTF8String++);

		if (c >= '0' && c <= '9')
			c -= '0';
		else if (c >= 'A' && c <= 'Z')
			c -= ('A' - 10);
		else if (of_ascii_isspace(c)) {
			while (*UTF8String != '\0')
				if (!of_ascii_isspace(*UTF8String++))
					@throw [OFInvalidFormatException
					    exception];

			break;
		} else
			@throw [OFInvalidFormatException exception];

		if (c >= base)
			@throw [OFInvalidFormatException exception];

		if (LLONG_MAX / base < value || LLONG_MAX - (value * base) < c)
			@throw [OFOutOfRangeException exception];

		value = (value * base) + c;
	}

	if (negative)
		value *= -1;

	objc_autoreleasePoolPop(pool);

	return value;
}

- (unsigned long long)unsignedLongLongValue
{
	return [self unsignedLongLongValueWithBase: 10];
}

- (unsigned long long)unsignedLongLongValueWithBase: (int)base
{
	void *pool = objc_autoreleasePoolPush();
	const char *UTF8String = self.UTF8String;

	unsigned long long value = 0;


	while (of_ascii_isspace(*UTF8String))
		UTF8String++;

	switch (*UTF8String) {
	case '-':
		@throw [OFInvalidFormatException exception];
	case '+':
		UTF8String++;
	}

	if (UTF8String[0] == '0') {
		if (UTF8String[1] == 'x') {
			if (base == 0)
				base = 16;

			if (base != 16 || UTF8String[2] == '\0')
				@throw [OFInvalidFormatException exception];

			UTF8String += 2;
		} else {
			if (base == 0)
				base = 8;

			UTF8String++;
		}
	}

	while (*UTF8String != '\0') {
		unsigned char c = of_ascii_toupper(*UTF8String++);

		if (c >= '0' && c <= '9')
			c -= '0';
		else if (c >= 'A' && c <= 'Z')
			c -= ('A' - 10);
		else if (of_ascii_isspace(c)) {
			while (*UTF8String != '\0')
				if (!of_ascii_isspace(*UTF8String++))
					@throw [OFInvalidFormatException
					    exception];

			break;
		} else
			@throw [OFInvalidFormatException exception];

		if (c >= base)
			@throw [OFInvalidFormatException exception];

		if (ULLONG_MAX / base < value ||
		    ULLONG_MAX - (value * base) < c)
			@throw [OFOutOfRangeException exception];

		value = (value * base) + c;
	}

	objc_autoreleasePoolPop(pool);

	return value;
}

- (float)floatValue

Modified src/OFURLHandler.m from [2d065f473d] to [b3dc531a71].

32
33
34
35
36
37
38






39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)
# import "OFHTTPURLHandler.h"
#endif

static OFMutableDictionary OF_GENERIC(OFString *, OFURLHandler *) *handlers;
#ifdef OF_HAVE_THREADS
static OFMutex *mutex;






#endif

@implementation OFURLHandler
@synthesize scheme = _scheme;

+ (void)initialize
{
	if (self != [OFURLHandler class])
		return;

	handlers = [[OFMutableDictionary alloc] init];
#ifdef OF_HAVE_THREADS
	mutex = [[OFMutex alloc] init];

#endif

#ifdef OF_HAVE_FILES
	[self registerClass: [OFFileURLHandler class]
		  forScheme: @"file"];
#endif
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)







>
>
>
>
>
>













>







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)
# import "OFHTTPURLHandler.h"
#endif

static OFMutableDictionary OF_GENERIC(OFString *, OFURLHandler *) *handlers;
#ifdef OF_HAVE_THREADS
static OFMutex *mutex;

static void
releaseMutex(void)
{
	[mutex release];
}
#endif

@implementation OFURLHandler
@synthesize scheme = _scheme;

+ (void)initialize
{
	if (self != [OFURLHandler class])
		return;

	handlers = [[OFMutableDictionary alloc] init];
#ifdef OF_HAVE_THREADS
	mutex = [[OFMutex alloc] init];
	atexit(releaseMutex);
#endif

#ifdef OF_HAVE_FILES
	[self registerClass: [OFFileURLHandler class]
		  forScheme: @"file"];
#endif
#if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS)

Modified src/OFUTF8String.m from [4b2268ed9f] to [212afc270e].

1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121






1122
1123


1124
1125
1126
1127
1128
1129
1130
}

- (OFArray *)componentsSeparatedByString: (OFString *)delimiter
				 options: (int)options
{
	void *pool;
	OFMutableArray *array;
	const char *cString = delimiter.UTF8String;
	size_t cStringLength = delimiter.UTF8StringLength;
	bool skipEmpty = (options & OF_STRING_SKIP_EMPTY);
	size_t last;
	OFString *component;







	array = [OFMutableArray array];
	pool = objc_autoreleasePoolPush();



	if (cStringLength > _s->cStringLength) {
		[array addObject: [[self copy] autorelease]];
		objc_autoreleasePoolPop(pool);

		return array;
	}







|
|




>
>
>
>
>
>


>
>







1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
}

- (OFArray *)componentsSeparatedByString: (OFString *)delimiter
				 options: (int)options
{
	void *pool;
	OFMutableArray *array;
	const char *cString;
	size_t cStringLength;
	bool skipEmpty = (options & OF_STRING_SKIP_EMPTY);
	size_t last;
	OFString *component;

	if (delimiter == nil)
		@throw [OFInvalidArgumentException exception];

	if (delimiter.length == 0)
		return [OFArray arrayWithObject: self];

	array = [OFMutableArray array];
	pool = objc_autoreleasePoolPush();
	cString = delimiter.UTF8String;
	cStringLength = delimiter.UTF8StringLength;

	if (cStringLength > _s->cStringLength) {
		[array addObject: [[self copy] autorelease]];
		objc_autoreleasePoolPop(pool);

		return array;
	}

Modified src/exceptions/OFException.m from [aa89efc62e] to [9ab19e4a0d].

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#import "OFString.h"
#import "OFSystemInfo.h"

#import "OFInitializationFailedException.h"
#import "OFLockFailedException.h"
#import "OFUnlockFailedException.h"

#if !defined(HAVE_STRERROR_R) && defined(OF_HAVE_THREADS)
# import "mutex.h"
#endif

#if defined(OF_WINDOWS) && defined(OF_HAVE_SOCKETS)
# include <winerror.h>
#endif








|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#import "OFString.h"
#import "OFSystemInfo.h"

#import "OFInitializationFailedException.h"
#import "OFLockFailedException.h"
#import "OFUnlockFailedException.h"

#ifdef OF_HAVE_THREADS
# import "mutex.h"
#endif

#if defined(OF_WINDOWS) && defined(OF_HAVE_SOCKETS)
# include <winerror.h>
#endif

71
72
73
74
75
76
77
78

79



80
81
82
83
84
85
86
#endif

#if !defined(HAVE_STRERROR_R) && defined(OF_HAVE_THREADS)
static of_mutex_t mutex;

OF_CONSTRUCTOR()
{
	if (of_mutex_new(&mutex) != 0)

		@throw [OFInitializationFailedException exception];



}
#endif

OFString *
of_strerror(int errNo)
{
	OFString *ret;







|
>
|
>
>
>







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#endif

#if !defined(HAVE_STRERROR_R) && defined(OF_HAVE_THREADS)
static of_mutex_t mutex;

OF_CONSTRUCTOR()
{
	OF_ENSURE(of_mutex_new(&mutex) == 0);
}

OF_DESTRUCTOR()
{
	of_mutex_free(&mutex);
}
#endif

OFString *
of_strerror(int errNo)
{
	OFString *ret;

Modified src/macros.h from [56e1068319] to [2f38259464].

146
147
148
149
150
151
152



153
154
155
156
157
158
159

#ifdef __GNUC__
# define OF_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#else
# define OF_GCC_VERSION 0
#endif




#ifndef __has_feature
# define __has_feature(x) 0
#endif

#ifndef __has_attribute
# define __has_attribute(x) 0
#endif







>
>
>







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

#ifdef __GNUC__
# define OF_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#else
# define OF_GCC_VERSION 0
#endif

#define OF_STRINGIFY(s) OF_STRINGIFY2(s)
#define OF_STRINGIFY2(s) #s

#ifndef __has_feature
# define __has_feature(x) 0
#endif

#ifndef __has_attribute
# define __has_attribute(x) 0
#endif
360
361
362
363
364
365
366
367
368
369


370
371
372
373
374
375
376
377
# endif
#endif

#define OF_RETAIN_COUNT_MAX UINT_MAX
#define OF_NOT_FOUND SIZE_MAX

#ifdef OBJC_COMPILING_RUNTIME
# define OF_ENSURE(cond)						   \
	do {								   \
		if OF_UNLIKELY (!(cond))				   \


			OBJC_ERROR("Failed to ensure condition:\n" #cond); \
	} while(0)
#else
# define OF_ENSURE(cond)						\
	do {								\
		if OF_UNLIKELY (!(cond)) {				\
			fprintf(stderr, "Failed to ensure condition "	\
			    "in " __FILE__ ":%d:\n" #cond "\n",		\







|
|
|
>
>
|







363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# endif
#endif

#define OF_RETAIN_COUNT_MAX UINT_MAX
#define OF_NOT_FOUND SIZE_MAX

#ifdef OBJC_COMPILING_RUNTIME
# define OF_ENSURE(cond)						\
	do {								\
		if OF_UNLIKELY (!(cond))				\
			objc_error("ObjFWRT @ " __FILE__ ":"		\
			    OF_STRINGIFY(__LINE__),			\
			    "Failed to ensure condition:\n" #cond);	\
	} while(0)
#else
# define OF_ENSURE(cond)						\
	do {								\
		if OF_UNLIKELY (!(cond)) {				\
			fprintf(stderr, "Failed to ensure condition "	\
			    "in " __FILE__ ":%d:\n" #cond "\n",		\

Modified src/runtime/amiga-glue.m from [a6b9e2e9b8] to [4201c9f909].

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
    "__restore_r13:\n"
    "	lwz	%r13, 44(%r12)\n"
    "	blr\n"
);
#endif

bool __saveds
glue_objc_init PPC_PARAMS(unsigned int version, struct objc_libc *libc,
    FILE **sF)
{
	M68K_ARG(unsigned int, version, d0)
	M68K_ARG(struct objc_libc *, libc, a0)
	M68K_ARG(FILE **, sF, a1)

	return objc_init(version, libc, sF);
}

void __saveds
glue___objc_exec_class PPC_PARAMS(struct objc_module *module)
{
	M68K_ARG(struct objc_module *, module, a0)








|
<



<

|







38
39
40
41
42
43
44
45

46
47
48

49
50
51
52
53
54
55
56
57
    "__restore_r13:\n"
    "	lwz	%r13, 44(%r12)\n"
    "	blr\n"
);
#endif

bool __saveds
glue_objc_init PPC_PARAMS(unsigned int version, struct objc_libc *libc)

{
	M68K_ARG(unsigned int, version, d0)
	M68K_ARG(struct objc_libc *, libc, a0)


	return objc_init(version, libc);
}

void __saveds
glue___objc_exec_class PPC_PARAMS(struct objc_module *module)
{
	M68K_ARG(struct objc_module *, module, a0)

Modified src/runtime/amiga-library.h from [65524391cb] to [491ea4b97d].

64
65
66
67
68
69
70
71
72
	int (*_Nonnull vsnprintf)(char *restrict _Nonnull str, size_t size,
	    const char *_Nonnull restrict fmt, va_list args);
# endif
	int (*_Nonnull atexit)(void (*_Nonnull)(void));
	void (*_Nonnull exit)(int);
};

extern bool objc_init(unsigned int, struct objc_libc *_Nonnull,
    FILE *_Nonnull *_Nonnull);







|
<
64
65
66
67
68
69
70
71

	int (*_Nonnull vsnprintf)(char *restrict _Nonnull str, size_t size,
	    const char *_Nonnull restrict fmt, va_list args);
# endif
	int (*_Nonnull atexit)(void (*_Nonnull)(void));
	void (*_Nonnull exit)(int);
};

extern bool objc_init(unsigned int, struct objc_libc *_Nonnull);

Modified src/runtime/amiga-library.m from [174921abc5] to [e97fca3c84].

162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
extern id glue_objc_createTaggedPointer(void);

#ifdef OF_MORPHOS
const ULONG __abox__ = 1;
#endif
struct ExecBase *SysBase;
struct objc_libc libc;
FILE **__sF;

#if defined(OF_AMIGAOS_M68K)
__asm__ (
    ".text\n"
    ".globl ___restore_a4\n"
    ".align 1\n"
    "___restore_a4:\n"







<







162
163
164
165
166
167
168

169
170
171
172
173
174
175
extern id glue_objc_createTaggedPointer(void);

#ifdef OF_MORPHOS
const ULONG __abox__ = 1;
#endif
struct ExecBase *SysBase;
struct objc_libc libc;


#if defined(OF_AMIGAOS_M68K)
__asm__ (
    ".text\n"
    ".globl ___restore_a4\n"
    ".align 1\n"
    "___restore_a4:\n"
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
static void *
lib_null(void)
{
	return NULL;
}

bool
objc_init(unsigned int version, struct objc_libc *libc_, FILE **sF)
{
#ifdef OF_AMIGAOS_M68K
	OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6)
#else
	register struct ObjFWRTBase *r12 __asm__("r12");
	struct ObjFWRTBase *base = r12;
#endif
#ifdef OF_MORPHOS
	void *frame;
#endif
	uintptr_t *iter, *iter0;

	if (version > 1)
		return false;

	if (base->initialized)
		return true;

	memcpy(&libc, libc_, sizeof(libc));
	__sF = sF;

#ifdef OF_AMIGAOS_M68K
	if ((size_t)_EH_FRAME_BEGINS__ != (size_t)_EH_FRAME_OBJECTS__)
		return false;

	for (size_t i = 1; i <= (size_t)_EH_FRAME_BEGINS__; i++)
		libc.__register_frame_info((&_EH_FRAME_BEGINS__)[i],







|



















<







411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437

438
439
440
441
442
443
444
static void *
lib_null(void)
{
	return NULL;
}

bool
objc_init(unsigned int version, struct objc_libc *libc_)
{
#ifdef OF_AMIGAOS_M68K
	OBJC_M68K_ARG(struct ObjFWRTBase *, base, a6)
#else
	register struct ObjFWRTBase *r12 __asm__("r12");
	struct ObjFWRTBase *base = r12;
#endif
#ifdef OF_MORPHOS
	void *frame;
#endif
	uintptr_t *iter, *iter0;

	if (version > 1)
		return false;

	if (base->initialized)
		return true;

	memcpy(&libc, libc_, sizeof(libc));


#ifdef OF_AMIGAOS_M68K
	if ((size_t)_EH_FRAME_BEGINS__ != (size_t)_EH_FRAME_OBJECTS__)
		return false;

	for (size_t i = 1; i <= (size_t)_EH_FRAME_BEGINS__; i++)
		libc.__register_frame_info((&_EH_FRAME_BEGINS__)[i],

Modified src/runtime/amigaos3.sfd from [9aed232916] to [27d28cf09f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
==base _ObjFWRTBase
==basetype struct Library *
==libname objfwrt68k.library
==bias 30
==public
* The following function is only for the linklib.
bool glue_objc_init(unsigned int version, struct objc_libc *_Nonnull libc, FILE *_Nonnull *_Nonnull sF)(d0,a0,a1)
void glue___objc_exec_class(struct objc_module *_Nonnull module)(a0)
IMP _Nonnull glue_objc_msg_lookup(id _Nullable object, SEL _Nonnull selector)(a0,a1)
IMP _Nonnull glue_objc_msg_lookup_stret(id _Nullable object, SEL _Nonnull selector)(a0,a1)
IMP _Nonnull glue_objc_msg_lookup_super(struct objc_super *_Nonnull super, SEL _Nonnull selector)(a0,a1)
IMP _Nonnull glue_objc_msg_lookup_super_stret(struct objc_super *_Nonnull super, SEL _Nonnull selector)(a0,a1)
Class _Nullable glue_objc_lookUpClass(const char *_Nonnull name)(a0)
Class _Nullable glue_objc_getClass(const char *_Nonnull name)(a0)






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
==base _ObjFWRTBase
==basetype struct Library *
==libname objfwrt68k.library
==bias 30
==public
* The following function is only for the linklib.
bool glue_objc_init(unsigned int version, struct objc_libc *libc)(d0,a0)
void glue___objc_exec_class(struct objc_module *_Nonnull module)(a0)
IMP _Nonnull glue_objc_msg_lookup(id _Nullable object, SEL _Nonnull selector)(a0,a1)
IMP _Nonnull glue_objc_msg_lookup_stret(id _Nullable object, SEL _Nonnull selector)(a0,a1)
IMP _Nonnull glue_objc_msg_lookup_super(struct objc_super *_Nonnull super, SEL _Nonnull selector)(a0,a1)
IMP _Nonnull glue_objc_msg_lookup_super_stret(struct objc_super *_Nonnull super, SEL _Nonnull selector)(a0,a1)
Class _Nullable glue_objc_lookUpClass(const char *_Nonnull name)(a0)
Class _Nullable glue_objc_getClass(const char *_Nonnull name)(a0)

Modified src/runtime/class.m from [0b3dadf0dd] to [c47f6af2b8].

339
340
341
342
343
344
345







346
347
348
349
350
351
352

	if (class->info & OBJC_CLASS_INFO_INITIALIZED)
		return;

	if (class->superclass)
		initializeClass(class->superclass);








	class->info |= OBJC_CLASS_INFO_DTABLE;
	class->isa->info |= OBJC_CLASS_INFO_DTABLE;

	objc_update_dtable(class);
	objc_update_dtable(class->isa);

	/*







>
>
>
>
>
>
>







339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359

	if (class->info & OBJC_CLASS_INFO_INITIALIZED)
		return;

	if (class->superclass)
		initializeClass(class->superclass);

	/*
	 * Avoid double-initialization: One of the superclasses' +[initialize]
	 * might have called this class and hence it already got initialized.
	 */
	if (class->info & OBJC_CLASS_INFO_INITIALIZED)
		return;

	class->info |= OBJC_CLASS_INFO_DTABLE;
	class->isa->info |= OBJC_CLASS_INFO_DTABLE;

	objc_update_dtable(class);
	objc_update_dtable(class->isa);

	/*

Modified src/runtime/linklib/linklib.m from [2cbbd07269] to [ec6bf583a1].

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
		return;

	if ((ObjFWRTBase = OpenLibrary(OBJFWRT_AMIGA_LIB,
	    OBJFWRT_LIB_MINOR)) == NULL)
		error("Failed to open " OBJFWRT_AMIGA_LIB " version %lu!",
		    OBJFWRT_LIB_MINOR);

	if (!glue_objc_init(1, &libc, __sF))
		error("Failed to initialize " OBJFWRT_AMIGA_LIB "!", 0);

	initialized = true;
}

static void __attribute__((__used__))
dtor(void)







|







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
		return;

	if ((ObjFWRTBase = OpenLibrary(OBJFWRT_AMIGA_LIB,
	    OBJFWRT_LIB_MINOR)) == NULL)
		error("Failed to open " OBJFWRT_AMIGA_LIB " version %lu!",
		    OBJFWRT_LIB_MINOR);

	if (!glue_objc_init(1, &libc))
		error("Failed to initialize " OBJFWRT_AMIGA_LIB "!", 0);

	initialized = true;
}

static void __attribute__((__used__))
dtor(void)

Modified src/runtime/misc.m from [2faf8bad32] to [5ec6e3911d].

19
20
21
22
23
24
25




26
27
28
29
30
31
32

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

#include "ObjFWRT.h"
#include "private.h"





#ifdef OF_AMIGAOS
# define USE_INLINE_STDARG
# include <proto/exec.h>
# include <clib/debug_protos.h>
# define __NOLIBBASE__
# define Class IntuitionClass







>
>
>
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

#include "ObjFWRT.h"
#include "private.h"

#ifdef OF_WINDOWS
# include <windows.h>
#endif

#ifdef OF_AMIGAOS
# define USE_INLINE_STDARG
# include <proto/exec.h>
# include <clib/debug_protos.h>
# define __NOLIBBASE__
# define Class IntuitionClass
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

















79
80
81
82
83
84
85
void
objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler_t handler)
{
	enumerationMutationHandler = handler;
}

void
objc_error(const char *file, unsigned int line, const char *format, ...)
{
#ifdef OF_AMIGAOS
# define BUF_LEN 256
	char title[BUF_LEN];
	char message[BUF_LEN];
	int status;
	va_list args;
	struct Library *IntuitionBase;
# ifdef OF_AMIGAOS4
	struct IntuitionIFace *IIntuition;
# endif
	struct EasyStruct easy;

	status = snprintf(title, BUF_LEN, "ObjFWRT @ %s:%u", file, line);
	if (status <= 0 || status >= BUF_LEN)
		title[0] = '\0';

	va_start(args, format);
	status = vsnprintf(message, BUF_LEN, format, args);
	if (status <= 0 || status >= BUF_LEN)
		message[0] = '\0';
	va_end(args);


















# ifndef OF_AMIGAOS4
	kprintf("[%s] %s\n", title, message);
# endif

	if ((IntuitionBase = OpenLibrary("intuition.library", 0)) == NULL)
		exit(EXIT_FAILURE);







|

|
|
<



<
<
<
<
<
<
<
<
<






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







53
54
55
56
57
58
59
60
61
62
63

64
65
66









67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
void
objc_setEnumerationMutationHandler(objc_enumeration_mutation_handler_t handler)
{
	enumerationMutationHandler = handler;
}

void
objc_error(const char *title, const char *format, ...)
{
#if defined(OF_WINDOWS) || defined(OF_AMIGAOS)
# define BUF_LEN 512

	char message[BUF_LEN];
	int status;
	va_list args;










	va_start(args, format);
	status = vsnprintf(message, BUF_LEN, format, args);
	if (status <= 0 || status >= BUF_LEN)
		message[0] = '\0';
	va_end(args);
# undef BUF_LEN
#endif

#if defined(OF_WINDOWS)
	fprintf(stderr, "[%s] %s\n", title, message);
	fflush(stderr);

	MessageBoxA(NULL, message, title,
	    MB_OK | MB_SYSTEMMODAL | MB_ICONERROR);

	exit(EXIT_FAILURE);
#elif defined(OF_AMIGAOS)
	struct Library *IntuitionBase;
# ifdef OF_AMIGAOS4
	struct IntuitionIFace *IIntuition;
# endif
	struct EasyStruct easy;

# ifndef OF_AMIGAOS4
	kprintf("[%s] %s\n", title, message);
# endif

	if ((IntuitionBase = OpenLibrary("intuition.library", 0)) == NULL)
		exit(EXIT_FAILURE);
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# ifdef OF_AMIGAOS4
	DropInterface((struct Interface *)IIntuition);
# endif

	CloseLibrary(IntuitionBase);

	exit(EXIT_FAILURE);
# undef BUF_LEN
#else
	va_list args;

	va_start(args, format);

	fprintf(stderr, "[ObjFWRT @ %s:%u] ", file, line);
	vfprintf(stderr, format, args);
	fprintf(stderr, "\n");
	fflush(stderr);

	va_end(args);

	abort();
#endif

	OF_UNREACHABLE
}







<





|











112
113
114
115
116
117
118

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# ifdef OF_AMIGAOS4
	DropInterface((struct Interface *)IIntuition);
# endif

	CloseLibrary(IntuitionBase);

	exit(EXIT_FAILURE);

#else
	va_list args;

	va_start(args, format);

	fprintf(stderr, "[%s] ", title);
	vfprintf(stderr, format, args);
	fprintf(stderr, "\n");
	fflush(stderr);

	va_end(args);

	abort();
#endif

	OF_UNREACHABLE
}

Modified src/runtime/morphos-clib.h from [6d0fa4e01f] to [750cbb9d7c].

1
2
3
4
5
6
7
8
9
/* The following function is only for the linklib. */
bool glue_objc_init(unsigned int, struct objc_libc *, FILE **);
void glue___objc_exec_class(struct objc_module *);
IMP glue_objc_msg_lookup(id, SEL);
IMP glue_objc_msg_lookup_stret(id, SEL);
IMP glue_objc_msg_lookup_super(struct objc_super *, SEL);
IMP glue_objc_msg_lookup_super_stret(struct objc_super *, SEL);
Class glue_objc_lookUpClass(const char *);
Class glue_objc_getClass(const char *);

|







1
2
3
4
5
6
7
8
9
/* The following function is only for the linklib. */
bool glue_objc_init(unsigned int, struct objc_libc *);
void glue___objc_exec_class(struct objc_module *);
IMP glue_objc_msg_lookup(id, SEL);
IMP glue_objc_msg_lookup_stret(id, SEL);
IMP glue_objc_msg_lookup_super(struct objc_super *, SEL);
IMP glue_objc_msg_lookup_super_stret(struct objc_super *, SEL);
Class glue_objc_lookUpClass(const char *);
Class glue_objc_getClass(const char *);

Modified src/runtime/morphos.fd from [708829bde1] to [4a176c28f2].

1
2
3
4
5
6
7
8
9
10
11
12
##base _ObjFWRTBase
##bias 30
##public
* The following function is only for the linklib.
glue_objc_init(version,libc,sF)(sysv,r12base)
glue___objc_exec_class(module)(sysv,r12base)
glue_objc_msg_lookup(object,selector)(sysv,r12base)
glue_objc_msg_lookup_stret(object,selector)(sysv,r12base)
glue_objc_msg_lookup_super(super,selector)(sysv,r12base)
glue_objc_msg_lookup_super_stret(super,selector)(sysv,r12base)
glue_objc_lookUpClass(name)(sysv,r12base)
glue_objc_getClass(name)(sysv,r12base)




|







1
2
3
4
5
6
7
8
9
10
11
12
##base _ObjFWRTBase
##bias 30
##public
* The following function is only for the linklib.
glue_objc_init(version,libc)(sysv,r12base)
glue___objc_exec_class(module)(sysv,r12base)
glue_objc_msg_lookup(object,selector)(sysv,r12base)
glue_objc_msg_lookup_stret(object,selector)(sysv,r12base)
glue_objc_msg_lookup_super(super,selector)(sysv,r12base)
glue_objc_msg_lookup_super_stret(super,selector)(sysv,r12base)
glue_objc_lookUpClass(name)(sysv,r12base)
glue_objc_getClass(name)(sysv,r12base)

Modified src/runtime/private.h from [cd3ba36b2b] to [b27511eb2a].

281
282
283
284
285
286
287
288
289
290


291
292
293
294
295
296
297
	uint8_t i = idx >> 8;
	uint8_t j = idx;

	return dtable->buckets[i]->buckets[j];
#endif
}

extern void OF_NO_RETURN_FUNC objc_error(const char *_Nonnull file,
    unsigned int line, const char *_Nonnull format, ...);
#define OBJC_ERROR(...) objc_error(__FILE__, __LINE__, __VA_ARGS__)



#if defined(OF_ELF)
# if defined(OF_X86_64) || defined(OF_X86) || defined(OF_POWERPC) || \
    defined(OF_ARM64) || defined(OF_ARM) || \
    defined(OF_MIPS64_N64) || defined(OF_MIPS) || \
    defined(OF_SPARC64) || defined(OF_SPARC)
#  define OF_ASM_LOOKUP







|
|
|
>
>







281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
	uint8_t i = idx >> 8;
	uint8_t j = idx;

	return dtable->buckets[i]->buckets[j];
#endif
}

extern void OF_NO_RETURN_FUNC objc_error(const char *_Nonnull title,
    const char *_Nonnull format, ...);
#define OBJC_ERROR(...)							\
	objc_error("ObjFWRT @ " __FILE__ ":" OF_STRINGIFY(__LINE__),	\
	    __VA_ARGS__)

#if defined(OF_ELF)
# if defined(OF_X86_64) || defined(OF_X86) || defined(OF_POWERPC) || \
    defined(OF_ARM64) || defined(OF_ARM) || \
    defined(OF_MIPS64_N64) || defined(OF_MIPS) || \
    defined(OF_SPARC64) || defined(OF_SPARC)
#  define OF_ASM_LOOKUP

Modified src/socket.m from [7f38594dbe] to [d886e134b6].

22
23
24
25
26
27
28



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58


59




60
61
62
63
64
65
66
#endif

#include <errno.h>

#import "OFArray.h"
#import "OFCharacterSet.h"
#import "OFLocale.h"



#import "OFString.h"

#import "OFException.h"  /* For some E* -> WSAE* defines */
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFLockFailedException.h"
#import "OFUnlockFailedException.h"

#import "socket.h"
#import "socket_helpers.h"
#ifdef OF_HAVE_THREADS
# if !defined(OF_AMIGAOS) || defined(OF_MORPHOS)
#  import "mutex.h"
# else
#  import "tlskey.h"
# endif
#endif
#import "once.h"

#ifdef OF_AMIGAOS
# include <proto/exec.h>
#endif

#ifdef OF_NINTENDO_3DS
# include <3ds/types.h>
# include <3ds/services/soc.h>
#endif

#if defined(OF_HAVE_THREADS) && (!defined(OF_AMIGAOS) || defined(OF_MORPHOS))


static of_mutex_t mutex;




#endif
#if !defined(OF_AMIGAOS) || defined(OF_MORPHOS) || !defined(OF_HAVE_THREADS)
static bool initSuccessful = false;
#endif

#ifdef OF_AMIGAOS
# if defined(OF_HAVE_THREADS) && !defined(OF_MORPHOS)







>
>
>












<
<
<
|
<













>
>
|
>
>
>
>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43



44

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#endif

#include <errno.h>

#import "OFArray.h"
#import "OFCharacterSet.h"
#import "OFLocale.h"
#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif
#import "OFString.h"

#import "OFException.h"  /* For some E* -> WSAE* defines */
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFLockFailedException.h"
#import "OFUnlockFailedException.h"

#import "socket.h"
#import "socket_helpers.h"
#ifdef OF_HAVE_THREADS



# import "tlskey.h"

#endif
#import "once.h"

#ifdef OF_AMIGAOS
# include <proto/exec.h>
#endif

#ifdef OF_NINTENDO_3DS
# include <3ds/types.h>
# include <3ds/services/soc.h>
#endif

#if defined(OF_HAVE_THREADS) && (!defined(OF_AMIGAOS) || defined(OF_MORPHOS))
static OFMutex *mutex;

static void
releaseMutex(void)
{
	[mutex release];
}
#endif
#if !defined(OF_AMIGAOS) || defined(OF_MORPHOS) || !defined(OF_HAVE_THREADS)
static bool initSuccessful = false;
#endif

#ifdef OF_AMIGAOS
# if defined(OF_HAVE_THREADS) && !defined(OF_MORPHOS)
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
150
151

152
153
154
155
156
157
158
	if (socInit(ctx, 0x100000) != 0)
		return;

	atexit((void (*)(void))socExit);
# endif

# if defined(OF_HAVE_THREADS) && (!defined(OF_AMIGAOS) || defined(OF_MORPHOS))
	if (of_mutex_new(&mutex) != 0)
		return;

#  ifdef OF_WII
	if (of_spinlock_new(&spinlock) != 0)
		return;
#  endif
# endif

	initSuccessful = true;
}

# ifdef OF_AMIGAOS
OF_DESTRUCTOR()
{

#  ifdef OF_AMIGAOS4
	if (ISocket != NULL)
		DropInterface((struct Interface *)ISocket);
#  endif

	if (SocketBase != NULL)
		CloseLibrary(SocketBase);
}
# endif

#endif

bool
of_socket_init(void)
{
#if !defined(OF_AMIGAOS) || defined(OF_MORPHOS) || !defined(OF_HAVE_THREADS)
	static of_once_t onceControl = OF_ONCE_INIT;







|
|










<


>







<

>







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
162
163
	if (socInit(ctx, 0x100000) != 0)
		return;

	atexit((void (*)(void))socExit);
# endif

# if defined(OF_HAVE_THREADS) && (!defined(OF_AMIGAOS) || defined(OF_MORPHOS))
	mutex = [[OFMutex alloc] init];
	atexit(releaseMutex);

#  ifdef OF_WII
	if (of_spinlock_new(&spinlock) != 0)
		return;
#  endif
# endif

	initSuccessful = true;
}


OF_DESTRUCTOR()
{
# ifdef OF_AMIGAOS
#  ifdef OF_AMIGAOS4
	if (ISocket != NULL)
		DropInterface((struct Interface *)ISocket);
#  endif

	if (SocketBase != NULL)
		CloseLibrary(SocketBase);

# endif
}
#endif

bool
of_socket_init(void)
{
#if !defined(OF_AMIGAOS) || defined(OF_MORPHOS) || !defined(OF_HAVE_THREADS)
	static of_once_t onceControl = OF_ONCE_INIT;
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
int
of_getsockname(of_socket_t sock, struct sockaddr *restrict addr,
    socklen_t *restrict addrLen)
{
	int ret;

# if defined(OF_HAVE_THREADS) && (!defined(OF_AMIGAOS) || defined(OF_MORPHOS))
	if (of_mutex_lock(&mutex) != 0)
		@throw [OFLockFailedException exception];

# endif

	ret = getsockname(sock, addr, addrLen);

# if defined(OF_HAVE_THREADS) && (!defined(OF_AMIGAOS) || defined(OF_MORPHOS))
	if (of_mutex_unlock(&mutex) != 0)
		@throw [OFUnlockFailedException exception];
# endif

	return ret;
}
#endif

of_socket_address_t







<
<
|

<

<

|
<







330
331
332
333
334
335
336


337
338

339

340
341

342
343
344
345
346
347
348
int
of_getsockname(of_socket_t sock, struct sockaddr *restrict addr,
    socklen_t *restrict addrLen)
{
	int ret;

# if defined(OF_HAVE_THREADS) && (!defined(OF_AMIGAOS) || defined(OF_MORPHOS))


	[mutex lock];
# endif

	ret = getsockname(sock, addr, addrLen);

# if defined(OF_HAVE_THREADS) && (!defined(OF_AMIGAOS) || defined(OF_MORPHOS))
	[mutex unlock];

# endif

	return ret;
}
#endif

of_socket_address_t

tests/OFIPXSocketTests.m became a regular file with contents [a065806b7f].

tests/OFSPXSocketTests.m became a regular file with contents [e438c57a59].

tests/OFSPXStreamSocketTests.m became a regular file with contents [4e87ecb1d0].

Modified tests/OFStringTests.m from [bb912e724d] to [484cb7d0ac].

601
602
603
604
605
606
607
608



609
610
611
612
613
614
615
	    componentsSeparatedByString: @"XX"]) &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    a.count == i)




	i = 0;
	TEST(@"-[componentsSeparatedByString:options:]",
	    (a = [C(@"fooXXbarXXXXbazXXXX")
	    componentsSeparatedByString: @"XX"
				options: OF_STRING_SKIP_EMPTY]) &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&







|
>
>
>







601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
	    componentsSeparatedByString: @"XX"]) &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&
	    [[a objectAtIndex: i++] isEqual: @"bar"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @"baz"] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    [[a objectAtIndex: i++] isEqual: @""] &&
	    a.count == i &&
	    (a = [C(@"foo") componentsSeparatedByString: @""]) &&
	    [[a objectAtIndex: 0] isEqual: @"foo"] &&
	    a.count == 1)

	i = 0;
	TEST(@"-[componentsSeparatedByString:options:]",
	    (a = [C(@"fooXXbarXXXXbazXXXX")
	    componentsSeparatedByString: @"XX"
				options: OF_STRING_SKIP_EMPTY]) &&
	    [[a objectAtIndex: i++] isEqual: @"foo"] &&