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
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ - (BOOL)to_isCopying
{
// When files are still being copied, their
// modification date is equal to the current device time.
return [self.to_modificationDate timeIntervalSinceDate:[NSDate date]]
NSDate *modificationDate = self.to_modificationDate;
if (modificationDate == nil) { return NO; }
return [modificationDate timeIntervalSinceDate:[NSDate date]]
> (-kTOFileSystemObserverCopyingTimeDelay - FLT_EPSILON);
}

Expand Down
8 changes: 4 additions & 4 deletions TOFileSystemObserver/Categories/NSURL+TOFileSystemUUID.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ NS_ASSUME_NONNULL_BEGIN
/** Returns the unique UUID value assigned to this file. */
- (nullable NSString *)to_fileSystemUUID;

/** Sets a predetermined UUID to be the value of the file. */
- (void)to_setFileSystemUUID:(NSString *)uuid;
/** Sets a predetermined UUID to be the value of the file. Returns YES if the attribute was written. */
- (BOOL)to_setFileSystemUUID:(NSString *)uuid;

/** Regardless if one exists, generate and save a new UUID. */
- (NSString *)to_generateFileSystemUUID;
/** Regardless if one exists, generate and save a new UUID. Returns nil if the write failed. */
- (nullable NSString *)to_generateFileSystemUUID;

@end

Expand Down
21 changes: 13 additions & 8 deletions TOFileSystemObserver/Categories/NSURL+TOFileSystemUUID.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,14 @@ - (NSString *)to_fileSystemUUID
// Allocate a buffer for the value (UUID values are always 36 characters)
char value[36];

// Fetch the value from disk
getxattr(filePath, keyName, value, 36, 0, 0);
// Fetch the value from disk. A short read means there's no valid UUID stored.
ssize_t bytesRead = getxattr(filePath, keyName, value, sizeof(value), 0, 0);
if (bytesRead != (ssize_t)sizeof(value)) {
return nil;
}

// Convert to a string, and return if successful
NSString *uuid = [[NSString alloc] initWithBytes:value length:36 encoding:NSUTF8StringEncoding];
NSString *uuid = [[NSString alloc] initWithBytes:value length:bytesRead encoding:NSUTF8StringEncoding];
if (uuid.length == 0) {
return nil;
}
Expand All @@ -64,9 +67,10 @@ - (NSString *)to_fileSystemUUID
return uuid;
}

- (void)to_setFileSystemUUID:(NSString *)uuid
- (BOOL)to_setFileSystemUUID:(NSString *)uuid
{
if (uuid.length > 0 && uuid.length != 36) {
if (uuid.length == 0) { return NO; }
if (uuid.length != 36) {
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:@"UUID must be 36 characters long!"
userInfo:nil];
Expand All @@ -78,15 +82,16 @@ - (void)to_setFileSystemUUID:(NSString *)uuid

// Convert the string to a C byte string
const char *uuidString = [uuid cStringUsingEncoding:NSUTF8StringEncoding];
if (uuidString == NULL) { return NO; }

// Save it to this file
setxattr(filePath, keyName, uuidString, strlen(uuidString), 0, 0);
// Save it to this file. UUID strings are always 36 ASCII bytes.
return setxattr(filePath, keyName, uuidString, 36, 0, 0) == 0;
}

- (NSString *)to_generateFileSystemUUID
{
NSString *uuid = [NSUUID UUID].UUIDString;
[self to_setFileSystemUUID:uuid];
if (![self to_setFileSystemUUID:uuid]) { return nil; }
return uuid;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,17 @@ NS_ASSUME_NONNULL_BEGIN
used to store re-usable instances of item and list
objects.
*/
@interface TOFileSystemItemMapTable : NSObject<NSFastEnumeration>
@interface TOFileSystemItemMapTable : NSObject

@property (nonatomic, readonly) NSInteger count;

- (void)setItem:(id)object forUUID:(NSString *)uuid;
- (id)itemForUUID:(NSString *)uuid;
- (void)removeItemForUUID:(NSString *)uuid;

/** A point-in-time snapshot of all current items. Safe to iterate while the table is being mutated. */
- (NSArray *)allItems;

/** Implementations for allowing dictionary style literal syntax. */
- (void)setObject:(nullable id)object forKeyedSubscript:(nonnull NSString *)key;
- (nullable id)objectForKeyedSubscript:(NSString *)key;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,17 @@ - (void)removeItemForUUID:(NSString *)uuid
});
}

- (NSArray *)allItems
{
__block NSArray *items = nil;
dispatch_sync(self.dispatchQueue, ^{
@autoreleasepool {
items = self.mapTable.objectEnumerator.allObjects;
}
});
return items ?: @[];
}

- (void)setObject:(nullable id)object forKeyedSubscript:(nonnull NSString *)key
{
[self setItem:object forUUID:key];
Expand All @@ -91,13 +102,4 @@ - (nullable id)objectForKeyedSubscript:(NSString *)key
return [self itemForUUID:key];
}

- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
objects:(id __unsafe_unretained _Nullable [_Nonnull])buffer
count:(NSUInteger)len
{
return [_mapTable countByEnumeratingWithState:state
objects:buffer
count:len];
}

@end
15 changes: 8 additions & 7 deletions TOFileSystemObserver/Entities/Items/TOFileSystemItemList.m
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ - (void)rebuildItemListForListingOrder
}

// Trigger the notification blocks to update any UI with this new order
for (TOFileSystemNotificationToken *token in self.notificationTokens) {
for (TOFileSystemNotificationToken *token in self.notificationTokens.allObjects) {
TOFileSystemItemListCallBlock(token.notificationBlock, self, changes);
}
}
Expand Down Expand Up @@ -242,7 +242,7 @@ - (void)addItemWithUUID:(NSString *)uuid itemURL:(NSURL *)url
// Perform the broadcast to any observing objects that this update ocurred
TOFileSystemItemListChanges *changes = [[TOFileSystemItemListChanges alloc] init];
[changes addInsertionIndex:sortedIndex];
for (TOFileSystemNotificationToken *token in self.notificationTokens) {
for (TOFileSystemNotificationToken *token in self.notificationTokens.allObjects) {
TOFileSystemItemListCallBlock(token.notificationBlock, self, changes);
}
}
Expand All @@ -267,7 +267,7 @@ - (void)removeItemWithUUID:(NSString *)uuid fileURL:(NSURL *)url
TOFileSystemItemListChanges *changes = [[TOFileSystemItemListChanges alloc] init];
[changes addDeletionIndex:index];

for (TOFileSystemNotificationToken *token in self.notificationTokens) {
for (TOFileSystemNotificationToken *token in self.notificationTokens.allObjects) {
TOFileSystemItemListCallBlock(token.notificationBlock, self, changes);
}
}
Expand Down Expand Up @@ -300,7 +300,7 @@ - (void)itemDidRefreshWithUUID:(NSString *)uuid
[changes addModificationIndex:newIndex];

// Broadcast the changes
for (TOFileSystemNotificationToken *token in self.notificationTokens) {
for (TOFileSystemNotificationToken *token in self.notificationTokens.allObjects) {
TOFileSystemItemListCallBlock(token.notificationBlock, self, changes);
}
}
Expand All @@ -322,16 +322,17 @@ - (void)synchronizeWithDisk
// Skip if every file was accounted for
if (changes.deletions.count == 0) { return; }

// Remove all of the deleted files from the list
for (NSNumber *deletedIndex in changes.deletions) {
// Remove all of the deleted files from the list. Iterate from highest index
// to lowest so each removal doesn't shift the indices we still need to use.
for (NSNumber *deletedIndex in [changes.deletions reverseObjectEnumerator]) {
NSString *uuid = self.sortedItems[deletedIndex.intValue];
[self.sortedItems removeObjectAtIndex:deletedIndex.intValue];
[self.items removeObjectForKey:uuid];
}

// Broadcast the changes
dispatch_async(dispatch_get_main_queue(), ^{
for (TOFileSystemNotificationToken *token in self.notificationTokens) {
for (TOFileSystemNotificationToken *token in self.notificationTokens.allObjects) {
TOFileSystemItemListCallBlock(token.notificationBlock, self, changes);
}
});
Expand Down
10 changes: 5 additions & 5 deletions TOFileSystemObserver/TOFileSystemObserver.m
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ - (void)scanOperationWillBeginFullScan:(TOFileSystemScanOperation *)scanOperatio
}

// Inform all notification tokens registered
for (TOFileSystemNotificationToken *token in self.notificationTokens) {
for (TOFileSystemNotificationToken *token in self.notificationTokens.allObjects) {
TOFileSystemObserverCallBlock(token.notificationBlock,
self,
TOFileSystemObserverNotificationTypeWillBeginFullScan,
Expand All @@ -618,8 +618,8 @@ - (void)scanOperationWillBeginFullScan:(TOFileSystemScanOperation *)scanOperatio
- (void)scanOperationDidCompleteFullScan:(TOFileSystemScanOperation *)scanOperation
{
// Loop through the list one more time to remove any headless entries
for (NSString *listUUID in self.itemListTable) {
[self.itemListTable[listUUID] synchronizeWithDisk];
for (TOFileSystemItemList *list in self.itemListTable.allItems) {
[list synchronizeWithDisk];
}

// Perform the Notification Center broadcast
Expand All @@ -631,7 +631,7 @@ - (void)scanOperationDidCompleteFullScan:(TOFileSystemScanOperation *)scanOperat
}

// Inform all notification tokens registered
for (TOFileSystemNotificationToken *token in self.notificationTokens) {
for (TOFileSystemNotificationToken *token in self.notificationTokens.allObjects) {
TOFileSystemObserverCallBlock(token.notificationBlock,
self,
TOFileSystemObserverNotificationTypeDidCompleteFullScan,
Expand Down Expand Up @@ -667,7 +667,7 @@ - (void)postNotificationsWithChanges:(TOFileSystemChanges *)changes
}

// Inform all notification tokens registered
for (TOFileSystemNotificationToken *token in self.notificationTokens) {
for (TOFileSystemNotificationToken *token in self.notificationTokens.allObjects) {
TOFileSystemObserverCallBlock(token.notificationBlock,
self,
TOFileSystemObserverNotificationTypeDidChange,
Expand Down
Loading