mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
Add two previously unimplemented methods.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28252 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
d79eb3cab4
commit
9cc306b2e1
3 changed files with 355 additions and 316 deletions
|
@ -1,3 +1,10 @@
|
|||
2009-04-27 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Headers/Foundation/NSData.h:
|
||||
* Source/NSData.m:
|
||||
Implement new MacOS-X methods for writing data (no support for
|
||||
returning NSError objects yet).
|
||||
|
||||
2009-04-26 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/GSFTPURLHandle.m: Implement full support for multiline
|
||||
|
|
|
@ -102,12 +102,23 @@ enum {
|
|||
- (BOOL) isEqualToData: (NSData*)other;
|
||||
- (NSUInteger) length;
|
||||
|
||||
// Storing Data
|
||||
|
||||
/**
|
||||
* <p>Writes a copy of the data encapsulated by the receiver to a file
|
||||
* at path. If the useAuxiliaryFile flag is YES, this writes to a
|
||||
* temporary file and then renames that to the file at path, thus
|
||||
* ensuring that path exists and does not contain partially written
|
||||
* data at any point.
|
||||
* </p>
|
||||
* <p>On success returns YES, on failure returns NO.
|
||||
* </p>
|
||||
*/
|
||||
- (BOOL) writeToFile: (NSString*)path
|
||||
atomically: (BOOL)useAuxiliaryFile;
|
||||
|
||||
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
|
||||
/**
|
||||
* Writes a copy of the contents of the receiver to the specified URL.
|
||||
*/
|
||||
- (BOOL) writeToURL: (NSURL*)anURL atomically: (BOOL)flag;
|
||||
#endif
|
||||
|
||||
|
@ -131,11 +142,23 @@ enum {
|
|||
atIndex: (unsigned int)index;
|
||||
|
||||
#if OS_API_VERSION(100400,GS_API_LATEST)
|
||||
/** Not implemented */
|
||||
/**
|
||||
* <p>Writes a copy of the data encapsulated by the receiver to a file
|
||||
* at path. If the NSAtomicWrite option is set, this writes to a
|
||||
* temporary file and then renames that to the file at path, thus
|
||||
* ensuring that path exists and does not contain partially written
|
||||
* data at any point.
|
||||
* </p>
|
||||
* <p>On success returns YES, on failure returns NO.
|
||||
* </p>
|
||||
*/
|
||||
- (BOOL) writeToFile: (NSString *)path
|
||||
options: (NSUInteger)writeOptionsMask
|
||||
error: (NSError **)errorPtr;
|
||||
/** Not implemented */
|
||||
|
||||
/**
|
||||
* Writes a copy of the contents of the receiver to the specified URL.
|
||||
*/
|
||||
- (BOOL) writeToURL: (NSURL *)url
|
||||
options: (NSUInteger)writeOptionsMask
|
||||
error: (NSError **)errorPtr;
|
||||
|
|
633
Source/NSData.m
633
Source/NSData.m
|
@ -839,334 +839,27 @@ failure:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Writes a copy of the data encapsulated by the receiver to a file
|
||||
* at path. If the useAuxiliaryFile flag is YES, this writes to a
|
||||
* temporary file and then renames that to the file at path, thus
|
||||
* ensuring that path exists and does not contain partially written
|
||||
* data at any point.
|
||||
* </p>
|
||||
* <p>On success returns YES, on failure returns NO.
|
||||
* </p>
|
||||
*/
|
||||
- (BOOL) writeToFile: (NSString*)path atomically: (BOOL)useAuxiliaryFile
|
||||
{
|
||||
#if defined(__MINGW32__)
|
||||
NSUInteger length = [path length];
|
||||
unichar wthePath[length + 100];
|
||||
unichar wtheRealPath[length + 100];
|
||||
#else
|
||||
char thePath[BUFSIZ*2+8];
|
||||
char theRealPath[BUFSIZ*2];
|
||||
#endif
|
||||
int c;
|
||||
FILE *theFile;
|
||||
BOOL error_BadPath = YES;
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
[path getCharacters: wtheRealPath];
|
||||
wtheRealPath[length] = L'\0';
|
||||
error_BadPath = (length <= 0);
|
||||
#else
|
||||
if ([path canBeConvertedToEncoding: [NSString defaultCStringEncoding]])
|
||||
{
|
||||
const char *local_c_path = [path cString];
|
||||
|
||||
if (local_c_path != 0 && strlen(local_c_path) < (BUFSIZ*2))
|
||||
{
|
||||
strcpy(theRealPath,local_c_path);
|
||||
error_BadPath = NO;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (error_BadPath)
|
||||
{
|
||||
NSWarnMLog(@"Open (%@) attempt failed - bad path",path);
|
||||
return NO;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MKSTEMP
|
||||
if (useAuxiliaryFile)
|
||||
{
|
||||
int desc;
|
||||
int mask;
|
||||
|
||||
strcpy(thePath, theRealPath);
|
||||
strcat(thePath, "XXXXXX");
|
||||
if ((desc = mkstemp(thePath)) < 0)
|
||||
{
|
||||
NSWarnMLog(@"mkstemp (%s) failed - %@", thePath, [NSError _last]);
|
||||
goto failure;
|
||||
}
|
||||
mask = umask(0);
|
||||
umask(mask);
|
||||
fchmod(desc, 0644 & ~mask);
|
||||
if ((theFile = fdopen(desc, "w")) == 0)
|
||||
{
|
||||
close(desc);
|
||||
}
|
||||
return [self writeToFile: path options: NSAtomicWrite error: 0];
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(thePath, theRealPath);
|
||||
theFile = fopen(thePath, "wb");
|
||||
return [self writeToFile: path options: 0 error: 0];
|
||||
}
|
||||
#else
|
||||
if (useAuxiliaryFile)
|
||||
{
|
||||
/* Use the path name of the destination file as a prefix for the
|
||||
* mktemp() call so that we can be sure that both files are on
|
||||
* the same filesystem and the subsequent rename() will work. */
|
||||
#if defined(__MINGW32__)
|
||||
wcscpy(wthePath, wtheRealPath);
|
||||
wcscat(wthePath, L"XXXXXX");
|
||||
if (_wmktemp(wthePath) == 0)
|
||||
{
|
||||
NSWarnMLog(@"mktemp (%@) failed - %@",
|
||||
[NSString stringWithCharacters: wthePath length: wcslen(wthePath)],
|
||||
[NSError _last]);
|
||||
goto failure;
|
||||
}
|
||||
#else
|
||||
strcpy(thePath, theRealPath);
|
||||
strcat(thePath, "XXXXXX");
|
||||
if (mktemp(thePath) == 0)
|
||||
{
|
||||
NSWarnMLog(@"mktemp (%s) failed - %@", thePath, [NSError _last]);
|
||||
goto failure;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(__MINGW32__)
|
||||
wcscpy(wthePath,wtheRealPath);
|
||||
#else
|
||||
strcpy(thePath, theRealPath);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Open the file (whether temp or real) for writing. */
|
||||
#if defined(__MINGW32__)
|
||||
theFile = _wfopen(wthePath, L"wb");
|
||||
#else
|
||||
theFile = fopen(thePath, "wb");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (theFile == 0)
|
||||
{
|
||||
/* Something went wrong; we weren't
|
||||
* even able to open the file. */
|
||||
#if defined(__MINGW32__)
|
||||
NSWarnMLog(@"Open (%@) failed - %@",
|
||||
[NSString stringWithCharacters: wthePath length: wcslen(wthePath)],
|
||||
[NSError _last]);
|
||||
#else
|
||||
NSWarnMLog(@"Open (%s) failed - %@", thePath, [NSError _last]);
|
||||
#endif
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Now we try and write the NSData's bytes to the file. Here `c' is
|
||||
* the number of bytes which were successfully written to the file
|
||||
* in the fwrite() call. */
|
||||
c = fwrite([self bytes], sizeof(char), [self length], theFile);
|
||||
|
||||
if (c < (int)[self length]) /* We failed to write everything for
|
||||
* some reason. */
|
||||
{
|
||||
#if defined(__MINGW32__)
|
||||
NSWarnMLog(@"Fwrite (%@) failed - %@",
|
||||
[NSString stringWithCharacters: wthePath length: wcslen(wthePath)],
|
||||
[NSError _last]);
|
||||
#else
|
||||
NSWarnMLog(@"Fwrite (%s) failed - %@", thePath, [NSError _last]);
|
||||
#endif
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* We're done, so close everything up. */
|
||||
c = fclose(theFile);
|
||||
|
||||
if (c != 0) /* I can't imagine what went wrong
|
||||
* closing the file, but we got here,
|
||||
* so we need to deal with it. */
|
||||
{
|
||||
#if defined(__MINGW32__)
|
||||
NSWarnMLog(@"Fclose (%@) failed - %@",
|
||||
[NSString stringWithCharacters: wthePath length: wcslen(wthePath)],
|
||||
[NSError _last]);
|
||||
#else
|
||||
NSWarnMLog(@"Fclose (%s) failed - %@", thePath, [NSError _last]);
|
||||
#endif
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* If we used a temporary file, we still need to rename() it be the
|
||||
* real file. Also, we need to try to retain the file attributes of
|
||||
* the original file we are overwriting (if we are) */
|
||||
if (useAuxiliaryFile)
|
||||
{
|
||||
NSFileManager *mgr = [NSFileManager defaultManager];
|
||||
NSMutableDictionary *att = nil;
|
||||
#if defined(__MINGW32__)
|
||||
NSUInteger perm;
|
||||
#endif
|
||||
|
||||
if ([mgr fileExistsAtPath: path])
|
||||
{
|
||||
att = [[mgr fileAttributesAtPath: path
|
||||
traverseLink: YES] mutableCopy];
|
||||
IF_NO_GC(TEST_AUTORELEASE(att));
|
||||
}
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
/* To replace the existing file on windows, it must be writable.
|
||||
*/
|
||||
perm = [att filePosixPermissions];
|
||||
if (perm != NSNotFound && (perm & 0200) == 0)
|
||||
{
|
||||
[mgr changeFileAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithUnsignedInt: 0777], NSFilePosixPermissions,
|
||||
nil] atPath: path];
|
||||
}
|
||||
/*
|
||||
* The windoze implementation of the POSIX rename() function is buggy
|
||||
* and doesn't work if the destination file already exists ... so we
|
||||
* try to use a windoze specific function instead.
|
||||
*/
|
||||
#if 0
|
||||
if (ReplaceFile(theRealPath, thePath, 0,
|
||||
REPLACEFILE_IGNORE_MERGE_ERRORS, 0, 0) != 0)
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = -1;
|
||||
}
|
||||
#else
|
||||
if (MoveFileExW(wthePath, wtheRealPath, MOVEFILE_REPLACE_EXISTING) != 0)
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
/* Windows 9x does not support MoveFileEx */
|
||||
else if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||
{
|
||||
unichar secondaryFile[length + 100];
|
||||
|
||||
wcscpy(secondaryFile, wthePath);
|
||||
wcscat(secondaryFile, L"-delete");
|
||||
// Delete the intermediate name just in case
|
||||
DeleteFileW(secondaryFile);
|
||||
// Move the existing file to the temp name
|
||||
if (MoveFileW(wtheRealPath, secondaryFile) != 0)
|
||||
{
|
||||
if (MoveFileW(wthePath, wtheRealPath) != 0)
|
||||
{
|
||||
c = 0;
|
||||
// Delete the old file if possible
|
||||
DeleteFileW(secondaryFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
c = -1; // failure, restore the old file if possible
|
||||
MoveFileW(secondaryFile, wtheRealPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c = -1; // failure
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c = -1;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
c = rename(thePath, theRealPath);
|
||||
#endif
|
||||
if (c != 0) /* Many things could go wrong, I guess. */
|
||||
{
|
||||
#if defined(__MINGW32__)
|
||||
NSWarnMLog(@"Rename ('%@' to '%@') failed - %@",
|
||||
[NSString stringWithCharacters: wthePath
|
||||
length: wcslen(wthePath)],
|
||||
[NSString stringWithCharacters: wtheRealPath
|
||||
length: wcslen(wtheRealPath)],
|
||||
[NSError _last]);
|
||||
#else
|
||||
NSWarnMLog(@"Rename ('%s' to '%s') failed - %@",
|
||||
thePath, theRealPath, [NSError _last]);
|
||||
#endif
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (att != nil)
|
||||
{
|
||||
/*
|
||||
* We have created a new file - so we attempt to make it's
|
||||
* attributes match that of the original.
|
||||
*/
|
||||
[att removeObjectForKey: NSFileSize];
|
||||
[att removeObjectForKey: NSFileModificationDate];
|
||||
[att removeObjectForKey: NSFileReferenceCount];
|
||||
[att removeObjectForKey: NSFileSystemNumber];
|
||||
[att removeObjectForKey: NSFileSystemFileNumber];
|
||||
[att removeObjectForKey: NSFileDeviceIdentifier];
|
||||
[att removeObjectForKey: NSFileType];
|
||||
if ([mgr changeFileAttributes: att atPath: path] == NO)
|
||||
{
|
||||
NSWarnMLog(@"Unable to correctly set all attributes for '%@'",
|
||||
path);
|
||||
}
|
||||
}
|
||||
#ifndef __MINGW32__
|
||||
else if (geteuid() == 0 && [@"root" isEqualToString: NSUserName()] == NO)
|
||||
{
|
||||
att = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
NSFileOwnerAccountName, NSUserName(), nil];
|
||||
if ([mgr changeFileAttributes: att atPath: path] == NO)
|
||||
{
|
||||
NSWarnMLog(@"Unable to correctly set ownership for '%@'", path);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* success: */
|
||||
return YES;
|
||||
|
||||
/* Just in case the failure action needs to be changed. */
|
||||
failure:
|
||||
/*
|
||||
* Attempt to tidy up by removing temporary file on failure.
|
||||
*/
|
||||
if (useAuxiliaryFile)
|
||||
{
|
||||
#if defined(__MINGW32__)
|
||||
_wunlink(wthePath);
|
||||
#else
|
||||
unlink(thePath);
|
||||
#endif
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a copy of the contents of the receiver to the specified URL.
|
||||
*/
|
||||
- (BOOL) writeToURL: (NSURL*)anURL atomically: (BOOL)flag
|
||||
{
|
||||
if ([anURL isFileURL] == YES)
|
||||
if (flag)
|
||||
{
|
||||
return [self writeToFile: [anURL path] atomically: flag];
|
||||
return [self writeToURL: anURL options: NSAtomicWrite error: 0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [anURL setResourceData: self];
|
||||
return [self writeToURL: anURL options: 0 error: 0];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1600,6 +1293,312 @@ failure:
|
|||
options: (NSUInteger)writeOptionsMask
|
||||
error: (NSError **)errorPtr
|
||||
{
|
||||
#if defined(__MINGW32__)
|
||||
NSUInteger length = [path length];
|
||||
unichar wthePath[length + 100];
|
||||
unichar wtheRealPath[length + 100];
|
||||
#else
|
||||
char thePath[BUFSIZ*2+8];
|
||||
char theRealPath[BUFSIZ*2];
|
||||
#endif
|
||||
int c;
|
||||
FILE *theFile;
|
||||
BOOL useAuxiliaryFile = NO;
|
||||
BOOL error_BadPath = YES;
|
||||
|
||||
if (writeOptionsMask & NSAtomicWrite)
|
||||
{
|
||||
useAuxiliaryFile = YES;
|
||||
}
|
||||
#if defined(__MINGW32__)
|
||||
[path getCharacters: wtheRealPath];
|
||||
wtheRealPath[length] = L'\0';
|
||||
error_BadPath = (length <= 0);
|
||||
#else
|
||||
if ([path canBeConvertedToEncoding: [NSString defaultCStringEncoding]])
|
||||
{
|
||||
const char *local_c_path = [path cString];
|
||||
|
||||
if (local_c_path != 0 && strlen(local_c_path) < (BUFSIZ*2))
|
||||
{
|
||||
strcpy(theRealPath,local_c_path);
|
||||
error_BadPath = NO;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (error_BadPath)
|
||||
{
|
||||
NSWarnMLog(@"Open (%@) attempt failed - bad path",path);
|
||||
return NO;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MKSTEMP
|
||||
if (useAuxiliaryFile)
|
||||
{
|
||||
int desc;
|
||||
int mask;
|
||||
|
||||
strcpy(thePath, theRealPath);
|
||||
strcat(thePath, "XXXXXX");
|
||||
if ((desc = mkstemp(thePath)) < 0)
|
||||
{
|
||||
NSWarnMLog(@"mkstemp (%s) failed - %@", thePath, [NSError _last]);
|
||||
goto failure;
|
||||
}
|
||||
mask = umask(0);
|
||||
umask(mask);
|
||||
fchmod(desc, 0644 & ~mask);
|
||||
if ((theFile = fdopen(desc, "w")) == 0)
|
||||
{
|
||||
close(desc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(thePath, theRealPath);
|
||||
theFile = fopen(thePath, "wb");
|
||||
}
|
||||
#else
|
||||
if (useAuxiliaryFile)
|
||||
{
|
||||
/* Use the path name of the destination file as a prefix for the
|
||||
* mktemp() call so that we can be sure that both files are on
|
||||
* the same filesystem and the subsequent rename() will work. */
|
||||
#if defined(__MINGW32__)
|
||||
wcscpy(wthePath, wtheRealPath);
|
||||
wcscat(wthePath, L"XXXXXX");
|
||||
if (_wmktemp(wthePath) == 0)
|
||||
{
|
||||
NSWarnMLog(@"mktemp (%@) failed - %@",
|
||||
[NSString stringWithCharacters: wthePath length: wcslen(wthePath)],
|
||||
[NSError _last]);
|
||||
goto failure;
|
||||
}
|
||||
#else
|
||||
strcpy(thePath, theRealPath);
|
||||
strcat(thePath, "XXXXXX");
|
||||
if (mktemp(thePath) == 0)
|
||||
{
|
||||
NSWarnMLog(@"mktemp (%s) failed - %@", thePath, [NSError _last]);
|
||||
goto failure;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(__MINGW32__)
|
||||
wcscpy(wthePath,wtheRealPath);
|
||||
#else
|
||||
strcpy(thePath, theRealPath);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Open the file (whether temp or real) for writing. */
|
||||
#if defined(__MINGW32__)
|
||||
theFile = _wfopen(wthePath, L"wb");
|
||||
#else
|
||||
theFile = fopen(thePath, "wb");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (theFile == 0)
|
||||
{
|
||||
/* Something went wrong; we weren't
|
||||
* even able to open the file. */
|
||||
#if defined(__MINGW32__)
|
||||
NSWarnMLog(@"Open (%@) failed - %@",
|
||||
[NSString stringWithCharacters: wthePath length: wcslen(wthePath)],
|
||||
[NSError _last]);
|
||||
#else
|
||||
NSWarnMLog(@"Open (%s) failed - %@", thePath, [NSError _last]);
|
||||
#endif
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Now we try and write the NSData's bytes to the file. Here `c' is
|
||||
* the number of bytes which were successfully written to the file
|
||||
* in the fwrite() call. */
|
||||
c = fwrite([self bytes], sizeof(char), [self length], theFile);
|
||||
|
||||
if (c < (int)[self length]) /* We failed to write everything for
|
||||
* some reason. */
|
||||
{
|
||||
#if defined(__MINGW32__)
|
||||
NSWarnMLog(@"Fwrite (%@) failed - %@",
|
||||
[NSString stringWithCharacters: wthePath length: wcslen(wthePath)],
|
||||
[NSError _last]);
|
||||
#else
|
||||
NSWarnMLog(@"Fwrite (%s) failed - %@", thePath, [NSError _last]);
|
||||
#endif
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* We're done, so close everything up. */
|
||||
c = fclose(theFile);
|
||||
|
||||
if (c != 0) /* I can't imagine what went wrong
|
||||
* closing the file, but we got here,
|
||||
* so we need to deal with it. */
|
||||
{
|
||||
#if defined(__MINGW32__)
|
||||
NSWarnMLog(@"Fclose (%@) failed - %@",
|
||||
[NSString stringWithCharacters: wthePath length: wcslen(wthePath)],
|
||||
[NSError _last]);
|
||||
#else
|
||||
NSWarnMLog(@"Fclose (%s) failed - %@", thePath, [NSError _last]);
|
||||
#endif
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* If we used a temporary file, we still need to rename() it be the
|
||||
* real file. Also, we need to try to retain the file attributes of
|
||||
* the original file we are overwriting (if we are) */
|
||||
if (useAuxiliaryFile)
|
||||
{
|
||||
NSFileManager *mgr = [NSFileManager defaultManager];
|
||||
NSMutableDictionary *att = nil;
|
||||
#if defined(__MINGW32__)
|
||||
NSUInteger perm;
|
||||
#endif
|
||||
|
||||
if ([mgr fileExistsAtPath: path])
|
||||
{
|
||||
att = [[mgr fileAttributesAtPath: path
|
||||
traverseLink: YES] mutableCopy];
|
||||
IF_NO_GC(TEST_AUTORELEASE(att));
|
||||
}
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
/* To replace the existing file on windows, it must be writable.
|
||||
*/
|
||||
perm = [att filePosixPermissions];
|
||||
if (perm != NSNotFound && (perm & 0200) == 0)
|
||||
{
|
||||
[mgr changeFileAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSNumber numberWithUnsignedInt: 0777], NSFilePosixPermissions,
|
||||
nil] atPath: path];
|
||||
}
|
||||
/*
|
||||
* The windoze implementation of the POSIX rename() function is buggy
|
||||
* and doesn't work if the destination file already exists ... so we
|
||||
* try to use a windoze specific function instead.
|
||||
*/
|
||||
#if 0
|
||||
if (ReplaceFile(theRealPath, thePath, 0,
|
||||
REPLACEFILE_IGNORE_MERGE_ERRORS, 0, 0) != 0)
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = -1;
|
||||
}
|
||||
#else
|
||||
if (MoveFileExW(wthePath, wtheRealPath, MOVEFILE_REPLACE_EXISTING) != 0)
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
/* Windows 9x does not support MoveFileEx */
|
||||
else if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||
{
|
||||
unichar secondaryFile[length + 100];
|
||||
|
||||
wcscpy(secondaryFile, wthePath);
|
||||
wcscat(secondaryFile, L"-delete");
|
||||
// Delete the intermediate name just in case
|
||||
DeleteFileW(secondaryFile);
|
||||
// Move the existing file to the temp name
|
||||
if (MoveFileW(wtheRealPath, secondaryFile) != 0)
|
||||
{
|
||||
if (MoveFileW(wthePath, wtheRealPath) != 0)
|
||||
{
|
||||
c = 0;
|
||||
// Delete the old file if possible
|
||||
DeleteFileW(secondaryFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
c = -1; // failure, restore the old file if possible
|
||||
MoveFileW(secondaryFile, wtheRealPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c = -1; // failure
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c = -1;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
c = rename(thePath, theRealPath);
|
||||
#endif
|
||||
if (c != 0) /* Many things could go wrong, I guess. */
|
||||
{
|
||||
#if defined(__MINGW32__)
|
||||
NSWarnMLog(@"Rename ('%@' to '%@') failed - %@",
|
||||
[NSString stringWithCharacters: wthePath
|
||||
length: wcslen(wthePath)],
|
||||
[NSString stringWithCharacters: wtheRealPath
|
||||
length: wcslen(wtheRealPath)],
|
||||
[NSError _last]);
|
||||
#else
|
||||
NSWarnMLog(@"Rename ('%s' to '%s') failed - %@",
|
||||
thePath, theRealPath, [NSError _last]);
|
||||
#endif
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (att != nil)
|
||||
{
|
||||
/*
|
||||
* We have created a new file - so we attempt to make it's
|
||||
* attributes match that of the original.
|
||||
*/
|
||||
[att removeObjectForKey: NSFileSize];
|
||||
[att removeObjectForKey: NSFileModificationDate];
|
||||
[att removeObjectForKey: NSFileReferenceCount];
|
||||
[att removeObjectForKey: NSFileSystemNumber];
|
||||
[att removeObjectForKey: NSFileSystemFileNumber];
|
||||
[att removeObjectForKey: NSFileDeviceIdentifier];
|
||||
[att removeObjectForKey: NSFileType];
|
||||
if ([mgr changeFileAttributes: att atPath: path] == NO)
|
||||
{
|
||||
NSWarnMLog(@"Unable to correctly set all attributes for '%@'",
|
||||
path);
|
||||
}
|
||||
}
|
||||
#ifndef __MINGW32__
|
||||
else if (geteuid() == 0 && [@"root" isEqualToString: NSUserName()] == NO)
|
||||
{
|
||||
att = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
NSFileOwnerAccountName, NSUserName(), nil];
|
||||
if ([mgr changeFileAttributes: att atPath: path] == NO)
|
||||
{
|
||||
NSWarnMLog(@"Unable to correctly set ownership for '%@'", path);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* success: */
|
||||
return YES;
|
||||
|
||||
/* Just in case the failure action needs to be changed. */
|
||||
failure:
|
||||
/*
|
||||
* Attempt to tidy up by removing temporary file on failure.
|
||||
*/
|
||||
if (useAuxiliaryFile)
|
||||
{
|
||||
#if defined(__MINGW32__)
|
||||
_wunlink(wthePath);
|
||||
#else
|
||||
unlink(thePath);
|
||||
#endif
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
@ -1607,6 +1606,16 @@ failure:
|
|||
options: (NSUInteger)writeOptionsMask
|
||||
error: (NSError **)errorPtr
|
||||
{
|
||||
if ([url isFileURL] == YES)
|
||||
{
|
||||
return [self writeToFile: [url path]
|
||||
options: writeOptionsMask
|
||||
error: errorPtr];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [url setResourceData: self];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
@end
|
||||
|
|
Loading…
Reference in a new issue