2

I have an OSX xcode project, which works perfectly until I turn the sandbox on.

Under Capabilities, I have turn on Sandbox, and File access: User Selected File - Read/Write

My project is like this, when user clicks on a button, the NSSavePanel will popup, user specifies the save directory and file name (ie. myfile.dmg), and once he or she clicks on save, the program will create dmg file using NSTask and hdiutil to the specific path. Here is my code:

__block NSSavePanel *saveDlg = [NSSavePanel savePanel];
    // Enable options in the dialog.
    [saveDlg setCanCreateDirectories:YES];
    [saveDlg setAllowedFileTypes:[NSArray arrayWithObject:@"dmg"]];
    [saveDlg setCanSelectHiddenExtension:YES];
    [saveDlg beginSheetModalForWindow:self.view.window completionHandler:^ (NSInteger result) {
        if (result == NSFileHandlingPanelOKButton) {

            BOOL bSuccess = [self checkErrorHandler: saveDlg.URL optionToCheck: 8];
            if (bSuccess) {
                [self createDMG:saveDlg.URL];
            }
        }

        saveDlg = nil;

    }];

Here is my createDMG method:

- (void)createDMG:(NSURL *)myurl{

self.url = myurl;
self.createTask = [[NSTask alloc] init];
NSPipe *outputPipe = [NSPipe pipe];
NSPipe *errorPipe = [NSPipe pipe];
NSPipe *writePipe = [NSPipe pipe];

self.fhCreateOutput = [outputPipe fileHandleForReading];
self.fhCreateError =  [errorPipe fileHandleForReading];

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

[nc addObserver:self selector:@selector(createNotifiedForStdOutput:) name:NSFileHandleReadCompletionNotification object:self.fhCreateOutput];
[nc addObserver:self selector:@selector(createNotifiedForStdError:)  name:NSFileHandleReadCompletionNotification object:self.fhCreateError];
[nc addObserver:self selector:@selector(createNotifiedForComplete:)  name:NSTaskDidTerminateNotification object:self.createTask];

NSFileHandle *writeHandle = [writePipe fileHandleForWriting];
NSString *pw = [self getPlainTextPassword:nil];

[writeHandle writeData: [[NSString stringWithFormat:@"%@\0\n", pw] dataUsingEncoding:NSUTF8StringEncoding]];
[writeHandle closeFile];
[self.createTask setStandardInput:writePipe];

NSString *directoryPath = [self.url.path stringByDeletingLastPathComponent];

NSString *fileName = [[self.url absoluteString] lastPathComponent];

[self.createTask setLaunchPath: @"/usr/bin/hdiutil"];
[self.createTask setCurrentDirectoryPath:directoryPath];

[self.createTask setArguments:[NSArray arrayWithObjects:@"create",  @"-puppetstrings", @"-encryption",@"AES-128", @"-size", @"100m", @"-verbose", @"-volname", @"test", fileName, @"-fs", @"HFS+J", @"-stdinpass", nil]];

[self.createTask setStandardOutput: outputPipe];
[self.createTask setStandardError:errorPipe];
[self.createTask launch];

[self.fhCreateOutput readInBackgroundAndNotify];
[self.fhCreateError readInBackgroundAndNotify];

}

and I got the following error:

2015-02-18 10:51:47.374 My DMG[41725:2016417] -[MyDMG 

createNotifiedForStdError:] verbose: 2015-02-18 10:51:46.745 diskimages-helper[41741:2016793] ERROR: couldn't connect to framework.
2015-02-18 10:51:47.376 My DMG[41725:2016417] -[MyDMG createNotifiedForStdError:] verbose: 2015-02-18 10:51:46.745 diskimages-helper[41741:2016793] DIHelper: setupConnectionToFrameworkWithUUID: failed
2015-02-18 10:51:46.747 hdiutil[41739:2016783] helper died
DIHLDiskImageCreate() returned 10
(null)
2015-02-18 10:51:47.665 My DMG[41725:2016417] -[MyDMG createNotifiedForStdError:] verbose: hdiutil: create: returning 10
2015-02-18 10:51:47.682 My DMG[41725:2016417] -[MyDMG createNotifiedForStdError:] verbose: hdiutil: create failed - No child processes
2015-02-18 10:51:47.687 My DMG[41725:2016417] task completed or was stopped with exit code 1

Some people said that NSTask doesn't work well with sandbox, but I have a couple other project that runs NSTask in sandbox and they worked. Also if you look at the mac app store, there is a similar app which creates dmg (user drags a folder and dmg file created)

Any help is appreciated :)

Josh
  • 692
  • 2
  • 9
  • 38
  • Does hdiutil create any intermediate files in the same folder? Have you tried creating the dmg in a temporary location inside your sandbox and then copying it to the URL specified by the user? – Aderstedt Feb 18 '15 at 17:04
  • not sure what do you mean by intermediate files. I have tried to create the dmg inside sandbox: NSArray* urlPaths = [fileManager URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask]; NSURL* appDirectory = [[urlPaths objectAtIndex:0] URLByAppendingPathComponent:bundleID isDirectory:YES]; NSURL *bUrl = [appDirectory URLByAppendingPathComponent: [saveDlg.URL stringByDeletingLastPathComponent]]; //and same thing happened – Josh Feb 18 '15 at 17:13
  • Ok. I'm using NSTask in a sandboxed app without any problems. Can you try launching a simple tool (e.g. "touch ") and see if hdiutil is the culprit? – Aderstedt Feb 18 '15 at 18:30
  • I have tried using NSTask to do a simple task like "ls -al" and it worked fine, I also have a couple other projects that use NSTask and Sandbox, it's just right now I'm using NSTask to create something, I'm not sure if it's the permission issue or what. But I'm 100% sure hdiutil works with sandbox, if you look at mac store, there are quite a few apps that create dmg, and to create dmg you have to use hdiutil – Josh Feb 18 '15 at 19:53
  • You can use hdiutil to create a DMG inside your app's sandbox, and then copy the DMG out into the destination file. If any additional temporary files are created, they will be inside your sandbox. – Aderstedt Jun 02 '15 at 10:12

0 Answers0