Mac Tracking File system changes

ruhi

macrumors member
Original poster
Jun 17, 2009
70
0
Hello,

In my cocoa application ,I m trying to track all filesystem changes like copy, create and renaming or deletion of file and folder. I am getting the notification through the code shown below but the path of the file/folder is coming as "/.vol/234881026/688946". Now my problem is how to get the path in proper strings like ...i do not know how these numbers can be converted.

What can be done?

Code:
-(id)init
{
	[super init];
	if(self!=nil)
	{
		[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(trackNotifications:)
													name:nil  object:nil];

	}
	return self;
}
- (void) trackNotifications: (NSNotification *) notification
{
	
	NSLog(@"notification");
	id nname = [notification name];
	nobj = [notification object];
	if(nobj != nil)
	{
		NSLog(@"object == %@", nobj);
		NSString *pt=[[NSFileManager defaultManager] displayNameAtPath:[nobj description] ] ;
		pt=[self deviceNameWithMountPath:[nobj description]];
		NSLog(@"description == %@",[[nobj description]pathComponents ] );
		NSLog(@"path--- %@",pt);
		
		NSLog(@"class == %@", [nobj class]);
	
	}
	id ndict = [notification userInfo];
	
	// output accompanying data dictionary
	int i;
	id keys = [ndict allKeys];
	for (i = 1; i < [ndict count]; i++)
	{
		id key = [keys objectAtIndex:i];
		id object = [ndict objectForKey:key];
		NSLog(@" key == %@ object ==  %@", key, object);
	}
	
	
	
}
Thanks,
Ruhi.
 

larkost

macrumors 6502a
Oct 13, 2007
536
1
Why are you not using fsevents to get your information? It sounds to me like you are going to be doing a lot of filtering otherwise, and I am not sure that the changes made by all layers go through the notification system (if they do, it is because fsevents is using it as a conduit, and this would be an implementation detail that is subject to change at any moment).
 
Comment

ehunt123

macrumors newbie
Dec 7, 2009
7
0
If you visit any of the Cocoa/Mac Dev sites, most have code ranging from snippets to robust categories for tracking around FSEvents. Search on github/google code and there are probably a dozen more. I personally use the one from Stu Connolly, who makes SafariTabs.
 
Comment

gnasher729

macrumors P6
Nov 25, 2005
16,699
3,440
Are you watching the complete file system? In that case, maybe the path you got is actually the path of an object that has changed, on an invisible volume named ".vol".
 
Comment

ruhi

macrumors member
Original poster
Jun 17, 2009
70
0
Tracking file system changes

Hello,

I used FSEvent as suggested , and now i am getting parth of all files or folder renamed , deleted or created but how to get what event actually occured.

Is there any identifier by which i could find out whether renaming is done, or file is created or when file is deleted.

My code is this :

Code:
static void feCallback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) {
		NSMutableArray *ctrl = (NSMutableArray*)clientCallBackInfo;
    NSDate *time = [NSDate date]; 
    char **paths = eventPaths;
    int i;
    for (i = 0; i < numEvents; i++) {
        [ctrl addObject:[NSDictionary dictionaryWithObjectsAndKeys:
						 [NSNumber numberWithUnsignedLongLong:eventIds[i]], @"id",
						 [NSString stringWithUTF8String:paths[i]], @"path",
						 [NSString stringWithFormat:@"%04x",eventFlags[i]] , @"flag",
						 time , @"time",
						 NULL]];
		NSLog(@"%@",[NSDictionary dictionaryWithObjectsAndKeys:
					 [NSNumber numberWithUnsignedLongLong:eventIds[i]], @"id",
					 [NSString stringWithUTF8String:paths[i]], @"path",
					 [NSString stringWithFormat:@"%04x",eventFlags[i]] , @"flag",
					 time , @"time",
					 NULL]);
	}
}

@implementation FileFolder
-(id)init
{
	[super init];
	if(self!=nil)
	{
		CFStringRef path = CFSTR("/");
		CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&path, 1, NULL);
		
		/* Use context only to simply pass the array controller */
		_context = (FSEventStreamContext*)malloc(sizeof(FSEventStreamContext));
		_context->version = 0;
		_context->info = (void*)ctrl; 
		_context->retain = NULL;
		_context->release = NULL;
		_context->copyDescription = NULL;
		
		_stream = FSEventStreamCreate(NULL,
									  &feCallback,
									  _context,
									  pathsToWatch,
									  kFSEventStreamEventIdSinceNow, /* Or a previous event ID */
									  1.0, /* Latency in seconds */
									  kFSEventStreamCreateFlagNone
									  );
		
		_running = NO;
		FSEventStreamScheduleWithRunLoop(_stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);    
		
		[NSApp setDelegate:self]; /* catch window close */
		[self play:nil];
		
	}
	return self;
}
- (void)addDummyEvent:(NSString*)flag {
    [ctrl addObject:[NSDictionary dictionaryWithObjectsAndKeys:
					 @"0", @"id",
					 @"-", @"path",
					 flag, @"flag",
					 [NSDate date], @"time",
					 NULL]];
	NSLog(@"%@",ctrl);
}

- (void)awakeFromNib {
    
}

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication { return YES; }

- (void)dealloc {
    if(_running) FSEventStreamStop(_stream);
	FSEventStreamInvalidate(_stream); /* will remove from runloop */
	FSEventStreamRelease(_stream);
	free(_context);
    [super dealloc];
}

- (NSString*)mesg { return (_running)?@"Stop":@"Start"; }
- (void)setMesg:(BOOL)enable { 
    [self addDummyEvent:[self mesg]];
    _running = enable; 
}

- (IBAction)play:(id)sender {
    if(_running) {
        FSEventStreamStop(_stream);
        [self setMesg:NO];
    } else {
        [self setMesg:FSEventStreamStart(_stream)];
    }    
}

- (IBAction)flag:(id)sender {
    [self addDummyEvent:@"Flag"];
}

- (IBAction)clear:(id)sender {
    NSArray *content = [ctrl content];
    int size = [content count];
    while(size > 0) {
        size--;
        [ctrl removeObject:[content objectAtIndex:size]];
    }
}

Thanks,
Ruhi.
 
Comment
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.