Compare commits

...

4 Commits
rawhide ... f25

5 changed files with 594 additions and 1 deletions

View File

@ -0,0 +1,236 @@
From 9338b244572e07bbff314b3570228e8cf43f1300 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Tue, 6 Sep 2016 17:38:26 +0200
Subject: [PATCH] ls: allow interruption when reading slow directories
Postpone installation of signal handlers until they're needed.
That is right before the first escape sequence is printed.
* src/ls.c (signal_setup): A new function refactored from main()
to set and restore signal handlers.
(main): Move signal handler setup to put_indicator()
so that the default signal handling is untouched as long as possible.
Adjusted condition for restoring signal handlers to reflect the change.
(put_indicator): Install signal handlers if called for the very first
time. It uses the same code that was in main() prior to this commit.
* NEWS: Mention the improvement.
See https://bugzilla.redhat.com/1365933
Fixes http://bugs.gnu.org/24232
Upstream-commit: 5445f7811ff945ea13aa2a0fd797eb4c0a0e4db0
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/ls.c | 161 ++++++++++++++++++++++++++++++++++++---------------------------
1 file changed, 93 insertions(+), 68 deletions(-)
diff --git a/src/ls.c b/src/ls.c
index d976036..66df307 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -1244,13 +1244,12 @@ process_signals (void)
}
}
-int
-main (int argc, char **argv)
-{
- int i;
- struct pending *thispend;
- int n_files;
+/* Setup signal handlers if INIT is true,
+ otherwise restore to the default. */
+static void
+signal_setup (bool init)
+{
/* The signals that are trapped, and the number of such signals. */
static int const sig[] =
{
@@ -1278,8 +1277,77 @@ main (int argc, char **argv)
enum { nsigs = ARRAY_CARDINALITY (sig) };
#if ! SA_NOCLDSTOP
- bool caught_sig[nsigs];
+ static bool caught_sig[nsigs];
+#endif
+
+ int j;
+
+ if (init)
+ {
+#if SA_NOCLDSTOP
+ struct sigaction act;
+
+ sigemptyset (&caught_signals);
+ for (j = 0; j < nsigs; j++)
+ {
+ sigaction (sig[j], NULL, &act);
+ if (act.sa_handler != SIG_IGN)
+ sigaddset (&caught_signals, sig[j]);
+ }
+
+ act.sa_mask = caught_signals;
+ act.sa_flags = SA_RESTART;
+
+ for (j = 0; j < nsigs; j++)
+ if (sigismember (&caught_signals, sig[j]))
+ {
+ act.sa_handler = sig[j] == SIGTSTP ? stophandler : sighandler;
+ sigaction (sig[j], &act, NULL);
+ }
+#else
+ for (j = 0; j < nsigs; j++)
+ {
+ caught_sig[j] = (signal (sig[j], SIG_IGN) != SIG_IGN);
+ if (caught_sig[j])
+ {
+ signal (sig[j], sig[j] == SIGTSTP ? stophandler : sighandler);
+ siginterrupt (sig[j], 0);
+ }
+ }
#endif
+ }
+ else /* restore. */
+ {
+#if SA_NOCLDSTOP
+ for (j = 0; j < nsigs; j++)
+ if (sigismember (&caught_signals, sig[j]))
+ signal (sig[j], SIG_DFL);
+#else
+ for (j = 0; j < nsigs; j++)
+ if (caught_sig[j])
+ signal (sig[j], SIG_DFL);
+#endif
+ }
+}
+
+static inline void
+signal_init (void)
+{
+ signal_setup (true);
+}
+
+static inline void
+signal_restore (void)
+{
+ signal_setup (false);
+}
+
+int
+main (int argc, char **argv)
+{
+ int i;
+ struct pending *thispend;
+ int n_files;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
@@ -1314,46 +1382,6 @@ main (int argc, char **argv)
|| (is_colored (C_EXEC) && color_symlink_as_referent)
|| (is_colored (C_MISSING) && format == long_format))
check_symlink_color = true;
-
- /* If the standard output is a controlling terminal, watch out
- for signals, so that the colors can be restored to the
- default state if "ls" is suspended or interrupted. */
-
- if (0 <= tcgetpgrp (STDOUT_FILENO))
- {
- int j;
-#if SA_NOCLDSTOP
- struct sigaction act;
-
- sigemptyset (&caught_signals);
- for (j = 0; j < nsigs; j++)
- {
- sigaction (sig[j], NULL, &act);
- if (act.sa_handler != SIG_IGN)
- sigaddset (&caught_signals, sig[j]);
- }
-
- act.sa_mask = caught_signals;
- act.sa_flags = SA_RESTART;
-
- for (j = 0; j < nsigs; j++)
- if (sigismember (&caught_signals, sig[j]))
- {
- act.sa_handler = sig[j] == SIGTSTP ? stophandler : sighandler;
- sigaction (sig[j], &act, NULL);
- }
-#else
- for (j = 0; j < nsigs; j++)
- {
- caught_sig[j] = (signal (sig[j], SIG_IGN) != SIG_IGN);
- if (caught_sig[j])
- {
- signal (sig[j], sig[j] == SIGTSTP ? stophandler : sighandler);
- siginterrupt (sig[j], 0);
- }
- }
-#endif
- }
}
if (dereference == DEREF_UNDEFINED)
@@ -1466,32 +1494,21 @@ main (int argc, char **argv)
print_dir_name = true;
}
- if (print_with_color)
+ if (print_with_color && used_color)
{
int j;
- if (used_color)
- {
- /* Skip the restore when it would be a no-op, i.e.,
- when left is "\033[" and right is "m". */
- if (!(color_indicator[C_LEFT].len == 2
- && memcmp (color_indicator[C_LEFT].string, "\033[", 2) == 0
- && color_indicator[C_RIGHT].len == 1
- && color_indicator[C_RIGHT].string[0] == 'm'))
- restore_default_color ();
- }
+ /* Skip the restore when it would be a no-op, i.e.,
+ when left is "\033[" and right is "m". */
+ if (!(color_indicator[C_LEFT].len == 2
+ && memcmp (color_indicator[C_LEFT].string, "\033[", 2) == 0
+ && color_indicator[C_RIGHT].len == 1
+ && color_indicator[C_RIGHT].string[0] == 'm'))
+ restore_default_color ();
+
fflush (stdout);
- /* Restore the default signal handling. */
-#if SA_NOCLDSTOP
- for (j = 0; j < nsigs; j++)
- if (sigismember (&caught_signals, sig[j]))
- signal (sig[j], SIG_DFL);
-#else
- for (j = 0; j < nsigs; j++)
- if (caught_sig[j])
- signal (sig[j], SIG_DFL);
-#endif
+ signal_restore ();
/* Act on any signals that arrived before the default was restored.
This can process signals out of order, but there doesn't seem to
@@ -4482,6 +4499,14 @@ put_indicator (const struct bin_str *ind)
if (! used_color)
{
used_color = true;
+
+ /* If the standard output is a controlling terminal, watch out
+ for signals, so that the colors can be restored to the
+ default state if "ls" is suspended or interrupted. */
+
+ if (0 <= tcgetpgrp (STDOUT_FILENO))
+ signal_init ();
+
prep_non_filename_text ();
}
--
2.7.4

View File

@ -0,0 +1,52 @@
From 8b89985a3904e0267750c430e01684edf008051b Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Mon, 28 Nov 2016 16:21:42 +0100
Subject: [PATCH] install,mkdir: fix handling of -DZ and -pZ, respectively
... in the case where two or more directories nested in each other are
created and each of them defaults to a different SELinux context.
* src/install.c (make_ancestor): When calling defaultcon(), give it the
same path that is given to mkdir(). The other path is not always valid
wrt. current working directory.
* src/mkdir.c (make_ancestor): Likewise.
* NEWS: Mention the bug fix.
Reported at https://bugzilla.redhat.com/1398913
Upstream-commit: d8104265f229ababd5a68a46eeccbccc07e72cdc
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/install.c | 2 +-
src/mkdir.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/install.c b/src/install.c
index 1b7a209..cae0a53 100644
--- a/src/install.c
+++ b/src/install.c
@@ -425,7 +425,7 @@ static int
make_ancestor (char const *dir, char const *component, void *options)
{
struct cp_options const *x = options;
- if (x->set_security_context && defaultcon (dir, S_IFDIR) < 0
+ if (x->set_security_context && defaultcon (component, S_IFDIR) < 0
&& ! ignorable_ctx_err (errno))
error (0, errno, _("failed to set default creation context for %s"),
quoteaf (dir));
diff --git a/src/mkdir.c b/src/mkdir.c
index 60fc08a..77af857 100644
--- a/src/mkdir.c
+++ b/src/mkdir.c
@@ -122,7 +122,7 @@ make_ancestor (char const *dir, char const *component, void *options)
{
struct mkdir_options const *o = options;
- if (o->set_security_context && defaultcon (dir, S_IFDIR) < 0
+ if (o->set_security_context && defaultcon (component, S_IFDIR) < 0
&& ! ignorable_ctx_err (errno))
error (0, errno, _("failed to set default creation context for %s"),
quoteaf (dir));
--
2.9.3

View File

@ -0,0 +1,115 @@
From 1e1a69da31b39e4d672ccb8a3ca0e5400d4720ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <P@draigBrady.com>
Date: Wed, 26 Oct 2016 15:45:01 +0100
Subject: [PATCH] md5sum,sha*sum: fix --ignore-missing with checksums starting
with 00
* NEWS: Mention the fix.
* src/md5sum.c (digest_file): Add a new MISSING parameter to
return whether the file was missing, separately from the digest.
* tests/misc/md5sum.pl: Add a test case.
Fixes http://bugs.gnu.org/24795
Upstream-commit: d0ddfadfb27def2861f35b1a45190a4c1780b257
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/md5sum.c | 20 ++++++++++++--------
tests/misc/md5sum.pl | 7 +++++++
2 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/src/md5sum.c b/src/md5sum.c
index 933ec99..fee28c7 100644
--- a/src/md5sum.c
+++ b/src/md5sum.c
@@ -465,15 +465,19 @@ print_filename (char const *file, bool escape)
text because it was a terminal.
Put the checksum in *BIN_RESULT, which must be properly aligned.
+ Put true in *MISSING if the file can't be opened due to ENOENT.
Return true if successful. */
static bool
-digest_file (const char *filename, int *binary, unsigned char *bin_result)
+digest_file (const char *filename, int *binary, unsigned char *bin_result,
+ bool *missing)
{
FILE *fp;
int err;
bool is_stdin = STREQ (filename, "-");
+ *missing = false;
+
if (is_stdin)
{
have_read_stdin = true;
@@ -493,7 +497,7 @@ digest_file (const char *filename, int *binary, unsigned char *bin_result)
{
if (ignore_missing && errno == ENOENT)
{
- *bin_result = '\0';
+ *missing = true;
return true;
}
error (0, errno, "%s", quotef (filename));
@@ -606,14 +610,14 @@ digest_check (const char *checkfile_name)
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f' };
bool ok;
+ bool missing;
/* Only escape in the edge case producing multiple lines,
to ease automatic processing of status output. */
bool needs_escape = ! status_only && strchr (filename, '\n');
properly_formatted_lines = true;
- *bin_buffer = '\1'; /* flag set to 0 for ignored missing files. */
- ok = digest_file (filename, &binary, bin_buffer);
+ ok = digest_file (filename, &binary, bin_buffer, &missing);
if (!ok)
{
@@ -626,10 +630,9 @@ digest_check (const char *checkfile_name)
printf (": %s\n", _("FAILED open or read"));
}
}
- else if (ignore_missing && ! *bin_buffer)
+ else if (ignore_missing && missing)
{
- /* Treat an empty buffer as meaning a missing file,
- which is ignored with --ignore-missing. */
+ /* Ignore missing files with --ignore-missing. */
;
}
else
@@ -879,8 +882,9 @@ main (int argc, char **argv)
else
{
int file_is_binary = binary;
+ bool missing;
- if (! digest_file (file, &file_is_binary, bin_buffer))
+ if (! digest_file (file, &file_is_binary, bin_buffer, &missing))
ok = false;
else
{
diff --git a/tests/misc/md5sum.pl b/tests/misc/md5sum.pl
index 2eb6369..6ea7457 100755
--- a/tests/misc/md5sum.pl
+++ b/tests/misc/md5sum.pl
@@ -149,6 +149,13 @@ my @Tests =
{ERR=>
"md5sum: f.md5: no file was verified\n"},
{EXIT=> 1}],
+ # coreutils-8.25 with --ignore-missing treated checksums starting with 00
+ # as if the file was not present
+ ['check-ignore-missing-6', '--check', '--ignore-missing',
+ {AUX=> {f=> '9t'}},
+ {IN=> {'f.md5' =>
+ "006999e6df389641adf1fa3a74801d9d f\n"}},
+ {OUT=>"f: OK\n"}],
['bsd-segv', '--check', {IN=> {'z' => "MD5 ("}}, {EXIT=> 1},
{ERR=> "$prog: z: no properly formatted MD5 checksum lines found\n"}],
--
2.7.4

View File

@ -0,0 +1,168 @@
From ba5fe2d4b8b6a8366f48b1ad1f97fe26c9089b53 Mon Sep 17 00:00:00 2001
From: Sebastian Kisela <skisela@redhat.com>
Date: Wed, 5 Apr 2017 09:40:41 +0200
Subject: [PATCH] tail: revert to polling if a followed directory is replaced
* src/tail.c (tail_forever_inotify): Add the IN_DELETE_SELF flag when
creating watch for the parent directory. After the parent directory
is removed, an event is caught and then we switch from inotify to
polling mode. Till now, inotify has always frozen because it waited for
an event from a watched dir, which has been already deleted and was not
added again.
* tests/tail-2/inotify-dir-recreate.sh: Add a test case.
* tests/local.mk: Reference the new test.
Fixes http://bugs.gnu.org/26363
Reported at https://bugzilla.redhat.com/1283760
Upstream commit: ba5fe2d4b8b6a8366f48b1ad1f97fe26c9089b53
---
src/tail.c | 22 +++++++++-
tests/local.mk | 1 +
tests/tail-2/inotify-dir-recreate.sh | 82 ++++++++++++++++++++++++++++++++++++
4 files changed, 107 insertions(+), 1 deletion(-)
create mode 100755 tests/tail-2/inotify-dir-recreate.sh
diff --git a/src/tail.c b/src/tail.c
index d1552d4..6328fe0 100644
--- a/src/tail.c
+++ b/src/tail.c
@@ -1457,7 +1457,8 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
In that case the same watch descriptor is returned. */
f[i].parent_wd = inotify_add_watch (wd, dirlen ? f[i].name : ".",
(IN_CREATE | IN_DELETE
- | IN_MOVED_TO | IN_ATTRIB));
+ | IN_MOVED_TO | IN_ATTRIB
+ | IN_DELETE_SELF));
f[i].name[dirlen] = prev;
@@ -1628,6 +1629,25 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
ev = void_ev;
evbuf_off += sizeof (*ev) + ev->len;
+ /* If a directory is deleted, IN_DELETE_SELF is emitted
+ with ev->name of length 0.
+ We need to catch it, otherwise it would wait forever,
+ as wd for directory becomes inactive. Revert to polling now. */
+ if ((ev->mask & IN_DELETE_SELF) && ! ev->len)
+ {
+ for (i = 0; i < n_files; i++)
+ {
+ if (ev->wd == f[i].parent_wd)
+ {
+ hash_free (wd_to_name);
+ error (0, 0,
+ _("directory containing watched file was removed"));
+ errno = 0; /* we've already diagnosed enough errno detail. */
+ return true;
+ }
+ }
+ }
+
if (ev->len) /* event on ev->name in watched directory. */
{
size_t j;
diff --git a/tests/local.mk b/tests/local.mk
index 3fe9ba8..e890c9a 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -176,6 +176,7 @@ all_tests = \
tests/tail-2/descriptor-vs-rename.sh \
tests/tail-2/inotify-rotate.sh \
tests/tail-2/inotify-rotate-resources.sh \
+ tests/tail-2/inotify-dir-recreate.sh \
tests/chmod/no-x.sh \
tests/chgrp/basic.sh \
tests/rm/dangling-symlink.sh \
diff --git a/tests/tail-2/inotify-dir-recreate.sh b/tests/tail-2/inotify-dir-recreate.sh
new file mode 100755
index 0000000..eaa8422
--- /dev/null
+++ b/tests/tail-2/inotify-dir-recreate.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+# Makes sure, inotify will switch to polling mode if directory
+# of the watched file was removed and recreated.
+# (...instead of getting stuck forever)
+
+# Copyright (C) 2006-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
+
+
+# Terminate any background tail process
+cleanup_() { kill $pid 2>/dev/null && wait $pid; }
+
+cleanup_fail_ ()
+{
+ warn_ $1
+ cleanup_
+ fail=1
+}
+
+# $check_re - string to be found
+# $check_f - file to be searched
+check_tail_output_ ()
+{
+ local delay="$1"
+ grep $check_re $check_f > /dev/null ||
+ { sleep $delay ; return 1; }
+}
+
+grep_timeout_ ()
+{
+ check_re="$1"
+ check_f="$2"
+ retry_delay_ check_tail_output_ .1 5
+}
+
+# Prepare the file to be watched
+mkdir dir && echo 'inotify' > dir/file || framework_failure_
+
+#tail must print content of the file to stdout, verify
+timeout 60 tail -F dir/file &>out & pid=$!
+grep_timeout_ 'inotify' 'out' ||
+{ cleanup_fail_ 'file to be tailed does not exist'; }
+
+# Remove the directory, should get the message about the deletion
+rm -r dir || framework_failure_
+grep_timeout_ 'polling' 'out' ||
+{ cleanup_fail_ 'tail did not switch to polling mode'; }
+
+# Recreate the dir, must get a message about recreation
+mkdir dir && touch dir/file || framework_failure_
+grep_timeout_ 'appeared' 'out' ||
+{ cleanup_fail_ 'previously removed file did not appear'; }
+
+cleanup_
+
+# Expected result for the whole process
+cat <<\EOF > exp || framework_failure_
+inotify
+tail: 'dir/file' has become inaccessible: No such file or directory
+tail: directory containing watched file was removed
+tail: inotify cannot be used, reverting to polling
+tail: 'dir/file' has appeared; following new file
+EOF
+
+compare exp out || fail=1
+
+Exit $fail
--
2.9.3

View File

@ -1,7 +1,7 @@
Summary: A set of basic GNU tools commonly used in shell scripts
Name: coreutils
Version: 8.25
Release: 14%{?dist}
Release: 17%{?dist}
License: GPLv3+
Group: System Environment/Base
Url: http://www.gnu.org/software/coreutils/
@ -21,6 +21,14 @@ Source10: coreutils-find-requires.sh
Patch952: coreutils-8.25-intall-Z-selinux.patch
# fix 'sort -h -k' in locales that use blank as thousands separator (#1355780)
Patch953: coreutils-8.25-sort-thousands-sep.patch
# ls: allow interruption when reading slow directories (#1365933)
Patch954: coreutils-8.25-ls-signal.patch
# md5sum,sha*sum: fix --ignore-missing with checksums starting with 00
Patch955: coreutils-8.25-sum-ignore-missing.patch
# install,mkdir: fix handling of -DZ and -pZ, respectively (#1398913)
Patch956: coreutils-8.25-mkdir-p-selinux.patch
# tail: revert to polling if a followed directory is replaced(#1283760)
Patch957: coreutils-tail-inotify-recreate.patch
# Our patches
#general patch to workaround koji build system issues
@ -213,6 +221,10 @@ tee DIR_COLORS{,.256color,.lightbgcolor} <src/dircolors.hin >/dev/null
# upstream patches
%patch953 -p1
%patch954 -p1
%patch955 -p1
%patch956 -p1
%patch957 -p1
chmod a+x \
tests/df/direct.sh \
@ -347,6 +359,16 @@ fi
%license COPYING
%changelog
* Fri Apr 28 2017 Sebastian Kisela <skisela@redhat.com> - 8.25-17
- tail: revert to polling if a followed directory is replaced
* Thu Mar 02 2017 Kamil Dudka <kdudka@redhat.com> - 8.25-16
- install,mkdir: fix handling of -DZ and -pZ, respectively (#1398913)
* Mon Oct 31 2016 Kamil Dudka <kdudka@redhat.com> - 8.25-15
- md5sum,sha*sum: fix --ignore-missing with checksums starting with 00
- ls: allow interruption when reading slow directories (#1365933)
* Tue Jul 19 2016 Kamil Dudka <kdudka@redhat.com> - 8.25-14
- run autoreconf in %%prep
- drop post-install fix for Japanese locales that no longer applies