"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "libinotifytools/src/inotifytools.c" between
inotify-tools-3.20.2.2.tar.gz and inotify-tools-3.20.11.0.tar.gz

About: inotify-tools offers commandline utilities relating to inotify (wait for or watch particular events on files).

inotifytools.c  (inotify-tools-3.20.2.2):inotifytools.c  (inotify-tools-3.20.11.0)
skipping to change at line 124 skipping to change at line 124
* @section TODO TODO list * @section TODO TODO list
* *
* @todo Improve wd/filename mapping. Currently there is no explicit code for * @todo Improve wd/filename mapping. Currently there is no explicit code for
* handling different filenames mapping to the same inode (and hence, wd). * handling different filenames mapping to the same inode (and hence, wd).
* gamin's approach sounds good: let the user watch an inode using several * gamin's approach sounds good: let the user watch an inode using several
* different filenames, and when an event occurs on the inode, generate an * different filenames, and when an event occurs on the inode, generate an
* event for each filename. * event for each filename.
*/ */
#define MAX_EVENTS 4096 #define MAX_EVENTS 4096
#define MAX_STRLEN 4096
#define INOTIFY_PROCDIR "/proc/sys/fs/inotify/" #define INOTIFY_PROCDIR "/proc/sys/fs/inotify/"
#define WATCHES_SIZE_PATH INOTIFY_PROCDIR "max_user_watches" #define WATCHES_SIZE_PATH INOTIFY_PROCDIR "max_user_watches"
#define QUEUE_SIZE_PATH INOTIFY_PROCDIR "max_queued_watches" #define QUEUE_SIZE_PATH INOTIFY_PROCDIR "max_queued_watches"
#define INSTANCES_PATH INOTIFY_PROCDIR "max_user_instances" #define INSTANCES_PATH INOTIFY_PROCDIR "max_user_instances"
static int inotify_fd; static int inotify_fd;
static unsigned num_access; static unsigned num_access;
static unsigned num_modify; static unsigned num_modify;
static unsigned num_attrib; static unsigned num_attrib;
static unsigned num_close_nowrite; static unsigned num_close_nowrite;
skipping to change at line 1120 skipping to change at line 1119
niceassert( init, "inotifytools_initialize not called yet" ); niceassert( init, "inotifytools_initialize not called yet" );
niceassert( num_events <= MAX_EVENTS, "too many events requested" ); niceassert( num_events <= MAX_EVENTS, "too many events requested" );
if ( num_events < 1 ) return NULL; if ( num_events < 1 ) return NULL;
static struct inotify_event event[MAX_EVENTS]; static struct inotify_event event[MAX_EVENTS];
static struct inotify_event * ret; static struct inotify_event * ret;
static int first_byte = 0; static int first_byte = 0;
static ssize_t bytes; static ssize_t bytes;
static jmp_buf jmp; static jmp_buf jmp;
static char match_name[MAX_STRLEN]; static struct nstring match_name;
static char match_name_string[MAX_STRLEN+1];
#define RETURN(A) {\ #define RETURN(A) {\
if (regex) {\ if (regex) {\
inotifytools_snprintf(match_name, MAX_STRLEN, A, "%w%f");\ inotifytools_snprintf(&match_name, MAX_STRLEN, A, "%w%f");\
if (0 == regexec(regex, match_name, 0, 0, 0)) {\ memcpy(&match_name_string, &match_name.buf, match_name.len);\
match_name_string[match_name.len] = '\0';\
if (0 == regexec(regex, match_name_string, 0, 0, 0)) {\
if (!invert_regexp)\ if (!invert_regexp)\
longjmp(jmp,0);\ longjmp(jmp,0);\
} else {\ } else {\
if (invert_regexp)\ if (invert_regexp)\
longjmp(jmp,0);\ longjmp(jmp,0);\
}\ }\
}\ }\
if ( collect_stats ) {\ if ( collect_stats ) {\
record_stats( A );\ record_stats( A );\
}\ }\
skipping to change at line 1654 skipping to change at line 1656
* @param event the event to use to construct a string. * @param event the event to use to construct a string.
* *
* @param fmt the format string used to construct a string. * @param fmt the format string used to construct a string.
* *
* @return number of characters written, or -1 if an error occurs. * @return number of characters written, or -1 if an error occurs.
* *
* @section syntax Format string syntax * @section syntax Format string syntax
* The following tokens will be replaced with the specified string: * The following tokens will be replaced with the specified string:
* \li \c \%w - This will be replaced with the name of the Watched file on * \li \c \%w - This will be replaced with the name of the Watched file on
* which an event occurred. * which an event occurred.
* \li \c \%c - This will be replaced with the cookie of the Watched file on
* which an event occurred.
* \li \c \%f - When an event occurs within a directory, this will be replaced * \li \c \%f - When an event occurs within a directory, this will be replaced
* with the name of the File which caused the event to occur. * with the name of the File which caused the event to occur.
* Otherwise, this will be replaced with an empty string. * Otherwise, this will be replaced with an empty string.
* \li \c \%e - Replaced with the Event(s) which occurred, comma-separated. * \li \c \%e - Replaced with the Event(s) which occurred, comma-separated.
* \li \c \%Xe - Replaced with the Event(s) which occurred, separated by * \li \c \%Xe - Replaced with the Event(s) which occurred, separated by
* whichever character is in the place of `X'. * whichever character is in the place of `X'.
* \li \c \%T - Replaced by the current Time in the format specified by the * \li \c \%T - Replaced by the current Time in the format specified by the
* string previously passed to inotifytools_set_printf_timefmt(), * string previously passed to inotifytools_set_printf_timefmt(),
* or replaced with an empty string if that function has never * or replaced with an empty string if that function has never
* been called. * been called.
* \li \c \%0 - Replaced with the 'NUL' character
* \li \c \%n - Replaced with the 'Line Feed' character
* *
* @section example Example * @section example Example
* @code * @code
* // suppose this is the only file watched. * // suppose this is the only file watched.
* inotifytools_watch_file( "mydir/", IN_CLOSE ); * inotifytools_watch_file( "mydir/", IN_CLOSE );
* *
* // wait until an event occurs * // wait until an event occurs
* struct inotify_event * event = inotifytools_next_event( -1 ); * struct inotify_event * event = inotifytools_next_event( -1 );
* *
* inotifytools_printf(stderr, event, "in %w, file %f had event(s): %.e\n"); * inotifytools_printf(stderr, event, "in %w, file %f had event(s): %.e\n");
skipping to change at line 1699 skipping to change at line 1705
* @param event the event to use to construct a string. * @param event the event to use to construct a string.
* *
* @param fmt the format string used to construct a string. * @param fmt the format string used to construct a string.
* *
* @return number of characters written, or -1 if an error occurs. * @return number of characters written, or -1 if an error occurs.
* *
* @section syntax Format string syntax * @section syntax Format string syntax
* The following tokens will be replaced with the specified string: * The following tokens will be replaced with the specified string:
* \li \c \%w - This will be replaced with the name of the Watched file on * \li \c \%w - This will be replaced with the name of the Watched file on
* which an event occurred. * which an event occurred.
* \li \c \%c - This will be replaced with the cookie of the Watched file on
* which an event occurred.
* \li \c \%f - When an event occurs within a directory, this will be replaced * \li \c \%f - When an event occurs within a directory, this will be replaced
* with the name of the File which caused the event to occur. * with the name of the File which caused the event to occur.
* Otherwise, this will be replaced with an empty string. * Otherwise, this will be replaced with an empty string.
* \li \c \%e - Replaced with the Event(s) which occurred, comma-separated. * \li \c \%e - Replaced with the Event(s) which occurred, comma-separated.
* \li \c \%Xe - Replaced with the Event(s) which occurred, separated by * \li \c \%Xe - Replaced with the Event(s) which occurred, separated by
* whichever character is in the place of `X'. * whichever character is in the place of `X'.
* \li \c \%T - Replaced by the current Time in the format specified by the * \li \c \%T - Replaced by the current Time in the format specified by the
* string previously passed to inotifytools_set_printf_timefmt(), * string previously passed to inotifytools_set_printf_timefmt(),
* or replaced with an empty string if that function has never * or replaced with an empty string if that function has never
* been called. * been called.
* \li \c \%0 - Replaced with the 'NUL' character
* \li \c \%n - Replaced with the 'Line Feed' character
* *
* @section example Example * @section example Example
* @code * @code
* // suppose this is the only file watched. * // suppose this is the only file watched.
* inotifytools_watch_file( "mydir/", IN_CLOSE ); * inotifytools_watch_file( "mydir/", IN_CLOSE );
* *
* // wait until an event occurs * // wait until an event occurs
* struct inotify_event * event = inotifytools_next_event( -1 ); * struct inotify_event * event = inotifytools_next_event( -1 );
* *
* inotifytools_fprintf(stderr, event, "in %w, file %f had event(s): %.e\n"); * inotifytools_fprintf(stderr, event, "in %w, file %f had event(s): %.e\n");
* // suppose the file 'myfile' in mydir was read from and closed. Then, * // suppose the file 'myfile' in mydir was read from and closed. Then,
* // this prints to standard error something like: * // this prints to standard error something like:
* // "in mydir/, file myfile had event(s): CLOSE_NOWRITE.CLOSE.ISDIR\n" * // "in mydir/, file myfile had event(s): CLOSE_NOWRITE.CLOSE.ISDIR\n"
* @endcode * @endcode
*/ */
int inotifytools_fprintf( FILE* file, struct inotify_event* event, char* fmt ) { int inotifytools_fprintf( FILE* file, struct inotify_event* event, char* fmt ) {
static char out[MAX_STRLEN+1]; static struct nstring out;
static int ret; static int ret;
ret = inotifytools_sprintf( out, event, fmt ); ret = inotifytools_sprintf( &out, event, fmt );
if ( -1 != ret ) fprintf( file, "%s", out ); if ( -1 != ret ) fwrite( out.buf, sizeof(char), out.len, file );
return ret; return ret;
} }
/** /**
* Construct a string using an inotify_event and a printf-like syntax. * Construct a string using an inotify_event and a printf-like syntax.
* The string can only ever be up to 4096 characters in length. * The string can only ever be up to 4096 characters in length.
* *
* This function will keep writing until it reaches 4096 characters. If your * This function will keep writing until it reaches 4096 characters. If your
* allocated array is not large enough to hold the entire string, your program * allocated array is not large enough to hold the entire string, your program
* may crash. * may crash.
* inotifytools_snprintf() is safer and you should use it where possible. * inotifytools_snprintf() is safer and you should use it where possible.
* *
* @param out location in which to store string. * @param out location in which to store nstring.
* *
* @param event the event to use to construct a string. * @param event the event to use to construct a nstring.
* *
* @param fmt the format string used to construct a string. * @param fmt the format string used to construct a nstring.
* *
* @return number of characters written, or -1 if an error occurs. * @return number of characters written, or -1 if an error occurs.
* *
* @section syntax Format string syntax * @section syntax Format string syntax
* The following tokens will be replaced with the specified string: * The following tokens will be replaced with the specified string:
* \li \c \%w - This will be replaced with the name of the Watched file on * \li \c \%w - This will be replaced with the name of the Watched file on
* which an event occurred. * which an event occurred.
* \li \c \%c - This will be replaced with the cookie of the Watched file on
* which an event occurred.
* \li \c \%f - When an event occurs within a directory, this will be replaced * \li \c \%f - When an event occurs within a directory, this will be replaced
* with the name of the File which caused the event to occur. * with the name of the File which caused the event to occur.
* Otherwise, this will be replaced with an empty string. * Otherwise, this will be replaced with an empty string.
* \li \c \%e - Replaced with the Event(s) which occurred, comma-separated. * \li \c \%e - Replaced with the Event(s) which occurred, comma-separated.
* \li \c \%Xe - Replaced with the Event(s) which occurred, separated by * \li \c \%Xe - Replaced with the Event(s) which occurred, separated by
* whichever character is in the place of `X'. * whichever character is in the place of `X'.
* \li \c \%T - Replaced by the current Time in the format specified by the * \li \c \%T - Replaced by the current Time in the format specified by the
* string previously passed to inotifytools_set_printf_timefmt(), * string previously passed to inotifytools_set_printf_timefmt(),
* or replaced with an empty string if that function has never * or replaced with an empty string if that function has never
* been called. * been called.
* \li \c \%0 - Replaced with the 'NUL' character
* \li \c \%n - Replaced with the 'Line Feed' character
* *
* @section example Example * @section example Example
* @code * @code
* // suppose this is the only file watched. * // suppose this is the only file watched.
* inotifytools_watch_file( "mydir/", IN_CLOSE ); * inotifytools_watch_file( "mydir/", IN_CLOSE );
* *
* // wait until an event occurs * // wait until an event occurs
* struct inotify_event * event = inotifytools_next_event( -1 ); * struct inotify_event * event = inotifytools_next_event( -1 );
* *
* char mystring[1024]; * nstring mynstring;
* // hope this doesn't crash - if filename is really long, might not fit into * inotifytools_sprintf(mynstring, event, "in %w, file %f had event(s): %.e\n");
* // mystring! * fwrite( mynstring.buf, sizeof(char), mynstring.len, stdout );
* inotifytools_sprintf(mystring, event, "in %w, file %f had event(s): %.e\n");
* printf( mystring );
* // suppose the file 'myfile' in mydir was written to and closed. Then, * // suppose the file 'myfile' in mydir was written to and closed. Then,
* // this prints something like: * // this prints something like:
* // "in mydir/, file myfile had event(s): CLOSE_WRITE.CLOSE.ISDIR\n" * // "in mydir/, file myfile had event(s): CLOSE_WRITE.CLOSE.ISDIR\n"
* @endcode * @endcode
*/ */
int inotifytools_sprintf( char * out, struct inotify_event* event, char* fmt ) { int inotifytools_sprintf( struct nstring * out, struct inotify_event* event, cha r* fmt ) {
return inotifytools_snprintf( out, MAX_STRLEN, event, fmt ); return inotifytools_snprintf( out, MAX_STRLEN, event, fmt );
} }
/** /**
* Construct a string using an inotify_event and a printf-like syntax. * Construct a string using an inotify_event and a printf-like syntax.
* The string can only ever be up to 4096 characters in length. * The string can only ever be up to 4096 characters in length.
* *
* @param out location in which to store string. * @param out location in which to store nstring.
* *
* @param size maximum amount of characters to write. * @param size maximum amount of characters to write.
* *
* @param event the event to use to construct a string. * @param event the event to use to construct a nstring.
* *
* @param fmt the format string used to construct a string. * @param fmt the format string used to construct a nstring.
* *
* @return number of characters written, or -1 if an error occurs. * @return number of characters written, or -1 if an error occurs.
* *
* @section syntax Format string syntax * @section syntax Format string syntax
* The following tokens will be replaced with the specified string: * The following tokens will be replaced with the specified string:
* \li \c \%w - This will be replaced with the name of the Watched file on * \li \c \%w - This will be replaced with the name of the Watched file on
* which an event occurred. * which an event occurred.
* \li \c \%c - This will be replaced with cookie of the Watched file on
* which an event occurred.
* \li \c \%f - When an event occurs within a directory, this will be replaced * \li \c \%f - When an event occurs within a directory, this will be replaced
* with the name of the File which caused the event to occur. * with the name of the File which caused the event to occur.
* Otherwise, this will be replaced with an empty string. * Otherwise, this will be replaced with an empty string.
* \li \c \%e - Replaced with the Event(s) which occurred, comma-separated. * \li \c \%e - Replaced with the Event(s) which occurred, comma-separated.
* \li \c \%Xe - Replaced with the Event(s) which occurred, separated by * \li \c \%Xe - Replaced with the Event(s) which occurred, separated by
* whichever character is in the place of `X'. * whichever character is in the place of `X'.
* \li \c \%T - Replaced by the current Time in the format specified by the * \li \c \%T - Replaced by the current Time in the format specified by the
* string previously passed to inotifytools_set_printf_timefmt(), * string previously passed to inotifytools_set_printf_timefmt(),
* or replaced with an empty string if that function has never * or replaced with an empty string if that function has never
* been called. * been called.
* \li \c \%0 - Replaced with the 'NUL' character
* \li \c \%n - Replaced with the 'Line Feed' character
* *
* @section example Example * @section example Example
* @code * @code
* // suppose this is the only file watched. * // suppose this is the only file watched.
* inotifytools_watch_file( "mydir/", IN_CLOSE ); * inotifytools_watch_file( "mydir/", IN_CLOSE );
* *
* // wait until an event occurs * // wait until an event occurs
* struct inotify_event * event = inotifytools_next_event( -1 ); * struct inotify_event * event = inotifytools_next_event( -1 );
* *
* char mystring[1024]; * struct nstring mynstring;
* inotifytools_snprintf( mystring, 1024, event, * inotifytools_snprintf( mynstring, MAX_STRLEN, event,
* "in %w, file %f had event(s): %.e\n" ); * "in %w, file %f had event(s): %.e\n" );
* printf( mystring ); * fwrite( mynstring.buf, sizeof(char), mynstring.len, stdout );
* // suppose the file 'myfile' in mydir was written to and closed. Then, * // suppose the file 'myfile' in mydir was written to and closed. Then,
* // this prints something like: * // this prints something like:
* // "in mydir/, file myfile had event(s): CLOSE_WRITE.CLOSE.ISDIR\n" * // "in mydir/, file myfile had event(s): CLOSE_WRITE.CLOSE.ISDIR\n"
* @endcode * @endcode
*/ */
int inotifytools_snprintf( char * out, int size, int inotifytools_snprintf( struct nstring * out, int size,
struct inotify_event* event, char* fmt ) { struct inotify_event* event, char* fmt ) {
static char * filename, * eventname, * eventstr; static char * filename, * eventname, * eventstr;
static unsigned int i, ind; static unsigned int i, ind;
static char ch1; static char ch1;
static char timestr[MAX_STRLEN]; static char timestr[MAX_STRLEN];
static time_t now; static time_t now;
if ( event->len > 0 ) { if ( event->len > 0 ) {
eventname = event->name; eventname = event->name;
} }
else { else {
eventname = NULL; eventname = NULL;
} }
filename = inotifytools_filename_from_wd( event->wd ); filename = inotifytools_filename_from_wd( event->wd );
if ( !fmt || 0 == strlen(fmt) ) { if ( !fmt || 0 == strlen(fmt) ) {
error = EINVAL; error = EINVAL;
skipping to change at line 1862 skipping to change at line 1878
} }
if ( strlen(fmt) > MAX_STRLEN || size > MAX_STRLEN) { if ( strlen(fmt) > MAX_STRLEN || size > MAX_STRLEN) {
error = EMSGSIZE; error = EMSGSIZE;
return -1; return -1;
} }
ind = 0; ind = 0;
for ( i = 0; i < strlen(fmt) && for ( i = 0; i < strlen(fmt) &&
(int)ind < size - 1; ++i ) { (int)ind < size - 1; ++i ) {
if ( fmt[i] != '%' ) { if ( fmt[i] != '%' ) {
out[ind++] = fmt[i]; out->buf[ind++] = fmt[i];
continue; continue;
} }
if ( i == strlen(fmt) - 1 ) { if ( i == strlen(fmt) - 1 ) {
// last character is %, invalid // last character is %, invalid
error = EINVAL; error = EINVAL;
return ind; return ind;
} }
ch1 = fmt[i+1]; ch1 = fmt[i+1];
if ( ch1 == '%' ) { if ( ch1 == '%' ) {
out[ind++] = '%'; out->buf[ind++] = '%';
++i;
continue;
}
if ( ch1 == '0' ) {
out->buf[ind++] = '\0';
++i;
continue;
}
if ( ch1 == 'n' ) {
out->buf[ind++] = '\n';
++i; ++i;
continue; continue;
} }
if ( ch1 == 'w' ) { if ( ch1 == 'w' ) {
if ( filename ) { if ( filename ) {
strncpy( &out[ind], filename, size - ind ); strncpy( &out->buf[ind], filename, size - ind );
ind += strlen(filename); ind += strlen(filename);
} }
++i; ++i;
continue; continue;
} }
if ( ch1 == 'f' ) { if ( ch1 == 'f' ) {
if ( eventname ) { if ( eventname ) {
strncpy( &out[ind], eventname, size - ind ); strncpy( &out->buf[ind], eventname, size - ind );
ind += strlen(eventname); ind += strlen(eventname);
} }
++i; ++i;
continue; continue;
} }
if ( ch1 == 'c' ) {
ind += snprintf( &out->buf[ind], size-ind, "%x", event->c
ookie);
++i;
continue;
}
if ( ch1 == 'e' ) { if ( ch1 == 'e' ) {
eventstr = inotifytools_event_to_str( event->mask ); eventstr = inotifytools_event_to_str( event->mask );
strncpy( &out[ind], eventstr, size - ind ); strncpy( &out->buf[ind], eventstr, size - ind );
ind += strlen(eventstr); ind += strlen(eventstr);
++i; ++i;
continue; continue;
} }
if ( ch1 == 'T' ) { if ( ch1 == 'T' ) {
if ( timefmt ) { if ( timefmt ) {
now = time(0); now = time(0);
if ( 0 >= strftime( timestr, MAX_STRLEN-1, timefm struct tm now_tm;
t, if (0 >= strftime(timestr, MAX_STRLEN - 1,
localtime( &now ) ) ) { timefmt,
localtime_r(&now, &now_tm))) {
// time format probably invalid // time format probably invalid
error = EINVAL; error = EINVAL;
return ind; return ind;
} }
} }
else { else {
timestr[0] = 0; timestr[0] = 0;
} }
strncpy( &out[ind], timestr, size - ind ); strncpy( &out->buf[ind], timestr, size - ind );
ind += strlen(timestr); ind += strlen(timestr);
++i; ++i;
continue; continue;
} }
// Check if next char in fmt is e // Check if next char in fmt is e
if ( i < strlen(fmt) - 2 && fmt[i+2] == 'e' ) { if ( i < strlen(fmt) - 2 && fmt[i+2] == 'e' ) {
eventstr = inotifytools_event_to_str_sep( event->mask, ch 1 ); eventstr = inotifytools_event_to_str_sep( event->mask, ch 1 );
strncpy( &out[ind], eventstr, size - ind ); strncpy( &out->buf[ind], eventstr, size - ind );
ind += strlen(eventstr); ind += strlen(eventstr);
i += 2; i += 2;
continue; continue;
} }
// OK, this wasn't a special format character, just output it as normal // OK, this wasn't a special format character, just output it as normal
if ( ind < MAX_STRLEN ) out[ind++] = '%'; if ( ind < MAX_STRLEN ) out->buf[ind++] = '%';
if ( ind < MAX_STRLEN ) out[ind++] = ch1; if ( ind < MAX_STRLEN ) out->buf[ind++] = ch1;
++i; ++i;
} }
out[ind] = 0; out->len = ind;
return ind - 1; return ind - 1;
} }
/** /**
* Set time format for printf functions. * Set time format for printf functions.
* *
* @param fmt A format string valid for use with strftime, or NULL. If NULL, * @param fmt A format string valid for use with strftime, or NULL. If NULL,
* time substitutions will no longer be made in printf functions. * time substitutions will no longer be made in printf functions.
* Note that this format string is not validated at all; using an * Note that this format string is not validated at all; using an
 End of changes. 38 change blocks. 
43 lines changed or deleted 77 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)