int main (int argc, char* argv[]) { if (geteuid() != 0) { fprintf(stderr,"Opening /dev/fsevents requires root permissions\n"); exit (1); } // Open the device int fsed = 0; fsed = open ("/dev/fsevents", O_RDONLY); if (fsed < 0) { perror ("open"); exit(2); } int8_t events[FSE_MAX_EVENTS]; for (int i = 0; i < FSE_MAX_EVENTS; i++) { events[i] = FSE_REPORT; } fsevent_clone_args clone_args; memset(&clone_args, '\0', sizeof(clone_args)); int cloned_fsed; clone_args.fd = &cloned_fsed; clone_args.event_queue_depth = 10; clone_args.event_list = events; clone_args.num_events = FSE_MAX_EVENTS; // Do it. int rc = ioctl (fsed, FSEVENTS_CLONE, &clone_args); if (rc < 0) { perror ("ioctl"); exit(3); } close (fsed); //unsigned short *arg_type; char buf[BUFSIZE]; while ((rc = read (cloned_fsed, buf, BUFSIZE)) || 1) { if (rc <= 0) { printf("***Warning: haven't read data, continue\n"); continue; } // rc returns the count of bytes for one or more events: int offInBuf = 0; while (offInBuf < rc) { struct kfs_event_a *fse = (struct kfs_event_a *)(buf + offInBuf); struct kfs_event_arg *fse_arg = NULL; if (offInBuf) { printf ("Next event: %d\n", offInBuf); }; printf ("%s (PID:%d) %s ", GetProcName(fse->pid), fse->pid , EvenTypeToString(fse->type) ); offInBuf += sizeof(struct kfs_event_a); fse_arg = (struct kfs_event_arg *) &buf[offInBuf]; printf ("%s\n", fse_arg->data); offInBuf += sizeof(kfs_event_arg) + fse_arg->pathlen; int arg_len = doArg(buf + offInBuf); offInBuf += arg_len; while (arg_len > 2) { arg_len = doArg(buf + offInBuf); offInBuf += arg_len; } } // end while (offInBuf < rc) if (rc > offInBuf) { printf ("***Warning: Some events may be lost\n"); } } return 0; }
void main (int argc, char **argv) { int fsed, cloned_fsed; int i; int rc; fsevent_clone_args clone_args; unsigned short *arg_type; char buf[BUFSIZE]; // Open the device fsed = open ("/dev/fsevents", O_RDONLY); int8_t events[FSE_MAX_EVENTS]; if (geteuid()) { fprintf(stderr,"Opening /dev/fsevents requires root permissions\n"); } if (fsed < 0) { perror ("open"); exit(1); } // Prepare event mask list. In our simple example, we want everything // (i.e. all events, so we say "FSE_REPORT" all). Otherwise, we // would have to specifically toggle FSE_IGNORE for each: // // e.g. // events[FSE_XATTR_MODIFIED] = FSE_IGNORE; // events[FSE_XATTR_REMOVED] = FSE_IGNORE; // etc.. for (i = 0; i < FSE_MAX_EVENTS; i++) { events[i] = FSE_REPORT; } // Get ready to clone the descriptor: memset(&clone_args, '\0', sizeof(clone_args)); clone_args.fd = &cloned_fsed; // This is the descriptor we get back clone_args.event_queue_depth = 10; clone_args.event_list = events; clone_args.num_events = FSE_MAX_EVENTS; // Do it. rc = ioctl (fsed, FSEVENTS_CLONE, &clone_args); if (rc < 0) { perror ("ioctl"); exit(2);} // We no longer need original.. close (fsed); // And now we simply read, ad infinitum (aut nauseam) while ((rc = read (cloned_fsed, buf, BUFSIZE)) > 0) { // rc returns the count of bytes for one or more events: int offInBuf = 0; while (offInBuf < rc) { struct kfs_event_a *fse = (struct kfs_event_a *)(buf + offInBuf); struct kfs_event_arg *fse_arg; // if (offInBuf) { printf ("Next event: %d\n", offInBuf);}; printf ("%s (PID:%d) %s ", getProcName(fse->pid), fse->pid , typeToString(fse->type) ); offInBuf+= sizeof(struct kfs_event_a); fse_arg = (struct kfs_event_arg *) &buf[offInBuf]; printf ("%s\n", fse_arg->data); offInBuf += sizeof(kfs_event_arg) + fse_arg->pathlen ; int arg_len = doArg(buf + offInBuf); offInBuf += arg_len; while (arg_len >2) { arg_len = doArg(buf + offInBuf); offInBuf += arg_len; } } if (rc > offInBuf) { printf ("***Warning: Some events may be lost\n"); } } }