Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Finally got DMGs working properly on 10.5 through a somewhat less bri…

…ttle method - ie, no more internetenable. Thanks to Steve Gehrman from CocoaTech.

Also fixed a bug with the host app extension method, the recursive find-the-app-in-the-archive method, and made the extension comparison case insensitive for extraction purposes.
  • Loading branch information...
commit 5d44acb0acda16ec6748d561976b1c8aeca14ad0 1 parent 690f04e
andym authored
View
2  NSFileManager+Authentication.h
@@ -7,5 +7,5 @@
//
@interface NSFileManager (SUAuthenticationAdditions)
-- (BOOL)movePathWithAuthentication:(NSString *)src toPath:(NSString *)dst;
+- (BOOL)copyPathWithAuthentication:(NSString *)src toPath:(NSString *)dst;
@end
View
38 NSFileManager+Authentication.m
@@ -14,8 +14,6 @@
#import <unistd.h>
#import <sys/stat.h>
#import <dirent.h>
-#include <sys/types.h>
-#include <sys/wait.h>
@implementation NSFileManager (SUAuthenticationAdditions)
@@ -52,7 +50,7 @@ - (BOOL)currentUserOwnsPath:(NSString *)oPath
return res;
}
-- (BOOL)_movePathWithForcedAuthentication:(NSString *)src toPath:(NSString *)dst
+- (BOOL)_copyPathWithForcedAuthentication:(NSString *)src toPath:(NSString *)dst
{
NSString *tmp = [[[dst stringByDeletingPathExtension] stringByAppendingString:@".old"] stringByAppendingPathExtension:[dst pathExtension]];
BOOL res = NO;
@@ -60,25 +58,20 @@ - (BOOL)_movePathWithForcedAuthentication:(NSString *)src toPath:(NSString *)dst
if((stat([src UTF8String], &sb) != 0) || (stat([tmp UTF8String], &sb) == 0) || stat([dst UTF8String], &sb) != 0)
return false;
- char* buf = NULL;
- asprintf(&buf,
- "mv -f \"$DST_PATH\" \"$TMP_PATH\" && "
- "mv -f \"$SRC_PATH\" \"$DST_PATH\" && "
- "rm -rf \"$TMP_PATH\" && "
- "chown -R %d:%d \"$DST_PATH\"",
- sb.st_uid, sb.st_gid);
-
- if(!buf)
- return false;
+ NSString *command = [NSString stringWithFormat:@"mv -f \"%@\" \"%@\" && cp -f -R \"%@\" \"%@\" && rm -rf \"%@\" && chown -R %d:%d \"%@\"",
+ dst,
+ tmp,
+ src,
+ dst,
+ tmp,
+ sb.st_uid,
+ sb.st_gid,
+ dst];
AuthorizationRef auth;
if(AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &auth) == errAuthorizationSuccess)
{
- setenv("SRC_PATH", [src UTF8String], 1);
- setenv("DST_PATH", [dst UTF8String], 1);
- setenv("TMP_PATH", [tmp UTF8String], 1);
- sig_t oldSigChildHandler = signal(SIGCHLD, SIG_DFL);
- char const* arguments[] = { "-c", buf, NULL };
+ char const* arguments[] = { "-c", [command UTF8String], NULL };
if(AuthorizationExecuteWithPrivileges(auth, "/bin/sh", kAuthorizationFlagDefaults, (char**)arguments, NULL) == errAuthorizationSuccess)
{
int status;
@@ -86,25 +79,24 @@ - (BOOL)_movePathWithForcedAuthentication:(NSString *)src toPath:(NSString *)dst
if(pid != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0)
res = YES;
}
- signal(SIGCHLD, oldSigChildHandler);
}
AuthorizationFree(auth, 0);
- free(buf);
+
return res;
}
-- (BOOL)movePathWithAuthentication:(NSString *)src toPath:(NSString *)dst
+- (BOOL)copyPathWithAuthentication:(NSString *)src toPath:(NSString *)dst
{
if ([[NSFileManager defaultManager] isWritableFileAtPath:dst] && [[NSFileManager defaultManager] isWritableFileAtPath:[dst stringByDeletingLastPathComponent]])
{
int tag = 0;
BOOL result = [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation source:[dst stringByDeletingLastPathComponent] destination:@"" files:[NSArray arrayWithObject:[dst lastPathComponent]] tag:&tag];
- result &= [[NSFileManager defaultManager] movePath:src toPath:dst handler:NULL];
+ result &= [[NSFileManager defaultManager] copyPath:src toPath:dst handler:nil];
return result;
}
else
{
- return [self _movePathWithForcedAuthentication:src toPath:dst];
+ return [self _copyPathWithForcedAuthentication:src toPath:dst];
}
}
View
26 NTSynchronousTask.h
@@ -0,0 +1,26 @@
+//
+// NTSynchronousTask.h
+// CocoatechCore
+//
+// Created by Steve Gehrman on 9/29/05.
+// Copyright 2005 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+@interface NTSynchronousTask : NSObject
+{
+ NSTask *mv_task;
+ NSPipe *mv_outputPipe;
+ NSPipe *mv_inputPipe;
+
+ NSData* mv_output;
+ BOOL mv_done;
+ int mv_result;
+}
+
+// pass nil for directory if not needed
+// returns the result
++ (NSData*)task:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input;
+
+@end
View
259 NTSynchronousTask.m
@@ -0,0 +1,259 @@
+//
+// NTSynchronousTask.m
+// CocoatechCore
+//
+// Created by Steve Gehrman on 9/29/05.
+// Copyright 2005 __MyCompanyName__. All rights reserved.
+//
+
+#import "NTSynchronousTask.h"
+
+@interface NTSynchronousTask (Private)
+- (void)run:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input;
+
+- (NSTask *)task;
+- (void)setTask:(NSTask *)theTask;
+
+- (NSPipe *)outputPipe;
+- (void)setOutputPipe:(NSPipe *)theOutputPipe;
+
+- (NSPipe *)inputPipe;
+- (void)setInputPipe:(NSPipe *)theInputPipe;
+
+- (NSData *)output;
+- (void)setOutput:(NSData *)theOutput;
+
+- (BOOL)done;
+- (void)setDone:(BOOL)flag;
+
+- (int)result;
+- (void)setResult:(int)theResult;
+@end
+
+@implementation NTSynchronousTask
+
+- (id)init;
+{
+ self = [super init];
+
+ [self setTask:[[[NSTask alloc] init] autorelease]];
+ [self setOutputPipe:[[[NSPipe alloc] init] autorelease]];
+ [self setInputPipe:[[[NSPipe alloc] init] autorelease]];
+
+ [[self task] setStandardInput:[self inputPipe]];
+ [[self task] setStandardOutput:[self outputPipe]];
+
+ return self;
+}
+
+//----------------------------------------------------------
+// dealloc
+//----------------------------------------------------------
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+
+ [self setTask:nil];
+ [self setOutputPipe:nil];
+ [self setInputPipe:nil];
+ [self setOutput:nil];
+
+ [super dealloc];
+}
+
++ (NSData*)task:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input;
+{
+ // we need this wacky pool here, otherwise we run out of pipes, the pipes are internally autoreleased
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSData* result=nil;
+
+ NS_DURING
+ {
+ NTSynchronousTask* task = [[NTSynchronousTask alloc] init];
+
+ [task run:toolPath directory:currentDirectory withArgs:args input:input];
+
+ if ([task result] == 0)
+ result = [[task output] retain];
+
+ [task release];
+ }
+ NS_HANDLER;
+ NS_ENDHANDLER;
+
+ [pool release];
+
+ // retained above
+ [result autorelease];
+
+ return result;
+}
+
+@end
+
+@implementation NTSynchronousTask (Private)
+
+- (void)run:(NSString*)toolPath directory:(NSString*)currentDirectory withArgs:(NSArray*)args input:(NSData*)input;
+{
+ BOOL success = NO;
+
+ if (currentDirectory)
+ [[self task] setCurrentDirectoryPath: currentDirectory];
+
+ [[self task] setLaunchPath:toolPath];
+ [[self task] setArguments:args];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(taskOutputAvailable:)
+ name:NSFileHandleReadToEndOfFileCompletionNotification
+ object:[[self outputPipe] fileHandleForReading]];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(taskDidTerminate:)
+ name:NSTaskDidTerminateNotification
+ object:[self task]];
+
+ [[[self outputPipe] fileHandleForReading] readToEndOfFileInBackgroundAndNotifyForModes:[NSArray arrayWithObjects:NSDefaultRunLoopMode, NSModalPanelRunLoopMode, NSEventTrackingRunLoopMode, nil]];
+
+ NS_DURING
+ [[self task] launch];
+ success = YES;
+ NS_HANDLER
+ ;
+ NS_ENDHANDLER
+
+ if (success)
+ {
+ if (input)
+ {
+ // feed the running task our input
+ [[[self inputPipe] fileHandleForWriting] writeData:input];
+ [[[self inputPipe] fileHandleForWriting] closeFile];
+ }
+
+ // loop until we are done receiving the data
+ if (![self done])
+ {
+ double resolution = 1;
+ BOOL isRunning;
+ NSDate* next;
+
+ do {
+ next = [NSDate dateWithTimeIntervalSinceNow:resolution];
+
+ isRunning = [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
+ beforeDate:next];
+ } while (isRunning && ![self done]);
+ }
+ }
+}
+
+//----------------------------------------------------------
+// task
+//----------------------------------------------------------
+- (NSTask *)task
+{
+ return mv_task;
+}
+
+- (void)setTask:(NSTask *)theTask
+{
+ if (mv_task != theTask) {
+ [mv_task release];
+ mv_task = [theTask retain];
+ }
+}
+
+//----------------------------------------------------------
+// outputPipe
+//----------------------------------------------------------
+- (NSPipe *)outputPipe
+{
+ return mv_outputPipe;
+}
+
+- (void)setOutputPipe:(NSPipe *)theOutputPipe
+{
+ if (mv_outputPipe != theOutputPipe) {
+ [mv_outputPipe release];
+ mv_outputPipe = [theOutputPipe retain];
+ }
+}
+
+//----------------------------------------------------------
+// inputPipe
+//----------------------------------------------------------
+- (NSPipe *)inputPipe
+{
+ return mv_inputPipe;
+}
+
+- (void)setInputPipe:(NSPipe *)theInputPipe
+{
+ if (mv_inputPipe != theInputPipe) {
+ [mv_inputPipe release];
+ mv_inputPipe = [theInputPipe retain];
+ }
+}
+
+//----------------------------------------------------------
+// output
+//----------------------------------------------------------
+- (NSData *)output
+{
+ return mv_output;
+}
+
+- (void)setOutput:(NSData *)theOutput
+{
+ if (mv_output != theOutput) {
+ [mv_output release];
+ mv_output = [theOutput retain];
+ }
+}
+
+//----------------------------------------------------------
+// done
+//----------------------------------------------------------
+- (BOOL)done
+{
+ return mv_done;
+}
+
+- (void)setDone:(BOOL)flag
+{
+ mv_done = flag;
+}
+
+//----------------------------------------------------------
+// result
+//----------------------------------------------------------
+- (int)result
+{
+ return mv_result;
+}
+
+- (void)setResult:(int)theResult
+{
+ mv_result = theResult;
+}
+
+@end
+
+@implementation NTSynchronousTask (Notifications)
+
+- (void)taskOutputAvailable:(NSNotification*)note
+{
+ [self setOutput:[[note userInfo] objectForKey:NSFileHandleNotificationDataItem]];
+
+ [self setDone:YES];
+}
+
+- (void)taskDidTerminate:(NSNotification*)note
+{
+ [self setResult:[[self task] terminationStatus]];
+}
+
+@end
+
+
View
1  SUStatusController.h
@@ -14,6 +14,7 @@
double progressValue, maxProgressValue;
NSString *title, *statusText, *buttonTitle;
IBOutlet NSButton *actionButton;
+ IBOutlet NSProgressIndicator* mProgressBar;
}
- initWithUtilities:(SUUtilities *)aUtility;
View
33 SUStatusController.m
@@ -9,6 +9,11 @@
#import "SUStatusController.h"
#import "SUUtilities.h"
+@interface SUStatusController (Private)
+- (NSProgressIndicator *)progressBar;
+- (void)setProgressBar:(NSProgressIndicator *)theProgressBar;
+@end
+
@implementation SUStatusController
- initWithUtilities:(SUUtilities *)aUtility
@@ -33,6 +38,8 @@ - (void)dealloc
[title release];
[statusText release];
[buttonTitle release];
+ [self setProgressBar:nil];
+
[super dealloc];
}
@@ -40,6 +47,9 @@ - (void)awakeFromNib
{
[[self window] center];
[[self window] setFrameAutosaveName:@"SUStatusFrame"];
+
+ // set progress bar to threaded animation
+ [[self progressBar] setUsesThreadedAnimation:YES];
}
- (NSString *)windowTitle
@@ -119,3 +129,26 @@ - (void)setStatusText:(NSString *)aStatusText
}
@end
+
+@implementation SUStatusController (Private)
+
+//----------------------------------------------------------
+// progressBar
+//----------------------------------------------------------
+- (NSProgressIndicator *)progressBar
+{
+ return mProgressBar;
+}
+
+- (void)setProgressBar:(NSProgressIndicator *)theProgressBar
+{
+ if (mProgressBar != theProgressBar)
+ {
+ [mProgressBar release];
+ mProgressBar = [theProgressBar retain];
+ }
+}
+
+@end
+
+
View
65 SUUnarchiver.m
@@ -7,7 +7,8 @@
//
#import "SUUnarchiver.h"
-
+#import <Carbon/Carbon.h>
+#import "NTSynchronousTask.h"
@implementation SUUnarchiver
@@ -23,7 +24,6 @@ - (BOOL)_extractArchivePath:archivePath pipingDataToCommand:(NSString *)command
long current = 0;
FILE *fp, *cmdFP;
- sig_t oldSigPipeHandler = signal(SIGPIPE, SIG_IGN);
if ((fp = fopen([archivePath UTF8String], "r")))
{
setenv("DESTINATION", [[archivePath stringByDeletingLastPathComponent] UTF8String], 1);
@@ -48,7 +48,7 @@ - (BOOL)_extractArchivePath:archivePath pipingDataToCommand:(NSString *)command
}
fclose(fp);
}
- signal(SIGPIPE, oldSigPipeHandler);
+
return YES;
}
@@ -73,19 +73,28 @@ - (BOOL)_extractZIP:(NSString *)archivePath
}
- (BOOL)_extractDMG:(NSString *)archivePath
-{
- sig_t oldSigChildHandler = signal(SIGCHLD, SIG_DFL);
- // First, we internet-enable the volume.
- NSTask *hdiTask = [NSTask launchedTaskWithLaunchPath:@"/usr/bin/env" arguments:[NSArray arrayWithObjects:@"hdiutil", @"internet-enable", @"-quiet", archivePath, nil]];
- [hdiTask waitUntilExit];
- if ([hdiTask terminationStatus] != 0) { return NO; }
+{
+ // get a unique mount point path
+ NSString *mountPoint = [[archivePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"mp"];
+ int cnt=1;
+ while ([[NSFileManager defaultManager] fileExistsAtPath:mountPoint] && cnt <= 999)
+ mountPoint = [[archivePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:[NSString stringWithFormat:@"mp%d", cnt++]];
- // Now, open the volume; it'll extract into its own directory.
- hdiTask = [NSTask launchedTaskWithLaunchPath:@"/usr/bin/env" arguments:[NSArray arrayWithObjects:@"hdiutil", @"attach", @"-idme", @"-noidmereveal", @"-noidmetrash", @"-noverify", @"-nobrowse", @"-noautoopen", @"-quiet", archivePath, nil]];
- [hdiTask waitUntilExit];
- if ([hdiTask terminationStatus] != 0) { return NO; }
-
- signal(SIGCHLD, oldSigChildHandler);
+ if (![[NSFileManager defaultManager] fileExistsAtPath:mountPoint])
+ {
+ // create mount point folder
+ [[NSFileManager defaultManager] createDirectoryAtPath:mountPoint attributes:nil];
+
+ if ([[NSFileManager defaultManager] fileExistsAtPath:mountPoint])
+ {
+ NSArray* arguments = [NSArray arrayWithObjects:@"attach", archivePath, @"-mountpoint", mountPoint, @"-noverify", @"-nobrowse", @"-noautoopen", nil];
+ // set up a pipe and push "yes" (y works too), this will accept any license agreement crap
+ // not every .dmg needs this, but this will make sure it works with everyone
+ NSData* yesData = [[[NSData alloc] initWithBytes:"yes\n" length:4] autorelease];
+
+ [NTSynchronousTask task:@"/usr/bin/hdiutil" directory:@"/" withArgs:arguments input:yesData];
+ }
+ }
return YES;
}
@@ -98,12 +107,26 @@ - (void)_unarchivePath:(NSString *)path
// The methods take the path of the archive to extract. They return a BOOL indicating whether
// we should continue with the update; returns NO if an error occurred.
NSDictionary *commandDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
- @"_extractTBZ:", @"tbz",
- @"_extractTGZ:", @"tgz",
- @"_extractTAR:", @"tar",
- @"_extractZIP:", @"zip",
- @"_extractDMG:", @"dmg", nil];
- SEL command = NSSelectorFromString([commandDictionary objectForKey:[path pathExtension]]);
+ @"_extractTBZ:", @".tbz",
+ @"_extractTBZ:", @".tar.bz2",
+ @"_extractTGZ:", @".tgz",
+ @"_extractTGZ:", @".tar.gz",
+ @"_extractTAR:", @".tar",
+ @"_extractZIP:", @".zip",
+ @"_extractDMG:", @".dmg",
+ nil];
+ SEL command = NULL;
+ NSString *theLastPathComponent = [[path lastPathComponent] lowercaseString];
+ NSEnumerator *theEnumerator = [[commandDictionary allKeys] objectEnumerator];
+ NSString *theExtension = NULL;
+ while ((theExtension = [theEnumerator nextObject]) != NULL)
+ {
+ if ([[theLastPathComponent substringFromIndex:[theLastPathComponent length] - [theExtension length]] isEqualToString:theExtension])
+ {
+ command = NSSelectorFromString([commandDictionary objectForKey:theExtension]);
+ break;
+ }
+ }
BOOL result;
if (command)
View
42 SUUpdater.m
@@ -462,11 +462,15 @@ - (void)download:(NSURLDownload *)download decideDestinationWithSuggestedFilenam
name = [name stringByDeletingPathExtension];
// We create a temporary directory in /tmp and stick the file there.
- NSString *tempDir = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
+ // Not using a GUID here because hdiutil for some reason chokes on GUIDs. Too long? I really have no idea.
+ NSString *tempDir = [NSTemporaryDirectory() stringByAppendingPathComponent:@"update"];
+ int cnt=1;
+ while ([[NSFileManager defaultManager] fileExistsAtPath:tempDir] && cnt <= 999)
+ tempDir = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"update%d", cnt++]];
BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:tempDir attributes:nil];
if (!success)
{
- [NSException raise:@"SUFailTmpWrite" format:@"Couldn't create temporary directory in /var/tmp"];
+ [NSException raise:@"SUFailTmpWrite" format:@"Couldn't create temporary directory at %@", tempDir];
[download cancel];
[download release];
}
@@ -608,7 +612,7 @@ - (IBAction)installAndRestart:sender
if ([file isEqualToString:@"/Applications"])
[dirEnum skipDescendents];
if ([[file pathExtension] isEqualToString:[utilities hostAppExtension]] &&
- [[file stringByDeletingPathExtension] isEqualToString:appName]) // We found one!
+ [[[file stringByDeletingPathExtension] lastPathComponent] isEqualToString:appName]) // We found one!
{
isPackage = NO;
newAppDownloadPath = [[downloadPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:file];
@@ -631,7 +635,7 @@ - (IBAction)installAndRestart:sender
if (!newAppDownloadPath || ![[NSFileManager defaultManager] fileExistsAtPath:newAppDownloadPath])
{
- [NSException raise:@"SUInstallException" format:@"The update archive didn't contain an application with the proper name: %@. Remember, the updated app's file name must be identical to {CFBundleString}.{Extension}", [[utilities unlocalizedInfoValueForKey:@"CFBundleName"] stringByAppendingPathExtension:[utilities hostAppExtension]]];
+ [NSException raise:@"SUInstallException" format:@"The update archive didn't contain an application with the proper name: %@. Remember, the updated app's file name must be identical to {CFBundleName}.{Extension}", [[utilities unlocalizedInfoValueForKey:@"CFBundleName"] stringByAppendingPathExtension:[utilities hostAppExtension]]];
}
}
@catch(NSException *e)
@@ -665,23 +669,22 @@ - (IBAction)installAndRestart:sender
}
else // But if we're updating by the action of the user, do an authenticated move.
{
- if (!isPackage)
+ if (isPackage)
{
- // Outside of the @try block because we want to be a little more informative on this error.
- if (![[NSFileManager defaultManager] movePathWithAuthentication:newAppDownloadPath toPath:currentBundlePath])
+ NSString *installerPath = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:@"com.apple.installer"];
+ installerPath = [installerPath stringByAppendingString:@"/Contents/MacOS/Installer"];
+ NSTask *installer = [NSTask launchedTaskWithLaunchPath:installerPath arguments:[NSArray arrayWithObjects:newAppDownloadPath, nil]];
+ processIdentifier = [installer processIdentifier];
+ }
+ else
+ {
+ if (![[NSFileManager defaultManager] copyPathWithAuthentication:newAppDownloadPath toPath:currentBundlePath])
{
[self showUpdateErrorAlertWithInfo:[NSString stringWithFormat:SULocalizedString(@"%@ does not have permission to write to the application's directory! Are you running off a disk image? If not, ask your system administrator for help.", nil), [utilities hostAppDisplayName]]];
[self abandonUpdate];
return;
}
}
- else
- {
- NSString *installerPath = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:@"com.apple.installer"];
- installerPath = [installerPath stringByAppendingString:@"/Contents/MacOS/Installer"];
- NSTask *installer = [NSTask launchedTaskWithLaunchPath:installerPath arguments:[NSArray arrayWithObjects:newAppDownloadPath, nil]];
- processIdentifier = [installer processIdentifier];
- }
}
// Prompt for permission to restart if we're automatically updating.
@@ -695,17 +698,24 @@ - (IBAction)installAndRestart:sender
}
}
+ // This is really sloppy and coupled, but gosh darn it, I'm not maintaining this codebase much longer. Sorry!
+ // If we've got a DMG, we've mounted it; now we've got to unmount it.
+ if ([[[downloadPath pathExtension] lowercaseString] isEqualToString:@"dmg"])
+ {
+ [NSTask launchedTaskWithLaunchPath:@"/usr/bin/hdiutil" arguments:[NSArray arrayWithObjects:@"detach", [newAppDownloadPath stringByDeletingLastPathComponent], @"-force", nil]];
+ }
+
[[NSNotificationCenter defaultCenter] postNotificationName:SUUpdaterWillRestartNotification object:self];
NSString *relaunchPath = [[[NSBundle bundleForClass:[self class]] executablePath] stringByDeletingLastPathComponent];
- if (!relaunchPath) // slight hack to resolve issues with running with in configurations
+ if (!relaunchPath) // slight hack to resolve issues with running within bundles
{
NSString *frameworkPath = [[[NSBundle mainBundle] sharedFrameworksPath] stringByAppendingPathComponent:@"Sparkle.framework"];
NSBundle *framework = [NSBundle bundleWithPath:frameworkPath];
relaunchPath = [[framework executablePath] stringByDeletingLastPathComponent];
}
relaunchPath = [relaunchPath stringByAppendingPathComponent:@"relaunch.app/Contents/MacOS/relaunch"];
-
+
[NSTask launchedTaskWithLaunchPath:relaunchPath arguments:[NSArray arrayWithObjects:currentAppPath, [NSString stringWithFormat:@"%d", processIdentifier], nil]];
[NSApp terminate:self];
}
View
2  SUUtilities.m
@@ -107,7 +107,7 @@ - (NSImage *)hostAppIcon
- (NSString *)hostAppExtension
{
- return [[[NSFileManager defaultManager] displayNameAtPath:[[updater updateBundle] bundlePath]] pathExtension];
+ return [[[updater updateBundle] bundlePath] pathExtension];
}
- (SUBundleDefaults *)standardBundleDefaults
View
6 Sparkle.xcodeproj/project.pbxproj
@@ -11,6 +11,7 @@
345AF9E50A5D707200D7DA6F /* SUStatusChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = 345AF9E30A5D707200D7DA6F /* SUStatusChecker.m */; };
610D5A1A0A1661B8004AAD9C /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* Sparkle.framework */; };
610D5A750A1670A4004AAD9C /* SUStatus.nib in Resources */ = {isa = PBXBuildFile; fileRef = 610D5A740A1670A4004AAD9C /* SUStatus.nib */; };
+ 610EC1E00CF3A5FE00AE239E /* NTSynchronousTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 610EC1BF0CF3914D00AE239E /* NTSynchronousTask.m */; };
6120721209CC5C4B007FE0F6 /* SUAutomaticUpdateAlert.h in Headers */ = {isa = PBXBuildFile; fileRef = 6120721009CC5C4B007FE0F6 /* SUAutomaticUpdateAlert.h */; settings = {ATTRIBUTES = (Public, ); }; };
6120721309CC5C4B007FE0F6 /* SUAutomaticUpdateAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 6120721109CC5C4B007FE0F6 /* SUAutomaticUpdateAlert.m */; };
61299A2F09CA2DAB00B7442F /* NSFileManager+Verification.h in Headers */ = {isa = PBXBuildFile; fileRef = 61299A2D09CA2DAB00B7442F /* NSFileManager+Verification.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -108,6 +109,8 @@
345AF9E20A5D707200D7DA6F /* SUStatusChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SUStatusChecker.h; sourceTree = "<group>"; };
345AF9E30A5D707200D7DA6F /* SUStatusChecker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUStatusChecker.m; sourceTree = "<group>"; };
610D5A740A1670A4004AAD9C /* SUStatus.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; path = SUStatus.nib; sourceTree = "<group>"; };
+ 610EC1BF0CF3914D00AE239E /* NTSynchronousTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NTSynchronousTask.m; sourceTree = "<group>"; };
+ 610EC1C00CF3914D00AE239E /* NTSynchronousTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NTSynchronousTask.h; sourceTree = "<group>"; };
6120721009CC5C4B007FE0F6 /* SUAutomaticUpdateAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SUAutomaticUpdateAlert.h; sourceTree = "<group>"; };
6120721109CC5C4B007FE0F6 /* SUAutomaticUpdateAlert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUAutomaticUpdateAlert.m; sourceTree = "<group>"; };
6129984309C9E2DA00B7442F /* NSFileManager+Authentication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSFileManager+Authentication.h"; sourceTree = "<group>"; };
@@ -397,6 +400,8 @@
61B5F8F309C4CE5900B25A18 /* Utilities */ = {
isa = PBXGroup;
children = (
+ 610EC1BF0CF3914D00AE239E /* NTSynchronousTask.m */,
+ 610EC1C00CF3914D00AE239E /* NTSynchronousTask.h */,
D18A64E60CE2588900C49C71 /* SUBundleDefaults.h */,
D18A64E70CE2588900C49C71 /* SUBundleDefaults.m */,
61B5F8DD09C4CE3C00B25A18 /* md5.c */,
@@ -645,6 +650,7 @@
6120721309CC5C4B007FE0F6 /* SUAutomaticUpdateAlert.m in Sources */,
345AF9E50A5D707200D7DA6F /* SUStatusChecker.m in Sources */,
D18A64E90CE2588900C49C71 /* SUBundleDefaults.m in Sources */,
+ 610EC1E00CF3A5FE00AE239E /* NTSynchronousTask.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Please sign in to comment.
Something went wrong with that request. Please try again.