void watch_limit() { ENTER verify((0 == mkdir(TEST_DIR, 0700)) || (EEXIST == errno)); INFO("Warning, this test may take a while\n"); #define INNER_LIMIT 16000 #define OUTER_LIMIT 5 verify(inotifytools_initialize()); inotifytools_initialize_stats(); for (int j = 0; j < OUTER_LIMIT; ++j) { char fn[1024]; int max = 0; for (int i = 0; i < INNER_LIMIT; ++i) { snprintf(fn, 1023, "%s/%d", TEST_DIR, i); int fd = creat(fn, 0700); verify(-1 != fd); verify(0 == close(fd)); int ret = inotifytools_watch_file(fn, IN_ALL_EVENTS); verify(ret || inotifytools_error() == ENOSPC); if (ret) { max = i + 1; int wd = inotifytools_wd_from_filename(fn); verify(wd > 0); verify(!strcmp(fn, inotifytools_filename_from_wd(wd))); } } compare(inotifytools_get_num_watches(), max); for (int i = 0; i < max; ++i) { snprintf(fn, 1023, "%s/%d", TEST_DIR, i); verify(inotifytools_remove_watch_by_filename(fn)); } } EXIT }
int main(int argc, char ** argv) { events = 0; int timeout = 0; int verbose = 0; zero = 0; int recursive = 0; char * fromfile = 0; sort = -1; done = false; char * regex = NULL; char * iregex = NULL; 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 ) ) { return EXIT_FAILURE; } if ( (regex && !inotifytools_ignore_events_by_regex(regex, REG_EXTENDED) ) || (iregex && !inotifytools_ignore_events_by_regex(iregex, REG_EXTENDED| REG_ICASE)) ) { fprintf(stderr, "Error in `exclude' regular expression.\n"); return EXIT_FAILURE; } if ( !inotifytools_initialize() ) { fprintf(stderr, "Couldn't initialize inotify. Are you running Linux " "2.6.13 or later, and was the\n" "CONFIG_INOTIFY option enabled when your kernel was " "compiled? If so, \n" "something mysterious has gone wrong. Please e-mail " PACKAGE_BUGREPORT "\n" " and mention that you saw this message.\n"); return EXIT_FAILURE; } // Attempt to watch file // If events is still 0, make it all events. if ( !events ) events = IN_ALL_EVENTS; FileList list = construct_path_list( argc, argv, fromfile ); if (0 == list.watch_files[0]) { fprintf(stderr, "No files specified to watch!\n"); return EXIT_FAILURE; } unsigned int num_watches = 0; unsigned int status; fprintf( stderr, "Establishing watches...\n" ); int i; for ( i = 0; list.watch_files[i]; ++i ) { char const *this_file = list.watch_files[i]; if ( recursive && verbose ) { fprintf( stderr, "Setting up watch(es) on %s\n", this_file ); } if ( recursive ) { status = inotifytools_watch_recursively_with_exclude( this_file, events, list.exclude_files ); } else { status = inotifytools_watch_file( this_file, events ); } if ( !status ) { if ( inotifytools_error() == ENOSPC ) { fprintf(stderr, "Failed to watch %s; upper limit on inotify " "watches reached!\n", this_file ); fprintf(stderr, "Please increase the amount of inotify watches " "allowed per user via `/proc/sys/fs/inotify/" "max_user_watches'.\n"); } else { fprintf(stderr, "Failed to watch %s: %s\n", this_file, strerror( inotifytools_error() ) ); } return EXIT_FAILURE; } if ( recursive && verbose ) { fprintf( stderr, "OK, %s is now being watched.\n", this_file ); } } num_watches = inotifytools_get_num_watches(); if ( verbose ) { fprintf( stderr, "Total of %d watches.\n", num_watches ); } fprintf( stderr, "Finished establishing watches, now collecting statistics.\n" ); if ( timeout && verbose ) { fprintf( stderr, "Will listen for events for %d seconds.\n", timeout ); } signal( SIGINT, handle_signal ); signal( SIGHUP, handle_signal ); signal( SIGTERM, handle_signal ); if ( timeout ) { signal( SIGALRM, handle_signal ); alarm( timeout ); } signal( SIGUSR1, print_info_now ); inotifytools_initialize_stats(); // Now wait till we get event struct inotify_event * event; char * moved_from = 0; do { event = inotifytools_next_event( 0 ); if ( !event ) { if ( !inotifytools_error() ) { return EXIT_TIMEOUT; } else if ( inotifytools_error() != EINTR ) { fprintf(stderr, "%s\n", strerror( inotifytools_error() ) ); return EXIT_FAILURE; } else { continue; } } // if we last had MOVED_FROM and don't currently have MOVED_TO, // moved_from file must have been moved outside of tree - so unwatch it. if ( moved_from && !(event->mask & IN_MOVED_TO) ) { if ( !inotifytools_remove_watch_by_filename( moved_from ) ) { fprintf( stderr, "Error removing watch on %s: %s\n", moved_from, strerror(inotifytools_error()) ); } free( moved_from ); moved_from = 0; } if ( recursive ) { if ((event->mask & IN_CREATE) || (!moved_from && (event->mask & IN_MOVED_TO))) { // New file - if it is a directory, watch it static char * new_file; nasprintf( &new_file, "%s%s", inotifytools_filename_from_wd( event->wd ), event->name ); if ( isdir(new_file) && !inotifytools_watch_recursively( new_file, events ) ) { fprintf( stderr, "Couldn't watch new directory %s: %s\n", new_file, strerror( inotifytools_error() ) ); } free( new_file ); } // IN_CREATE else if (event->mask & IN_MOVED_FROM) { nasprintf( &moved_from, "%s%s/", inotifytools_filename_from_wd( event->wd ), event->name ); // if not watched... if ( inotifytools_wd_from_filename(moved_from) == -1 ) { free( moved_from ); moved_from = 0; } } // IN_MOVED_FROM else if (event->mask & IN_MOVED_TO) { if ( moved_from ) { static char * new_name; nasprintf( &new_name, "%s%s/", inotifytools_filename_from_wd( event->wd ), event->name ); inotifytools_replace_filename( moved_from, new_name ); free( moved_from ); moved_from = 0; } // moved_from } } } while ( !done ); return print_info(); }