~tcurdt/sparkle/devel

« back to all changes in this revision

Viewing changes to SUDiskImageUnarchiver.m

  • Committer: Andy Matuschak
  • Date: 2008-06-19 05:53:16 UTC
  • Revision ID: andy@andymatuschak.org-20080619055316-zktlbz5mxa9ezvs5
Fixes 236695

Refactored Sparkle's unarchiving system into SUUnarchiver, a factory for SUPipedUnarchiver and SUDiskImageUnarchiver. I removed that nasty cleanUp call by now copying out the contents of the DMG into the /tmp directory and unmounting. Nice!

This changed a fair amount so please test with your build and let me know if it explodes things. Works in my tests, though.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
//  SUDiskImageUnarchiver.m
 
3
//  Sparkle
 
4
//
 
5
//  Created by Andy Matuschak on 6/16/08.
 
6
//  Copyright 2008 Andy Matuschak. All rights reserved.
 
7
//
 
8
 
 
9
#import "SUDiskImageUnarchiver.h"
 
10
#import "SUUnarchiver_Private.h"
 
11
#import "NTSynchronousTask.h"
 
12
 
 
13
@implementation SUDiskImageUnarchiver
 
14
 
 
15
+ (BOOL)_canUnarchiveURL:(NSURL *)URL
 
16
{
 
17
        return [URL conformsToType:@"public.disk-image"];
 
18
}
 
19
 
 
20
- (void)start
 
21
{
 
22
        [NSThread detachNewThreadSelector:@selector(_extractDMG) toTarget:self withObject:nil];
 
23
}
 
24
 
 
25
- (void)_extractDMG
 
26
{               
 
27
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
28
        NSString *archivePath = [archiveURL path];
 
29
        BOOL mountedSuccessfully = NO;
 
30
        
 
31
        // get a unique mount point path
 
32
        NSString *mountPrefix = [@"/Volumes" stringByAppendingPathComponent:[[archivePath lastPathComponent] stringByDeletingPathExtension]];
 
33
        NSString *mountPoint = [mountPrefix stringByAppendingString:[[NSProcessInfo processInfo] globallyUniqueString]];
 
34
        
 
35
        if ([[NSFileManager defaultManager] fileExistsAtPath:mountPoint]) goto reportError;
 
36
 
 
37
        // create mount point folder
 
38
        [[NSFileManager defaultManager] createDirectoryAtPath:mountPoint attributes:nil];
 
39
        if (![[NSFileManager defaultManager] fileExistsAtPath:mountPoint]) goto reportError;
 
40
 
 
41
        NSArray* arguments = [NSArray arrayWithObjects:@"attach", archivePath, @"-mountpoint", mountPoint, @"-noverify", @"-nobrowse", @"-noautoopen", nil];
 
42
        // set up a pipe and push "yes" (y works too), this will accept any license agreement crap
 
43
        // not every .dmg needs this, but this will make sure it works with everyone
 
44
        NSData* yesData = [[[NSData alloc] initWithBytes:"yes\n" length:4] autorelease];
 
45
        
 
46
        NSData *result = [NTSynchronousTask task:@"/usr/bin/hdiutil" directory:@"/" withArgs:arguments input:yesData];
 
47
        if (!result) goto reportError;
 
48
        mountedSuccessfully = YES;
 
49
        
 
50
        // Now that we've mounted it, we need to copy out its contents.
 
51
        NSString *targetPath = [[archivePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:[mountPoint lastPathComponent]];
 
52
        if (![[NSFileManager defaultManager] createDirectoryAtPath:targetPath attributes:nil]) goto reportError;
 
53
        
 
54
        // We can't just copyPath: from the volume root because that always fails. Seems to be a bug.
 
55
        id subpathEnumerator = [[[NSFileManager defaultManager] directoryContentsAtPath:mountPoint] objectEnumerator], currentSubpath;
 
56
        while ((currentSubpath = [subpathEnumerator nextObject]))
 
57
        {
 
58
                if (![[NSFileManager defaultManager] copyPath:[mountPoint stringByAppendingPathComponent:currentSubpath] toPath:[targetPath stringByAppendingPathComponent:currentSubpath] handler:nil])
 
59
                        goto reportError;
 
60
        }
 
61
                        
 
62
        [self performSelectorOnMainThread:@selector(_notifyDelegateOfSuccess) withObject:nil waitUntilDone:NO];
 
63
        goto finally;
 
64
        
 
65
reportError:
 
66
        [self performSelectorOnMainThread:@selector(_notifyDelegateOfFailure) withObject:nil waitUntilDone:NO];
 
67
 
 
68
finally:
 
69
        if (mountedSuccessfully)
 
70
                [NSTask launchedTaskWithLaunchPath:@"/usr/bin/hdiutil" arguments:[NSArray arrayWithObjects:@"detach", mountPoint, @"-force", nil]];     
 
71
        [pool drain];
 
72
}
 
73
 
 
74
+ (void)load
 
75
{
 
76
        [self _registerImplementation:self];
 
77
}
 
78
 
 
79
@end