Revision: 2684 http://skim-app.svn.sourceforge.net/skim-app/?rev=2684&view=rev Author: hofman Date: 2007-08-19 04:28:18 -0700 (Sun, 19 Aug 2007)
Log Message: ----------- Use carbon file manager to copy and delete items for disk image creation. Modified Paths: -------------- trunk/Files_SKExtensions.h trunk/Files_SKExtensions.m trunk/SKDocument.m Modified: trunk/Files_SKExtensions.h =================================================================== --- trunk/Files_SKExtensions.h 2007-08-18 19:40:05 UTC (rev 2683) +++ trunk/Files_SKExtensions.h 2007-08-19 11:28:18 UTC (rev 2684) @@ -43,4 +43,9 @@ extern BOOL SKFileIsInTrash(NSURL *fileURL); extern BOOL SKFileExistsAtPath(NSString *path); extern NSDate *SKFileModificationDateAtPath(NSString *path); -extern NSString *SKTemporaryDirectoryCreating(BOOL create); +extern NSString *SKUniqueDirectoryCreating(NSString *basePath, BOOL create); + +extern OSErr FSDeleteContainerContents(const FSRef *container); +extern OSErr FSDeleteContainer(const FSRef *container); +extern OSErr FSPathDeleteContainer(const UInt8 *containerPath); + \ No newline at end of file Modified: trunk/Files_SKExtensions.m =================================================================== --- trunk/Files_SKExtensions.m 2007-08-18 19:40:05 UTC (rev 2683) +++ trunk/Files_SKExtensions.m 2007-08-19 11:28:18 UTC (rev 2684) @@ -81,22 +81,160 @@ return nil; } -NSString *SKTemporaryDirectoryCreating(BOOL create) { - NSString *baseTmpDir = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSBundle mainBundle] bundleIdentifier]]; - NSString *tmpDir = baseTmpDir; - NSString *tmpDirName; - int i = 0; +NSString *SKUniqueDirectoryCreating(NSString *basePath, BOOL create) { + CFUUIDRef uuid = CFUUIDCreate(NULL); + NSString *tmpDirName = [(NSString *)CFUUIDCreateString(NULL, uuid) autorelease]; + CFRelease(uuid); + BOOL success = YES; - while (SKFileExistsAtPath(tmpDir)) - tmpDir = [baseTmpDir stringByAppendingFormat:@"-%i", ++i]; - - tmpDirName = [tmpDir lastPathComponent]; - if (success && create) { + if (create) { FSRef tmpRef; - success = noErr == FSPathMakeRef((UInt8 *)[NSTemporaryDirectory() fileSystemRepresentation], &tmpRef, NULL) && + success = noErr == FSPathMakeRef((UInt8 *)[basePath fileSystemRepresentation], &tmpRef, NULL) && noErr == FSCreateDirectoryUnicode(&tmpRef, [tmpDirName length], (const UniChar *)[tmpDirName cStringUsingEncoding:NSUnicodeStringEncoding], kFSCatInfoNone, NULL, NULL, NULL, NULL); } - return success ? tmpDir : nil; + return success ? [basePath stringByAppendingPathComponent:tmpDirName] : nil; } + +// These are taken from MoreFilesX + +struct FSDeleteContainerGlobals +{ + OSErr result; /* result */ + ItemCount actualObjects; /* number of objects returned */ + FSCatalogInfo catalogInfo; /* FSCatalogInfo */ +}; +typedef struct FSDeleteContainerGlobals FSDeleteContainerGlobals; + +static +void +FSDeleteContainerLevel( + const FSRef *container, + FSDeleteContainerGlobals *theGlobals) +{ + /* level locals */ + FSIterator iterator; + FSRef itemToDelete; + UInt16 nodeFlags; + + /* Open FSIterator for flat access and give delete optimization hint */ + theGlobals->result = FSOpenIterator(container, kFSIterateFlat + kFSIterateDelete, &iterator); + require_noerr(theGlobals->result, FSOpenIterator); + + /* delete the contents of the directory */ + do + { + /* get 1 item to delete */ + theGlobals->result = FSGetCatalogInfoBulk(iterator, 1, &theGlobals->actualObjects, + NULL, kFSCatInfoNodeFlags, &theGlobals->catalogInfo, + &itemToDelete, NULL, NULL); + if ( (noErr == theGlobals->result) && (1 == theGlobals->actualObjects) ) + { + /* save node flags in local in case we have to recurse */ + nodeFlags = theGlobals->catalogInfo.nodeFlags; + + /* is it a file or directory? */ + if ( 0 != (nodeFlags & kFSNodeIsDirectoryMask) ) + { + /* it's a directory -- delete its contents before attempting to delete it */ + FSDeleteContainerLevel(&itemToDelete, theGlobals); + } + /* are we still OK to delete? */ + if ( noErr == theGlobals->result ) + { + /* is item locked? */ + if ( 0 != (nodeFlags & kFSNodeLockedMask) ) + { + /* then attempt to unlock it (ignore result since FSDeleteObject will set it correctly) */ + theGlobals->catalogInfo.nodeFlags = nodeFlags & ~kFSNodeLockedMask; + (void) FSSetCatalogInfo(&itemToDelete, kFSCatInfoNodeFlags, &theGlobals->catalogInfo); + } + /* delete the item */ + theGlobals->result = FSDeleteObject(&itemToDelete); + } + } + } while ( noErr == theGlobals->result ); + + /* we found the end of the items normally, so return noErr */ + if ( errFSNoMoreItems == theGlobals->result ) + { + theGlobals->result = noErr; + } + + /* close the FSIterator (closing an open iterator should never fail) */ + verify_noerr(FSCloseIterator(iterator)); + +FSOpenIterator: + + return; +} + +OSErr +FSDeleteContainerContents( + const FSRef *container) +{ + FSDeleteContainerGlobals theGlobals; + + /* delete container's contents */ + FSDeleteContainerLevel(container, &theGlobals); + + return ( theGlobals.result ); +} + +OSErr +FSDeleteContainer( + const FSRef *container) +{ + OSErr result; + FSCatalogInfo catalogInfo; + + /* get nodeFlags for container */ + result = FSGetCatalogInfo(container, kFSCatInfoNodeFlags, &catalogInfo, NULL, NULL,NULL); + require_noerr(result, FSGetCatalogInfo); + + /* make sure container is a directory */ + require_action(0 != (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask), ContainerNotDirectory, result = dirNFErr); + + /* delete container's contents */ + result = FSDeleteContainerContents(container); + require_noerr(result, FSDeleteContainerContents); + + /* is container locked? */ + if ( 0 != (catalogInfo.nodeFlags & kFSNodeLockedMask) ) + { + /* then attempt to unlock container (ignore result since FSDeleteObject will set it correctly) */ + catalogInfo.nodeFlags &= ~kFSNodeLockedMask; + (void) FSSetCatalogInfo(container, kFSCatInfoNodeFlags, &catalogInfo); + } + + /* delete the container */ + result = FSDeleteObject(container); + +FSDeleteContainerContents: +ContainerNotDirectory: +FSGetCatalogInfo: + + return ( result ); +} + +OSErr +FSPathDeleteContainer( + const UInt8 *containerPath) +{ + OSErr result; + FSRef container; + Boolean isDirectory; + + result = FSPathMakeRef(containerPath, &container, &isDirectory); + if (isDirectory == false) + result = errFSNotAFolder; + require_noerr(result, FSPathMakeRef); + + /* delete the container recursively */ + result = FSDeleteContainer(&container); + +FSPathMakeRef: + + return ( result ); +} Modified: trunk/SKDocument.m =================================================================== --- trunk/SKDocument.m 2007-08-18 19:40:05 UTC (rev 2683) +++ trunk/SKDocument.m 2007-08-19 11:28:18 UTC (rev 2684) @@ -591,7 +591,7 @@ NSAutoreleasePool *pool = [NSAutoreleasePool new]; - NSString *tmpDir = SKTemporaryDirectoryCreating(YES); + NSString *tmpDir = SKUniqueDirectoryCreating(NSTemporaryDirectory(), YES); BOOL success = tmpDir != nil; NSString *sourcePath = [[[info objectForKey:@"sourcePath"] copy] autorelease]; @@ -599,9 +599,11 @@ NSString *name = [[targetPath lastPathComponent] stringByDeletingPathExtension]; NSString *tmpImagePath1 = [[tmpDir stringByAppendingPathComponent:name] stringByAppendingPathExtension:@"sparseimage"]; NSString *tmpImagePath2 = [[tmpDir stringByAppendingPathComponent:name] stringByAppendingPathExtension:@"dmg"]; - NSString *tmpMountPath = [tmpDir stringByAppendingPathComponent:name]; + NSString *tmpMountPath = SKUniqueDirectoryCreating(@"/tmp", NO); // we don't use tmpDir because the mountpath has a maximum length of 90 BOOL didAttach = NO; + + @try { if (success) { success = [NSTask runTaskWithLaunchPath:@"/usr/bin/hdiutil" @@ -619,10 +621,7 @@ } if (success) { - // we can't use NSFileManager because it's not thread safe, while FSPathCopyObjectSync complains about not enough space - success = [NSTask runTaskWithLaunchPath:@"/bin/cp" - arguments:[NSArray arrayWithObjects:@"-f", sourcePath, tmpMountPath, nil] - currentDirectoryPath:tmpDir]; + success = noErr == FSPathCopyObjectSync((const char *)[sourcePath fileSystemRepresentation], (const char *)[tmpMountPath fileSystemRepresentation], (CFStringRef)[sourcePath lastPathComponent], NULL, kFSFileOperationOverwrite); } if (didAttach) { @@ -638,13 +637,10 @@ } if (success) { - success = [NSTask runTaskWithLaunchPath:@"/bin/cp" - arguments:[NSArray arrayWithObjects:@"-f", tmpImagePath2, targetPath, nil] - currentDirectoryPath:tmpDir]; + success = noErr == FSPathCopyObjectSync((const char *)[tmpImagePath2 fileSystemRepresentation], (const char *)[[targetPath stringByDeletingLastPathComponent] fileSystemRepresentation], (CFStringRef)[targetPath lastPathComponent], NULL, kFSFileOperationOverwrite); } - // easier than FSDeleteObject, because that cannot delete the directory recursively - [NSTask launchedTaskWithLaunchPath:@"/bin/rm" arguments:[NSArray arrayWithObjects:@"-rf", tmpDir, nil]]; + FSPathDeleteContainer((const UInt8 *)[tmpDir fileSystemRepresentation]); } @catch(id exception) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ Skim-app-commit mailing list Skim-app-commit@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/skim-app-commit