Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions FirebaseDatabase/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# 12.7.0
- [fixed] Fix `Fatal Exception: FirebaseDatabasePersistenceFailure`. (#4493)
- [fixed] Concurrency crash in FView. (#15514)

# 11.9.0
Expand Down
38 changes: 29 additions & 9 deletions FirebaseDatabase/Sources/Persistence/FLevelDBStorageEngine.m
Original file line number Diff line number Diff line change
Expand Up @@ -977,17 +977,40 @@ - (id)deserializePrimitive:(NSData *)data {
}

+ (void)ensureDir:(NSString *)path markAsDoNotBackup:(BOOL)markAsDoNotBackup {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
BOOL success =
[[NSFileManager defaultManager] createDirectoryAtPath:path
withIntermediateDirectories:YES
attributes:nil
error:&error];

// Create the directory if it doesn't exist. This call is a no-op if it
// already exists.
BOOL success = [fileManager createDirectoryAtPath:path
withIntermediateDirectories:YES
attributes:nil
error:&error];
if (!success) {
@throw [NSException
exceptionWithName:@"FailedToCreatePersistenceDir"
reason:@"Failed to create persistence directory."
userInfo:@{@"path" : path}];
userInfo:@{
@"path" : path,
@"error" : error ?: [NSNull null]
}];
}

// Now, ensure the file protection attribute is set. This will apply it
// whether the directory was just created or already existed. Note, this
// attribute has no effect on simulators.
NSDictionary *attributes = @{
NSFileProtectionKey :
NSFileProtectionCompleteUntilFirstUserAuthentication
};
success = [fileManager setAttributes:attributes
ofItemAtPath:path
error:&error];
if (!success) {
FFWarn(@"I-RDB076036",
@"Failed to set file protection attribute on persistence "
@"directory: %@",
error);
}

if (markAsDoNotBackup) {
Expand All @@ -1000,9 +1023,6 @@ + (void)ensureDir:(NSString *)path markAsDoNotBackup:(BOOL)markAsDoNotBackup {
@"I-RDB076035",
@"Failed to mark firebase database folder as do not backup: %@",
error);
[NSException raise:@"Error marking as do not backup"
format:@"Failed to mark folder %@ as do not backup",
firebaseDirURL];
}
}
}
Expand Down
50 changes: 49 additions & 1 deletion FirebaseDatabase/Tests/Unit/FLevelDBStorageEngineTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
#import "FirebaseDatabase/Sources/Snapshot/FSnapshotUtilities.h"
#import "FirebaseDatabase/Tests/Helpers/FTestHelpers.h"

@interface FLevelDBStorageEngineTests : XCTestCase
@interface FLevelDBStorageEngine (Tests)
+ (void)ensureDir:(NSString *)path markAsDoNotBackup:(BOOL)markAsDoNotBackup;
@end

@interface FLevelDBStorageEngineTests : XCTestCase
@end

@implementation FLevelDBStorageEngineTests
Expand Down Expand Up @@ -685,4 +688,49 @@ - (void)testRemoveTrackedQueryRemovesTrackedQueryKeys {
([NSSet setWithArray:@[ @"b", @"c" ]]));
}

- (void)testEnsureDirSetsCorrectFileProtection {
NSString *testDirName =
[NSString stringWithFormat:@"fdb_persistence_test_%lu", (unsigned long)arc4random()];
NSString *testPath = [NSTemporaryDirectory() stringByAppendingPathComponent:testDirName];
NSFileManager *fileManager = [NSFileManager defaultManager];

// --- Test creation ---
[fileManager removeItemAtPath:testPath error:nil];
[FLevelDBStorageEngine ensureDir:testPath markAsDoNotBackup:NO];

NSError *error = nil;
NSDictionary<NSFileAttributeKey, id> *attributes = [fileManager attributesOfItemAtPath:testPath
error:&error];
XCTAssertNil(error, @"Failed to get attributes of directory: %@", error);

#if !TARGET_OS_SIMULATOR
// On a physical device, file protection should be set.
XCTAssertEqualObjects(attributes[NSFileProtectionKey],
NSFileProtectionCompleteUntilFirstUserAuthentication);
#else
XCTAssertNil(attributes[NSFileProtectionKey]);
#endif

// --- Test update on existing directory ---
#if !TARGET_OS_SIMULATOR
// This part of the test is only relevant on devices where file protection is supported.
[fileManager removeItemAtPath:testPath error:nil];
NSDictionary *initialAttributes = @{NSFileProtectionKey : NSFileProtectionNone};
XCTAssertTrue([fileManager createDirectoryAtPath:testPath
withIntermediateDirectories:YES
attributes:initialAttributes
error:&error],
@"Failed to create directory for update test: %@", error);

[FLevelDBStorageEngine ensureDir:testPath markAsDoNotBackup:NO];

attributes = [fileManager attributesOfItemAtPath:testPath error:&error];
XCTAssertNil(error, @"Failed to get attributes after update: %@", error);
XCTAssertEqualObjects(attributes[NSFileProtectionKey],
NSFileProtectionCompleteUntilFirstUserAuthentication);
#endif // !TARGET_OS_SIMULATOR

// Clean up
[fileManager removeItemAtPath:testPath error:nil];
}
@end
Loading