/* * usage: * * watchf [-i] [-e] [-- ...] * * -i infinite loop * * -e (events) * A Access * M Modify * R Attribute * W Close write * N Close NoWrite * O Open * F Move From * T Move To * L Delete Subdir * X Delete File * C Create File * D Create Subdir * S Create self * U Unmount * E Everything * */ #include #include #include #include #include #include #include #include #include #include #include "inotify.h" #define INOTIFY_DEV "/udev/inotify" #define EVENT_SIZE(ev) ( ((ev)->len) + sizeof(struct inotify_event) ) #define DEFAULT_MASK (IN_CLOSE_WRITE | IN_MOVED_TO) #define min(x,y) ( (x)<(y)?(x):(y) ) int main(int argc, char* argv[]) { int infinite = 0; const char* file = NULL; int ch, ifd, wd, fd, len, i; char* ptr; struct inotify_watch_request wr; char buffer[1024]; char filename[1024]; char cmd[1024]; struct inotify_event* ev; __u32 mask = DEFAULT_MASK; while ((ch = getopt(argc, argv, "ie:")) != -1) { switch(ch) { case 'i': infinite = 1; break; case 'e': mask = 0; while (*optarg) { switch(*optarg) { case 'A': mask |= IN_ACCESS; break; case 'M': mask |= IN_MODIFY; break; case 'R': mask |= IN_ATTRIB; break; case 'W': mask |= IN_CLOSE_WRITE; break; case 'N': mask |= IN_CLOSE_NOWRITE; break; case 'O': mask |= IN_OPEN; break; case 'F': mask |= IN_MOVED_FROM; break; case 'T': mask |= IN_MOVED_TO; break; case 'L': mask |= IN_DELETE_SUBDIR; break; case 'X': mask |= IN_DELETE_FILE; break; case 'C': mask |= IN_CREATE_SUBDIR; break; case 'D': mask |= IN_CREATE_FILE; break; case 'S': mask |= IN_DELETE_SELF; break; case 'U': mask |= IN_UNMOUNT; break; case 'E': mask |= IN_ALL_EVENTS; break; default: fprintf(stderr, "%s: Unknown event type '%c'\n", argv[0], *optarg); return -1; } optarg++; } break; case '?': default: return -1; } } if (optind >= argc) { fprintf(stderr, "%s: Missing filename\n", argv[0]); return -1; } /* Open file user specified */ file = argv[optind]; fd = open(file, 0); if (fd == -1) { fprintf(stderr, "%s: Unable to open file '%s'\n", argv[0], file); return -1; } /* Open inotify control device */ ifd = open("/udev/inotify", 0); if (ifd == -1) { fprintf(stderr, "%s: Unable to open %s\n", argv[0], INOTIFY_DEV); close(fd); return -1; } /* Add specified watch */ wr.fd = fd; wr.mask = mask; wd = ioctl(ifd, INOTIFY_WATCH, &wr); if (wd == -1) { fprintf(stderr, "%s: Unable to set watch (%s)\n", argv[0], strerror(errno)); close(fd); close(ifd); return -1; } /* Done with the file itself */ close(fd); do { /* Wait for an inotify event */ len = read(ifd, buffer, sizeof(buffer)); if (len < sizeof(struct inotify_event)) break; ev = (struct inotify_event*)buffer; while (len) { if (ev->len) { strncpy(filename, ev->name, min(ev->len, sizeof(filename)-1)); filename[sizeof(filename)-1] = '\0'; cmd[0] = '\0'; for (i=optind+1; imask; } len -= EVENT_SIZE(ev); ev = (struct inotify_event*)((char*)ev + EVENT_SIZE(ev)); } } while(infinite); close(ifd); return 0; }