aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Nazaryev <sergey@nazaryev.ru>2020-07-09 16:39:35 +0000
committerSergey Nazaryev <sergey@nazaryev.ru>2020-07-11 21:05:18 +0000
commite8f8a5617079e24b87bacb136ad0c2ab1b93ceb3 (patch)
tree8fbc14bd87351934400fcb0ba9e4e7af0fd6507d
parentc598851c60aade135285339c7e9126d74d7cf59b (diff)
downloadinotify-tools-null-terminated.zip
inotify-tools-null-terminated.tar.gz
inotify-tools-null-terminated.tar.bz2
inotify-tools: Add --no-newline optionnull-terminated
It allows to not to put '\n' after user-specified format in the --format option
-rw-r--r--man/inotifywait.1.in15
-rw-r--r--src/inotifywait.c37
-rwxr-xr-xt/inotifywait-format-option-null.t48
3 files changed, 91 insertions, 9 deletions
diff --git a/man/inotifywait.1.in b/man/inotifywait.1.in
index 3c9a0a9..2292a58 100644
--- a/man/inotifywait.1.in
+++ b/man/inotifywait.1.in
@@ -150,6 +150,10 @@ Set a time format string as accepted by strftime(3) for use with the `%T' conver
in the \-\-format option.
.TP
+.B \-\-no-newline
+Don't print newline symbol after user-specified format in the \-\-format option.
+
+.TP
.B \-\-format <fmt>
Output in a user-specified format, using printf-like syntax. The event strings
output are limited to around 4000 characters and will be truncated to this length.
@@ -343,6 +347,17 @@ CLOSE_WRITE:CLOSE goodfile
DELETE badfile
.fi
+.SS Example 4
+Enforce file permissions in directory `~/test'
+
+.nf
+inotifywait -qmr -e 'moved_to,create' --format '%w%f%0' --no-newline ~/test |\\
+ while IFS= read -r -d '' file
+ do
+ chmod -v a+rX "$file"
+ done
+.fi
+
.SH BUGS
There are race conditions in the recursive directory watching code
diff --git a/src/inotifywait.c b/src/inotifywait.c
index 73471f4..e346fb9 100644
--- a/src/inotifywait.c
+++ b/src/inotifywait.c
@@ -37,7 +37,7 @@ bool parse_opts(int *argc, char ***argv, int *events, bool *monitor, int *quiet,
bool *syslog, bool *no_dereference, char **format,
char **timefmt, char **fromfile, char **outfile,
char **exc_regex, char **exc_iregex, char **inc_regex,
- char **inc_iregex);
+ char **inc_iregex, bool *no_newline);
void print_help();
@@ -146,13 +146,14 @@ int main(int argc, char **argv) {
char *exc_iregex = NULL;
char *inc_regex = NULL;
char *inc_iregex = NULL;
+ bool no_newline = false;
int fd;
// Parse commandline options, aborting if something goes wrong
if (!parse_opts(&argc, &argv, &events, &monitor, &quiet, &timeout,
&recursive, &csv, &dodaemon, &syslog, &no_dereference,
&format, &timefmt, &fromfile, &outfile, &exc_regex,
- &exc_iregex, &inc_regex, &inc_iregex)) {
+ &exc_iregex, &inc_regex, &inc_iregex, &no_newline)) {
return EXIT_FAILURE;
}
@@ -420,7 +421,7 @@ bool parse_opts(int *argc, char ***argv, int *events, bool *monitor, int *quiet,
bool *syslog, bool *no_dereference, char **format,
char **timefmt, char **fromfile, char **outfile,
char **exc_regex, char **exc_iregex, char **inc_regex,
- char **inc_iregex) {
+ char **inc_iregex, bool *no_newline) {
assert(argc);
assert(argv);
assert(events);
@@ -452,8 +453,8 @@ bool parse_opts(int *argc, char ***argv, int *events, bool *monitor, int *quiet,
const char *regex_warning =
"only the last option will be taken into consideration.\n";
- // format with trailing newline
- static char *newlineformat;
+ // format provided by the user
+ static char *customformat = NULL;
// Short options
static const char opt_string[] = "mrhcdsPqt:fo:e:";
@@ -472,6 +473,7 @@ bool parse_opts(int *argc, char ***argv, int *events, bool *monitor, int *quiet,
{"syslog", no_argument, NULL, 's'},
{"no-dereference", no_argument, NULL, 'P'},
{"format", required_argument, NULL, 'n'},
+ {"no-newline", no_argument, NULL, '0'},
{"timefmt", required_argument, NULL, 'i'},
{"fromfile", required_argument, NULL, 'z'},
{"outfile", required_argument, NULL, 'o'},
@@ -542,10 +544,13 @@ bool parse_opts(int *argc, char ***argv, int *events, bool *monitor, int *quiet,
// --format
case 'n':
- newlineformat = (char *)malloc(strlen(optarg) + 2);
- strcpy(newlineformat, optarg);
- strcat(newlineformat, "\n");
- (*format) = newlineformat;
+ customformat = (char *)malloc(strlen(optarg) + 2);
+ strcpy(customformat, optarg);
+ break;
+
+ // --no-newline
+ case '0':
+ (*no_newline) = true;
break;
// --timefmt
@@ -623,6 +628,13 @@ bool parse_opts(int *argc, char ***argv, int *events, bool *monitor, int *quiet,
curr_opt = getopt_long(*argc, *argv, opt_string, long_opts, NULL);
}
+ if (customformat) {
+ if(!(*no_newline)) {
+ strcat(customformat, "\n");
+ }
+ (*format) = customformat;
+ }
+
if (*exc_regex && *exc_iregex) {
fprintf(stderr, "--exclude and --excludei cannot both be specified.\n");
return false;
@@ -645,6 +657,11 @@ bool parse_opts(int *argc, char ***argv, int *events, bool *monitor, int *quiet,
return false;
}
+ if (!*format && *no_newline) {
+ fprintf(stderr, "--no-newline cannot be specified without --format.\n");
+ return false;
+ }
+
if (!*format && *timefmt) {
fprintf(stderr, "--timefmt cannot be specified without --format.\n");
return false;
@@ -719,6 +736,8 @@ void print_help() {
printf("\t-qq \tPrint nothing (not even events).\n");
printf("\t--format <fmt>\tPrint using a specified printf-like format\n"
"\t \tstring; read the man page for more details.\n");
+ printf("\t--no-newline \tDon't print newline symbol after\n"
+ "\t \t--format string.\n");
printf("\t--timefmt <fmt>\tstrftime-compatible format string for use with\n"
"\t \t%%T in --format string.\n");
printf("\t-c|--csv \tPrint events in CSV format.\n");
diff --git a/t/inotifywait-format-option-null.t b/t/inotifywait-format-option-null.t
new file mode 100755
index 0000000..ce29147
--- /dev/null
+++ b/t/inotifywait-format-option-null.t
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+test_description='Check producing NUL-delimited output'
+
+. ./sharness.sh
+
+logfile="log"
+
+run_() {
+ touch $logfile
+
+ export LD_LIBRARY_PATH="../../libinotifytools/src/.libs/"
+
+ ../../src/.libs/inotifywait \
+ --monitor \
+ --quiet \
+ --outfile $logfile \
+ --format '%w%f%0' \
+ --no-newline \
+ --event create \
+ --event moved_to \
+ --event moved_from \
+ $(realpath ./) &
+
+ PID="$!"
+ sleep 1
+
+ touch test-file-src
+
+ mv test-file-src test-file-dst
+
+ sleep 1
+
+ kill ${PID}
+}
+
+test_expect_success 'the output is delimited by NUL' \
+ '
+ set -e
+ trap "set +e" RETURN
+ run_
+ srcfile="${PWD}/test-file-src"
+ dstfile="${PWD}/test-file-dst"
+
+ return $(printf "${srcfile}\0${srcfile}\0${dstfile}\0" | cmp -s "${logfile}")
+ '
+
+test_done