From 706006539ff317fbf0877e07d6e6994ebde96632 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 20 Feb 2018 20:16:12 -0500 Subject: [PATCH] Improve the robustness of the migration logic. --- SignalMessaging/profiles/OWSProfileManager.m | 3 +- .../Messages/Attachments/TSAttachmentStream.m | 3 +- .../src/Storage/TSStorageManager.m | 30 ++++++++---- SignalServiceKit/src/Util/OWSFileSystem.h | 6 +-- SignalServiceKit/src/Util/OWSFileSystem.m | 47 +++++++++++-------- 5 files changed, 54 insertions(+), 35 deletions(-) diff --git a/SignalMessaging/profiles/OWSProfileManager.m b/SignalMessaging/profiles/OWSProfileManager.m index e7c8651ce..90c280a52 100644 --- a/SignalMessaging/profiles/OWSProfileManager.m +++ b/SignalMessaging/profiles/OWSProfileManager.m @@ -1118,8 +1118,7 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640; DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__); return [OWSFileSystem moveAppFilePath:self.legacyProfileAvatarsDirPath - sharedDataFilePath:self.sharedDataProfileAvatarsDirPath - exceptionName:@"ProfileManagerCouldNotMigrateProfileDirectory"]; + sharedDataFilePath:self.sharedDataProfileAvatarsDirPath]; } - (NSString *)profileAvatarsDirPath diff --git a/SignalServiceKit/src/Messages/Attachments/TSAttachmentStream.m b/SignalServiceKit/src/Messages/Attachments/TSAttachmentStream.m index 3ef9bad23..11b829c4c 100644 --- a/SignalServiceKit/src/Messages/Attachments/TSAttachmentStream.m +++ b/SignalServiceKit/src/Messages/Attachments/TSAttachmentStream.m @@ -199,8 +199,7 @@ NS_ASSUME_NONNULL_BEGIN DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__); return [OWSFileSystem moveAppFilePath:self.legacyAttachmentsDirPath - sharedDataFilePath:self.sharedDataAttachmentsDirPath - exceptionName:@"CouldNotMigrateAttachmentsDirectory"]; + sharedDataFilePath:self.sharedDataAttachmentsDirPath]; } + (NSString *)attachmentsFolder diff --git a/SignalServiceKit/src/Storage/TSStorageManager.m b/SignalServiceKit/src/Storage/TSStorageManager.m index 6245b7e86..5b94e8495 100644 --- a/SignalServiceKit/src/Storage/TSStorageManager.m +++ b/SignalServiceKit/src/Storage/TSStorageManager.m @@ -18,8 +18,6 @@ NS_ASSUME_NONNULL_BEGIN -NSString *const TSStorageManagerExceptionName_CouldNotMoveDatabaseFile - = @"TSStorageManagerExceptionName_CouldNotMoveDatabaseFile"; NSString *const TSStorageManagerExceptionName_CouldNotCreateDatabaseDirectory = @"TSStorageManagerExceptionName_CouldNotCreateDatabaseDirectory"; @@ -255,21 +253,35 @@ void runAsyncRegistrationsForStorage(OWSStorage *storage) [OWSFileSystem protectFileOrFolderAtPath:self.legacyDatabaseFilePath_WAL]; NSError *_Nullable error = nil; - error = [OWSFileSystem moveAppFilePath:self.legacyDatabaseFilePath - sharedDataFilePath:self.sharedDataDatabaseFilePath - exceptionName:TSStorageManagerExceptionName_CouldNotMoveDatabaseFile]; + if ([fileManager fileExistsAtPath:self.legacyDatabaseFilePath] && + [fileManager fileExistsAtPath:self.sharedDataDatabaseFilePath]) { + // In the case that we have a "database conflict" (i.e. database files + // in the src and dst locations), ensure database integrity by renaming + // all of the dst database files. + for (NSString *filePath in @[ + self.sharedDataDatabaseFilePath, + self.sharedDataDatabaseFilePath_SHM, + self.sharedDataDatabaseFilePath_WAL, + ]) { + error = [OWSFileSystem renameFilePathUsingRandomExtension:filePath]; + if (error) { + return error; + } + } + } + + error = + [OWSFileSystem moveAppFilePath:self.legacyDatabaseFilePath sharedDataFilePath:self.sharedDataDatabaseFilePath]; if (error) { return error; } error = [OWSFileSystem moveAppFilePath:self.legacyDatabaseFilePath_SHM - sharedDataFilePath:self.sharedDataDatabaseFilePath_SHM - exceptionName:TSStorageManagerExceptionName_CouldNotMoveDatabaseFile]; + sharedDataFilePath:self.sharedDataDatabaseFilePath_SHM]; if (error) { return error; } error = [OWSFileSystem moveAppFilePath:self.legacyDatabaseFilePath_WAL - sharedDataFilePath:self.sharedDataDatabaseFilePath_WAL - exceptionName:TSStorageManagerExceptionName_CouldNotMoveDatabaseFile]; + sharedDataFilePath:self.sharedDataDatabaseFilePath_WAL]; if (error) { return error; } diff --git a/SignalServiceKit/src/Util/OWSFileSystem.h b/SignalServiceKit/src/Util/OWSFileSystem.h index df657e305..c5c7da271 100644 --- a/SignalServiceKit/src/Util/OWSFileSystem.h +++ b/SignalServiceKit/src/Util/OWSFileSystem.h @@ -17,9 +17,9 @@ NS_ASSUME_NONNULL_BEGIN + (NSString *)cachesDirectoryPath; -+ (nullable NSError *)moveAppFilePath:(NSString *)oldFilePath - sharedDataFilePath:(NSString *)newFilePath - exceptionName:(NSString *)exceptionName; ++ (nullable NSError *)renameFilePathUsingRandomExtension:(NSString *)oldFilePath; + ++ (nullable NSError *)moveAppFilePath:(NSString *)oldFilePath sharedDataFilePath:(NSString *)newFilePath; // Returns NO IFF the directory does not exist and could not be created. + (BOOL)ensureDirectoryExists:(NSString *)dirPath; diff --git a/SignalServiceKit/src/Util/OWSFileSystem.m b/SignalServiceKit/src/Util/OWSFileSystem.m index b6d4ce320..d4fcf5d17 100644 --- a/SignalServiceKit/src/Util/OWSFileSystem.m +++ b/SignalServiceKit/src/Util/OWSFileSystem.m @@ -108,9 +108,32 @@ NS_ASSUME_NONNULL_BEGIN return paths[0]; } -+ (nullable NSError *)moveAppFilePath:(NSString *)oldFilePath - sharedDataFilePath:(NSString *)newFilePath - exceptionName:(NSString *)exceptionName ++ (nullable NSError *)renameFilePathUsingRandomExtension:(NSString *)oldFilePath +{ + NSFileManager *fileManager = [NSFileManager defaultManager]; + if (![fileManager fileExistsAtPath:oldFilePath]) { + return nil; + } + + NSString *newFilePath = + [[oldFilePath stringByAppendingString:@"."] stringByAppendingString:[NSUUID UUID].UUIDString]; + + DDLogInfo(@"%@ Moving file or directory from: %@ to: %@", self.logTag, oldFilePath, newFilePath); + + NSError *_Nullable error; + BOOL success = [fileManager moveItemAtPath:oldFilePath toPath:newFilePath error:&error]; + if (!success || error) { + OWSProdLogAndFail(@"%@ Could not move file or directory from: %@ to: %@, error: %@", + self.logTag, + oldFilePath, + newFilePath, + error); + return error; + } + return nil; +} + ++ (nullable NSError *)moveAppFilePath:(NSString *)oldFilePath sharedDataFilePath:(NSString *)newFilePath { NSFileManager *fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:oldFilePath]) { @@ -122,22 +145,8 @@ NS_ASSUME_NONNULL_BEGIN if ([fileManager fileExistsAtPath:newFilePath]) { // If a file/directory already exists at the destination, // try to move it "aside" by renaming it with an extension. - NSString *legacyFilePath = - [[newFilePath stringByAppendingString:@"."] stringByAppendingString:[NSUUID UUID].UUIDString]; - DDLogInfo(@"%@ Trying to rename pre-existing destination file or directory from: %@ to: %@", - self.logTag, - newFilePath, - legacyFilePath); - - NSError *_Nullable error; - BOOL success = [fileManager moveItemAtPath:newFilePath toPath:legacyFilePath error:&error]; - if (!success || error) { - OWSProdLogAndFail( - @"%@ Could not move pre-existing destination file or directory from: %@ to: %@, error: %@", - self.logTag, - newFilePath, - legacyFilePath, - error); + NSError *_Nullable error = [self renameFilePathUsingRandomExtension:newFilePath]; + if (error) { return error; } }