215
// Directory operations
340
* Changes the current directory used for all subsequent operations.<br />
341
* All non-absolute paths are interpreted relative to this directory.<br />
342
* The current directory is set on a per-task basis, so the current
343
* directory for other file manager instances will also be changed
217
346
- (BOOL) changeCurrentDirectoryPath: (NSString*)path
219
const char* cpath = [self fileSystemRepresentationWithPath: path];
348
const _CHAR *lpath = OS2LOCAL(self, path);
221
349
#if defined(__MINGW__)
222
return SetCurrentDirectory(cpath) == TRUE ? YES : NO;
224
return (chdir(cpath) == 0);
350
return SetCurrentDirectory(lpath) == TRUE ? YES : NO;
352
return (chdir(lpath) == 0) ? YES : NO;
357
* Change the attributes of the file at path to those specified.<br />
358
* Returns YES if all requested changes were made (or if the dictionary
359
* was nil or empty, so no changes were requested), NO otherwise.<br />
360
* On failure, some fo the requested changes may have taken place.<br />
362
- (BOOL) changeFileAttributes: (NSDictionary*)attributes atPath: (NSString*)path
364
const _CHAR *lpath = 0;
370
if (attributes == nil)
374
lpath = OS2LOCAL(defaultManager, path);
377
num = [attributes fileOwnerAccountID];
378
if (num != NSNotFound)
380
if (chown(lpath, num, -1) != 0)
383
str = [NSString stringWithFormat:
384
@"Unable to change NSFileOwnerAccountID to '%u' - %s",
385
num, GSLastErrorStr(errno)];
386
ASSIGN(_lastError, str);
391
if ((str = [attributes fileOwnerAccountName]) != nil)
395
struct passwd *pw = getpwnam([str cString]);
399
ok = (chown(lpath, pw->pw_uid, -1) == 0);
400
chown(lpath, -1, pw->pw_gid);
406
str = [NSString stringWithFormat:
407
@"Unable to change NSFileOwnerAccountName to '%@' - %s",
408
str, GSLastErrorStr(errno)];
409
ASSIGN(_lastError, str);
414
num = [attributes fileGroupOwnerAccountID];
415
if (num != NSNotFound)
417
if (chown(lpath, -1, num) != 0)
420
str = [NSString stringWithFormat:
421
@"Unable to change NSFileGroupOwnerAccountID to '%u' - %s",
422
num, GSLastErrorStr(errno)];
423
ASSIGN(_lastError, str);
426
else if ((str = [attributes fileGroupOwnerAccountName]) != nil)
430
struct group *gp = getgrnam([str cString]);
434
if (chown(lpath, -1, gp->gr_gid) == 0)
441
str = [NSString stringWithFormat:
442
@"Unable to change NSFileGroupOwnerAccountName to '%@' - %s",
443
str, GSLastErrorStr(errno)];
444
ASSIGN(_lastError, str);
447
#endif /* __MINGW__ */
449
num = [attributes filePosixPermissions];
450
if (num != NSNotFound)
452
if (_CHMOD(lpath, num) != 0)
455
str = [NSString stringWithFormat:
456
@"Unable to change NSFilePosixPermissions to '%o' - %s",
457
num, GSLastErrorStr(errno)];
458
ASSIGN(_lastError, str);
462
date = [attributes fileModificationDate];
468
#if defined(__WIN32__) || defined(_POSIX_VERSION)
474
if (_STAT(lpath, &sb) != 0)
478
#if defined(__WIN32__)
479
else if (sb.st_mode & _S_IFDIR)
481
ok = YES; // Directories don't have modification times.
486
#if defined(__WIN32__) || defined(_POSIX_VERSION)
487
ub.actime = sb.st_atime;
488
ub.modtime = [date timeIntervalSince1970];
489
ok = (_UTIME(lpath, &ub) == 0);
492
ub[1] = [date timeIntervalSince1970];
493
ok = (_UTIME(lpath, ub) == 0);
499
str = [NSString stringWithFormat:
500
@"Unable to change NSFileModificationDate to '%@' - %s",
501
date, GSLastErrorStr(errno)];
502
ASSIGN(_lastError, str);
510
* Returns an array of path components suitably modified for display
511
* to the end user. This modification may render the returned strings
512
* unusable for path manipulation, so you should work with two arrays ...
513
* one returned by this method (for display tio the user), and a
514
* parallel one returned by [NSString-pathComponents] (for path
517
- (NSArray*) componentsToDisplayForPath: (NSString*)path
519
return [path pathComponents];
523
* Reads the file at path an returns its contents as an NSData object.<br />
524
* If an error occurs or if path specifies a directory etc then nil is
527
- (NSData*) contentsAtPath: (NSString*)path
529
return [NSData dataWithContentsOfFile: path];
533
* Returns YES if the contents of the file or directory at path1 are the same
534
* as those at path2.<br />
535
* If path1 and path2 are files, this is a simple comparison. If they are
536
* directories, the contents of the files in those subdirectories are
537
* compared recursively.<br />
538
* Symbolic links are not followed.<br />
539
* A comparison checks first file identity, then size, then content.
541
- (BOOL) contentsEqualAtPath: (NSString*)path1 andPath: (NSString*)path2
547
if ([path1 isEqual: path2])
549
d1 = [self fileAttributesAtPath: path1 traverseLink: NO];
550
d2 = [self fileAttributesAtPath: path2 traverseLink: NO];
552
if ([t isEqual: [d2 fileType]] == NO)
556
if ([t isEqual: NSFileTypeRegular])
558
if ([d1 fileSize] == [d2 fileSize])
560
NSData *c1 = [NSData dataWithContentsOfFile: path1];
561
NSData *c2 = [NSData dataWithContentsOfFile: path2];
563
if ([c1 isEqual: c2])
570
else if ([t isEqual: NSFileTypeDirectory])
572
NSArray *a1 = [self directoryContentsAtPath: path1];
573
NSArray *a2 = [self directoryContentsAtPath: path2];
574
unsigned index, count = [a1 count];
577
if ([a1 isEqual: a2] == NO)
581
for (index = 0; ok == YES && index < count; index++)
583
NSString *n = [a1 objectAtIndex: index];
586
CREATE_AUTORELEASE_POOL(pool);
588
p1 = [path1 stringByAppendingPathComponent: n];
589
p2 = [path2 stringByAppendingPathComponent: n];
590
d1 = [self fileAttributesAtPath: p1 traverseLink: NO];
591
d2 = [self fileAttributesAtPath: p2 traverseLink: NO];
593
if ([t isEqual: [d2 fileType]] == NO)
597
else if ([t isEqual: NSFileTypeDirectory])
599
ok = [self contentsEqualAtPath: p1 andPath: p2];
612
* Creates a new directory, and sets its attributes as specified.<br />
613
* Creates other directories in the path as necessary.<br />
614
* Returns YES on success, NO on failure.
228
616
- (BOOL) createDirectoryAtPath: (NSString*)path
229
617
attributes: (NSDictionary*)attributes
231
619
#if defined(__MINGW__)
232
NSEnumerator *paths = [[path pathComponents] objectEnumerator];
234
NSString *completePath = nil;
620
NSEnumerator *paths = [[path pathComponents] objectEnumerator];
622
NSString *completePath = nil;
625
char dirpath[PATH_MAX+1];
626
struct _STATB statbuf;
628
NSDictionary *needChown = nil;
631
/* This is consistent with MacOSX - just return NO for an invalid path. */
632
if ([path length] == 0)
635
#if defined(__MINGW__)
236
636
while ((subPath = [paths nextObject]))
239
640
if (completePath == nil)
240
641
completePath = subPath;
242
completePath = [completePath stringByAppendingPathComponent:subPath];
643
completePath = [completePath stringByAppendingPathComponent: subPath];
244
if ([self fileExistsAtPath:completePath isDirectory:&isDir])
645
if ([self fileExistsAtPath: completePath isDirectory: &isDir])
247
648
NSLog(@"WARNING: during creation of directory %@:"
248
649
@" sub path %@ exists, but is not a directory !",
249
650
path, completePath);
254
cpath = [self fileSystemRepresentationWithPath: completePath];
255
if (CreateDirectory(cpath, NULL) == FALSE)
656
lpath = OS2LOCAL(self, completePath);
657
if (CreateDirectory(lpath, 0) == FALSE)
260
// change attributes of last directory
261
return [self changeFileAttributes: attributes atPath: path];
265
char dirpath[PATH_MAX+1];
268
NSDictionary *needChown = nil;
271
667
* If there is no file owner specified, and we are running setuid to
272
668
* root, then we assume we need to change ownership to correct user.
274
if ([attributes objectForKey: NSFileOwnerAccountName] == nil
275
&& [attributes objectForKey: NSFileOwnerAccountNumber] == nil
276
&& geteuid() == 0 && [@"root" isEqualToString: NSUserName()] == NO)
670
if (attributes == nil || ([attributes fileOwnerAccountID] == NSNotFound
671
&& [attributes fileOwnerAccountName] == nil))
278
needChown = [NSDictionary dictionaryWithObjectsAndKeys:
279
NSFileOwnerAccountName, NSUserName(), nil];
673
if (geteuid() == 0 && [@"root" isEqualToString: NSUserName()] == NO)
675
needChown = [NSDictionary dictionaryWithObjectsAndKeys:
676
NSFileOwnerAccountName, NSUserName(), nil];
282
cpath = [self fileSystemRepresentationWithPath: path];
679
lpath = [self fileSystemRepresentationWithPath: path];
284
681
if (len > PATH_MAX) // name too long
286
683
ASSIGN(_lastError, @"Could not create directory - name too long");
290
if (strcmp(cpath, "/") == 0 || len == 0) // cannot use "/" or ""
687
if (strcmp(lpath, "/") == 0 || len == 0) // cannot use "/" or ""
292
689
ASSIGN(_lastError, @"Could not create directory - no name given");
296
strcpy(dirpath, cpath);
693
strcpy(dirpath, lpath);
297
694
dirpath[len] = '\0';
298
695
if (dirpath[len-1] == '/')
299
696
dirpath[len-1] = '\0';
358
756
while (cur < len);
361
758
#endif /* !MINGW */
760
// change attributes of last directory
761
if ([attributes count] == 0)
765
return [self changeFileAttributes: attributes atPath: path];
769
* Creates a new file, and sets its attributes as specified.<br />
770
* Initialises the file content with the specified data.<br />
771
* Returns YES on success, NO on failure.
773
- (BOOL) createFileAtPath: (NSString*)path
774
contents: (NSData*)contents
775
attributes: (NSDictionary*)attributes
777
#if defined(__MINGW__)
778
const _CHAR *lpath = OS2LOCAL(self, path);
781
DWORD len = [contents length];
789
/* This is consitent with MacOSX - just return NO for an invalid path. */
790
if ([path length] == 0)
793
#if defined(__MINGW__)
794
fh = CreateFile(lpath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
795
FILE_ATTRIBUTE_NORMAL, 0);
796
if (fh == INVALID_HANDLE_VALUE)
804
WriteFile(fh, [contents bytes], len, &written, 0);
807
if (attributes != nil
808
&& [self changeFileAttributes: attributes atPath: path] == NO)
815
lpath = [self fileSystemRepresentationWithPath: path];
817
fd = open(lpath, GSBINIO|O_WRONLY|O_TRUNC|O_CREAT, 0644);
822
if (attributes != nil
823
&& [self changeFileAttributes: attributes atPath: path] == NO)
830
* If there is no file owner specified, and we are running setuid to
831
* root, then we assume we need to change ownership to correct user.
833
if (attributes == nil || ([attributes fileOwnerAccountID] == NSNotFound
834
&& [attributes fileOwnerAccountName] == nil))
836
if (geteuid() == 0 && [@"root" isEqualToString: NSUserName()] == NO)
838
attributes = [NSDictionary dictionaryWithObjectsAndKeys:
839
NSFileOwnerAccountName, NSUserName(), nil];
840
if (![self changeFileAttributes: attributes atPath: path])
842
NSLog(@"Failed to change ownership of '%@' to '%@'",
847
len = [contents length];
850
written = write(fd, [contents bytes], len);
858
return written == len;
862
* Returns the current working directory used by all instance of the file
863
* manager in the current task.
364
865
- (NSString*) currentDirectoryPath
867
NSString *currentDir = nil;
869
#if defined(__MINGW__)
870
int len = GetCurrentDirectory(0, 0);
873
_CHAR *lpath = (_CHAR*)calloc(len+10,sizeof(_CHAR));
877
if (GetCurrentDirectory(len, lpath)>0)
882
path = [NSString stringWithCharacters: lpath length: len];
884
path = [NSString stringWithCString: lpath length: len];
887
currentDir = [self openStepPathFromLocal: path];
366
893
char path[PATH_MAX];
368
#if defined(__MINGW__)
369
if (GetCurrentDirectory(PATH_MAX, path) > PATH_MAX)
372
894
#ifdef HAVE_GETCWD
373
if (getcwd(path, PATH_MAX-1) == NULL)
895
if (getcwd(path, PATH_MAX-1) == 0)
376
if (getwd(path) == NULL)
898
if (getwd(path) == 0)
378
900
#endif /* HAVE_GETCWD */
901
currentDir = [self stringWithFileSystemRepresentation: path
902
length: strlen(path)];
379
903
#endif /* !MINGW */
381
return [self stringWithFileSystemRepresentation: path length: strlen(path)];
909
* Copies the file or directory at source to destination, using a
910
* handler object which should respond to
911
* [NSObject-fileManager:willProcessPath:] and
912
* [NSObject-fileManager:shouldProceedAfterError:] messages.<br />
913
* Will not copy to a destination which already exists.
386
915
- (BOOL) copyPath: (NSString*)source
387
916
toPath: (NSString*)destination
391
919
NSDictionary *attrs;
392
920
NSString *fileType;
394
attrs = [self _attributesAtPath: source traverseLink: NO forCopy: YES];
922
if ([self fileExistsAtPath: destination] == YES)
926
attrs = [self fileAttributesAtPath: source traverseLink: NO];
395
927
if (attrs == nil)
399
fileExists = [self fileExistsAtPath: destination];
404
fileType = [attrs objectForKey: NSFileType];
931
fileType = [attrs fileType];
405
932
if ([fileType isEqualToString: NSFileTypeDirectory] == YES)
407
934
/* If destination directory is a descendant of source directory copying
652
1271
result = [self removeFileAtPath: next handler: handler];
654
1273
if (result == NO)
658
if (rmdir([path fileSystemRepresentation]) < 0)
664
NSMutableDictionary *info;
666
info = [[NSMutableDictionary alloc] initWithCapacity: 3];
667
[info setObject: path forKey: @"Path"];
668
[info setObject: [NSString stringWithCString:
669
GSLastErrorStr(errno)]
671
result = [handler fileManager: self
672
shouldProceedAfterError: info];
1279
if (_RMDIR(OS2LOCAL(self, path)) < 0)
1281
return [self _proceedAccordingToHandler: handler
1282
forError: [NSString stringWithCString: GSLastErrorStr (errno)]
684
- (BOOL) createFileAtPath: (NSString*)path
685
contents: (NSData*)contents
686
attributes: (NSDictionary*)attributes
688
const char *cpath = [self fileSystemRepresentationWithPath: path];
690
#if defined(__MINGW__)
693
DWORD len = [contents length];
695
fh = CreateFile(cpath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
696
FILE_ATTRIBUTE_NORMAL, 0);
697
if (fh == INVALID_HANDLE_VALUE)
706
WriteFile(fh, [contents bytes], len, &written, NULL);
709
if ([self changeFileAttributes: attributes atPath: path] == NO)
719
fd = open(cpath, GSBINIO|O_WRONLY|O_TRUNC|O_CREAT, 0644);
724
if ([self changeFileAttributes: attributes atPath: path] == NO)
731
* If there is no file owner specified, and we are running setuid to
732
* root, then we assume we need to change ownership to correct user.
734
if ([attributes objectForKey: NSFileOwnerAccountName] == nil
735
&& [attributes objectForKey: NSFileOwnerAccountNumber] == nil
736
&& geteuid() == 0 && [@"root" isEqualToString: NSUserName()] == NO)
738
attributes = [NSDictionary dictionaryWithObjectsAndKeys:
739
NSFileOwnerAccountName, NSUserName(), nil];
740
if (![self changeFileAttributes: attributes atPath: path])
742
NSLog(@"Failed to change ownership of '%@' to '%@'",
747
len = [contents length];
750
written = write(fd, [contents bytes], len);
758
return written == len;
761
// Getting and comparing file contents
763
- (NSData*) contentsAtPath: (NSString*)path
765
return [NSData dataWithContentsOfFile: path];
768
- (BOOL) contentsEqualAtPath: (NSString*)path1 andPath: (NSString*)path2
774
if ([path1 isEqual: path2])
776
d1 = [self fileAttributesAtPath: path1 traverseLink: NO];
777
d2 = [self fileAttributesAtPath: path2 traverseLink: NO];
778
t = [d1 objectForKey: NSFileType];
779
if ([t isEqual: [d2 objectForKey: NSFileType]] == NO)
781
if ([t isEqual: NSFileTypeRegular])
783
id s1 = [d1 objectForKey: NSFileSize];
784
id s2 = [d2 objectForKey: NSFileSize];
786
if ([s1 isEqual: s2] == YES)
788
NSData *c1 = [NSData dataWithContentsOfFile: path1];
789
NSData *c2 = [NSData dataWithContentsOfFile: path2];
791
if ([c1 isEqual: c2])
796
else if ([t isEqual: NSFileTypeDirectory])
798
NSArray *a1 = [self directoryContentsAtPath: path1];
799
NSArray *a2 = [self directoryContentsAtPath: path2];
800
unsigned index, count = [a1 count];
803
if ([a1 isEqual: a2] == NO)
806
for (index = 0; ok == YES && index < count; index++)
808
NSString *n = [a1 objectAtIndex: index];
811
CREATE_AUTORELEASE_POOL(pool);
813
p1 = [path1 stringByAppendingPathComponent: n];
814
p2 = [path2 stringByAppendingPathComponent: n];
815
d1 = [self fileAttributesAtPath: p1 traverseLink: NO];
816
d2 = [self fileAttributesAtPath: p2 traverseLink: NO];
817
t = [d1 objectForKey: NSFileType];
818
if ([t isEqual: [d2 objectForKey: NSFileType]] == NO)
822
else if ([t isEqual: NSFileTypeDirectory])
824
ok = [self contentsEqualAtPath: p1 andPath: p2];
834
// Determining access to files
1293
* Returns YES if a file (or directory etc) exists at the specified path.
836
1295
- (BOOL) fileExistsAtPath: (NSString*)path
838
return [self fileExistsAtPath: path isDirectory: NULL];
1297
return [self fileExistsAtPath: path isDirectory: 0];
1301
* Returns YES if a file (or directory etc) exists at the specified path.<br />
1302
* If the isDirectory argument is not a nul pointer, stores a flag
1303
* in the location it points to, indicating whether the file is a
1304
* directory or not.<br />
841
1306
- (BOOL) fileExistsAtPath: (NSString*)path isDirectory: (BOOL*)isDirectory
843
const char* cpath = [self fileSystemRepresentationWithPath: path];
845
if (cpath == 0 || *cpath == '\0')
1308
const _CHAR *lpath = OS2LOCAL(self, path);
1310
if (isDirectory != 0)
1315
if (lpath == 0 || *lpath == _NUL)
851
1320
#if defined(__MINGW__)
854
res = GetFileAttributes(cpath);
1324
res = GetFileAttributes(lpath);
855
1325
if (res == WIN32ERR)
863
1333
*isDirectory = YES;
874
if (stat(cpath, &statbuf) != 0)
1340
struct _STATB statbuf;
1342
if (_STAT(lpath, &statbuf) != 0)
877
1347
if (isDirectory)
879
*isDirectory = ((statbuf.st_mode & S_IFMT) == S_IFDIR);
1349
if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
883
1357
#endif /* MINGW */
1361
* Returns YES if a file (or directory etc) exists at the specified path
887
1364
- (BOOL) isReadableFileAtPath: (NSString*)path
889
const char* cpath = [self fileSystemRepresentationWithPath: path];
1366
const _CHAR* lpath = OS2LOCAL(self, path);
891
if (cpath == 0 || *cpath == '\0')
1368
if (lpath == 0 || *lpath == _NUL)
895
1373
#if defined(__MINGW__)
896
DWORD res= GetFileAttributes(cpath);
1375
DWORD res = GetFileAttributes(lpath);
898
1377
if (res == WIN32ERR)
902
return (access(cpath, R_OK) == 0);
1385
if (access(lpath, R_OK) == 0)
1395
* Returns YES if a file (or directory etc) exists at the specified path
907
1398
- (BOOL) isWritableFileAtPath: (NSString*)path
909
const char* cpath = [self fileSystemRepresentationWithPath: path];
1400
const _CHAR* lpath = OS2LOCAL(self, path);
911
if (cpath == 0 || *cpath == '\0')
1402
if (lpath == 0 || *lpath == _NUL)
915
1407
#if defined(__MINGW__)
916
DWORD res= GetFileAttributes(cpath);
1409
DWORD res= GetFileAttributes(lpath);
918
1411
if (res == WIN32ERR)
920
return (res & FILE_ATTRIBUTE_READONLY) ? NO : YES;
1415
if (res & FILE_ATTRIBUTE_READONLY)
922
return (access(cpath, W_OK) == 0);
1423
if (access(lpath, W_OK) == 0)
1433
* Returns YES if a file (or directory etc) exists at the specified path
1434
* and is executable (if a directory is executable, you can access its
927
1437
- (BOOL) isExecutableFileAtPath: (NSString*)path
929
const char* cpath = [self fileSystemRepresentationWithPath: path];
1439
const _CHAR* lpath = OS2LOCAL(self, path);
931
if (cpath == 0 || *cpath == '\0')
1441
if (lpath == 0 || *lpath == _NUL)
935
1446
#if defined(__MINGW__)
936
DWORD res= GetFileAttributes(cpath);
937
int len = strlen(cpath);
1448
DWORD res= GetFileAttributes(lpath);
939
1450
if (res == WIN32ERR)
941
if (len > 4 && strcmp(&cpath[len-4], ".exe") == 0)
1454
if ([[[path pathExtension] lowercaseString] isEqualToString: @"exe"])
943
1458
/* FIXME: On unix, directory accessable == executable, so we simulate that
944
here for Windows. Is there a better check for directory access? */
1459
here for Windows. Is there a better check for directory access? */
945
1460
if (res & FILE_ATTRIBUTE_DIRECTORY)
949
return (access(cpath, X_OK) == 0);
1468
if (access(lpath, X_OK) == 0)
1478
* Returns YES if a file (or directory etc) exists at the specified path
954
1481
- (BOOL) isDeletableFileAtPath: (NSString*)path
956
const char* cpath = [self fileSystemRepresentationWithPath: path];
1483
const _CHAR* lpath = OS2LOCAL(self, path);
958
if (cpath == 0 || *cpath == '\0')
1485
if (lpath == 0 || *lpath == _NUL)
962
// TODO - handle directories
963
1490
#if defined(__MINGW__)
964
DWORD res= GetFileAttributes(cpath);
1492
// TODO - handle directories
1493
DWORD res= GetFileAttributes(lpath);
966
1495
if (res == WIN32ERR)
968
1499
return (res & FILE_ATTRIBUTE_READONLY) ? NO : YES;
970
cpath = [self fileSystemRepresentationWithPath:
971
[path stringByDeletingLastPathComponent]];
973
return (access(cpath, X_OK || W_OK) != 0);
1503
// TODO - handle directories
1504
path = [path stringByDeletingLastPathComponent];
1505
if ([path length] == 0)
1509
lpath = OS2LOCAL(self, path);
1511
if (access(lpath, X_OK | W_OK) == 0)
1522
* If a file (or directory etc) exists at the specified path, and can be
1523
* queried for its attributes, this method returns a dictionary containing
1524
* the various attributes of that file. Otherwise nil is returned.<br />
1525
* If the flag is NO and the file is a symbolic link, the attributes of
1526
* the link itself (rather than the file it points to) are returned.<br />
1528
* The dictionary keys for attributes are -
1531
* <term><code>NSFileAppendOnly</code></term>
1532
* <desc>NSNumber ... boolean</desc>
1533
* <term><code>NSFileCreationDate</code></term>
1534
* <desc>NSDate when the file was created (if supported)</desc>
1535
* <term><code>NSFileDeviceIdentifier</code></term>
1536
* <desc>NSNumber (identifies the device on which the file is stored)</desc>
1537
* <term><code>NSFileExtensionHidden</code></term>
1538
* <desc>NSNumber ... boolean</desc>
1539
* <term><code>NSFileGroupOwnerAccountName</code></term>
1540
* <desc>NSString name of the file group</desc>
1541
* <term><code>NSFileGroupOwnerAccountID</code></term>
1542
* <desc>NSNumber ID of the file group</desc>
1543
* <term><code>NSFileHFSCreatorCode</code></term>
1544
* <desc>NSNumber not used</desc>
1545
* <term><code>NSFileHFSTypeCode</code></term>
1546
* <desc>NSNumber not used</desc>
1547
* <term><code>NSFileImmutable</code></term>
1548
* <desc>NSNumber ... boolean</desc>
1549
* <term><code>NSFileModificationDate</code></term>
1550
* <desc>NSDate when the file was last modified</desc>
1551
* <term><code>NSFileOwnerAccountName</code></term>
1552
* <desc>NSString name of the file owner</desc>
1553
* <term><code>NSFileOwnerAccountID</code></term>
1554
* <desc>NSNumber ID of the file owner</desc>
1555
* <term><code>NSFilePosixPermissions</code></term>
1556
* <desc>NSNumber posix access permissions mask</desc>
1557
* <term><code>NSFileReferenceCount</code></term>
1558
* <desc>NSNumber number of links to this file</desc>
1559
* <term><code>NSFileSize</code></term>
1560
* <desc>NSNumber size of the file in bytes</desc>
1561
* <term><code>NSFileSystemFileNumber</code></term>
1562
* <desc>NSNumber the identifier for the file on the filesystem</desc>
1563
* <term><code>NSFileSystemNumber</code></term>
1564
* <desc>NSNumber the filesystem on which the file is stored</desc>
1565
* <term><code>NSFileType</code></term>
1566
* <desc>NSString the type of file</desc>
1569
* The [NSDictionary] class also has a set of convenience accessor methods
1570
* which enable you to get at file attribute information more efficiently
1571
* than using the keys above to extract it. You should generally
1572
* use the accessor methods where they are available.
1575
* <item>[NSDictionary-fileCreationDate]</item>
1576
* <item>[NSDictionary-fileExtensionHidden]</item>
1577
* <item>[NSDictionary-fileHFSCreatorCode]</item>
1578
* <item>[NSDictionary-fileHFSTypeCode]</item>
1579
* <item>[NSDictionary-fileIsAppendOnly]</item>
1580
* <item>[NSDictionary-fileIsImmutable]</item>
1581
* <item>[NSDictionary-fileSize]</item>
1582
* <item>[NSDictionary-fileType]</item>
1583
* <item>[NSDictionary-fileOwnerAccountName]</item>
1584
* <item>[NSDictionary-fileOwnerAccountID]</item>
1585
* <item>[NSDictionary-fileGroupOwnerAccountName]</item>
1586
* <item>[NSDictionary-fileGroupOwnerAccountID]</item>
1587
* <item>[NSDictionary-fileModificationDate]</item>
1588
* <item>[NSDictionary-filePosixPermissions]</item>
1589
* <item>[NSDictionary-fileSystemNumber]</item>
1590
* <item>[NSDictionary-fileSystemFileNumber]</item>
978
1593
- (NSDictionary*) fileAttributesAtPath: (NSString*)path traverseLink: (BOOL)flag
980
return [self _attributesAtPath: path traverseLink: flag forCopy: NO];
1595
const _CHAR *lpath = OS2LOCAL(self, path);
1598
d = [GSAttrDictionary attributesAt: lpath traverseLink: flag];
1603
* Returns a dictionary containing the filesystem attributes for the
1604
* specified path (or nil if the path is not valid).<br />
1606
* <term><code>NSFileSystemSize</code></term>
1607
* <desc>NSNumber the size of the filesystem in bytes</desc>
1608
* <term><code>NSFileSystemFreeSize</code></term>
1609
* <desc>NSNumber the amount of unused space on the filesystem in bytes</desc>
1610
* <term><code>NSFileSystemNodes</code></term>
1611
* <desc>NSNumber the number of nodes in use to store files</desc>
1612
* <term><code>NSFileSystemFreeNodes</code></term>
1613
* <desc>NSNumber the number of nodes available to create files</desc>
1614
* <term><code>NSFileSystemNumber</code></term>
1615
* <desc>NSNumber the identifying number for the filesystem</desc>
983
1618
- (NSDictionary*) fileSystemAttributesAtPath: (NSString*)path
985
1620
#if defined(__MINGW__)
986
1621
unsigned long long totalsize, freesize;
990
NSFileSystemFreeSize,
992
NSFileSystemFreeNodes,
1625
NSFileSystemFreeSize,
1627
NSFileSystemFreeNodes,
995
1630
DWORD SectorsPerCluster, BytesPerSector, NumberFreeClusters;
996
1631
DWORD TotalNumberClusters;
997
const char *cpath = [self fileSystemRepresentationWithPath: path];
1632
const _CHAR *lpath = OS2LOCAL(self, path);
999
if (!GetDiskFreeSpace(cpath, &SectorsPerCluster,
1634
if (!GetDiskFreeSpace(lpath, &SectorsPerCluster,
1000
1635
&BytesPerSector, &NumberFreeClusters, &TotalNumberClusters))
1003
1640
totalsize = (unsigned long long)TotalNumberClusters
1004
1641
* (unsigned long long)SectorsPerCluster
1255
1796
if (![self fileExistsAtPath: path isDirectory: &isDir] || !isDir)
1258
direnum = [[NSDirectoryEnumerator alloc] initWithDirectoryPath: path
1800
direnum = [[NSDirectoryEnumerator alloc] initWithDirectoryPath: path
1259
1801
recurseIntoSubdirectories: YES
1260
1802
followSymlinks: NO
1261
1803
justContents: NO];
1262
1804
content = [NSMutableArray arrayWithCapacity: 128];
1264
1806
nxtImp = [direnum methodForSelector: @selector(nextObject)];
1265
1807
addImp = [content methodForSelector: @selector(addObject:)];
1267
1809
while ((path = (*nxtImp)(direnum, @selector(nextObject))) != nil)
1269
1811
(*addImp)(content, @selector(addObject:), path);
1272
1814
RELEASE(direnum);
1816
return [content makeImmutableCopyOnFail: NO];
1277
// Symbolic-link operations
1820
* Creates a symbolic link at path which links to the location
1821
* specified by otherPath.
1279
1823
- (BOOL) createSymbolicLinkAtPath: (NSString*)path
1280
1824
pathContent: (NSString*)otherPath
1283
1827
const char* newpath = [self fileSystemRepresentationWithPath: path];
1284
1828
const char* oldpath = [self fileSystemRepresentationWithPath: otherPath];
1286
1830
return (symlink(oldpath, newpath) == 0);
1837
* Returns the name of the file or directory that the symbolic link
1838
* at path points to.
1292
1840
- (NSString*) pathContentOfSymbolicLinkAtPath: (NSString*)path
1295
char lpath[PATH_MAX];
1296
const char* cpath = [self fileSystemRepresentationWithPath: path];
1297
int llen = readlink(cpath, lpath, PATH_MAX-1);
1842
#ifdef HAVE_READLINK
1844
const char* lpath = [self fileSystemRepresentationWithPath: path];
1845
int llen = readlink(lpath, buf, PATH_MAX-1);
1300
return [self stringWithFileSystemRepresentation: lpath length: llen];
1849
return [self stringWithFileSystemRepresentation: buf length: llen];
1308
// Converting file-system representations
1861
* Convert from OpenStep internal path format (Unix-style) to a string in
1862
* the local filesystem format, suitable for passing to system functions.<br />
1863
* Under Unix, this simply standardizes the path and converts to a
1865
* Under Windoze, this attempts to use local conventions to convert to a
1866
* windows path. In GNUstep, the conventional unix syntax '~user/...' can
1867
* be used to indicate a windoze drive specification by using the drive
1868
* letter in place of the username, and the syntax '~@server/...' can be used
1869
* to indicate a file located on the named windoze network server (the
1870
* '~@' maps to the leading '//' in a windoze UNC path specification.
1310
1872
- (const char*) fileSystemRepresentationWithPath: (NSString*)path
1874
NSString *localPath;
1875
const char *local_c_path = 0;
1877
localPath = [self localFromOpenStepPath: path];
1879
&& [localPath canBeConvertedToEncoding: [NSString defaultCStringEncoding]])
1881
local_c_path = [localPath cString];
1883
return (local_c_path);
1887
* Convert from OpenStep internal path format (Unix-style) to a NSString in
1888
* the local filesystem format.
1889
* Under Windoze, this attempts to use local conventions to convert to a
1890
* windows path. In GNUstep, the conventional unix syntax '~user/...' can
1891
* be used to indicate a windoze drive specification by using the drive
1892
* letter in place of the username, and the syntax '~@server/...' can be used
1893
* to indicate a file located on the named windoze network server (the
1894
* '~@' maps to the leading '//' in a windoze UNC path specification.
1896
- (NSString*) localFromOpenStepPath: (NSString*)path
1898
NSString *newpath = nil;
1312
1899
#ifdef __MINGW__
1314
* If path is in Unix format, transmorgrify it so Windows functions
1317
NSString *newpath = path;
1318
const char *c_path = [path cString];
1319
int len = [path length];
1325
if (len >= 3 && c_path[0] == '/' && c_path[1] == '/' && isalpha(c_path[2]))
1327
if (len == 3 || c_path[3] == '/')
1329
/* Cygwin "//c/" type absolute path */
1330
newpath = [NSString stringWithFormat: @"%c:%s", c_path[2],
1332
newpath = [newpath stringByReplacingString: @"/" withString: @"\\"];
1901
* If path is in Unix format, transmogrify it so Windows functions
1904
int wcount; // count unichars
1905
unichar *wc_path = 0;
1908
path = [path stringByStandardizingPath];
1909
wcount = [path length];
1913
wc_path = (unichar*)calloc(wcount+10,sizeof(unichar));
1914
[path getCharacters: (unichar *)wc_path];
1916
if (l >= 2 && wc_path[0] == L'~' && wc_path[1] == L'@')
1918
// Convert to windows UNC path.
1921
newpath = [NSString stringWithCharacters: wc_path length: wcount];
1923
else if (l >= 2 && wc_path[0] == L'~' && iswalpha(wc_path[1])
1924
&& (l == 2 || wc_path[2] == L'/'))
1926
wc_path[0] = wc_path[1];
1928
newpath = [NSString stringWithCharacters: wc_path length: wcount];
1930
else if (l >= 3 && wc_path[0] == L'/' && wc_path[1] == L'/'
1931
&& iswalpha(wc_path[2]))
1933
if (l == 3 || wc_path[3] == L'/')
1935
/* Cygwin "//c/" type absolute path */
1936
wc_path[1] = wc_path[2];
1938
newpath = [NSString stringWithCharacters: &wc_path[1]
1943
/* Windows absolute UNC path "//name/" */
1947
else if (isalpha(wc_path[0]) && wc_path[1] == L':')
1949
/* Windows absolute path */
1952
else if (wc_path[0] == L'/')
1955
if (l > 11 && wcsncmp(wc_path, L"/cygdrive/", 10) == 0
1956
&& wc_path[11] == L'/')
1958
wc_path[9] = wc_path[10];
1960
newpath = [NSString stringWithCharacters: &wc_path[9]
1968
env = [[NSProcessInfo processInfo] environment];
1969
cyghome = [env objectForKey: @"CYGWIN_HOME"];
1972
/* FIXME: Find cygwin drive? */
1974
newpath = [newpath stringByAppendingPathComponent: path];
1982
if (l >= 2 && wc_path[0] == L'/' && iswalpha(wc_path[1])
1983
&& (l == 2 || wc_path[2] == L'/'))
1985
/* Mingw /drive/... format */
1987
newpath = [NSString stringWithCharacters: &wc_path[1]
1336
/* Windows absolute UNC path "//name/" */
1337
newpath = [newpath stringByReplacingString: @"/" withString: @"\\"];
1340
else if (isalpha(c_path[0]) && c_path[1] == ':')
1342
/* Unix absolute path */
1343
2000
newpath = [newpath stringByReplacingString: @"/" withString: @"\\"];
1345
else if (c_path[0] == '/')
1350
env = [[NSProcessInfo processInfo] environment];
1351
cyghome = [env objectForKey: @"CYGWIN_HOME"];
1354
/* FIXME: Find cygwin drive? */
1356
newpath = [newpath stringByAppendingPathComponent: path];
1357
newpath = [newpath stringByReplacingString: @"/" withString: @"\\"];
1360
/* FIXME: Should we translate relative paths? */
1361
return [newpath cString];
1363
return [path cString];
2012
* NB ... Don't standardize path, since that would automatically
2013
* follow symbolic links ... and mess up any code wishing to
2014
* examine the link itsself.
2015
* We just need the path in a form where it can be interpreted by
2016
* operating system calls (no '~' abbreviations for user directories).
2018
newpath = [path stringByExpandingTildeInPath];
2025
* This method converts from a local system specific filename representation
2026
* to the internal OpenStep representation (unix-style). This should be used
2027
* whenever a filename is read in from the local system.<br />
2028
* In GNUstep, windoze drive specifiers are encoded in the internal path
2029
* using the conventuional unix syntax of '~user/...' where the drive letter
2030
* is used instead of a username.
1367
2032
- (NSString*) stringWithFileSystemRepresentation: (const char*)string
1368
2033
length: (unsigned int)len
1370
return [NSString stringWithCString: string length: len];
2035
NSString *localPath = nil;
2039
localPath = [NSString stringWithCString: string length: len];
2042
return([self openStepPathFromLocal: localPath]);
2046
* This method converts from a local system specific filename representation
2047
* to the internal OpenStep representation (unix-style). This should be used
2048
* whenever a filename is read in from the local system.<br />
2049
* In GNUstep, windoze drive specifiers are encoded in the internal path
2050
* using the conventuional unix syntax of '~user/...' where the drive letter
2051
* is used instead of a username.
2053
- (NSString*) openStepPathFromLocal: (NSString*)localPath
2057
int len; // count unichars
2058
unichar *wc_path = 0;
2060
len = [localPath length];
2063
wc_path = (unichar*)calloc(len+10,sizeof(unichar));
2064
[localPath getCharacters: (unichar *)wc_path];
2068
const unichar *ptr = wc_path;
2069
unichar buf[len + 20];
2074
* If path is in Windows format, transmogrify it so Unix functions
2082
if (len >= 2 && ((ptr[1] == L'/' && ptr[0] == L'/')
2083
|| (ptr[1] == L'\\' && ptr[0] == L'\\')))
2086
* Convert '//<servername>/' to '~@<servername>/' sequences.
2092
else if (len >= 2 && ptr[1] == L':' && iswalpha(ptr[0]))
2095
* Convert '<driveletter>:' to '~<driveletter>/' sequences.
2105
else if (len > 9 && wcsncmp(ptr, L"/cygdrive/", 10) == 0)
2113
else if (len >= 2 && ptr[0] == L'/' && iswalpha(ptr[1])
2114
&& (len == 2 || ptr[2] == L'/'))
2117
* Convert '/<driveletter>' to '~<driveletter>' sequences.
2128
* Convert backslashes to slashes, colaescing adjacent slashes.
2129
* Also elide '/./' sequences, because we can do so efficiently.
2134
if (ptr[i] == L'\\')
2136
if (j == 0 || buf[j-1] != L'/')
2138
if (j > 2 && buf[j-2] == L'/' && buf[j-1] == L'.')
2155
// NSLog(@"Map '%s' to '%s'", string, buf);
2157
return [NSString stringWithCharacters: buf length: j];
1373
2168
@end /* NSFileManager */
1376
* NSDirectoryEnumerator implementation
1378
* The Objective-C interface hides a traditional C implementation.
1379
* This was the only way I could get near the speed of standard unix
1380
* tools for big directories.
1383
2170
/* A directory to enumerate. We keep a stack of the directories we
1384
2171
still have to enumerate. We start by putting the top-level
1385
2172
directory into the stack, then we start reading files from it
1516
2285
GSIArrayEmpty(_stack);
1517
2286
NSZoneFree([self zone], _stack);
1518
NSZoneFree(NSDefaultMallocZone(), _top_path);
1519
if (_current_file_path != NULL)
1521
NSZoneFree(NSDefaultMallocZone(), _current_file_path);
2288
DESTROY(_currentFilePath);
1523
2289
[super dealloc];
1526
// Getting attributes
2293
* Returns a dictionary containing the attributes of the directory
2294
* at which enumeration started. <br />
2295
* The contents of this dictionary are as produced by
2296
* [NSFileManager-fileAttributesAtPath:traverseLink:]
1528
2298
- (NSDictionary*) directoryAttributes
1532
topPath = _stringWithFileSysImp(defaultManager, swfsSel, _top_path,
1535
return [defaultManager fileAttributesAtPath: topPath
1536
traverseLink: _flags.isFollowing];
2300
return [defaultManager fileAttributesAtPath: _topPath
2301
traverseLink: _flags.isFollowing];
2305
* Returns a dictionary containing the attributes of the file
2306
* currently being enumerated. <br />
2307
* The contents of this dictionary are as produced by
2308
* [NSFileManager-fileAttributesAtPath:traverseLink:]
1539
2310
- (NSDictionary*) fileAttributes
1541
NSString *currentFilePath;
1543
currentFilePath = _stringWithFileSysImp(defaultManager, swfsSel,
1545
strlen(_current_file_path));
1547
return [defaultManager fileAttributesAtPath: currentFilePath
1548
traverseLink: _flags.isFollowing];
2312
return [defaultManager fileAttributesAtPath: _currentFilePath
2313
traverseLink: _flags.isFollowing];
1551
// Skipping subdirectories
2317
* Informs the receiver that any descendents of the current directory
2318
* should be skipped rather than enumerated. Use this to avaoid enumerating
2319
* the contents of directories you are not interested in.
1553
2321
- (void) skipDescendents
1555
2323
if (GSIArrayCount(_stack) > 0)
1557
2325
GSIArrayRemoveLastItem(_stack);
1558
if (_current_file_path != NULL)
2326
if (_currentFilePath != 0)
1560
NSZoneFree(NSDefaultMallocZone(), _current_file_path);
1561
_current_file_path = NULL;
2328
DESTROY(_currentFilePath);
2334
* finds the next file according to the top enumerator
2335
* - if there is a next file it is put in currentFile
2336
* - if the current file is a directory and if isRecursive calls
2337
* recurseIntoDirectory: currentFile
2338
* - if the current file is a symlink to a directory and if isRecursive
2339
* and isFollowing calls recurseIntoDirectory: currentFile
2340
* - if at end of current directory pops stack and attempts to
2341
* find the next entry in the parent
2342
* - sets currentFile to nil if there are no more files to enumerate
1568
2344
- (id) nextObject
1571
finds the next file according to the top enumerator
1572
- if there is a next file it is put in currentFile
1573
- if the current file is a directory and if isRecursive calls
1574
recurseIntoDirectory: currentFile
1575
- if the current file is a symlink to a directory and if isRecursive
1576
and isFollowing calls recurseIntoDirectory: currentFile
1577
- if at end of current directory pops stack and attempts to
1578
find the next entry in the parent
1579
- sets currentFile to nil if there are no more files to enumerate
1581
char *return_file_name = NULL;
2346
NSString *returnFileName = 0;
1583
if (_current_file_path != NULL)
2348
if (_currentFilePath != 0)
1585
NSZoneFree(NSDefaultMallocZone(), _current_file_path);
1586
_current_file_path = NULL;
2350
DESTROY(_currentFilePath);
1589
2353
while (GSIArrayCount(_stack) > 0)
1591
2355
GSEnumeratedDirectory dir = GSIArrayLastItem(_stack).ext;
1592
struct dirent *dirbuf;
1593
struct stat statbuf;
1595
dirbuf = readdir(dir.pointer);
2356
struct _DIRENT *dirbuf;
2357
struct _STATB statbuf;
2359
dirbuf = _READDIR(dir.pointer);
1598
/* Skip "." and ".." directory entries */
1599
if (strcmp(dirbuf->d_name, ".") == 0
1600
|| strcmp(dirbuf->d_name, "..") == 0)
1603
/* Name of file to return */
1604
return_file_name = append_file_to_path(dir.path, dirbuf->d_name);
2363
#if defined(__MINGW__) && defined(UNICODE)
2364
/* Skip "." and ".." directory entries */
2365
if (wcscmp(dirbuf->d_name, L".") == 0
2366
|| wcscmp(dirbuf->d_name, L"..") == 0)
2370
/* Name of file to return */
2371
returnFileName = _openStepPathFromLocalImp(defaultManager, ospfl,
2372
[NSString stringWithCharacters: dirbuf->d_name
2373
length: wcslen(dirbuf->d_name)]);
2375
/* Skip "." and ".." directory entries */
2376
if (strcmp(dirbuf->d_name, ".") == 0
2377
|| strcmp(dirbuf->d_name, "..") == 0)
2381
/* Name of file to return */
2382
returnFileName = _openStepPathFromLocalImp(defaultManager, ospfl,
2383
[NSString stringWithCString: dirbuf->d_name]);
2385
returnFileName = [dir.path stringByAppendingPathComponent:
2387
RETAIN(returnFileName);
1606
2389
/* TODO - can this one can be removed ? */
1607
2390
if (!_flags.justContents)
1609
_current_file_path = append_file_to_path(_top_path,
1612
if (_flags.isRecursive == YES)
2391
_currentFilePath = RETAIN([_topPath stringByAppendingPathComponent:
2394
if (_flags.isRecursive == YES)
1614
2396
// Do not follow links
2399
#warning "lstat does not support unichars"
1616
2401
if (!_flags.isFollowing)
1618
if (lstat(_current_file_path, &statbuf) != 0)
2403
if (lstat([_currentFilePath fileSystemRepresentation],
1620
2408
// If link then return it as link
1621
if (S_IFLNK == (S_IFMT & statbuf.st_mode))
2409
if (S_IFLNK == (S_IFMT & statbuf.st_mode))
1627
if (stat(_current_file_path, &statbuf) != 0)
2418
if (_STAT(OS2LOCAL(defaultManager, _currentFilePath),
1630
2424
if (S_IFDIR == (S_IFMT & statbuf.st_mode))
1634
dir_pointer = opendir(_current_file_path);
2429
= _OPENDIR(OS2LOCAL(defaultManager, _currentFilePath));
1636
2430
if (dir_pointer)
1638
2432
GSIArrayItem item;
1640
item.ext.path = custom_strdup(return_file_name);
2434
item.ext.path = RETAIN(returnFileName);
1641
2435
item.ext.pointer = dir_pointer;
1643
2437
GSIArrayAddItem(_stack, item);
1647
NSLog(@"Failed to recurse into directory '%s' - %s",
1648
_current_file_path, GSLastErrorStr(errno));
2441
NSLog(@"Failed to recurse into directory '%@' - %s",
2442
_currentFilePath, GSLastErrorStr(errno));
1656
2450
GSIArrayRemoveLastItem(_stack);
1657
if (_current_file_path != NULL)
2451
if (_currentFilePath != 0)
1659
NSZoneFree(NSDefaultMallocZone(), _current_file_path);
1660
_current_file_path = NULL;
2453
DESTROY(_currentFilePath);
1664
if (return_file_name == NULL)
1670
NSString *result = _stringWithFileSysImp(defaultManager, swfsSel,
1672
strlen(return_file_name));
1673
NSZoneFree(NSDefaultMallocZone(), return_file_name);
2457
return AUTORELEASE(returnFileName);
1678
2460
@end /* NSDirectoryEnumerator */
1680
@implementation NSDirectoryEnumerator (PrivateMethods)
1681
- (NSDictionary*) _attributesForCopy
1683
NSString *currentFilePath;
1685
currentFilePath = _stringWithFileSysImp(defaultManager, swfsSel,
1687
strlen(_current_file_path));
1689
return [defaultManager _attributesAtPath: currentFilePath
1690
traverseLink: _flags.isFollowing
1696
* Attributes dictionary access
2463
* Convenience methods for accessing named file attributes in a dictionary.
1699
2465
@implementation NSDictionary(NSFileAttributes)
2468
* Return the file creation date attribute (or nil if not found).
2470
- (NSDate*) fileCreationDate
2472
return [self objectForKey: NSFileCreationDate];
2476
* Return the file extension hidden attribute (or NO if not found).
2478
- (BOOL) fileExtensionHidden
2480
return [[self objectForKey: NSFileExtensionHidden] boolValue];
2484
* Returns HFS creator attribute (OS X).
2486
- (int) fileHFSCreatorCode
2488
return [[self objectForKey: NSFileHFSCreatorCode] intValue];
2492
* Returns HFS type code attribute (OS X).
2494
- (int) fileHFSTypeCode
2496
return [[self objectForKey: NSFileHFSTypeCode] intValue];
2500
* Return the file append only attribute (or NO if not found).
2502
- (BOOL) fileIsAppendOnly
2504
return [[self objectForKey: NSFileAppendOnly] boolValue];
2508
* Return the file immutable attribute (or NO if not found).
2510
- (BOOL) fileIsImmutable
2512
return [[self objectForKey: NSFileImmutable] boolValue];
2516
* Return the size of the file, or NSNotFound if the file size attribute
2517
* is not found in the dictionary.
1700
2519
- (unsigned long long) fileSize
1702
return [[self objectForKey: NSFileSize] unsignedLongLongValue];
2521
NSNumber *n = [self objectForKey: NSFileSize];
2527
return [n unsignedLongLongValue];
2531
* Return the file type attribute or nil if not present.
1705
2533
- (NSString*) fileType
1707
2535
return [self objectForKey: NSFileType];
2539
* Return the file owner account name attribute or nil if not present.
1710
2541
- (NSString*) fileOwnerAccountName
1712
2543
return [self objectForKey: NSFileOwnerAccountName];
1715
- (unsigned long) fileOwnerAccountNumber
2547
* Return the numeric value of the NSFileOwnerAccountID attribute
2548
* in the dictionary, or NSNotFound if the attribute is not present.
2550
- (unsigned long) fileOwnerAccountID
1717
return [[self objectForKey: NSFileOwnerAccountNumber] unsignedIntValue];
2552
NSNumber *n = [self objectForKey: NSFileOwnerAccountID];
2558
return [n unsignedIntValue];
2562
* Return the file group owner account name attribute or nil if not present.
1720
2564
- (NSString*) fileGroupOwnerAccountName
1722
2566
return [self objectForKey: NSFileGroupOwnerAccountName];
1725
- (unsigned long) fileGroupOwnerAccountNumber
2570
* Return the numeric value of the NSFileGroupOwnerAccountID attribute
2571
* in the dictionary, or NSNotFound if the attribute is not present.
2573
- (unsigned long) fileGroupOwnerAccountID
1727
return [[self objectForKey: NSFileGroupOwnerAccountNumber] unsignedIntValue];
2575
NSNumber *n = [self objectForKey: NSFileGroupOwnerAccountID];
2581
return [n unsignedIntValue];
2585
* Return the file modification date attribute (or nil if not found)
1730
2587
- (NSDate*) fileModificationDate
1732
2589
return [self objectForKey: NSFileModificationDate];
2593
* Return the file posix permissions attribute (or NSNotFound if
2594
* the attribute is not present in the dictionary).
1735
2596
- (unsigned long) filePosixPermissions
1737
return [[self objectForKey: NSFilePosixPermissions] unsignedLongValue];
2598
NSNumber *n = [self objectForKey: NSFilePosixPermissions];
2604
return [n unsignedLongValue];
2608
* Return the file system number attribute (or NSNotFound if
2609
* the attribute is not present in the dictionary).
1740
2611
- (unsigned long) fileSystemNumber
1742
return [[self objectForKey: NSFileSystemNumber] unsignedLongValue];
2613
NSNumber *n = [self objectForKey: NSFileSystemNumber];
2619
return [n unsignedLongValue];
2623
* Return the file system file identification number attribute
2624
* or NSNotFound if the attribute is not present in the dictionary).
1745
2626
- (unsigned long) fileSystemFileNumber
1747
return [[self objectForKey: NSFileSystemFileNumber] unsignedLongValue];
2628
NSNumber *n = [self objectForKey: NSFileSystemFileNumber];
2634
return [n unsignedLongValue];
2001
#if (defined(sparc) && defined(DEBUG))
2002
static int sparc_warn = 0;
2831
- (BOOL) _linkPath: (NSString*)source
2832
toPath: (NSString*)destination
2836
NSDirectoryEnumerator *enumerator;
2838
CREATE_AUTORELEASE_POOL(pool);
2840
enumerator = [self enumeratorAtPath: source];
2841
while ((dirEntry = [enumerator nextObject]))
2843
NSString *sourceFile;
2845
NSString *destinationFile;
2846
NSDictionary *attributes;
2848
attributes = [enumerator fileAttributes];
2849
fileType = [attributes fileType];
2850
sourceFile = [source stringByAppendingPathComponent: dirEntry];
2852
= [destination stringByAppendingPathComponent: dirEntry];
2854
[self _sendToHandler: handler willProcessPath: sourceFile];
2856
if ([fileType isEqual: NSFileTypeDirectory] == YES)
2858
if ([self createDirectoryAtPath: destinationFile
2859
attributes: attributes] == NO)
2861
if ([self _proceedAccordingToHandler: handler
2862
forError: _lastError
2863
inPath: destinationFile
2864
fromPath: sourceFile
2865
toPath: destinationFile] == NO)
2872
[enumerator skipDescendents];
2873
if ([self _linkPath: sourceFile
2874
toPath: destinationFile
2875
handler: handler] == NO)
2881
else if ([fileType isEqual: NSFileTypeSymbolicLink])
2885
path = [self pathContentOfSymbolicLinkAtPath: sourceFile];
2886
if ([self createSymbolicLinkAtPath: destinationFile
2887
pathContent: path] == NO)
2889
if ([self _proceedAccordingToHandler: handler
2890
forError: @"cannot create symbolic link"
2892
fromPath: sourceFile
2893
toPath: destinationFile] == NO)
2901
if (link([sourceFile fileSystemRepresentation],
2902
[destinationFile fileSystemRepresentation]) < 0)
2904
if ([self _proceedAccordingToHandler: handler
2905
forError: @"cannot create hard link"
2907
fromPath: sourceFile
2908
toPath: destinationFile] == NO)
2914
[self changeFileAttributes: attributes atPath: destinationFile];
2005
- (NSDictionary*) _attributesAtPath: (NSString*)path
2006
traverseLink: (BOOL)traverse
2009
struct stat statbuf;
2010
const char* cpath = [self fileSystemRepresentationWithPath: path];
2016
NSFileModificationDate,
2017
NSFileReferenceCount,
2019
NSFileSystemFileNumber,
2020
NSFileDeviceIdentifier,
2021
NSFilePosixPermissions,
2023
NSFileOwnerAccountName,
2024
NSFileGroupOwnerAccountName,
2025
NSFileOwnerAccountNumber,
2026
NSFileGroupOwnerAccountNumber
2029
#if defined(__MINGW__)
2030
if (stat(cpath, &statbuf) != 0)
2923
- (void) _sendToHandler: (id) handler
2924
willProcessPath: (NSString*) path
2926
if ([handler respondsToSelector: @selector (fileManager:willProcessPath:)])
2928
[handler fileManager: self willProcessPath: path];
2932
- (BOOL) _proceedAccordingToHandler: (id) handler
2933
forError: (NSString*) error
2934
inPath: (NSString*) path
2936
if ([handler respondsToSelector:
2937
@selector (fileManager:shouldProceedAfterError:)])
2939
NSDictionary *errorInfo = [NSDictionary dictionaryWithObjectsAndKeys:
2941
error, @"Error", nil];
2942
return [handler fileManager: self
2943
shouldProceedAfterError: errorInfo];
2948
- (BOOL) _proceedAccordingToHandler: (id) handler
2949
forError: (NSString*) error
2950
inPath: (NSString*) path
2951
fromPath: (NSString*) fromPath
2952
toPath: (NSString*) toPath
2954
if ([handler respondsToSelector:
2955
@selector (fileManager:shouldProceedAfterError:)])
2957
NSDictionary *errorInfo = [NSDictionary dictionaryWithObjectsAndKeys:
2959
fromPath, @"FromPath",
2961
error, @"Error", nil];
2962
return [handler fileManager: self
2963
shouldProceedAfterError: errorInfo];
2968
@end /* NSFileManager (PrivateMethods) */
2972
@implementation GSAttrDictionary
2974
static NSSet *fileKeys = nil;
2976
+ (NSDictionary*) attributesAt: (const _CHAR*)lpath
2977
traverseLink: (BOOL)traverse
2979
GSAttrDictionary *d;
2981
if (lpath == 0 || *lpath == 0)
2034
#else /* !(__MINGW__) */
2037
if (stat(cpath, &statbuf) != 0)
2045
if (lstat(cpath, &statbuf) != 0)
2050
#endif /* (S_IFLNK) */
2051
#endif /* (__MINGW__) */
2053
values[0] = [NSNumber numberWithUnsignedLongLong: statbuf.st_size];
2054
values[1] = [NSDate dateWithTimeIntervalSince1970: statbuf.st_mtime];
2055
values[2] = [NSNumber numberWithUnsignedInt: statbuf.st_nlink];
2056
values[3] = [NSNumber numberWithUnsignedLong: statbuf.st_dev];
2057
values[4] = [NSNumber numberWithUnsignedLong: statbuf.st_ino];
2058
values[5] = [NSNumber numberWithUnsignedInt: statbuf.st_dev];
2059
values[6] = [NSNumber numberWithUnsignedInt: statbuf.st_mode];
2061
mode = statbuf.st_mode & S_IFMT;
2063
if (mode == S_IFREG)
2064
values[7] = NSFileTypeRegular;
2065
else if (mode == S_IFDIR)
2066
values[7] = NSFileTypeDirectory;
2067
else if (mode == S_IFCHR)
2068
values[7] = NSFileTypeCharacterSpecial;
2069
else if (mode == S_IFBLK)
2070
values[7] = NSFileTypeBlockSpecial;
2072
else if (mode == S_IFLNK)
2073
values[7] = NSFileTypeSymbolicLink;
2075
else if (mode == S_IFIFO)
2076
values[7] = NSFileTypeFifo;
2985
d = (GSAttrDictionary*)NSAllocateObject(self, 0, NSDefaultMallocZone());
2987
#if defined(S_IFLNK) && !defined(__MINGW__)
2990
if (lstat(lpath, &d->statbuf) != 0)
2997
if (_STAT(lpath, &d->statbuf) != 0)
3001
return AUTORELEASE(d);
3006
if (fileKeys == nil)
3008
fileKeys = [NSSet setWithObjects:
3011
NSFileDeviceIdentifier,
3012
NSFileExtensionHidden,
3013
NSFileGroupOwnerAccountName,
3014
NSFileGroupOwnerAccountID,
3015
NSFileHFSCreatorCode,
3018
NSFileModificationDate,
3019
NSFileOwnerAccountName,
3020
NSFileOwnerAccountID,
3021
NSFilePosixPermissions,
3022
NSFileReferenceCount,
3024
NSFileSystemFileNumber,
3032
- (unsigned int) count
3034
return [fileKeys count];
3037
- (NSDate*) fileCreationDate
3040
* FIXME ... not sure there is any way to get a creation date :-(
3041
* Use the earlier of ctime or mtime
3043
if (statbuf.st_ctime < statbuf.st_mtime)
3044
return [NSDate dateWithTimeIntervalSince1970: statbuf.st_ctime];
3046
return [NSDate dateWithTimeIntervalSince1970: statbuf.st_mtime];
3049
- (BOOL) fileExtensionHidden
3054
- (unsigned long) fileGroupOwnerAccountID
3056
return statbuf.st_gid;
3059
- (NSString*) fileGroupOwnerAccountName
3061
NSString *result = @"UnknownGroup";
3062
#if defined(HAVE_GRP_H)
3065
gp = getgrgid(statbuf.st_gid);
3068
result = [NSString stringWithCString: gp->gr_name];
3074
- (int) fileHFSCreatorCode
3079
- (int) fileHFSTypeCode
3084
- (BOOL) fileIsAppendOnly
3089
- (BOOL) fileIsImmutable
3094
- (NSDate*) fileModificationDate
3096
return [NSDate dateWithTimeIntervalSince1970: statbuf.st_mtime];
3099
- (unsigned long) filePosixPermissions
3101
return (statbuf.st_mode & ~S_IFMT);
3104
- (unsigned long) fileOwnerAccountID
3106
return statbuf.st_uid;
3109
- (NSString*) fileOwnerAccountName
3111
NSString *result = @"UnknownUser";
3112
#ifdef __MINGW_NOT_AVAILABLE_YET
3114
DWORD dwRtnCode = 0;
3116
BOOL bRtnBool = TRUE;
3119
DWORD dwAcctName = 1;
3120
DWORD dwDomainName = 1;
3121
SID_NAME_USE eUse = SidTypeUnknown;
3123
PSECURITY_DESCRIPTOR pSD;
3125
// Get the handle of the file object.
3132
FILE_ATTRIBUTE_NORMAL,
3135
// Check GetLastError for CreateFile error code.
3136
if (hFile == INVALID_HANDLE_VALUE)
3138
DWORD dwErrorCode = 0;
3140
dwErrorCode = GetLastError();
3141
_tprintf(TEXT("CreateFile error = %d\n"), dwErrorCode);
3145
// Allocate memory for the SID structure.
3146
pSidOwner = (PSID)GlobalAlloc(
3150
// Allocate memory for the security descriptor structure.
3151
pSD = (PSECURITY_DESCRIPTOR)GlobalAlloc(
3153
sizeof(PSECURITY_DESCRIPTOR));
3155
// Get the owner SID of the file.
3156
dwRtnCode = GetSecurityInfo(
3159
OWNER_SECURITY_INFORMATION,
3166
// Check GetLastError for GetSecurityInfo error condition.
3167
if (dwRtnCode != ERROR_SUCCESS)
3169
DWORD dwErrorCode = 0;
3171
dwErrorCode = GetLastError();
3172
_tprintf(TEXT("GetSecurityInfo error = %d\n"), dwErrorCode);
3176
// First call to LookupAccountSid to get the buffer sizes.
3177
bRtnBool = LookupAccountSid(
3178
0, // local computer
3181
(LPDWORD)&dwAcctName,
3183
(LPDWORD)&dwDomainName,
3186
// Reallocate memory for the buffers.
3187
AcctName = (char *)GlobalAlloc(
3191
// Check GetLastError for GlobalAlloc error condition.
3194
DWORD dwErrorCode = 0;
3196
dwErrorCode = GetLastError();
3197
_tprintf(TEXT("GlobalAlloc error = %d\n"), dwErrorCode);
3201
DomainName = (char *)GlobalAlloc(
3205
// Check GetLastError for GlobalAlloc error condition.
3206
if (DomainName == 0)
3208
DWORD dwErrorCode = 0;
3210
dwErrorCode = GetLastError();
3211
_tprintf(TEXT("GlobalAlloc error = %d\n"), dwErrorCode);
3215
// Second call to LookupAccountSid to get the account name.
3216
bRtnBool = LookupAccountSid(
3217
0, // name of local or remote computer
3218
pSidOwner, // security identifier
3219
AcctName, // account name buffer
3220
(LPDWORD)&dwAcctName, // size of account name buffer
3221
DomainName, // domain name
3222
(LPDWORD)&dwDomainName, // size of domain name buffer
3225
// Check GetLastError for LookupAccountSid error condition.
3226
if (bRtnBool == FALSE)
3228
DWORD dwErrorCode = 0;
3230
dwErrorCode = GetLastError();
3232
if (dwErrorCode == ERROR_NONE_MAPPED)
3233
_tprintf(TEXT("Account owner not found for specified SID.\n"));
3235
_tprintf(TEXT("Error in LookupAccountSid.\n"));
3238
else if (bRtnBool == TRUE)
3240
// Print the account name.
3241
_tprintf(TEXT("Account owner = %s\n"), AcctName);
3250
pw = getpwuid(statbuf.st_uid);
3254
result = [NSString stringWithCString: pw->pw_name];
3256
#endif /* HAVE_PWD_H */
3260
- (unsigned long long) fileSize
3262
return statbuf.st_size;
3265
- (unsigned long) fileSystemFileNumber
3267
return statbuf.st_ino;
3270
- (unsigned long) fileSystemNumber
3272
return statbuf.st_dev;
3275
- (NSString*) fileType
3277
switch (statbuf.st_mode & S_IFMT)
3279
case S_IFREG: return NSFileTypeRegular;
3280
case S_IFDIR: return NSFileTypeDirectory;
3281
case S_IFCHR: return NSFileTypeCharacterSpecial;
3282
case S_IFBLK: return NSFileTypeBlockSpecial;
3284
case S_IFLNK: return NSFileTypeSymbolicLink;
3286
case S_IFIFO: return NSFileTypeFifo;
2077
3287
#ifdef S_IFSOCK
2078
else if (mode == S_IFSOCK)
2079
values[7] = NSFileTypeSocket;
2082
values[7] = NSFileTypeUnknown;
2090
pw = getpwuid(statbuf.st_uid);
2094
values[8] = [NSString stringWithCString: pw->pw_name];
2098
values[8] = @"UnknownUser";
2102
values[8] = @"UnknownUser";
2103
#endif /* HAVE_PWD_H */
2105
#if defined(HAVE_GRP_H) && !(defined(sparc) && defined(DEBUG))
2110
while ((gp = getgrent()) != 0)
2112
if (gp->gr_gid == statbuf.st_gid)
2119
values[9] = [NSString stringWithCString: gp->gr_name];
2123
values[9] = @"UnknownGroup";
2128
#if (defined(sparc) && defined(DEBUG))
2129
if (sparc_warn == 0)
2132
/* Can't be NSLog - causes recursion in [NSUser -synchronize] */
2133
fprintf(stderr, "WARNING (NSFileManager): Disabling group enums (setgrent, etc) since this crashes gdb on sparc machines\n");
2136
values[9] = @"UnknownGroup";
2138
values[10] = [NSNumber numberWithUnsignedInt: statbuf.st_uid];
2139
values[11] = [NSNumber numberWithUnsignedInt: statbuf.st_gid];
3288
case S_IFSOCK: return NSFileTypeSocket;
3290
default: return NSFileTypeUnknown;
3294
- (NSEnumerator*) keyEnumerator
3296
return [fileKeys objectEnumerator];
3299
- (NSEnumerator*) objectEnumerator
3301
return [GSAttrDictionaryEnumerator enumeratorFor: self];
3304
- (id) objectForKey: (NSString*)key
3308
while (key != 0 && count < 2)
2144
NSString *u = NSUserName();
3310
if (key == NSFileAppendOnly)
3311
return [NSNumber numberWithBool: [self fileIsAppendOnly]];
3312
if (key == NSFileCreationDate)
3313
return [self fileCreationDate];
3314
if (key == NSFileDeviceIdentifier)
3315
return [NSNumber numberWithUnsignedInt: statbuf.st_dev];
3316
if (key == NSFileExtensionHidden)
3317
return [NSNumber numberWithBool: [self fileExtensionHidden]];
3318
if (key == NSFileGroupOwnerAccountName)
3319
return [self fileGroupOwnerAccountName];
3320
if (key == NSFileGroupOwnerAccountID)
3321
return [NSNumber numberWithInt: [self fileGroupOwnerAccountID]];
3322
if (key == NSFileHFSCreatorCode)
3323
return [NSNumber numberWithInt: [self fileHFSCreatorCode]];
3324
if (key == NSFileHFSTypeCode)
3325
return [NSNumber numberWithInt: [self fileHFSTypeCode]];
3326
if (key == NSFileImmutable)
3327
return [NSNumber numberWithBool: [self fileIsImmutable]];
3328
if (key == NSFileModificationDate)
3329
return [self fileModificationDate];
3330
if (key == NSFileOwnerAccountName)
3331
return [self fileOwnerAccountName];
3332
if (key == NSFileOwnerAccountID)
3333
return [NSNumber numberWithInt: [self fileOwnerAccountID]];
3334
if (key == NSFilePosixPermissions)
3335
return [NSNumber numberWithUnsignedInt: [self filePosixPermissions]];
3336
if (key == NSFileReferenceCount)
3337
return [NSNumber numberWithUnsignedInt: statbuf.st_nlink];
3338
if (key == NSFileSize)
3339
return [NSNumber numberWithUnsignedLongLong: [self fileSize]];
3340
if (key == NSFileSystemFileNumber)
3341
return [NSNumber numberWithUnsignedInt: [self fileSystemFileNumber]];
3342
if (key == NSFileSystemNumber)
3343
return [NSNumber numberWithUnsignedInt: [self fileSystemNumber]];
3344
if (key == NSFileType)
3345
return [self fileType];
2146
count = 8; /* No ownership details needed. */
2148
* If we are running setuid to root - we need to specify the user
2149
* to be the owner of copied files.
3348
* Now, if we didn't get an exact pointer match, check for
3349
* string equalities and ensure we get an exact match next
3350
* time round the loop.
2152
if (geteuid() == 0 && [@"root" isEqualToString: u] == NO)
2154
values[count++] = u;
2159
return [NSDictionary dictionaryWithObjects: values
2164
@end /* NSFileManager (PrivateMethods) */
3353
key = [fileKeys member: key];
3357
NSLog(@"Warning ... key '%@' not handled", key);
3362
@end /* GSAttrDictionary */
3364
@implementation GSAttrDictionaryEnumerator
3365
+ (NSEnumerator*) enumeratorFor: (NSDictionary*)d
3367
GSAttrDictionaryEnumerator *e;
3369
e = (GSAttrDictionaryEnumerator*)
3370
NSAllocateObject(self, 0, NSDefaultMallocZone());
3371
e->dictionary = RETAIN(d);
3372
e->enumerator = RETAIN([fileKeys objectEnumerator]);
3373
return AUTORELEASE(e);
3378
RELEASE(enumerator);
3379
RELEASE(dictionary);
3385
NSString *key = [enumerator nextObject];
3390
val = [dictionary objectForKey: key];
3396
NSString * const NSFileAppendOnly = @"NSFileAppendOnly";
3397
NSString * const NSFileCreationDate = @"NSFileCreationDate";
3398
NSString * const NSFileDeviceIdentifier = @"NSFileDeviceIdentifier";
3399
NSString * const NSFileExtensionHidden = @"NSFileExtensionHidden";
3400
NSString * const NSFileGroupOwnerAccountID = @"NSFileGroupOwnerAccountID";
3401
NSString * const NSFileGroupOwnerAccountName = @"NSFileGroupOwnerAccountName";
3402
NSString * const NSFileHFSCreatorCode = @"NSFileHFSCreatorCode";
3403
NSString * const NSFileHFSTypeCode = @"NSFileHFSTypeCode";
3404
NSString * const NSFileImmutable = @"NSFileImmutable";
3405
NSString * const NSFileModificationDate = @"NSFileModificationDate";
3406
NSString * const NSFileOwnerAccountID = @"NSFileOwnerAccountID";
3407
NSString * const NSFileOwnerAccountName = @"NSFileOwnerAccountName";
3408
NSString * const NSFilePosixPermissions = @"NSFilePosixPermissions";
3409
NSString * const NSFileReferenceCount = @"NSFileReferenceCount";
3410
NSString * const NSFileSize = @"NSFileSize";
3411
NSString * const NSFileSystemFileNumber = @"NSFileSystemFileNumber";
3412
NSString * const NSFileSystemFreeNodes = @"NSFileSystemFreeNodes";
3413
NSString * const NSFileSystemFreeSize = @"NSFileSystemFreeSize";
3414
NSString * const NSFileSystemNodes = @"NSFileSystemNodes";
3415
NSString * const NSFileSystemNumber = @"NSFileSystemNumber";
3416
NSString * const NSFileSystemSize = @"NSFileSystemSize";
3417
NSString * const NSFileType = @"NSFileType";
3418
NSString * const NSFileTypeBlockSpecial = @"NSFileTypeBlockSpecial";
3419
NSString * const NSFileTypeCharacterSpecial = @"NSFileTypeCharacterSpecial";
3420
NSString * const NSFileTypeDirectory = @"NSFileTypeDirectory";
3421
NSString * const NSFileTypeFifo = @"NSFileTypeFifo";
3422
NSString * const NSFileTypeRegular = @"NSFileTypeRegular";
3423
NSString * const NSFileTypeSocket = @"NSFileTypeSocket";
3424
NSString * const NSFileTypeSymbolicLink = @"NSFileTypeSymbolicLink";
3425
NSString * const NSFileTypeUnknown = @"NSFileTypeUnknown";