Tracking File system changes

Discussion in 'Mac Programming' started by ruhi, Dec 6, 2009.

  1. ruhi macrumors member

    Joined:
    Jun 17, 2009
    #1
    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.
     
  2. larkost macrumors 6502a

    Joined:
    Oct 13, 2007
    #2
    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).
     
  3. ehunt123 macrumors newbie

    Joined:
    Dec 7, 2009
    #3
    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.
     
  4. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #4
    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".
     
  5. ruhi thread starter macrumors member

    Joined:
    Jun 17, 2009
    #5
    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.
     

Share This Page