]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
tail: only use inotify with regular files
authorPádraig Brady <P@draigBrady.com>
Sat, 17 Jun 2017 06:50:47 +0000 (23:50 -0700)
committerPádraig Brady <P@draigBrady.com>
Sat, 17 Jun 2017 21:50:04 +0000 (14:50 -0700)
* src/tail.c (any_non_regular): A new function to check passed files.
(main): Use the above to skip inotify if any non regular files passed
like /dev/tty or /dev/ttyUSB0 etc.
* tests/tail-2/inotify-only-regular.sh: A new test.
* tests/local.mk: Reference the new test.
* NEWS: Mention the bug fix.
Fixes http://bugs.gnu.org/21265 and http://bugs.gnu.org/27368

NEWS
src/tail.c
tests/local.mk
tests/tail-2/inotify-only-regular.sh [new file with mode: 0755]

diff --git a/NEWS b/NEWS
index eb0271cf8f1291cedb6b481bc87f4ed268dddb9a..071be4bb49c1399dfe33f426ba88d48cf45ee85e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   or ignored until future events on the monitored files.
   [bug introduced with inotify support added in coreutils-7.5]
 
+  tail -f /dev/tty is now supported by not using inotify when any
+  non regular files are specified, as inotify is ineffective with these.
+  [bug introduced with inotify support added in coreutils-7.5]
+
   uptime no longer outputs the AM/PM component of the current time,
   as that's inconsistent with the 24 hour time format used.
   [bug introduced in coreutils-7.0]
index 2f9b981f0daafc7c3e2ec698ff6d903e6058c233..b8be1d21df7016acec4a15532717d422039ccdae 100644 (file)
@@ -1339,6 +1339,22 @@ any_symlinks (const struct File_spec *f, size_t n_files)
   return false;
 }
 
+/* Return true if any of the N_FILES files in F is not
+   a regular file.  This is used to avoid adding inotify
+   watches on a device file for example, which inotify
+   will accept, but not give any events for.  */
+
+static bool
+any_non_regular (const struct File_spec *f, size_t n_files)
+{
+  size_t i;
+
+  for (i = 0; i < n_files; i++)
+    if (0 <= f[i].fd && ! S_ISREG (f[i].mode))
+      return true;
+  return false;
+}
+
 /* Return true if any of the N_FILES files in F represents
    stdin and is tailable.  */
 
@@ -2457,6 +2473,7 @@ main (int argc, char **argv)
                                || any_remote_file (F, n_files)
                                || ! any_non_remote_file (F, n_files)
                                || any_symlinks (F, n_files)
+                               || any_non_regular (F, n_files)
                                || (!ok && follow_mode == Follow_descriptor)))
         disable_inotify = true;
 
index fdf3edfb2216b52d678f8c9cebe7f74ed4a4f8d6..6112e88ed632f7e2e00723e3aafcfb6f09cc8ef3 100644 (file)
@@ -177,6 +177,7 @@ all_tests =                                 \
   tests/tail-2/inotify-rotate.sh               \
   tests/tail-2/inotify-rotate-resources.sh     \
   tests/tail-2/inotify-dir-recreate.sh         \
+  tests/tail-2/inotify-only-regular.sh         \
   tests/chmod/no-x.sh                          \
   tests/chgrp/basic.sh                         \
   tests/rm/dangling-symlink.sh                 \
diff --git a/tests/tail-2/inotify-only-regular.sh b/tests/tail-2/inotify-only-regular.sh
new file mode 100755 (executable)
index 0000000..4d106fb
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+# ensure that tail -f only uses inotify for regular files
+
+# Copyright (C) 2017 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ tail
+
+grep '^#define HAVE_INOTIFY 1' "$CONFIG_HEADER" >/dev/null \
+  || skip_ 'inotify support required'
+
+require_strace_ 'inotify_add_watch'
+
+returns_ 124 timeout .1 strace -e inotify_add_watch -o strace.out \
+  tail -f /dev/null || fail=1
+
+grep 'inotify' strace.out && fail=1
+
+Exit $fail