mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Error handling tweaks based on code/ideas by Sergey Golovin
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@35266 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
7ccc71d1ab
commit
a29118d5a0
2 changed files with 226 additions and 86 deletions
|
@ -51,6 +51,7 @@
|
|||
#import "Foundation/NSDate.h"
|
||||
#import "Foundation/NSDictionary.h"
|
||||
#import "Foundation/NSEnumerator.h"
|
||||
#import "Foundation/NSError.h"
|
||||
#import "Foundation/NSException.h"
|
||||
#import "Foundation/NSFileManager.h"
|
||||
#import "Foundation/NSLock.h"
|
||||
|
@ -294,9 +295,16 @@ static Class GSAttrDictionaryClass = 0;
|
|||
fromPath: (NSString*) fromPath
|
||||
toPath: (NSString*) toPath;
|
||||
|
||||
|
||||
|
||||
|
||||
/* A convenience method to return an NSError object.
|
||||
* If the _lastError message is set, this creates an NSError using
|
||||
* that message in the NSCocoaErrorDomain, otherwise it used the
|
||||
* most recent system error and the Posix error domain.
|
||||
* The userInfo is set to contain NSLocalizedDescriptionKey for the
|
||||
* message text, 'Path' if only the fromPath argument is specified,
|
||||
* and 'FromPath' and 'ToPath' if both path argument are specified.
|
||||
*/
|
||||
- (NSError*) _errorFrom: (NSString*)fromPath to: (NSString*)toPath;
|
||||
|
||||
@end /* NSFileManager (PrivateMethods) */
|
||||
|
||||
/**
|
||||
|
@ -693,13 +701,30 @@ static NSStringEncoding defaultEncoding;
|
|||
|
||||
- (NSArray*) contentsOfDirectoryAtPath: (NSString*)path error: (NSError**)error
|
||||
{
|
||||
return [self directoryContentsAtPath: path];
|
||||
NSArray *result;
|
||||
|
||||
DESTROY(_lastError);
|
||||
result = [self directoryContentsAtPath: path];
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
if (nil == result)
|
||||
{
|
||||
*error = [self _errorFrom: path to: nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
*error = nil;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new directory and all intermediate directories
|
||||
* if flag is YES, creates only the last directory in the path
|
||||
* if flag is NO. The directory is created with the attributes
|
||||
* Creates a new directory and all intermediate directories. if flag is YES.
|
||||
* Creates only the last directory in the path if flag is NO.<br />
|
||||
* The directory is created with the attributes
|
||||
* specified in attributes and any error is returned in error.<br />
|
||||
* returns YES on success, NO on failure.
|
||||
*/
|
||||
|
@ -710,17 +735,18 @@ static NSStringEncoding defaultEncoding;
|
|||
{
|
||||
BOOL result = NO;
|
||||
|
||||
if (flag == YES)
|
||||
DESTROY(_lastError);
|
||||
if (YES == flag)
|
||||
{
|
||||
NSEnumerator *paths = [[path pathComponents] objectEnumerator];
|
||||
NSString *path = nil;
|
||||
NSString *dir = [NSString string];
|
||||
NSEnumerator *paths = [[path pathComponents] objectEnumerator];
|
||||
NSString *path = nil;
|
||||
NSString *dir = [NSString string];
|
||||
|
||||
while ((path = (NSString *)[paths nextObject]) != nil)
|
||||
{
|
||||
dir = [dir stringByAppendingPathComponent: path];
|
||||
result = [self createDirectoryAtPath: dir
|
||||
attributes: attributes];
|
||||
attributes: attributes];
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -736,14 +762,22 @@ static NSStringEncoding defaultEncoding;
|
|||
else
|
||||
{
|
||||
result = NO;
|
||||
ASSIGN(_lastError, @"Could not create directory - intermediate paths did not exist or were not a directory");
|
||||
ASSIGN(_lastError, @"Could not create directory - intermediate path did not exist or was not a directory");
|
||||
}
|
||||
}
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
*error = [NSError _last];
|
||||
if (NO == result)
|
||||
{
|
||||
*error = [self _errorFrom: path to: nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
*error = nil;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -769,7 +803,10 @@ static NSStringEncoding defaultEncoding;
|
|||
|
||||
/* This is consistent with MacOSX - just return NO for an invalid path. */
|
||||
if ([path length] == 0)
|
||||
return NO;
|
||||
{
|
||||
ASSIGN(_lastError, @"no path given");
|
||||
return NO;
|
||||
}
|
||||
|
||||
#if defined(__MINGW__)
|
||||
while ((subPath = [paths nextObject]))
|
||||
|
@ -927,7 +964,10 @@ static NSStringEncoding defaultEncoding;
|
|||
|
||||
/* This is consistent with MacOSX - just return NO for an invalid path. */
|
||||
if ([path length] == 0)
|
||||
return NO;
|
||||
{
|
||||
ASSIGN(_lastError, @"no path given");
|
||||
return NO;
|
||||
}
|
||||
|
||||
#if defined(__MINGW__)
|
||||
fh = CreateFileW(lpath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
|
||||
|
@ -1075,6 +1115,7 @@ static NSStringEncoding defaultEncoding;
|
|||
if ([[destination stringByAppendingString: @"/"]
|
||||
hasPrefix: [source stringByAppendingString: @"/"]])
|
||||
{
|
||||
ASSIGN(_lastError, @"Could not copy - destination is a descendant of source");
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
@ -1145,9 +1186,23 @@ static NSStringEncoding defaultEncoding;
|
|||
toPath: (NSString*)dst
|
||||
error: (NSError**)error
|
||||
{
|
||||
BOOL result;
|
||||
BOOL result;
|
||||
|
||||
DESTROY(_lastError);
|
||||
result = [self copyPath: src toPath: dst handler: nil];
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
if (NO == result)
|
||||
{
|
||||
*error = [self _errorFrom: src to: dst];
|
||||
}
|
||||
else
|
||||
{
|
||||
*error = nil;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1200,6 +1255,7 @@ static NSStringEncoding defaultEncoding;
|
|||
if (sourceIsDir && [[destination stringByAppendingString: @"/"]
|
||||
hasPrefix: [source stringByAppendingString: @"/"]])
|
||||
{
|
||||
ASSIGN(_lastError, @"Could not move - destination is a descendant of source");
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
@ -1241,9 +1297,23 @@ static NSStringEncoding defaultEncoding;
|
|||
toPath: (NSString*)dst
|
||||
error: (NSError**)error
|
||||
{
|
||||
BOOL result;
|
||||
BOOL result;
|
||||
|
||||
DESTROY(_lastError);
|
||||
result = [self movePath: src toPath: dst handler: nil];
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
if (NO == result)
|
||||
{
|
||||
*error = [self _errorFrom: src to: dst];
|
||||
}
|
||||
else
|
||||
{
|
||||
*error = nil;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1297,6 +1367,7 @@ static NSStringEncoding defaultEncoding;
|
|||
if ([[destination stringByAppendingString: @"/"]
|
||||
hasPrefix: [source stringByAppendingString: @"/"]])
|
||||
{
|
||||
ASSIGN(_lastError, @"Could not link - destination is a descendant of source");
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
@ -1350,7 +1421,8 @@ static NSStringEncoding defaultEncoding;
|
|||
[self changeFileAttributes: attrs atPath: destination];
|
||||
return YES;
|
||||
#else
|
||||
return NO; // Links not supported on this platform
|
||||
ASSIN(_lastError, @"Links not supported on this platform");
|
||||
return NO;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1378,6 +1450,7 @@ static NSStringEncoding defaultEncoding;
|
|||
lpath = [self fileSystemRepresentationWithPath: path];
|
||||
if (lpath == 0 || *lpath == 0)
|
||||
{
|
||||
ASSIGN(_lastError, @"Could not remove - no path");
|
||||
return NO;
|
||||
}
|
||||
else
|
||||
|
@ -1472,7 +1545,21 @@ static NSStringEncoding defaultEncoding;
|
|||
{
|
||||
BOOL result;
|
||||
|
||||
DESTROY(_lastError);
|
||||
result = [self removeFileAtPath: path handler: nil];
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
if (NO == result)
|
||||
{
|
||||
*error = [self _errorFrom: path to: nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
*error = nil;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1501,6 +1588,7 @@ static NSStringEncoding defaultEncoding;
|
|||
|
||||
if (lpath == 0 || *lpath == _NUL)
|
||||
{
|
||||
ASSIGN(_lastError, @"no path given");
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
@ -1555,6 +1643,7 @@ static NSStringEncoding defaultEncoding;
|
|||
|
||||
if (lpath == 0 || *lpath == _NUL)
|
||||
{
|
||||
ASSIGN(_lastError, @"no path given");
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
@ -1591,6 +1680,7 @@ static NSStringEncoding defaultEncoding;
|
|||
|
||||
if (lpath == 0 || *lpath == _NUL)
|
||||
{
|
||||
ASSIGN(_lastError, @"no path given");
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
@ -1632,6 +1722,7 @@ static NSStringEncoding defaultEncoding;
|
|||
|
||||
if (lpath == 0 || *lpath == _NUL)
|
||||
{
|
||||
ASSIGN(_lastError, @"no path given");
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
@ -1679,6 +1770,7 @@ static NSStringEncoding defaultEncoding;
|
|||
|
||||
if (lpath == 0 || *lpath == _NUL)
|
||||
{
|
||||
ASSIGN(_lastError, @"no path given");
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
@ -1872,7 +1964,8 @@ static NSStringEncoding defaultEncoding;
|
|||
error: (NSError**)error
|
||||
{
|
||||
NSDictionary *d;
|
||||
|
||||
|
||||
DESTROY(_lastError);
|
||||
d = [GSAttrDictionaryClass attributesAt:
|
||||
[self fileSystemRepresentationWithPath: path] traverseLink: NO];
|
||||
|
||||
|
@ -1880,7 +1973,7 @@ static NSStringEncoding defaultEncoding;
|
|||
{
|
||||
if (nil == d)
|
||||
{
|
||||
*error = [NSError _last];
|
||||
*error = [self _errorFrom: path to: nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2013,6 +2106,7 @@ static NSStringEncoding defaultEncoding;
|
|||
return [NSDictionary dictionaryWithObjects: values forKeys: keys count: 5];
|
||||
#else
|
||||
NSLog(@"NSFileManager", @"no support for filesystem attributes");
|
||||
ASSIGN(_lastError, @"no support for filesystem attributes");
|
||||
return nil;
|
||||
#endif
|
||||
#endif /* MINGW */
|
||||
|
@ -2138,6 +2232,7 @@ static NSStringEncoding defaultEncoding;
|
|||
|
||||
return (symlink(oldpath, newpath) == 0);
|
||||
#else
|
||||
ASSIGN(_lastError, @"symbolic links not supported on this system");
|
||||
return NO;
|
||||
#endif
|
||||
}
|
||||
|
@ -2162,6 +2257,7 @@ static NSStringEncoding defaultEncoding;
|
|||
return nil;
|
||||
}
|
||||
#else
|
||||
ASSIGN(_lastError, @"symbolic links not supported on this system");
|
||||
return nil;
|
||||
#endif
|
||||
}
|
||||
|
@ -2934,6 +3030,7 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
|
|||
[pool drain];
|
||||
return YES;
|
||||
#else
|
||||
ASSIGN(_lastError, @"Links not supported on this platform");
|
||||
return NO;
|
||||
#endif
|
||||
}
|
||||
|
@ -2983,6 +3080,57 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
|
|||
return NO;
|
||||
}
|
||||
|
||||
- (NSError*) _errorFrom: (NSString *)fromPath to: (NSString *)toPath
|
||||
{
|
||||
NSError *error;
|
||||
NSDictionary *errorInfo;
|
||||
NSString *message;
|
||||
NSString *domain;
|
||||
NSInteger code;
|
||||
|
||||
if (_lastError)
|
||||
{
|
||||
message = _lastError;
|
||||
domain = NSCocoaErrorDomain;
|
||||
code = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = [NSError _last];
|
||||
message = [error localizedDescription];
|
||||
domain = [error domain];
|
||||
code = [error code];
|
||||
}
|
||||
|
||||
if (fromPath && toPath)
|
||||
{
|
||||
errorInfo = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
fromPath, @"FromPath",
|
||||
toPath, @"ToPath",
|
||||
message, NSLocalizedDescriptionKey,
|
||||
nil];
|
||||
}
|
||||
else if (fromPath)
|
||||
{
|
||||
errorInfo = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
fromPath, @"Path",
|
||||
message, NSLocalizedDescriptionKey,
|
||||
nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
errorInfo = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
message, NSLocalizedDescriptionKey,
|
||||
nil];
|
||||
}
|
||||
|
||||
error = [NSError errorWithDomain: domain
|
||||
code: code
|
||||
userInfo: errorInfo];
|
||||
DESTROY(_lastError);
|
||||
return error;
|
||||
}
|
||||
|
||||
@end /* NSFileManager (PrivateMethods) */
|
||||
|
||||
|
||||
|
|
|
@ -4,15 +4,20 @@
|
|||
#import <Foundation/NSFileManager.h>
|
||||
#import <Foundation/NSProcessInfo.h>
|
||||
#import <Foundation/NSPathUtilities.h>
|
||||
#import <Foundation/NSError.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
NSAutoreleasePool *arp = [NSAutoreleasePool new];
|
||||
NSFileManager *mgr = [NSFileManager defaultManager];
|
||||
NSString *dir = @"NSFileManagerTestDir";
|
||||
NSDictionary *attr;
|
||||
NSString *dirInDir;
|
||||
NSString *str1,*str2;
|
||||
NSError *err;
|
||||
NSDictionary *errInfo;
|
||||
BOOL exists;
|
||||
BOOL isDir;
|
||||
|
||||
dirInDir
|
||||
= [@"TestDirectory" stringByAppendingPathComponent: @"WithinDirectory"];
|
||||
|
@ -20,46 +25,38 @@ int main()
|
|||
PASS(mgr != nil && [mgr isKindOfClass: [NSFileManager class]],
|
||||
"NSFileManager understands +defaultManager");
|
||||
|
||||
/* remove test directory if it exists */
|
||||
{
|
||||
BOOL exists,isDir;
|
||||
exists = [mgr fileExistsAtPath: dir isDirectory: &isDir];
|
||||
if (exists)
|
||||
{
|
||||
[mgr removeFileAtPath: dir handler: nil];
|
||||
}
|
||||
}
|
||||
/* remove test directory if it exists */
|
||||
exists = [mgr fileExistsAtPath: dir isDirectory: &isDir];
|
||||
if (exists)
|
||||
{
|
||||
[mgr removeFileAtPath: dir handler: nil];
|
||||
}
|
||||
PASS([mgr fileAttributesAtPath: dir traverseLink: NO] == nil,
|
||||
"NSFileManager returns nil for attributes of non-existent file");
|
||||
|
||||
|
||||
{
|
||||
NSDictionary *attr;
|
||||
BOOL isDir;
|
||||
PASS([mgr createDirectoryAtPath: dir attributes: nil],
|
||||
"NSFileManager can create a directory");
|
||||
PASS([mgr fileExistsAtPath: dir isDirectory: &isDir] &&
|
||||
isDir == YES,
|
||||
"exists and is a directory");
|
||||
PASS([mgr fileAttributesAtPath: dir traverseLink: NO] != nil,
|
||||
"NSFileManager returns non-nil for attributes of existing file");
|
||||
attr = [mgr fileAttributesAtPath: dir traverseLink: NO];
|
||||
PASS(attr != nil,
|
||||
"NSFileManager returns non-nil for attributes of existing file");
|
||||
PASS([NSUserName() isEqual: [attr fileOwnerAccountName]],
|
||||
"newly created file is owned by current user");
|
||||
PASS([mgr createDirectoryAtPath: dir attributes: nil],
|
||||
"NSFileManager can create a directory");
|
||||
PASS([mgr fileExistsAtPath: dir isDirectory: &isDir] &&
|
||||
isDir == YES,
|
||||
"exists and is a directory");
|
||||
PASS([mgr fileAttributesAtPath: dir traverseLink: NO] != nil,
|
||||
"NSFileManager returns non-nil for attributes of existing file");
|
||||
attr = [mgr fileAttributesAtPath: dir traverseLink: NO];
|
||||
PASS(attr != nil,
|
||||
"NSFileManager returns non-nil for attributes of existing file");
|
||||
PASS([NSUserName() isEqual: [attr fileOwnerAccountName]],
|
||||
"newly created file is owned by current user");
|
||||
NSLog(@"'%@', '%@'", NSUserName(), [attr fileOwnerAccountName]);
|
||||
attr = [mgr attributesOfItemAtPath: dir error: &err];
|
||||
PASS(attr != nil && err == nil,
|
||||
"[NSFileManager attributesOfItemAtPath:error:] returns non-nil for "
|
||||
"attributes and nil for error in the case of existing file");
|
||||
attr = [mgr attributesOfItemAtPath:
|
||||
[dir stringByAppendingPathComponent:
|
||||
@"thispathMUSTNOTexistatyoursystem"] error: &err];
|
||||
PASS(attr == nil && err != nil,
|
||||
"[NSFileManager attributesOfItemAtPath:error:] returns nil for "
|
||||
"attributes and non-nil for error in the case of non-existent file");
|
||||
}
|
||||
attr = [mgr attributesOfItemAtPath: dir error: &err];
|
||||
PASS(attr != nil && err == nil,
|
||||
"[NSFileManager attributesOfItemAtPath:error:] returns non-nil for "
|
||||
"attributes and nil for error in the case of existing file");
|
||||
attr = [mgr attributesOfItemAtPath:
|
||||
[dir stringByAppendingPathComponent:
|
||||
@"thispathMUSTNOTexistatyoursystem"] error: &err];
|
||||
PASS(attr == nil && err != nil,
|
||||
"[NSFileManager attributesOfItemAtPath:error:] returns nil for "
|
||||
"attributes and non-nil for error in the case of non-existent file");
|
||||
|
||||
PASS([mgr changeCurrentDirectoryPath: dir],
|
||||
"NSFileManager can change directories");
|
||||
|
@ -160,23 +157,23 @@ NSLog(@"'%@', '%@'", NSUserName(), [attr fileOwnerAccountName]);
|
|||
PASS([mgr changeCurrentDirectoryPath: @"subdir"],
|
||||
"NSFileManager can move into subdir");
|
||||
|
||||
{
|
||||
BOOL isDir;
|
||||
PASS([mgr createDirectoryAtPath: dirInDir
|
||||
withIntermediateDirectories: NO
|
||||
attributes: nil
|
||||
error: NULL] == NO,
|
||||
"NSFileManager refuses to create non-existent intermediate directories withIntermediateDirectories == NO");
|
||||
|
||||
PASS([mgr createDirectoryAtPath: dirInDir
|
||||
withIntermediateDirectories: YES
|
||||
attributes: nil
|
||||
error: NULL],
|
||||
"NSFileManager can create intermediate directories withIntermediateDirectories == YES");
|
||||
PASS([mgr fileExistsAtPath: dirInDir isDirectory: &isDir] && isDir == YES,
|
||||
"NSFileManager create directory and intermediate directory that actually exist");
|
||||
PASS([mgr createDirectoryAtPath: dirInDir
|
||||
withIntermediateDirectories: NO
|
||||
attributes: nil
|
||||
error: &err] == NO
|
||||
&& err != nil && [[err domain] isEqual: NSCocoaErrorDomain]
|
||||
&& (errInfo = [err userInfo]) != nil
|
||||
&& [errInfo objectForKey: NSLocalizedDescriptionKey] != nil
|
||||
&& [errInfo objectForKey: @"Path"] != nil,
|
||||
"NSFileManager refuses to create intermediate directories");
|
||||
|
||||
}
|
||||
PASS([mgr createDirectoryAtPath: dirInDir
|
||||
withIntermediateDirectories: YES
|
||||
attributes: nil
|
||||
error: &err] && err == nil,
|
||||
"NSFileManager can create intermediate directories");
|
||||
PASS([mgr fileExistsAtPath: dirInDir isDirectory: &isDir] && isDir == YES,
|
||||
"NSFileManager create directory and intermediate directory");
|
||||
|
||||
PASS_EXCEPTION([mgr removeFileAtPath: @"." handler: nil];,
|
||||
NSInvalidArgumentException,
|
||||
|
@ -186,19 +183,14 @@ NSLog(@"'%@', '%@'", NSUserName(), [attr fileOwnerAccountName]);
|
|||
NSInvalidArgumentException,
|
||||
"NSFileManager -removeFileAtPath: @\"..\" throws exception");
|
||||
/* clean up */
|
||||
{
|
||||
BOOL exists,isDir;
|
||||
[mgr changeCurrentDirectoryPath: [[[mgr currentDirectoryPath] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent]];
|
||||
exists = [mgr fileExistsAtPath: dir isDirectory: &isDir];
|
||||
if (exists || isDir)
|
||||
{
|
||||
PASS([mgr removeFileAtPath: dir handler: nil],
|
||||
"NSFileManager removes a directory");
|
||||
PASS(![mgr fileExistsAtPath: dir],"directory no longer exists");
|
||||
}
|
||||
|
||||
isDir = NO;
|
||||
}
|
||||
[mgr changeCurrentDirectoryPath: [[[mgr currentDirectoryPath] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent]];
|
||||
exists = [mgr fileExistsAtPath: dir isDirectory: &isDir];
|
||||
if (exists || isDir)
|
||||
{
|
||||
PASS([mgr removeFileAtPath: dir handler: nil],
|
||||
"NSFileManager removes a directory");
|
||||
PASS(![mgr fileExistsAtPath: dir],"directory no longer exists");
|
||||
}
|
||||
|
||||
[arp release]; arp = nil;
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue