ObjFW  Diff

Differences From Artifact [2c5d56a419]:

To Artifact [f5483886a4]:


35
36
37
38
39
40
41
42
43


44
45
46
47
48
49
50
35
36
37
38
39
40
41


42
43
44
45
46
47
48
49
50







-
-
+
+







#endif
#import "OFFileManager.h"
#import "OFLocale.h"
#import "OFNumber.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFSystemInfo.h"
#import "OFURL.h"
#import "OFURLHandler.h"
#import "OFURI.h"
#import "OFURIHandler.h"

#import "OFChangeCurrentDirectoryFailedException.h"
#import "OFCopyItemFailedException.h"
#import "OFCreateDirectoryFailedException.h"
#import "OFGetCurrentDirectoryFailedException.h"
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
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
308
309
310
311
312

313
314

315
316

317
318
319
320


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
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
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
308
309
310
311

312
313

314
315

316
317
318


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







-
+


-
+

-
+







-
+

-
+

-
+


-
-
+
+

-
+








-
+









-
+

-
+

-
+


-
-
+
+

-
+








-
+




-
+

-
+

-
+


-
-
+
+

-
+








-
+







-
+

-
+

-
+


-
-
+
+

-
+








-
+







-
+

-
+

-
+


-
-
+
+

-
+


-
+
-


-
+

-
-
+
+


-
+



-
+










-
+



-
+











-
-
+
+



-
-
-
-
+
+
+
+


-
+

-
-
-
+
+
+


-
-
-
-
+
+
+
+



-
+

-
+







-
-
+
+









-
+









-
+






-
+

-
+

-
+


-
-
+
+

-
+






-
+


-
-
+
+

-
-
+
+







#  endif

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

- (OFURL *)currentDirectoryURL
- (OFURI *)currentDirectoryURI
{
	void *pool = objc_autoreleasePoolPush();
	OFURL *ret;
	OFURI *ret;

	ret = [OFURL fileURLWithPath: self.currentDirectoryPath];
	ret = [OFURI fileURIWithPath: self.currentDirectoryPath];

	[ret retain];
	objc_autoreleasePoolPop(pool);
	return [ret autorelease];
}
#endif

- (OFFileAttributes)attributesOfItemAtURL: (OFURL *)URL
- (OFFileAttributes)attributesOfItemAtURI: (OFURI *)URI
{
	OFURLHandler *URLHandler;
	OFURIHandler *URIHandler;

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

	if ((URLHandler = [OFURLHandler handlerForURL: URL]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURL: URL];
	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	return [URLHandler attributesOfItemAtURL: URL];
	return [URIHandler attributesOfItemAtURI: URI];
}

#ifdef OF_HAVE_FILES
- (OFFileAttributes)attributesOfItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFFileAttributes ret;

	ret = [self attributesOfItemAtURL: [OFURL fileURLWithPath: path]];
	ret = [self attributesOfItemAtURI: [OFURI fileURIWithPath: path]];

	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}
#endif

- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURL: (OFURL *)URL
- (void)setAttributes: (OFFileAttributes)attributes ofItemAtURI: (OFURI *)URI
{
	OFURLHandler *URLHandler;
	OFURIHandler *URIHandler;

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

	if ((URLHandler = [OFURLHandler handlerForURL: URL]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURL: URL];
	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	[URLHandler setAttributes: attributes ofItemAtURL: URL];
	[URIHandler setAttributes: attributes ofItemAtURI: URI];
}

#ifdef OF_HAVE_FILES
- (void)setAttributes: (OFFileAttributes)attributes
	 ofItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	[self setAttributes: attributes
		ofItemAtURL: [OFURL fileURLWithPath: path]];
		ofItemAtURI: [OFURI fileURIWithPath: path]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (bool)fileExistsAtURL: (OFURL *)URL
- (bool)fileExistsAtURI: (OFURI *)URI
{
	OFURLHandler *URLHandler;
	OFURIHandler *URIHandler;

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

	if ((URLHandler = [OFURLHandler handlerForURL: URL]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURL: URL];
	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	return [URLHandler fileExistsAtURL: URL];
	return [URIHandler fileExistsAtURI: URI];
}

#ifdef OF_HAVE_FILES
- (bool)fileExistsAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	bool ret;

	ret = [self fileExistsAtURL: [OFURL fileURLWithPath: path]];
	ret = [self fileExistsAtURI: [OFURI fileURIWithPath: path]];

	objc_autoreleasePoolPop(pool);

	return ret;
}
#endif

- (bool)directoryExistsAtURL: (OFURL *)URL
- (bool)directoryExistsAtURI: (OFURI *)URI
{
	OFURLHandler *URLHandler;
	OFURIHandler *URIHandler;

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

	if ((URLHandler = [OFURLHandler handlerForURL: URL]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURL: URL];
	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	return [URLHandler directoryExistsAtURL: URL];
	return [URIHandler directoryExistsAtURI: URI];
}

#ifdef OF_HAVE_FILES
- (bool)directoryExistsAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	bool ret;

	ret = [self directoryExistsAtURL: [OFURL fileURLWithPath: path]];
	ret = [self directoryExistsAtURI: [OFURI fileURIWithPath: path]];

	objc_autoreleasePoolPop(pool);

	return ret;
}
#endif

- (void)createDirectoryAtURL: (OFURL *)URL
- (void)createDirectoryAtURI: (OFURI *)URI
{
	OFURLHandler *URLHandler;
	OFURIHandler *URIHandler;

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

	if ((URLHandler = [OFURLHandler handlerForURL: URL]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURL: URL];
	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	[URLHandler createDirectoryAtURL: URL];
	[URIHandler createDirectoryAtURI: URI];
}

- (void)createDirectoryAtURL: (OFURL *)URL
- (void)createDirectoryAtURI: (OFURI *)URI createParents: (bool)createParents
	       createParents: (bool)createParents
{
	void *pool = objc_autoreleasePoolPush();
	OFMutableURL *mutableURL;
	OFMutableURI *mutableURI;
	OFArray OF_GENERIC(OFString *) *components;
	OFMutableArray OF_GENERIC(OFURL *) *componentURLs;
	size_t componentURLsCount;
	OFMutableArray OF_GENERIC(OFURI *) *componentURIs;
	size_t componentURIsCount;
	ssize_t i;

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

	if (!createParents) {
		[self createDirectoryAtURL: URL];
		[self createDirectoryAtURI: URI];
		return;
	}

	/*
	 * Try blindly creating the directory first.
	 *
	 * The reason for this is that we might be sandboxed, so attempting to
	 * create any of the parent directories will fail, while creating the
	 * directory itself will work.
	 */
	if ([self directoryExistsAtURL: URL])
	if ([self directoryExistsAtURI: URI])
		return;

	@try {
		[self createDirectoryAtURL: URL];
		[self createDirectoryAtURI: URI];
		return;
	} @catch (OFCreateDirectoryFailedException *e) {
		/*
		 * If we didn't fail because any of the parents is missing,
		 * there is no point in trying to create the parents.
		 */
		if (e.errNo != ENOENT)
			@throw e;
	}

	/*
	 * Because we might be sandboxed (and for remote URLs don't even know
	 * anything at all), we generate the URL for every component. We then
	 * Because we might be sandboxed (and for remote URIs don't even know
	 * anything at all), we generate the URI for every component. We then
	 * iterate them in reverse order until we find the first existing
	 * directory, and then create subdirectories from there.
	 */
	mutableURL = [[URL mutableCopy] autorelease];
	mutableURL.URLEncodedPath = @"/";
	components = URL.pathComponents;
	componentURLs = [OFMutableArray arrayWithCapacity: components.count];
	mutableURI = [[URI mutableCopy] autorelease];
	mutableURI.percentEncodedPath = @"/";
	components = URI.pathComponents;
	componentURIs = [OFMutableArray arrayWithCapacity: components.count];

	for (OFString *component in components) {
		[mutableURL appendPathComponent: component];
		[mutableURI appendPathComponent: component];

		if (![mutableURL.URLEncodedPath isEqual: @"/"])
			[componentURLs addObject:
			    [[mutableURL copy] autorelease]];
		if (![mutableURI.percentEncodedPath isEqual: @"/"])
			[componentURIs addObject:
			    [[mutableURI copy] autorelease]];
	}

	componentURLsCount = componentURLs.count;
	for (i = componentURLsCount - 1; i > 0; i--) {
		if ([self directoryExistsAtURL:
		    [componentURLs objectAtIndex: i]])
	componentURIsCount = componentURIs.count;
	for (i = componentURIsCount - 1; i > 0; i--) {
		if ([self directoryExistsAtURI:
		    [componentURIs objectAtIndex: i]])
			break;
	}

	if (++i == (ssize_t)componentURLsCount) {
	if (++i == (ssize_t)componentURIsCount) {
		/*
		 * The URL exists, even though before we made sure it did not.
		 * The URI exists, even though before we made sure it did not.
		 * That means it was created in the meantime by something else,
		 * so we're done here.
		 */
		objc_autoreleasePoolPop(pool);
		return;
	}

	for (; i < (ssize_t)componentURLsCount; i++)
		[self createDirectoryAtURL: [componentURLs objectAtIndex: i]];
	for (; i < (ssize_t)componentURIsCount; i++)
		[self createDirectoryAtURI: [componentURIs objectAtIndex: i]];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_FILES
- (void)createDirectoryAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();

	[self createDirectoryAtURL: [OFURL fileURLWithPath: path]];
	[self createDirectoryAtURI: [OFURI fileURIWithPath: path]];

	objc_autoreleasePoolPop(pool);
}

- (void)createDirectoryAtPath: (OFString *)path
		createParents: (bool)createParents
{
	void *pool = objc_autoreleasePoolPush();

	[self createDirectoryAtURL: [OFURL fileURLWithPath: path]
	[self createDirectoryAtURI: [OFURI fileURIWithPath: path]
		     createParents: createParents];

	objc_autoreleasePoolPop(pool);
}
#endif

- (OFArray OF_GENERIC(OFURL *) *)contentsOfDirectoryAtURL: (OFURL *)URL
- (OFArray OF_GENERIC(OFURI *) *)contentsOfDirectoryAtURI: (OFURI *)URI
{
	OFURLHandler *URLHandler;
	OFURIHandler *URIHandler;

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

	if ((URLHandler = [OFURLHandler handlerForURL: URL]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURL: URL];
	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	return [URLHandler contentsOfDirectoryAtURL: URL];
	return [URIHandler contentsOfDirectoryAtURI: URI];
}

#ifdef OF_HAVE_FILES
- (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	OFArray OF_GENERIC(OFURL *) *URLs;
	OFArray OF_GENERIC(OFURI *) *URIs;
	OFMutableArray OF_GENERIC(OFString *) *ret;

	URLs = [self contentsOfDirectoryAtURL: [OFURL fileURLWithPath: path]];
	ret = [OFMutableArray arrayWithCapacity: URLs.count];
	URIs = [self contentsOfDirectoryAtURI: [OFURI fileURIWithPath: path]];
	ret = [OFMutableArray arrayWithCapacity: URIs.count];

	for (OFURL *URL in URLs)
		[ret addObject: URL.lastPathComponent];
	for (OFURI *URI in URIs)
		[ret addObject: URI.lastPathComponent];

	[ret makeImmutable];
	[ret retain];

	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
542
543
544
545
546
547
548
549

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
541
542
543
544
545
546
547

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







-
+



-
+








-
-
+
+





-
+


-
+








-
+

-
+

-
+


-
+

-
-
+
+



-
+


-
-
+
+






-
+


-
+













-
+




-
+









-
-
+
+





-
+

-
-
+
+


-
+











-
+

-
-
+
+







	if (status != 0)
		@throw [OFChangeCurrentDirectoryFailedException
		    exceptionWithPath: path
				errNo: errno];
# endif
}

- (void)changeCurrentDirectoryURL: (OFURL *)URL
- (void)changeCurrentDirectoryURI: (OFURI *)URI
{
	void *pool = objc_autoreleasePoolPush();

	[self changeCurrentDirectoryPath: URL.fileSystemRepresentation];
	[self changeCurrentDirectoryPath: URI.fileSystemRepresentation];

	objc_autoreleasePoolPop(pool);
}

- (void)copyItemAtPath: (OFString *)source toPath: (OFString *)destination
{
	void *pool = objc_autoreleasePoolPush();

	[self copyItemAtURL: [OFURL fileURLWithPath: source]
		      toURL: [OFURL fileURLWithPath: destination]];
	[self copyItemAtURI: [OFURI fileURIWithPath: source]
		      toURI: [OFURI fileURIWithPath: destination]];

	objc_autoreleasePoolPop(pool);
}
#endif

- (void)copyItemAtURL: (OFURL *)source toURL: (OFURL *)destination
- (void)copyItemAtURI: (OFURI *)source toURI: (OFURI *)destination
{
	void *pool;
	OFURLHandler *URLHandler;
	OFURIHandler *URIHandler;
	OFFileAttributes attributes;
	OFFileAttributeType type;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();

	if ((URLHandler = [OFURLHandler handlerForURL: source]) == nil)
	if ((URIHandler = [OFURIHandler handlerForURI: source]) == nil)
		@throw [OFUnsupportedProtocolException
		    exceptionWithURL: source];
		    exceptionWithURI: source];

	if ([URLHandler copyItemAtURL: source toURL: destination])
	if ([URIHandler copyItemAtURI: source toURI: destination])
		return;

	if ([self fileExistsAtURL: destination])
	if ([self fileExistsAtURI: destination])
		@throw [OFCopyItemFailedException
		    exceptionWithSourceURL: source
			    destinationURL: destination
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: EEXIST];

	@try {
		attributes = [self attributesOfItemAtURL: source];
		attributes = [self attributesOfItemAtURI: source];
	} @catch (OFGetItemAttributesFailedException *e) {
		@throw [OFCopyItemFailedException
		    exceptionWithSourceURL: source
			    destinationURL: destination
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: e.errNo];
	}

	type = attributes.fileType;

	if ([type isEqual: OFFileTypeDirectory]) {
		OFArray OF_GENERIC(OFURL *) *contents;
		OFArray OF_GENERIC(OFURI *) *contents;

		@try {
			[self createDirectoryAtURL: destination];
			[self createDirectoryAtURI: destination];

			@try {
				OFFileAttributeKey key = OFFilePOSIXPermissions;
				OFNumber *permissions =
				    [attributes objectForKey: key];
				OFFileAttributes destinationAttributes;

				if (permissions != nil) {
					destinationAttributes = [OFDictionary
					    dictionaryWithObject: permissions
							  forKey: key];
					[self
					    setAttributes: destinationAttributes
					      ofItemAtURL: destination];
					      ofItemAtURI: destination];
				}
			} @catch (OFNotImplementedException *e) {
			}

			contents = [self contentsOfDirectoryAtURL: source];
			contents = [self contentsOfDirectoryAtURI: source];
		} @catch (id e) {
			/*
			 * Only convert exceptions to OFCopyItemFailedException
			 * that have an errNo property. This covers all I/O
			 * related exceptions from the operations used to copy
			 * an item, all others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFCopyItemFailedException
				    exceptionWithSourceURL: source
					    destinationURL: destination
				    exceptionWithSourceURI: source
					    destinationURI: destination
						     errNo: [e errNo]];

			@throw e;
		}

		for (OFURL *item in contents) {
		for (OFURI *item in contents) {
			void *pool2 = objc_autoreleasePoolPush();
			OFURL *destinationURL = [destination
			    URLByAppendingPathComponent:
			OFURI *destinationURI = [destination
			    URIByAppendingPathComponent:
			    item.lastPathComponent];

			[self copyItemAtURL: item toURL: destinationURL];
			[self copyItemAtURI: item toURI: destinationURI];

			objc_autoreleasePoolPop(pool2);
		}
	} else if ([type isEqual: OFFileTypeRegular]) {
		size_t pageSize = [OFSystemInfo pageSize];
		OFStream *sourceStream = nil;
		OFStream *destinationStream = nil;
		char *buffer;

		buffer = OFAllocMemory(1, pageSize);
		@try {
			sourceStream = [OFURLHandler openItemAtURL: source
			sourceStream = [OFURIHandler openItemAtURI: source
							      mode: @"r"];
			destinationStream = [OFURLHandler
			    openItemAtURL: destination
			destinationStream = [OFURIHandler
			    openItemAtURI: destination
				     mode: @"w"];

			while (!sourceStream.atEndOfStream) {
				size_t length;

				length = [sourceStream
				    readIntoBuffer: buffer
684
685
686
687
688
689
690
691

692
693
694
695
696
697
698
699
700
701
702
703
704
705


706
707
708
709
710
711
712
713
714
715
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
743
744
745
746
747
748
749
750


751
752
753
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
805
806

807
808

809
810

811
812
813
814


815
816

817
818
819
820
821
822
823

824
825
826
827
828

829
830
831

832
833
834
835
836
837
838
839

840
841

842
843

844
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
683
684
685
686
687
688
689

690
691
692
693
694
695
696
697
698
699
700
701
702


703
704
705
706
707
708
709
710
711
712
713
714
715
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
743
744
745
746
747


748
749
750
751
752
753

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

805
806

807
808

809
810
811


812
813
814

815
816
817
818
819
820
821

822
823
824
825
826

827
828
829

830
831
832
833
834
835
836
837

838
839

840
841

842
843

844
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







-
+












-
-
+
+













-
+










-
-
+
+






-
-
+
+









-
-
+
+




-
+


-
+






-
+

-
+


-
+






-
+

-
-
+
+



-
+

-
+


-
-
+
+




-
+


-
-
+
+






-
+

-
+

-
+


-
-
+
+

-
+






-
+




-
+


-
+







-
+

-
+

-
+

-
+








-
-
+
+




-
+



-
+

-
+


-
+

-
-
+
+

-
+









-
+








				if (permissions != nil) {
					destinationAttributes = [OFDictionary
					    dictionaryWithObject: permissions
							  forKey: key];
					[self
					    setAttributes: destinationAttributes
					      ofItemAtURL: destination];
					      ofItemAtURI: destination];
				}
			} @catch (OFNotImplementedException *e) {
			}
		} @catch (id e) {
			/*
			 * Only convert exceptions to OFCopyItemFailedException
			 * that have an errNo property. This covers all I/O
			 * related exceptions from the operations used to copy
			 * an item, all others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFCopyItemFailedException
				    exceptionWithSourceURL: source
					    destinationURL: destination
				    exceptionWithSourceURI: source
					    destinationURI: destination
						     errNo: [e errNo]];

			@throw e;
		} @finally {
			[sourceStream close];
			[destinationStream close];
			OFFreeMemory(buffer);
		}
	} else if ([type isEqual: OFFileTypeSymbolicLink]) {
		@try {
			OFString *linkDestination =
			    attributes.fileSymbolicLinkDestination;

			[self createSymbolicLinkAtURL: destination
			[self createSymbolicLinkAtURI: destination
				  withDestinationPath: linkDestination];
		} @catch (id e) {
			/*
			 * Only convert exceptions to OFCopyItemFailedException
			 * that have an errNo property. This covers all I/O
			 * related exceptions from the operations used to copy
			 * an item, all others should be left as is.
			 */
			if ([e respondsToSelector: @selector(errNo)])
				@throw [OFCopyItemFailedException
				    exceptionWithSourceURL: source
					    destinationURL: destination
				    exceptionWithSourceURI: source
					    destinationURI: destination
						     errNo: [e errNo]];

			@throw e;
		}
	} else
		@throw [OFCopyItemFailedException
		    exceptionWithSourceURL: source
			    destinationURL: destination
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: EINVAL];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_HAVE_FILES
- (void)moveItemAtPath: (OFString *)source toPath: (OFString *)destination
{
	void *pool = objc_autoreleasePoolPush();
	[self moveItemAtURL: [OFURL fileURLWithPath: source]
		      toURL: [OFURL fileURLWithPath: destination]];
	[self moveItemAtURI: [OFURI fileURIWithPath: source]
		      toURI: [OFURI fileURIWithPath: destination]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)moveItemAtURL: (OFURL *)source toURL: (OFURL *)destination
- (void)moveItemAtURI: (OFURI *)source toURI: (OFURI *)destination
{
	void *pool;
	OFURLHandler *URLHandler;
	OFURIHandler *URIHandler;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	pool = objc_autoreleasePoolPush();

	if ((URLHandler = [OFURLHandler handlerForURL: source]) == nil)
	if ((URIHandler = [OFURIHandler handlerForURI: source]) == nil)
		@throw [OFUnsupportedProtocolException
		    exceptionWithURL: source];
		    exceptionWithURI: source];

	@try {
		if ([URLHandler moveItemAtURL: source toURL: destination])
		if ([URIHandler moveItemAtURI: source toURI: destination])
			return;
	} @catch (OFMoveItemFailedException *e) {
		if (e.errNo != EXDEV)
			@throw e;
	}

	if ([self fileExistsAtURL: destination])
	if ([self fileExistsAtURI: destination])
		@throw [OFMoveItemFailedException
		    exceptionWithSourceURL: source
			    destinationURL: destination
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: EEXIST];

	@try {
		[self copyItemAtURL: source toURL: destination];
		[self copyItemAtURI: source toURI: destination];
	} @catch (OFCopyItemFailedException *e) {
		[self removeItemAtURL: destination];
		[self removeItemAtURI: destination];

		@throw [OFMoveItemFailedException
		    exceptionWithSourceURL: source
			    destinationURL: destination
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: e.errNo];
	}

	@try {
		[self removeItemAtURL: source];
		[self removeItemAtURI: source];
	} @catch (OFRemoveItemFailedException *e) {
		@throw [OFMoveItemFailedException
		    exceptionWithSourceURL: source
			    destinationURL: destination
		    exceptionWithSourceURI: source
			    destinationURI: destination
				     errNo: e.errNo];
	}

	objc_autoreleasePoolPop(pool);
}

- (void)removeItemAtURL: (OFURL *)URL
- (void)removeItemAtURI: (OFURI *)URI
{
	OFURLHandler *URLHandler;
	OFURIHandler *URIHandler;

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

	if ((URLHandler = [OFURLHandler handlerForURL: URL]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURL: URL];
	if ((URIHandler = [OFURIHandler handlerForURI: URI]) == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	[URLHandler removeItemAtURL: URL];
	[URIHandler removeItemAtURI: URI];
}

#ifdef OF_HAVE_FILES
- (void)removeItemAtPath: (OFString *)path
{
	void *pool = objc_autoreleasePoolPush();
	[self removeItemAtURL: [OFURL fileURLWithPath: path]];
	[self removeItemAtURI: [OFURI fileURIWithPath: path]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)linkItemAtURL: (OFURL *)source toURL: (OFURL *)destination
- (void)linkItemAtURI: (OFURI *)source toURI: (OFURI *)destination
{
	void *pool = objc_autoreleasePoolPush();
	OFURLHandler *URLHandler;
	OFURIHandler *URIHandler;

	if (source == nil || destination == nil)
		@throw [OFInvalidArgumentException exception];

	if (![destination.scheme isEqual: source.scheme])
		@throw [OFInvalidArgumentException exception];

	URLHandler = [OFURLHandler handlerForURL: source];
	URIHandler = [OFURIHandler handlerForURI: source];

	if (URLHandler == nil)
	if (URIHandler == nil)
		@throw [OFUnsupportedProtocolException
		    exceptionWithURL: source];
		    exceptionWithURI: source];

	[URLHandler linkItemAtURL: source toURL: destination];
	[URIHandler linkItemAtURI: source toURI: destination];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS
- (void)linkItemAtPath: (OFString *)source toPath: (OFString *)destination
{
	void *pool = objc_autoreleasePoolPush();
	[self linkItemAtURL: [OFURL fileURLWithPath: source]
		      toURL: [OFURL fileURLWithPath: destination]];
	[self linkItemAtURI: [OFURI fileURIWithPath: source]
		      toURI: [OFURI fileURIWithPath: destination]];
	objc_autoreleasePoolPop(pool);
}
#endif

- (void)createSymbolicLinkAtURL: (OFURL *)URL
- (void)createSymbolicLinkAtURI: (OFURI *)URI
	    withDestinationPath: (OFString *)target
{
	void *pool = objc_autoreleasePoolPush();
	OFURLHandler *URLHandler;
	OFURIHandler *URIHandler;

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

	URLHandler = [OFURLHandler handlerForURL: URL];
	URIHandler = [OFURIHandler handlerForURI: URI];

	if (URLHandler == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURL: URL];
	if (URIHandler == nil)
		@throw [OFUnsupportedProtocolException exceptionWithURI: URI];

	[URLHandler createSymbolicLinkAtURL: URL withDestinationPath: target];
	[URIHandler createSymbolicLinkAtURI: URI withDestinationPath: target];

	objc_autoreleasePoolPop(pool);
}

#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
- (void)createSymbolicLinkAtPath: (OFString *)path
	     withDestinationPath: (OFString *)target
{
	void *pool = objc_autoreleasePoolPush();
	[self createSymbolicLinkAtURL: [OFURL fileURLWithPath: path]
	[self createSymbolicLinkAtURI: [OFURI fileURIWithPath: path]
		  withDestinationPath: target];
	objc_autoreleasePoolPop(pool);
}
#endif
@end

@implementation OFDefaultFileManager