ObjFW  Diff

Differences From Artifact [db7a703dd2]:

To Artifact [451e6c48b2]:


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







-
+

-
+


-
+


-
+

-
+

-
+







# ifdef OF_AMIGAOS4
#  define DeleteFile(path) Delete(path)
# endif
#endif

#if defined(OF_WINDOWS) || defined(OF_AMIGAOS)
typedef struct {
	of_offset_t st_size;
	OFFileOffset st_size;
	unsigned int st_mode;
	of_time_interval_t st_atime, st_mtime, st_ctime;
	OFTimeInterval st_atime, st_mtime, st_ctime;
# ifdef OF_WINDOWS
#  define HAVE_STRUCT_STAT_ST_BIRTHTIME
	of_time_interval_t st_birthtime;
	OFTimeInterval st_birthtime;
	DWORD fileAttributes;
# endif
} of_stat_t;
} Stat;
#elif defined(HAVE_STAT64)
typedef struct stat64 of_stat_t;
typedef struct stat64 Stat;
#else
typedef struct stat of_stat_t;
typedef struct stat Stat;
#endif

#ifdef OF_WINDOWS
# define S_IFLNK 0x10000
# define S_ISLNK(mode) (mode & S_IFLNK)
#endif

123
124
125
126
127
128
129
130
131
132



133
134
135
136
137

138
139
140
141
142
143
144
123
124
125
126
127
128
129



130
131
132
133
134
135
136

137
138
139
140
141
142
143
144







-
-
-
+
+
+




-
+







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,
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_WINDOWS
static of_time_interval_t
static OFTimeInterval
filetimeToTimeInterval(const FILETIME *filetime)
{
	return (double)((int64_t)filetime->dwHighDateTime << 32 |
	    filetime->dwLowDateTime) / 10000000.0 - 11644473600.0;
}

static int
192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
192
193
194
195
196
197
198

199
200
201
202
203
204
205
206







-
+







	default:
		return EIO;
	}
}
#endif

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

	if ([OFSystemInfo isWindowsNT])
		success = GetFileAttributesExW(path.UTF16String,
258
259
260
261
262
263
264
265

266
267
268
269
270
271
272
258
259
260
261
262
263
264

265
266
267
268
269
270
271
272







-
+







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

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

311
312
313
314
315
316
317
318

319
320
321
322
323
324
325
311
312
313
314
315
316
317

318
319
320
321
322
323
324
325







-
+







# ifdef OF_AMIGAOS4
	date = &ed->Date;
# else
	date = &fib.fib_Date;
# endif
	timeInterval += date->ds_Days * 86400.0;
	timeInterval += date->ds_Minute * 60.0;
	timeInterval += date->ds_Tick / (of_time_interval_t)TICKS_PER_SECOND;
	timeInterval += date->ds_Tick / (OFTimeInterval)TICKS_PER_SECOND;

	buffer->st_atime = buffer->st_mtime = buffer->st_ctime = timeInterval;

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

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

363
364
365

366
367
368

369
370
371
372
373


374
375
376




377
378


379
380
381
382
383
384
385
386
387
388


389
390
391
392

393
394
395
396
397
398

399
400
401
402
403

404
405
406

407
408
409

410
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
445
446
447
448
449
450

451
452
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
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
363
364

365

366

367

368
369


370
371
372
373
374
375
376
377
378


379
380
381





382
383


384
385
386
387
388

389

390
391
392
393

394
395
396
397
398

399
400
401

402
403
404

405
406
407
408

409
410
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

445
446
447
448
449
450
451
452
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







-
+














-
+




-
+


-
+
-

-
+
-


-
-
+
+



+
+
+
+
-
-
+
+

-
-
-
-
-


-
-
+
+



-
+
-




-
+




-
+


-
+


-
+



-
+




-
+
-



-
+

-
+





-
+









-
+








-
+











-
+




-
+



-













-
-
+
+




-
+
















-







		return errno;

	return 0;
#endif
}

static int
of_lstat(OFString *path, of_stat_t *buffer)
lstatWrapper(OFString *path, Stat *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);
	return statWrapper(path, buffer);
#endif
}

static void
setTypeAttribute(of_mutable_file_attributes_t attributes, of_stat_t *s)
setTypeAttribute(OFMutableFileAttributes attributes, Stat *s)
{
	if (S_ISREG(s->st_mode))
		[attributes setObject: of_file_type_regular
		[attributes setObject: OFFileTypeRegular forKey: OFFileType];
			       forKey: of_file_attribute_key_type];
	else if (S_ISDIR(s->st_mode))
		[attributes setObject: of_file_type_directory
		[attributes setObject: OFFileTypeDirectory forKey: OFFileType];
			       forKey: of_file_attribute_key_type];
#ifdef S_ISLNK
	else if (S_ISLNK(s->st_mode))
		[attributes setObject: of_file_type_symbolic_link
			       forKey: of_file_attribute_key_type];
		[attributes setObject: OFFileTypeSymbolicLink
			       forKey: OFFileType];
#endif
#ifdef S_ISFIFO
	else if (S_ISFIFO(s->st_mode))
		[attributes setObject: OFFileTypeFIFO forKey: OFFileType];
#endif
#ifdef S_ISCHR
	else if (S_ISCHR(s->st_mode))
		[attributes setObject: of_file_type_fifo
			       forKey: of_file_attribute_key_type];
		[attributes setObject: OFFileTypeCharacterSpecial
			       forKey: OFFileType];
#endif
#ifdef S_ISCHR
	else if (S_ISCHR(s->st_mode))
		[attributes setObject: of_file_type_character_special
			       forKey: of_file_attribute_key_type];
#endif
#ifdef S_ISBLK
	else if (S_ISBLK(s->st_mode))
		[attributes setObject: of_file_type_block_special
			       forKey: of_file_attribute_key_type];
		[attributes setObject: OFFileTypeBlockSpecial
			       forKey: OFFileType];
#endif
#ifdef S_ISSOCK
	else if (S_ISSOCK(s->st_mode))
		[attributes setObject: of_file_type_socket
		[attributes setObject: OFFileTypeSocket forKey: OFFileType];
			       forKey: of_file_attribute_key_type];
#endif
}

static void
setDateAttributes(of_mutable_file_attributes_t attributes, of_stat_t *s)
setDateAttributes(OFMutableFileAttributes attributes, Stat *s)
{
	/* FIXME: We could be more precise on some OSes */
	[attributes
	    setObject: [OFDate dateWithTimeIntervalSince1970: s->st_atime]
	       forKey: of_file_attribute_key_last_access_date];
	       forKey: OFFileLastAccessDate];
	[attributes
	    setObject: [OFDate dateWithTimeIntervalSince1970: s->st_mtime]
	       forKey: of_file_attribute_key_modification_date];
	       forKey: OFFileModificationDate];
	[attributes
	    setObject: [OFDate dateWithTimeIntervalSince1970: s->st_ctime]
	       forKey: of_file_attribute_key_status_change_date];
	       forKey: OFFileStatusChangeDate];
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
	[attributes
	    setObject: [OFDate dateWithTimeIntervalSince1970: s->st_birthtime]
	       forKey: of_file_attribute_key_creation_date];
	       forKey: OFFileCreationDate];
#endif
}

static void
setOwnerAndGroupAttributes(of_mutable_file_attributes_t attributes,
setOwnerAndGroupAttributes(OFMutableFileAttributes attributes, Stat *s)
    of_stat_t *s)
{
#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER
	[attributes setObject: [NSNumber numberWithUnsignedLong: s->st_uid]
		       forKey: of_file_attribute_key_posix_uid];
		       forKey: OFFileOwnerAccountID];
	[attributes setObject: [NSNumber numberWithUnsignedLong: s->st_gid]
		       forKey: of_file_attribute_key_posix_gid];
		       forKey: OFFileGroupOwnerAccountID];

# ifdef OF_HAVE_THREADS
	[passwdMutex lock];
	@try {
# endif
		of_string_encoding_t encoding = [OFLocale encoding];
		OFStringEncoding encoding = [OFLocale encoding];
		struct passwd *passwd = getpwuid(s->st_uid);
		struct group *group_ = getgrgid(s->st_gid);

		if (passwd != NULL) {
			OFString *owner = [OFString
			    stringWithCString: passwd->pw_name
				     encoding: encoding];

			[attributes setObject: owner
				       forKey: of_file_attribute_key_owner];
				       forKey: OFFileOwnerAccountName];
		}

		if (group_ != NULL) {
			OFString *group = [OFString
			    stringWithCString: group_->gr_name
				     encoding: encoding];

			[attributes setObject: group
				       forKey: of_file_attribute_key_group];
				       forKey: OFFileGroupOwnerAccountName];
		}
# ifdef OF_HAVE_THREADS
	} @finally {
		[passwdMutex unlock];
	}
# endif
#endif
}

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
static void
setSymbolicLinkDestinationAttribute(of_mutable_file_attributes_t attributes,
setSymbolicLinkDestinationAttribute(OFMutableFileAttributes attributes,
    OFURL *URL)
{
	OFString *path = URL.fileSystemRepresentation;
# ifndef OF_WINDOWS
	of_string_encoding_t encoding = [OFLocale encoding];
	OFStringEncoding encoding = [OFLocale encoding];
	char destinationC[PATH_MAX];
	ssize_t length;
	OFString *destination;
	of_file_attribute_key_t key;

	length = readlink([path cStringWithEncoding: encoding], destinationC,
	    PATH_MAX);

	if (length < 0)
		@throw [OFRetrieveItemAttributesFailedException
		    exceptionWithURL: URL
			       errNo: errno];

	destination = [OFString stringWithCString: destinationC
					 encoding: encoding
					   length: length];

	key = of_file_attribute_key_symbolic_link_destination;
	[attributes setObject: destination forKey: key];
	[attributes setObject: destination
		       forKey: OFFileSymbolicLinkDestination];
# else
	HANDLE handle;
	OFString *destination;

	if (func_CreateSymbolicLinkW == NULL)
	if (createSymbolicLinkWFuncPtr == NULL)
		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()];
524
525
526
527
528
529
530
531
532


533
534


535
536
537
538
539
540
541
517
518
519
520
521
522
523


524
525


526
527
528
529
530
531
532
533
534







-
-
+
+
-
-
+
+







		    (slrb.SubstituteNameOffset / sizeof(wchar_t));

		destination = [OFString
		    stringWithUTF16String: tmp
				   length: slrb.SubstituteNameLength /
					   sizeof(wchar_t)];

		[attributes setObject: of_file_type_symbolic_link
			       forKey: of_file_attribute_key_type];
		[attributes setObject: OFFileTypeSymbolicLink
			       forKey: OFFileType];
		key = of_file_attribute_key_symbolic_link_destination;
		[attributes setObject: destination forKey: key];
		[attributes setObject: destination
			       forKey: OFFileSymbolicLinkDestination];
#  undef slrb
	} @finally {
		CloseHandle(handle);
	}
# endif
}
#endif
557
558
559
560
561
562
563
564

565
566
567
568

569
570
571

572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587

588
589

590
591
592
593
594
595
596
597
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
626
627
628
629
630
631
632

633
634
635
636
637

638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655

656
657
658
659


660
661
662
663
664
665
666
667
668

669
670
671
672
673
674
675
676

677
678
679
680
681
682
683
550
551
552
553
554
555
556

557
558
559
560

561
562
563

564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579

580
581

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
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
626
627
628
629

630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647

648
649
650


651
652

653
654
655
656
657
658
659

660
661
662
663
664
665
666
667

668
669
670
671
672
673
674
675







-
+



-
+


-
+















-
+

-
+

















-
+

-
+



-
+









-
+








-
+




-
+

















-
+


-
-
+
+
-







-
+







-
+







#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 *,
		_wutime64FuncPtr = (int (*)(const wchar_t *,
		    struct __utimbuf64 *))GetProcAddress(module, "_wutime64");

	if ((module = LoadLibrary("kernel32.dll")) != NULL) {
		func_CreateSymbolicLinkW =
		createSymbolicLinkWFuncPtr =
		    (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR, DWORD))
		    GetProcAddress(module, "CreateSymbolicLinkW");
		func_CreateHardLinkW =
		createHardLinkWFuncPtr =
		    (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR,
		    LPSECURITY_ATTRIBUTES))
		    GetProcAddress(module, "CreateHardLinkW");
	}
#endif

	/*
	 * Make sure OFFile is initialized.
	 * On some systems, this is needed to initialize the file system driver.
	 */
	[OFFile class];
}

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

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

	return S_ISDIR(s.st_mode);
}

- (OFStream *)openItemAtURL: (OFURL *)URL mode: (OFString *)mode
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *file = [[OFFile alloc]
	    initWithPath: URL.fileSystemRepresentation
		    mode: mode];

	objc_autoreleasePoolPop(pool);

	return [file autorelease];
}

- (of_file_attributes_t)attributesOfItemAtURL: (OFURL *)URL
- (OFFileAttributes)attributesOfItemAtURL: (OFURL *)URL
{
	of_mutable_file_attributes_t ret = [OFMutableDictionary dictionary];
	OFMutableFileAttributes ret = [OFMutableDictionary dictionary];
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	int error;
	of_stat_t s;
	Stat 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)
	if ((error = lstatWrapper(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];
		forKey: OFFileSize];

	setTypeAttribute(ret, &s);

	[ret setObject: [NSNumber numberWithUnsignedLong: s.st_mode]
		forKey: of_file_attribute_key_posix_permissions];
		forKey: OFFilePOSIXPermissions];

	setOwnerAndGroupAttributes(ret, &s);
	setDateAttributes(ret, &s);

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
	if (S_ISLNK(s.st_mode))
		setSymbolicLinkDestinationAttribute(ret, URL);
#endif

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (void)of_setLastAccessDate: (OFDate *)lastAccessDate
	 andModificationDate: (OFDate *)modificationDate
		 ofItemAtURL: (OFURL *)URL
		  attributes: (of_file_attributes_t)attributes OF_DIRECT
		  attributes: (OFFileAttributes)attributes OF_DIRECT
{
	OFString *path = URL.fileSystemRepresentation;
	of_file_attribute_key_t attributeKey = (modificationDate != nil
	    ? of_file_attribute_key_modification_date
	OFFileAttributeKey attributeKey = (modificationDate != nil
	    ? OFFileModificationDate : OFFileLastAccessDate);
	    : of_file_attribute_key_last_access_date);

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

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

		if (func__wutime64([path UTF16String], &times) != 0)
		if (_wutime64FuncPtr([path UTF16String], &times) != 0)
			@throw [OFSetItemAttributesFailedException
			    exceptionWithURL: URL
				  attributes: attributes
			     failedAttribute: attributeKey
				       errNo: errno];
	} else {
		struct _utimbuf times = {
699
700
701
702
703
704
705
706

707
708
709
710
711
712
713
691
692
693
694
695
696
697

698
699
700
701
702
703
704
705







-
+







			    exceptionWithURL: URL
				  attributes: attributes
			     failedAttribute: attributeKey
				       errNo: errno];
	}
#elif defined(OF_AMIGAOS)
	/* AmigaOS does not support access time. */
	of_time_interval_t modificationTime =
	OFTimeInterval modificationTime =
	    modificationDate.timeIntervalSince1970;
	struct Locale *locale;
	struct DateStamp date;

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

	if (modificationTime < 0)
735
736
737
738
739
740
741
742
743
744


745
746
747
748
749
750
751
727
728
729
730
731
732
733



734
735
736
737
738
739
740
741
742







-
-
-
+
+







# endif
		@throw [OFSetItemAttributesFailedException
		    exceptionWithURL: URL
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: retrieveError()];
#else
	of_time_interval_t lastAccessTime =
	    lastAccessDate.timeIntervalSince1970;
	of_time_interval_t modificationTime =
	OFTimeInterval lastAccessTime = lastAccessDate.timeIntervalSince1970;
	OFTimeInterval modificationTime =
	    modificationDate.timeIntervalSince1970;
	struct timeval times[2] = {
		{
			.tv_sec = (time_t)lastAccessTime,
			.tv_usec =
			    (int)((lastAccessTime - times[0].tv_sec) * 1000000)
		},
763
764
765
766
767
768
769
770

771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789

790
791
792
793
794
795
796
797
798
799
800





801
802
803
804
805
806

807
808
809
810
811
812
813
754
755
756
757
758
759
760

761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779

780
781
782
783
784
785
786





787
788
789
790
791
792
793
794
795
796

797
798
799
800
801
802
803
804







-
+


















-
+






-
-
-
-
-
+
+
+
+
+





-
+







		     failedAttribute: attributeKey
			       errNo: errno];
#endif
}

- (void)of_setPOSIXPermissions: (OFNumber *)permissions
		   ofItemAtURL: (OFURL *)URL
		    attributes: (of_file_attributes_t)attributes OF_DIRECT
		    attributes: (OFFileAttributes)attributes OF_DIRECT
{
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
	mode_t mode = (mode_t)permissions.unsignedLongValue;
	OFString *path = URL.fileSystemRepresentation;
	int status;

# ifdef OF_WINDOWS
	if ([OFSystemInfo isWindowsNT])
		status = _wchmod(path.UTF16String, mode);
	else
# endif
		status = chmod(
		    [path cStringWithEncoding: [OFLocale encoding]], mode);

	if (status != 0)
		@throw [OFSetItemAttributesFailedException
		    exceptionWithURL: URL
			  attributes: attributes
		     failedAttribute: of_file_attribute_key_posix_permissions
		     failedAttribute: OFFilePOSIXPermissions
			       errNo: errno];
#else
	OF_UNRECOGNIZED_SELECTOR
#endif
}

- (void)of_setOwner: (OFString *)owner
	   andGroup: (OFString *)group
	ofItemAtURL: (OFURL *)URL
       attributeKey: (of_file_attribute_key_t)attributeKey
	 attributes: (of_file_attributes_t)attributes OF_DIRECT
- (void)of_setOwnerAccountName: (OFString *)owner
      andGroupOwnerAccountName: (OFString *)group
		   ofItemAtURL: (OFURL *)URL
		  attributeKey: (OFFileAttributeKey)attributeKey
		    attributes: (OFFileAttributes)attributes OF_DIRECT
{
#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER
	OFString *path = URL.fileSystemRepresentation;
	uid_t uid = -1;
	gid_t gid = -1;
	of_string_encoding_t encoding;
	OFStringEncoding encoding;

	if (owner == nil && group == nil)
		@throw [OFInvalidArgumentException exception];

	encoding = [OFLocale encoding];

# ifdef OF_HAVE_THREADS
854
855
856
857
858
859
860
861
862

863
864
865

866
867

868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883


884
885

886
887
888
889
890
891
892
893
894
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
957

958
959
960
961
962
963
964
845
846
847
848
849
850
851


852
853
854

855
856

857
858
859
860
861
862
863
864
865
866
867
868
869
870
871


872
873
874

875
876
877
878












879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
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







-
-
+


-
+

-
+














-
-
+
+

-
+



-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+






-
+
-
-
+
-













-
+








-
+














-
+








-
+







		     failedAttribute: attributeKey
			       errNo: errno];
#else
	OF_UNRECOGNIZED_SELECTOR
#endif
}

- (void)setAttributes: (of_file_attributes_t)attributes
	  ofItemAtURL: (OFURL *)URL
- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURL: (OFURL *)URL
{
	void *pool = objc_autoreleasePoolPush();
	OFEnumerator OF_GENERIC(of_file_attribute_key_t) *keyEnumerator;
	OFEnumerator OF_GENERIC(OFFileAttributeKey) *keyEnumerator;
	OFEnumerator *objectEnumerator;
	of_file_attribute_key_t key;
	OFFileAttributeKey key;
	id object;
	OFDate *lastAccessDate, *modificationDate;

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

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

	keyEnumerator = [attributes keyEnumerator];
	objectEnumerator = [attributes objectEnumerator];

	while ((key = [keyEnumerator nextObject]) != nil &&
	    (object = [objectEnumerator nextObject]) != nil) {
		if ([key isEqual: of_file_attribute_key_modification_date] ||
		    [key isEqual: of_file_attribute_key_last_access_date])
		if ([key isEqual: OFFileModificationDate] ||
		    [key isEqual: OFFileLastAccessDate])
			continue;
		else if ([key isEqual: of_file_attribute_key_posix_permissions])
		else if ([key isEqual: OFFilePOSIXPermissions])
			[self of_setPOSIXPermissions: object
					 ofItemAtURL: URL
					  attributes: attributes];
		else if ([key isEqual: of_file_attribute_key_owner])
			[self of_setOwner: object
				 andGroup: nil
			      ofItemAtURL: URL
			     attributeKey: key
			       attributes: attributes];
		else if ([key isEqual: of_file_attribute_key_group])
			[self of_setOwner: nil
				 andGroup: object
			      ofItemAtURL: URL
			     attributeKey: key
			       attributes: attributes];
		else if ([key isEqual: OFFileOwnerAccountName])
			[self of_setOwnerAccountName: object
			    andGroupOwnerAccountName: nil
					 ofItemAtURL: URL
					attributeKey: key
					  attributes: attributes];
		else if ([key isEqual: OFFileGroupOwnerAccountName])
			[self of_setOwnerAccountName: nil
			    andGroupOwnerAccountName: object
					 ofItemAtURL: URL
					attributeKey: key
					  attributes: attributes];
		else
			@throw [OFNotImplementedException
			    exceptionWithSelector: _cmd
					   object: self];
	}

	lastAccessDate = [attributes
	lastAccessDate = [attributes objectForKey: OFFileLastAccessDate];
	    objectForKey: of_file_attribute_key_last_access_date];
	modificationDate = [attributes
	modificationDate = [attributes objectForKey: OFFileModificationDate];
	    objectForKey: of_file_attribute_key_modification_date];

	if (lastAccessDate != nil || modificationDate != nil)
		[self of_setLastAccessDate: lastAccessDate
		       andModificationDate: modificationDate
			       ofItemAtURL: URL
				attributes: attributes];

	objc_autoreleasePoolPop(pool);
}

- (bool)fileExistsAtURL: (OFURL *)URL
{
	void *pool = objc_autoreleasePoolPush();
	of_stat_t s;
	Stat s;
	bool ret;

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

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

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

	ret = S_ISREG(s.st_mode);

	objc_autoreleasePoolPop(pool);

	return ret;
}

- (bool)directoryExistsAtURL: (OFURL *)URL
{
	void *pool = objc_autoreleasePoolPush();
	of_stat_t s;
	Stat s;
	bool ret;

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

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

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

	ret = S_ISDIR(s.st_mode);

	objc_autoreleasePoolPop(pool);
1064
1065
1066
1067
1068
1069
1070
1071

1072
1073
1074
1075
1076
1077
1078
1052
1053
1054
1055
1056
1057
1058

1059
1060
1061
1062
1063
1064
1065
1066







-
+







				    exceptionWithObject: self
					requestedLength: 0
						  errNo: retrieveError()];
		} @finally {
			FindClose(handle);
		}
	} else {
		of_string_encoding_t encoding = [OFLocale encoding];
		OFStringEncoding encoding = [OFLocale encoding];
		WIN32_FIND_DATA fd;

		if ((handle = FindFirstFileA(
		    [path cStringWithEncoding: encoding], &fd)) ==
		    INVALID_HANDLE_VALUE)
			@throw [OFOpenItemFailedException
			    exceptionWithURL: URL
1104
1105
1106
1107
1108
1109
1110
1111

1112
1113
1114
1115
1116
1117
1118
1092
1093
1094
1095
1096
1097
1098

1099
1100
1101
1102
1103
1104
1105
1106







-
+







					requestedLength: 0
						  errNo: retrieveError()];
		} @finally {
			FindClose(handle);
		}
	}
#elif defined(OF_AMIGAOS)
	of_string_encoding_t encoding = [OFLocale encoding];
	OFStringEncoding encoding = [OFLocale encoding];
	BPTR lock;

	if ((lock = Lock([path cStringWithEncoding: encoding],
	    SHARED_LOCK)) == 0)
		@throw [OFOpenItemFailedException
		    exceptionWithURL: URL
				mode: nil
1174
1175
1176
1177
1178
1179
1180
1181

1182
1183
1184
1185
1186
1187
1188
1162
1163
1164
1165
1166
1167
1168

1169
1170
1171
1172
1173
1174
1175
1176







-
+







			    exceptionWithObject: self
				requestedLength: 0
					  errNo: retrieveError()];
	} @finally {
		UnLock(lock);
	}
#else
	of_string_encoding_t encoding = [OFLocale encoding];
	OFStringEncoding encoding = [OFLocale encoding];
	DIR *dir;
	if ((dir = opendir([path cStringWithEncoding: encoding])) == NULL)
		@throw [OFOpenItemFailedException exceptionWithURL: URL
							      mode: nil
							     errNo: errno];

# if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS)
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
1241
1242
1243
1244
1245
1246
1247

1248
1249
1250
1251
1252
1253
1254
1255
1256
1257

1258
1259
1260
1261
1262
1263
1264
1265







-
+









-
+







}

- (void)removeItemAtURL: (OFURL *)URL
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path;
	int error;
	of_stat_t s;
	Stat 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)
	if ((error = lstatWrapper(path, &s)) != 0)
		@throw [OFRemoveItemFailedException exceptionWithURL: URL
							       errNo: error];

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

		@try {
1356
1357
1358
1359
1360
1361
1362
1363

1364
1365
1366
1367
1368
1369
1370
1371
1372

1373
1374
1375
1376

1377
1378
1379
1380
1381
1382
1383
1344
1345
1346
1347
1348
1349
1350

1351
1352
1353
1354
1355
1356
1357
1358
1359

1360
1361
1362
1363

1364
1365
1366
1367
1368
1369
1370
1371







-
+








-
+



-
+







	    ![destination.scheme isEqual: _scheme])
		@throw [OFInvalidArgumentException exception];

	sourcePath = source.fileSystemRepresentation;
	destinationPath = destination.fileSystemRepresentation;

# ifndef OF_WINDOWS
	of_string_encoding_t encoding = [OFLocale encoding];
	OFStringEncoding encoding = [OFLocale encoding];

	if (link([sourcePath cStringWithEncoding: encoding],
	    [destinationPath cStringWithEncoding: encoding]) != 0)
		@throw [OFLinkFailedException
		    exceptionWithSourceURL: source
			    destinationURL: destination
				     errNo: errno];
# else
	if (func_CreateHardLinkW == NULL)
	if (createHardLinkWFuncPtr == NULL)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

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

1397
1398
1399
1400
1401
1402
1403
1404

1405
1406
1407
1408
1409
1410
1411
1412
1413

1414
1415
1416
1417


1418
1419
1420
1421
1422
1423
1424
1385
1386
1387
1388
1389
1390
1391

1392
1393
1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404

1405
1406
1407
1408
1409
1410
1411
1412
1413







-
+








-
+



-
+
+








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

	path = URL.fileSystemRepresentation;

# ifndef OF_WINDOWS
	of_string_encoding_t encoding = [OFLocale encoding];
	OFStringEncoding encoding = [OFLocale encoding];

	if (symlink([target cStringWithEncoding: encoding],
	    [path cStringWithEncoding: encoding]) != 0)
		@throw [OFCreateSymbolicLinkFailedException
		    exceptionWithURL: URL
			      target: target
			       errNo: errno];
# else
	if (func_CreateSymbolicLinkW == NULL)
	if (createSymbolicLinkWFuncPtr == NULL)
		@throw [OFNotImplementedException exceptionWithSelector: _cmd
								 object: self];

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

	objc_autoreleasePoolPop(pool);
1438
1439
1440
1441
1442
1443
1444
1445

1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464

1465
1466
1467
1468
1469
1470
1471
1427
1428
1429
1430
1431
1432
1433

1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452

1453
1454
1455
1456
1457
1458
1459
1460







-
+


















-
+







		    exceptionWithSourceURL: source
			    destinationURL: destination
				     errNo: EEXIST];

	pool = objc_autoreleasePoolPush();

#ifdef OF_AMIGAOS
	of_string_encoding_t encoding = [OFLocale encoding];
	OFStringEncoding 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);
	else {
# endif
		of_string_encoding_t encoding = [OFLocale encoding];
		OFStringEncoding encoding = [OFLocale encoding];

		status = rename([source.fileSystemRepresentation
		    cStringWithEncoding: encoding],
		    [destination.fileSystemRepresentation
		    cStringWithEncoding: encoding]);
# ifdef OF_WINDOWS
	}