From e61e2d910e248da70735c4554a27c069e0ea4b32 Mon Sep 17 00:00:00 2001 From: Colin Cornaby Date: Sun, 4 Feb 2024 15:40:46 -0800 Subject: [PATCH] Handling self patch copy errors --- .../Apps/plClient/Mac-Cocoa/PLSPatcher.h | 2 +- .../Apps/plClient/Mac-Cocoa/PLSPatcher.mm | 29 ++++++++++++++----- .../Plasma/Apps/plClient/Mac-Cocoa/main.mm | 14 ++++++++- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h index fb6c956512..6e18ecffa2 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.h @@ -60,7 +60,7 @@ NS_ASSUME_NONNULL_BEGIN @property(weak) id delegate; @property(readonly) BOOL selfPatched; -- (NSURL*)completeSelfPatch; +- (NSURL*)completeSelfPatch:(NSError **)error; - (void)start; @end diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm index ac506f1145..2138b7b5d5 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/PLSPatcher.mm @@ -114,21 +114,36 @@ - (void)start self.patcher->Start(); } -- (NSURL *)completeSelfPatch +- (NSURL *)completeSelfPatch:(NSError **)error; { NSString* destinationPath = [NSString stringWithSTString:plManifest::PatcherExecutable().AsString()]; NSURL* destinationURL = [NSURL fileURLWithPath:[NSString stringWithSTString:plManifest::PatcherExecutable().AsString()]]; + NSError* errorInScope; + if ([NSFileManager.defaultManager fileExistsAtPath:destinationPath]) { // need to swap - renamex_np(destinationURL.path.fileSystemRepresentation, self.updatedClientURL.path.fileSystemRepresentation, RENAME_SWAP); - - // delete the old version - this is very likely us - // we want to terminate after. Our bundle will no longer be valid. - [NSFileManager.defaultManager removeItemAtURL:self.updatedClientURL error:nil]; + int swapError = renamex_np(destinationURL.path.fileSystemRepresentation, self.updatedClientURL.path.fileSystemRepresentation, RENAME_SWAP); + if (swapError == 0) { + // delete the old version - this is very likely us + // we want to terminate after. Our bundle will no longer be valid. + [NSFileManager.defaultManager removeItemAtURL:self.updatedClientURL error:&errorInScope]; + } else { + // abort and return an error + errorInScope = [NSError errorWithDomain:NSPOSIXErrorDomain code:swapError userInfo:nil]; + } } else { // no executable already present! Just move things into place. - [NSFileManager.defaultManager moveItemAtURL:self.updatedClientURL toURL:destinationURL error:nil]; + [NSFileManager.defaultManager moveItemAtURL:self.updatedClientURL toURL:destinationURL error:&errorInScope]; + } + + if (errorInScope) { + // Try to clean up if there was an error + [NSFileManager.defaultManager removeItemAtURL:self.updatedClientURL error:nil]; + if (error) { + *error = errorInScope; + } + return nil; } return destinationURL; diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm index 37fc214ebb..bdac9f5115 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm @@ -427,7 +427,19 @@ - (void)patcherCompleted:(PLSPatcher *)patcher didSelfPatch:(BOOL)selfPatched [NSApp endModalSession:self.currentModalSession]; [self.patcherWindow.window close]; if (selfPatched) { - NSURL* finalURL = [patcher completeSelfPatch]; + NSError *error; + NSURL* finalURL = [patcher completeSelfPatch:&error]; + + if (error) { + // uh oh, we couldn't self patch, present the error and bail + // this should be very rare and could be related to permissions issues + // we expect the game directory to be writable by all + NSAlert *errorAlert = [NSAlert alertWithError:error]; + [errorAlert runModal]; + [NSApp terminate:self]; + // return just in case we ever reach here + return; + } // Pass the "we've already patched" argument NSArray* applicationArguments = [[[NSProcessInfo processInfo] arguments] arrayByAddingObject:@"-NoSelfPatch"];