### adapted from https://github.com/rvoicilas/inotify-tools/pull/28 ### diff -urp inotify-tools-3.14/libinotifytools/src/inotifytools/inotifytools.h inotify-tools.new/libinotifytools/src/inotifytools/inotifytools.h --- inotify-tools-3.14/libinotifytools/src/inotifytools/inotifytools.h 2010-03-12 13:53:46.000000000 +0000 +++ inotify-tools.new/libinotifytools/src/inotifytools/inotifytools.h 2015-05-10 02:22:22.971561931 +0000 @@ -28,7 +28,7 @@ int inotifytools_watch_recursively_with_ int events, char const ** exclude_list ); // [UH] -int inotifytools_ignore_events_by_regex( char const *pattern, int flags ); +int inotifytools_ignore_events_by_regex( char const *pattern, int flags, int invert ); struct inotify_event * inotifytools_next_event( int timeout ); struct inotify_event * inotifytools_next_events( int timeout, int num_events ); int inotifytools_error(); diff -urp inotify-tools-3.14/libinotifytools/src/inotifytools.c inotify-tools.new/libinotifytools/src/inotifytools.c --- inotify-tools-3.14/libinotifytools/src/inotifytools.c 2010-03-12 13:53:46.000000000 +0000 +++ inotify-tools.new/libinotifytools/src/inotifytools.c 2015-05-10 02:21:08.839560752 +0000 @@ -149,6 +149,7 @@ static int error = 0; static int init = 0; static char* timefmt = 0; static regex_t* regex = 0; +static int invert_regex = 0; int isdir( char const * path ); void record_stats( struct inotify_event const * event ); @@ -1103,12 +1104,14 @@ struct inotify_event * inotifytools_next static ssize_t bytes; static jmp_buf jmp; static char match_name[MAX_STRLEN]; + static int rv; #define RETURN(A) {\ if (regex) {\ inotifytools_snprintf(match_name, MAX_STRLEN, A, "%w%f");\ - if (0 == regexec(regex, match_name, 0, 0, 0)) {\ - longjmp(jmp,0);\ + rv = regexec(regex, match_name, 0, 0, 0); \ + if ((!invert_regex && 0 == rv) || (invert_regex && 0 != rv)) { \ + longjmp(jmp,0); \ }\ }\ if ( collect_stats ) {\ @@ -1999,7 +2002,7 @@ int inotifytools_get_max_user_watches() * events occur. If the regular expression matches, the matched event will be * ignored. */ -int inotifytools_ignore_events_by_regex( char const *pattern, int flags ) { +int inotifytools_ignore_events_by_regex( char const *pattern, int flags, int invert ) { if (!pattern) { if (regex) { regfree(regex); @@ -2013,7 +2016,10 @@ int inotifytools_ignore_events_by_regex( else { regex = (regex_t *)malloc(sizeof(regex_t)); } int ret = regcomp(regex, pattern, flags | REG_NOSUB); - if (0 == ret) return 1; + if (0 == ret) { + invert_regex = invert; + return 1; + } regfree(regex); free(regex); diff -urp inotify-tools-3.14/src/inotifywait.c inotify-tools.new/src/inotifywait.c --- inotify-tools-3.14/src/inotifywait.c 2010-03-12 13:53:46.000000000 +0000 +++ inotify-tools.new/src/inotifywait.c 2015-05-10 16:53:20.384393049 +0000 @@ -48,7 +48,9 @@ bool parse_opts( char ** fromfile, char ** outfile, char ** regex, - char ** iregex + char ** iregex, + char ** include_regex, + char ** include_iregex ); void print_help(); @@ -157,16 +159,29 @@ int main(int argc, char ** argv) char * outfile = NULL; char * regex = NULL; char * iregex = NULL; + char * include_regex = NULL; + char * include_iregex = NULL; + bool invert_regex = false; pid_t pid; int fd; // Parse commandline options, aborting if something goes wrong if ( !parse_opts(&argc, &argv, &events, &monitor, &quiet, &timeout, - &recursive, &csv, &daemon, &syslog, &format, &timefmt, - &fromfile, &outfile, ®ex, &iregex) ) { + &recursive, &csv, &daemon, &syslog, &format, &timefmt, + &fromfile, &outfile, ®ex, &iregex, &include_regex, &include_iregex) ) { return EXIT_FAILURE; } + if (include_regex) { + regex = include_regex; + invert_regex = true; + } + + if (include_iregex) { + iregex = include_iregex; + invert_regex = true; + } + if ( !inotifytools_initialize() ) { fprintf(stderr, "Couldn't initialize inotify. Are you running Linux " "2.6.13 or later, and was the\n" @@ -180,11 +195,11 @@ int main(int argc, char ** argv) if ( timefmt ) inotifytools_set_printf_timefmt( timefmt ); if ( - (regex && !inotifytools_ignore_events_by_regex(regex, REG_EXTENDED) ) || + (regex && !inotifytools_ignore_events_by_regex(regex, REG_EXTENDED, invert_regex) ) || (iregex && !inotifytools_ignore_events_by_regex(iregex, REG_EXTENDED| - REG_ICASE)) + REG_ICASE, invert_regex)) ) { - fprintf(stderr, "Error in `exclude' regular expression.\n"); + fprintf(stderr, "Error in `exclude' or `include' regular expression.\n"); return EXIT_FAILURE; } @@ -423,18 +438,20 @@ bool parse_opts( char ** fromfile, char ** outfile, char ** regex, - char ** iregex + char ** iregex, + char ** include_regex, + char ** include_iregex ) { assert( argc ); assert( argv ); assert( events ); assert( monitor ); assert( quiet ); assert( timeout ); assert( csv ); assert( daemon ); - assert( syslog ); assert( format ); assert( timefmt ); assert( fromfile ); + assert( syslog ); assert( format ); assert( timefmt ); assert( fromfile ); assert( outfile ); assert( regex ); assert( iregex ); // Short options char * opt_string = "mrhcdsqt:fo:e:"; // Construct array - struct option long_opts[17]; + struct option long_opts[19]; // --help long_opts[0].name = "help"; @@ -520,11 +537,21 @@ bool parse_opts( long_opts[15].has_arg = 1; long_opts[15].flag = NULL; long_opts[15].val = (int)'b'; + // --include + long_opts[16].name = "include"; + long_opts[16].has_arg = 1; + long_opts[16].flag = NULL; + long_opts[16].val = (int)'j'; + // --includei + long_opts[17].name = "includei"; + long_opts[17].has_arg = 1; + long_opts[17].flag = NULL; + long_opts[17].val = (int)'k'; // Empty last element - long_opts[16].name = 0; - long_opts[16].has_arg = 0; - long_opts[16].flag = 0; - long_opts[16].val = 0; + long_opts[18].name = 0; + long_opts[18].has_arg = 0; + long_opts[18].flag = 0; + long_opts[18].val = 0; // Get first option char curr_opt = getopt_long(*argc, *argv, opt_string, long_opts, NULL); @@ -604,6 +631,16 @@ bool parse_opts( (*iregex) = optarg; break; + // --include + case 'j': + (*include_regex) = optarg; + break; + + // --includei + case 'k': + (*include_iregex) = optarg; + break; + // --fromfile case 'z': if (*fromfile) { @@ -671,6 +708,16 @@ bool parse_opts( return false; } + if ( *include_regex && *include_iregex ) { + fprintf(stderr, "--include and --includei cannot both be specified.\n"); + return false; + } + + if ( ( *include_regex || *include_iregex ) && ( *regex || *iregex ) ) { + fprintf(stderr, "Cannot use include and exclude options simultaneously.\n"); + return false; + } + if ( *format && *csv ) { fprintf(stderr, "-c and --format cannot both be specified.\n"); return false; @@ -715,6 +762,11 @@ void print_help() "\t \textended regular expression .\n"); printf("\t--excludei \n" "\t \tLike --exclude but case insensitive.\n"); + printf("\t--include \n" + "\t \tInclude all events on only those files matching\n" + "\t \tthe extended regular expression .\n"); + printf("\t--includei \n" + "\t \tLike --include but case insensitive.\n"); printf("\t-m|--monitor \tKeep listening for events forever. Without\n" "\t \tthis option, inotifywait will exit after one\n" "\t \tevent is received.\n"); diff -urp inotify-tools-3.14/src/inotifywatch.c inotify-tools.new/src/inotifywatch.c --- inotify-tools-3.14/src/inotifywatch.c 2010-03-12 13:53:46.000000000 +0000 +++ inotify-tools.new/src/inotifywatch.c 2015-05-10 16:51:40.060391453 +0000 @@ -43,7 +43,9 @@ bool parse_opts( int * recursive, char ** fromfile, char ** regex, - char ** iregex + char ** iregex, + char ** include_regex, + char ** include_iregex ); void print_help(); @@ -91,21 +93,34 @@ int main(int argc, char ** argv) done = false; char * regex = NULL; char * iregex = NULL; + char * include_regex = NULL; + char * include_iregex = NULL; + bool invert_regex = false; signal( SIGINT, handle_impatient_user ); // Parse commandline options, aborting if something goes wrong if ( !parse_opts( &argc, &argv, &events, &timeout, &verbose, &zero, &sort, - &recursive, &fromfile, ®ex, &iregex ) ) { + &recursive, &fromfile, ®ex, &iregex, &include_regex, &include_iregex ) ) { return EXIT_FAILURE; } + if (include_regex) { + regex = include_regex; + invert_regex = true; + } + + if (include_iregex) { + iregex = include_iregex; + invert_regex = true; + } + if ( - (regex && !inotifytools_ignore_events_by_regex(regex, REG_EXTENDED) ) || + (regex && !inotifytools_ignore_events_by_regex(regex, REG_EXTENDED, invert_regex) ) || (iregex && !inotifytools_ignore_events_by_regex(iregex, REG_EXTENDED| - REG_ICASE)) + REG_ICASE, invert_regex)) ) { - fprintf(stderr, "Error in `exclude' regular expression.\n"); + fprintf(stderr, "Error in `exclude' or `include' regular expression.\n"); return EXIT_FAILURE; } @@ -390,7 +405,9 @@ bool parse_opts( int * recursive, char ** fromfile, char ** regex, - char ** iregex + char ** iregex, + char ** include_regex, + char ** include_iregex ) { assert( argc ); assert( argv ); assert( events ); assert( timeout ); assert( verbose ); assert( zero ); assert( sort ); assert( recursive ); @@ -400,7 +417,7 @@ bool parse_opts( char * opt_string = "hra:d:zve:t:"; // Construct array - struct option long_opts[12]; + struct option long_opts[14]; // --help long_opts[0].name = "help"; @@ -460,11 +477,21 @@ bool parse_opts( long_opts[10].has_arg = 1; long_opts[10].flag = NULL; long_opts[10].val = (int)'b'; + // --include + long_opts[11].name = "include"; + long_opts[11].has_arg = 1; + long_opts[11].flag = NULL; + long_opts[11].val = (int)'j'; + // --includei + long_opts[12].name = "includei"; + long_opts[12].has_arg = 1; + long_opts[12].flag = NULL; + long_opts[12].val = (int)'k'; // Empty last element - long_opts[11].name = 0; - long_opts[11].has_arg = 0; - long_opts[11].flag = 0; - long_opts[11].val = 0; + long_opts[13].name = 0; + long_opts[13].has_arg = 0; + long_opts[13].flag = 0; + long_opts[13].val = 0; // Get first option char curr_opt = getopt_long(*argc, *argv, opt_string, long_opts, NULL); @@ -506,6 +533,16 @@ bool parse_opts( (*iregex) = optarg; break; + // --include + case 'j': + (*include_regex) = optarg; + break; + + // --includei + case 'k': + (*include_iregex) = optarg; + break; + // --fromfile case 'o': if (*fromfile) { @@ -625,6 +662,16 @@ bool parse_opts( return false; } + if ( *include_regex && *include_iregex ) { + fprintf(stderr, "--include and --includei cannot both be specified.\n"); + return false; + } + + if ( ( *include_regex || *include_iregex ) && ( *regex || *iregex ) ) { + fprintf(stderr, "Cannot use include and exclude options simultaneously.\n"); + return false; + } + // If ? returned, invalid option return (curr_opt != '?'); } @@ -647,6 +694,11 @@ void print_help() "\t\texpression .\n"); printf("\t--excludei \n" "\t\tLike --exclude but case insensitive.\n"); + printf("\t--include \n" + "\t\tInclude all events only those files matching the extended\n" + "\t\tregular expression .\n"); + printf("\t--includei \n" + "\t\tLike --include but case insensitive.\n"); printf("\t-z|--zero\n" "\t\tIn the final table of results, output rows and columns even\n" "\t\tif they consist only of zeros (the default is to not output\n"