From 17ee3c675e595bf872a0ae1f1503f47462395704 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Wed, 6 Oct 2021 10:51:18 -0400 Subject: [PATCH] import coreutils-8.30-12.el8 --- SOURCES/coreutils-8.30-statx.patch | 1358 +++++++++++++++++ SOURCES/coreutils-8.30-tail-use-poll.patch | 469 ++++++ ...coreutils-8.32-df-duplicated-entries.patch | 72 + SOURCES/coreutils-8.32-fuse-portal.patch | 38 + SOURCES/coreutils-8.32-rm-stray-skip.patch | 109 ++ SOURCES/coreutils-8.32-split-number.patch | 100 ++ SPECS/coreutils.spec | 34 +- 7 files changed, 2179 insertions(+), 1 deletion(-) create mode 100644 SOURCES/coreutils-8.30-statx.patch create mode 100644 SOURCES/coreutils-8.30-tail-use-poll.patch create mode 100644 SOURCES/coreutils-8.32-df-duplicated-entries.patch create mode 100644 SOURCES/coreutils-8.32-fuse-portal.patch create mode 100644 SOURCES/coreutils-8.32-rm-stray-skip.patch create mode 100644 SOURCES/coreutils-8.32-split-number.patch diff --git a/SOURCES/coreutils-8.30-statx.patch b/SOURCES/coreutils-8.30-statx.patch new file mode 100644 index 0000000..7cda82d --- /dev/null +++ b/SOURCES/coreutils-8.30-statx.patch @@ -0,0 +1,1358 @@ +From b6a4efe4347a061161054698857b6dde0f3ed67c Mon Sep 17 00:00:00 2001 +From: Martin Bukatovic +Date: Sat, 2 Mar 2019 19:57:17 -0800 +Subject: [PATCH 1/5] stat: print birth time on systems supporting statx + +* configure.ac: Check for statx(), available on glibc >= 2.28. +* src/stat.c (get_birthtime): Call statx() when available. +* NEWS: Mention the improvement. + +Upstream-commit: 186896d65f6182dff15cad6c1045d22ad2004962 +Signed-off-by: Kamil Dudka +--- + configure.ac | 3 +++ + src/stat.c | 19 +++++++++++++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 9f7a8a5..c24ce2a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -318,6 +318,9 @@ if test $ac_cv_func_getattrat = yes; then + AC_SUBST([LIB_NVPAIR]) + fi + ++# glibc >= 2.28 and linux kernel >= 4.11 ++AC_CHECK_FUNCS([statx]) ++ + # SCO-ODT-3.0 is reported to need -los to link programs using initgroups + AC_CHECK_FUNCS([initgroups]) + if test $ac_cv_func_initgroups = no; then +diff --git a/src/stat.c b/src/stat.c +index 0a5ef3c..9e71cbe 100644 +--- a/src/stat.c ++++ b/src/stat.c +@@ -1007,6 +1007,25 @@ get_birthtime (int fd, char const *filename, struct stat const *st) + } + #endif + ++#if HAVE_STATX ++ if (ts.tv_nsec < 0) ++ { ++ struct statx stx; ++ if ((fd < 0 ++ ? statx (AT_FDCWD, filename, ++ follow_links ? 0 : AT_SYMLINK_NOFOLLOW, ++ STATX_BTIME, &stx) ++ : statx (fd, "", AT_EMPTY_PATH, STATX_BTIME, &stx)) == 0) ++ { ++ if ((stx.stx_mask & STATX_BTIME) && stx.stx_btime.tv_sec != 0) ++ { ++ ts.tv_sec = stx.stx_btime.tv_sec; ++ ts.tv_nsec = stx.stx_btime.tv_nsec; ++ } ++ } ++ } ++#endif ++ + return ts; + } + +-- +2.20.1 + + +From 21ff41c1e5ef4668669f92d04c69a258708ba20e Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Tue, 28 May 2019 08:21:42 -0400 +Subject: [PATCH 2/5] stat: Use statx where available and support --cached + +* src/stat.c: Drop statbuf argument from out_epoch_sec(). +Use statx() rather than [lf]stat() where available, +so a separate call is not required to get birth time. +Set STATX_* mask bits only for things we want to print, +which can be more efficient on some file systems. +Add a new --cache= command-line option that sets the appropriate hint +flags in the statx call. These are primarily used with network +file systems to indicate what level of cache coherency is desired. +The new option is available unconditionally for better portability, +and ignored where not implemented. +* doc/coreutils.texi: Add documention for --cached. +* man/stat.x (SEE ALSO): Mention statx(). + +Upstream-commit: 6cc35de16fdc52d417602b66d5e90694d7e02994 +Signed-off-by: Kamil Dudka +--- + doc/coreutils.texi | 21 ++ + man/stat.x | 2 +- + src/stat.c | 623 ++++++++++++++++++++++++++++++--------------- + 3 files changed, 444 insertions(+), 202 deletions(-) + +diff --git a/doc/coreutils.texi b/doc/coreutils.texi +index 6ac99be..547d17b 100644 +--- a/doc/coreutils.texi ++++ b/doc/coreutils.texi +@@ -12201,6 +12201,27 @@ Report information about the file systems where the given files are located + instead of information about the files themselves. + This option implies the @option{-L} option. + ++@item --cached=@var{mode} ++@opindex --cached=@var{mode} ++@cindex attribute caching ++Control how attributes are read from the file system; ++if supported by the system. This allows one to ++control the trade-off between freshness and efficiency ++of attribute access, especially useful with remote file systems. ++@var{mode} can be: ++ ++@table @samp ++@item always ++Always read the already cached attributes if available. ++ ++@item never ++Always sychronize with the latest file system attributes. ++ ++@item default ++Leave the caching behavior to the underlying file system. ++ ++@end table ++ + @item -c + @itemx --format=@var{format} + @opindex -c +diff --git a/man/stat.x b/man/stat.x +index dc3781e..b9f8c68 100644 +--- a/man/stat.x ++++ b/man/stat.x +@@ -3,4 +3,4 @@ stat \- display file or file system status + [DESCRIPTION] + .\" Add any additional description here + [SEE ALSO] +-stat(2), statfs(2) ++stat(2), statfs(2), statx(2) +diff --git a/src/stat.c b/src/stat.c +index 9e71cbe..32ffb6d 100644 +--- a/src/stat.c ++++ b/src/stat.c +@@ -28,6 +28,12 @@ + # define USE_STATVFS 0 + #endif + ++#if HAVE_STATX && defined STATX_INO ++# define USE_STATX 1 ++#else ++# define USE_STATX 0 ++#endif ++ + #include + #include + #include +@@ -194,6 +200,23 @@ enum + PRINTF_OPTION = CHAR_MAX + 1 + }; + ++enum cached_mode ++{ ++ cached_default, ++ cached_never, ++ cached_always ++}; ++ ++static char const *const cached_args[] = ++{ ++ "default", "never", "always", NULL ++}; ++ ++static enum cached_mode const cached_modes[] = ++{ ++ cached_default, cached_never, cached_always ++}; ++ + static struct option const long_options[] = + { + {"dereference", no_argument, NULL, 'L'}, +@@ -201,6 +224,7 @@ static struct option const long_options[] = + {"format", required_argument, NULL, 'c'}, + {"printf", required_argument, NULL, PRINTF_OPTION}, + {"terse", no_argument, NULL, 't'}, ++ {"cached", required_argument, NULL, 0}, + {GETOPT_HELP_OPTION_DECL}, + {GETOPT_VERSION_OPTION_DECL}, + {NULL, 0, NULL, 0} +@@ -221,6 +245,10 @@ static char const *trailing_delim = ""; + static char const *decimal_point; + static size_t decimal_point_len; + ++static bool ++print_stat (char *pformat, size_t prefix_len, unsigned int m, ++ int fd, char const *filename, void const *data); ++ + /* Return the type of the specified file system. + Some systems have statfvs.f_basetype[FSTYPSZ] (AIX, HP-UX, and Solaris). + Others have statvfs.f_fstypename[_VFS_NAMELEN] (NetBSD 3.0). +@@ -674,7 +702,6 @@ out_minus_zero (char *pformat, size_t prefix_len) + acts like printf's %f format. */ + static void + out_epoch_sec (char *pformat, size_t prefix_len, +- struct stat const *statbuf _GL_UNUSED, + struct timespec arg) + { + char *dot = memchr (pformat, '.', prefix_len); +@@ -978,57 +1005,6 @@ print_mount_point: + return fail; + } + +-static struct timespec +-get_birthtime (int fd, char const *filename, struct stat const *st) +-{ +- struct timespec ts = get_stat_birthtime (st); +- +-#if HAVE_GETATTRAT +- if (ts.tv_nsec < 0) +- { +- nvlist_t *response; +- if ((fd < 0 +- ? getattrat (AT_FDCWD, XATTR_VIEW_READWRITE, filename, &response) +- : fgetattr (fd, XATTR_VIEW_READWRITE, &response)) +- == 0) +- { +- uint64_t *val; +- uint_t n; +- if (nvlist_lookup_uint64_array (response, A_CRTIME, &val, &n) == 0 +- && 2 <= n +- && val[0] <= TYPE_MAXIMUM (time_t) +- && val[1] < 1000000000 * 2 /* for leap seconds */) +- { +- ts.tv_sec = val[0]; +- ts.tv_nsec = val[1]; +- } +- nvlist_free (response); +- } +- } +-#endif +- +-#if HAVE_STATX +- if (ts.tv_nsec < 0) +- { +- struct statx stx; +- if ((fd < 0 +- ? statx (AT_FDCWD, filename, +- follow_links ? 0 : AT_SYMLINK_NOFOLLOW, +- STATX_BTIME, &stx) +- : statx (fd, "", AT_EMPTY_PATH, STATX_BTIME, &stx)) == 0) +- { +- if ((stx.stx_mask & STATX_BTIME) && stx.stx_btime.tv_sec != 0) +- { +- ts.tv_sec = stx.stx_btime.tv_sec; +- ts.tv_nsec = stx.stx_btime.tv_nsec; +- } +- } +- } +-#endif +- +- return ts; +-} +- + /* Map a TS with negative TS.tv_nsec to {0,0}. */ + static inline struct timespec + neg_to_zero (struct timespec ts) +@@ -1065,139 +1041,6 @@ getenv_quoting_style (void) + /* Equivalent to quotearg(), but explicit to avoid syntax checks. */ + #define quoteN(x) quotearg_style (get_quoting_style (NULL), x) + +-/* Print stat info. Return zero upon success, nonzero upon failure. */ +-static bool +-print_stat (char *pformat, size_t prefix_len, unsigned int m, +- int fd, char const *filename, void const *data) +-{ +- struct stat *statbuf = (struct stat *) data; +- struct passwd *pw_ent; +- struct group *gw_ent; +- bool fail = false; +- +- switch (m) +- { +- case 'n': +- out_string (pformat, prefix_len, filename); +- break; +- case 'N': +- out_string (pformat, prefix_len, quoteN (filename)); +- if (S_ISLNK (statbuf->st_mode)) +- { +- char *linkname = areadlink_with_size (filename, statbuf->st_size); +- if (linkname == NULL) +- { +- error (0, errno, _("cannot read symbolic link %s"), +- quoteaf (filename)); +- return true; +- } +- printf (" -> "); +- out_string (pformat, prefix_len, quoteN (linkname)); +- free (linkname); +- } +- break; +- case 'd': +- out_uint (pformat, prefix_len, statbuf->st_dev); +- break; +- case 'D': +- out_uint_x (pformat, prefix_len, statbuf->st_dev); +- break; +- case 'i': +- out_uint (pformat, prefix_len, statbuf->st_ino); +- break; +- case 'a': +- out_uint_o (pformat, prefix_len, statbuf->st_mode & CHMOD_MODE_BITS); +- break; +- case 'A': +- out_string (pformat, prefix_len, human_access (statbuf)); +- break; +- case 'f': +- out_uint_x (pformat, prefix_len, statbuf->st_mode); +- break; +- case 'F': +- out_string (pformat, prefix_len, file_type (statbuf)); +- break; +- case 'h': +- out_uint (pformat, prefix_len, statbuf->st_nlink); +- break; +- case 'u': +- out_uint (pformat, prefix_len, statbuf->st_uid); +- break; +- case 'U': +- pw_ent = getpwuid (statbuf->st_uid); +- out_string (pformat, prefix_len, +- pw_ent ? pw_ent->pw_name : "UNKNOWN"); +- break; +- case 'g': +- out_uint (pformat, prefix_len, statbuf->st_gid); +- break; +- case 'G': +- gw_ent = getgrgid (statbuf->st_gid); +- out_string (pformat, prefix_len, +- gw_ent ? gw_ent->gr_name : "UNKNOWN"); +- break; +- case 't': +- out_uint_x (pformat, prefix_len, major (statbuf->st_rdev)); +- break; +- case 'm': +- fail |= out_mount_point (filename, pformat, prefix_len, statbuf); +- break; +- case 'T': +- out_uint_x (pformat, prefix_len, minor (statbuf->st_rdev)); +- break; +- case 's': +- out_int (pformat, prefix_len, statbuf->st_size); +- break; +- case 'B': +- out_uint (pformat, prefix_len, ST_NBLOCKSIZE); +- break; +- case 'b': +- out_uint (pformat, prefix_len, ST_NBLOCKS (*statbuf)); +- break; +- case 'o': +- out_uint (pformat, prefix_len, ST_BLKSIZE (*statbuf)); +- break; +- case 'w': +- { +- struct timespec t = get_birthtime (fd, filename, statbuf); +- if (t.tv_nsec < 0) +- out_string (pformat, prefix_len, "-"); +- else +- out_string (pformat, prefix_len, human_time (t)); +- } +- break; +- case 'W': +- out_epoch_sec (pformat, prefix_len, statbuf, +- neg_to_zero (get_birthtime (fd, filename, statbuf))); +- break; +- case 'x': +- out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf))); +- break; +- case 'X': +- out_epoch_sec (pformat, prefix_len, statbuf, get_stat_atime (statbuf)); +- break; +- case 'y': +- out_string (pformat, prefix_len, human_time (get_stat_mtime (statbuf))); +- break; +- case 'Y': +- out_epoch_sec (pformat, prefix_len, statbuf, get_stat_mtime (statbuf)); +- break; +- case 'z': +- out_string (pformat, prefix_len, human_time (get_stat_ctime (statbuf))); +- break; +- case 'Z': +- out_epoch_sec (pformat, prefix_len, statbuf, get_stat_ctime (statbuf)); +- break; +- case 'C': +- fail |= out_file_context (pformat, prefix_len, filename); +- break; +- default: +- fputc ('?', stdout); +- break; +- } +- return fail; +-} +- + /* Output a single-character \ escape. */ + + static void +@@ -1239,6 +1082,17 @@ print_esc_char (char c) + putchar (c); + } + ++static size_t _GL_ATTRIBUTE_PURE ++format_code_offset (char const* directive) ++{ ++ size_t len = strspn (directive + 1, printf_flags); ++ char const *fmt_char = directive + len + 1; ++ fmt_char += strspn (fmt_char, digits); ++ if (*fmt_char == '.') ++ fmt_char += 1 + strspn (fmt_char + 1, digits); ++ return fmt_char - directive; ++} ++ + /* Print the information specified by the format string, FORMAT, + calling PRINT_FUNC for each %-directive encountered. + Return zero upon success, nonzero upon failure. */ +@@ -1268,33 +1122,28 @@ print_it (char const *format, int fd, char const *filename, + { + case '%': + { +- size_t len = strspn (b + 1, printf_flags); +- char const *fmt_char = b + len + 1; +- fmt_char += strspn (fmt_char, digits); +- if (*fmt_char == '.') +- fmt_char += 1 + strspn (fmt_char + 1, digits); +- len = fmt_char - (b + 1); +- unsigned int fmt_code = *fmt_char; +- memcpy (dest, b, len + 1); +- +- b = fmt_char; +- switch (fmt_code) ++ size_t len = format_code_offset (b); ++ char const *fmt_char = b + len; ++ memcpy (dest, b, len); ++ b += len; ++ ++ switch (*fmt_char) + { + case '\0': + --b; + FALLTHROUGH; + case '%': +- if (0 < len) ++ if (1 < len) + { +- dest[len + 1] = *fmt_char; +- dest[len + 2] = '\0'; ++ dest[len] = *fmt_char; ++ dest[len + 1] = '\0'; + die (EXIT_FAILURE, 0, _("%s: invalid directive"), + quote (dest)); + } + putchar ('%'); + break; + default: +- fail |= print_func (dest, len + 1, fmt_code, ++ fail |= print_func (dest, len, to_uchar (*fmt_char), + fd, filename, data); + break; + } +@@ -1382,6 +1231,204 @@ do_statfs (char const *filename, char const *format) + return ! fail; + } + ++struct print_args { ++ struct stat *st; ++ struct timespec btime; ++}; ++ ++/* Ask statx to avoid syncing? */ ++static bool dont_sync; ++ ++/* Ask statx to force sync? */ ++static bool force_sync; ++ ++#if USE_STATX ++/* Much of the format printing requires a struct stat or timespec */ ++static struct timespec ++statx_timestamp_to_timespec (struct statx_timestamp tsx) ++{ ++ struct timespec ts; ++ ++ ts.tv_sec = tsx.tv_sec; ++ ts.tv_nsec = tsx.tv_nsec; ++ return ts; ++} ++ ++static void ++statx_to_stat (struct statx *stx, struct stat *stat) ++{ ++ stat->st_dev = makedev (stx->stx_dev_major, stx->stx_dev_minor); ++ stat->st_ino = stx->stx_ino; ++ stat->st_mode = stx->stx_mode; ++ stat->st_nlink = stx->stx_nlink; ++ stat->st_uid = stx->stx_uid; ++ stat->st_gid = stx->stx_gid; ++ stat->st_rdev = makedev (stx->stx_rdev_major, stx->stx_rdev_minor); ++ stat->st_size = stx->stx_size; ++ stat->st_blksize = stx->stx_blksize; ++/* define to avoid sc_prohibit_stat_st_blocks. */ ++# define SC_ST_BLOCKS st_blocks ++ stat->SC_ST_BLOCKS = stx->stx_blocks; ++ stat->st_atim = statx_timestamp_to_timespec (stx->stx_atime); ++ stat->st_mtim = statx_timestamp_to_timespec (stx->stx_mtime); ++ stat->st_ctim = statx_timestamp_to_timespec (stx->stx_ctime); ++} ++ ++static unsigned int ++fmt_to_mask (char fmt) ++{ ++ switch (fmt) ++ { ++ case 'N': ++ return STATX_MODE|STATX_SIZE; ++ case 'd': ++ case 'D': ++ return STATX_MODE; ++ case 'i': ++ return STATX_INO; ++ case 'a': ++ case 'A': ++ return STATX_MODE; ++ case 'f': ++ return STATX_MODE|STATX_TYPE; ++ case 'F': ++ return STATX_TYPE; ++ case 'h': ++ return STATX_NLINK; ++ case 'u': ++ case 'U': ++ return STATX_UID; ++ case 'g': ++ case 'G': ++ return STATX_GID; ++ case 'm': ++ return STATX_MODE|STATX_INO; ++ case 's': ++ return STATX_SIZE; ++ case 't': ++ case 'T': ++ return STATX_MODE; ++ case 'b': ++ return STATX_BLOCKS; ++ case 'w': ++ case 'W': ++ return STATX_BTIME; ++ case 'x': ++ case 'X': ++ return STATX_ATIME; ++ case 'y': ++ case 'Y': ++ return STATX_MTIME; ++ case 'z': ++ case 'Z': ++ return STATX_CTIME; ++ } ++ return 0; ++} ++ ++static unsigned int _GL_ATTRIBUTE_PURE ++format_to_mask (char const *format) ++{ ++ unsigned int mask = 0; ++ char const *b; ++ ++ for (b = format; *b; b++) ++ { ++ if (*b != '%') ++ continue; ++ ++ b += format_code_offset (b); ++ if (*b == '\0') ++ break; ++ mask |= fmt_to_mask (*b); ++ } ++ return mask; ++} ++ ++/* statx the file and print what we find */ ++static bool ATTRIBUTE_WARN_UNUSED_RESULT ++do_stat (char const *filename, char const *format, char const *format2) ++{ ++ int fd = STREQ (filename, "-") ? 0 : AT_FDCWD; ++ int flags = 0; ++ struct stat st; ++ struct statx stx; ++ const char *pathname = filename; ++ struct print_args pa; ++ pa.st = &st; ++ pa.btime = (struct timespec) {-1, -1}; ++ ++ if (AT_FDCWD != fd) ++ { ++ pathname = ""; ++ flags = AT_EMPTY_PATH; ++ } ++ else if (!follow_links) ++ { ++ flags = AT_SYMLINK_NOFOLLOW; ++ } ++ ++ if (dont_sync) ++ flags |= AT_STATX_DONT_SYNC; ++ else if (force_sync) ++ flags |= AT_STATX_FORCE_SYNC; ++ ++ fd = statx (fd, pathname, flags, format_to_mask (format), &stx); ++ if (fd < 0) ++ { ++ if (flags & AT_EMPTY_PATH) ++ error (0, errno, _("cannot stat standard input")); ++ else ++ error (0, errno, _("cannot statx %s"), quoteaf (filename)); ++ return false; ++ } ++ ++ if (S_ISBLK (stx.stx_mode) || S_ISCHR (stx.stx_mode)) ++ format = format2; ++ ++ statx_to_stat (&stx, &st); ++ if (stx.stx_mask & STATX_BTIME) ++ pa.btime = statx_timestamp_to_timespec (stx.stx_btime); ++ ++ bool fail = print_it (format, fd, filename, print_stat, &pa); ++ return ! fail; ++} ++ ++#else /* USE_STATX */ ++ ++static struct timespec ++get_birthtime (int fd, char const *filename, struct stat const *st) ++{ ++ struct timespec ts = get_stat_birthtime (st); ++ ++# if HAVE_GETATTRAT ++ if (ts.tv_nsec < 0) ++ { ++ nvlist_t *response; ++ if ((fd < 0 ++ ? getattrat (AT_FDCWD, XATTR_VIEW_READWRITE, filename, &response) ++ : fgetattr (fd, XATTR_VIEW_READWRITE, &response)) ++ == 0) ++ { ++ uint64_t *val; ++ uint_t n; ++ if (nvlist_lookup_uint64_array (response, A_CRTIME, &val, &n) == 0 ++ && 2 <= n ++ && val[0] <= TYPE_MAXIMUM (time_t) ++ && val[1] < 1000000000 * 2 /* for leap seconds */) ++ { ++ ts.tv_sec = val[0]; ++ ts.tv_nsec = val[1]; ++ } ++ nvlist_free (response); ++ } ++ } ++# endif ++ ++ return ts; ++} ++ ++ + /* stat the file and print what we find */ + static bool ATTRIBUTE_WARN_UNUSED_RESULT + do_stat (char const *filename, char const *format, +@@ -1389,6 +1436,9 @@ do_stat (char const *filename, char const *format, + { + int fd = STREQ (filename, "-") ? 0 : -1; + struct stat statbuf; ++ struct print_args pa; ++ pa.st = &statbuf; ++ pa.btime = (struct timespec) {-1, -1}; + + if (0 <= fd) + { +@@ -1412,9 +1462,152 @@ do_stat (char const *filename, char const *format, + if (S_ISBLK (statbuf.st_mode) || S_ISCHR (statbuf.st_mode)) + format = format2; + +- bool fail = print_it (format, fd, filename, print_stat, &statbuf); ++ bool fail = print_it (format, fd, filename, print_stat, &pa); + return ! fail; + } ++#endif /* USE_STATX */ ++ ++ ++/* Print stat info. Return zero upon success, nonzero upon failure. */ ++static bool ++print_stat (char *pformat, size_t prefix_len, unsigned int m, ++ int fd, char const *filename, void const *data) ++{ ++ struct print_args *parg = (struct print_args *) data; ++ struct stat *statbuf = parg->st; ++ struct timespec btime = parg->btime; ++ struct passwd *pw_ent; ++ struct group *gw_ent; ++ bool fail = false; ++ ++ switch (m) ++ { ++ case 'n': ++ out_string (pformat, prefix_len, filename); ++ break; ++ case 'N': ++ out_string (pformat, prefix_len, quoteN (filename)); ++ if (S_ISLNK (statbuf->st_mode)) ++ { ++ char *linkname = areadlink_with_size (filename, statbuf->st_size); ++ if (linkname == NULL) ++ { ++ error (0, errno, _("cannot read symbolic link %s"), ++ quoteaf (filename)); ++ return true; ++ } ++ printf (" -> "); ++ out_string (pformat, prefix_len, quoteN (linkname)); ++ free (linkname); ++ } ++ break; ++ case 'd': ++ out_uint (pformat, prefix_len, statbuf->st_dev); ++ break; ++ case 'D': ++ out_uint_x (pformat, prefix_len, statbuf->st_dev); ++ break; ++ case 'i': ++ out_uint (pformat, prefix_len, statbuf->st_ino); ++ break; ++ case 'a': ++ out_uint_o (pformat, prefix_len, statbuf->st_mode & CHMOD_MODE_BITS); ++ break; ++ case 'A': ++ out_string (pformat, prefix_len, human_access (statbuf)); ++ break; ++ case 'f': ++ out_uint_x (pformat, prefix_len, statbuf->st_mode); ++ break; ++ case 'F': ++ out_string (pformat, prefix_len, file_type (statbuf)); ++ break; ++ case 'h': ++ out_uint (pformat, prefix_len, statbuf->st_nlink); ++ break; ++ case 'u': ++ out_uint (pformat, prefix_len, statbuf->st_uid); ++ break; ++ case 'U': ++ pw_ent = getpwuid (statbuf->st_uid); ++ out_string (pformat, prefix_len, ++ pw_ent ? pw_ent->pw_name : "UNKNOWN"); ++ break; ++ case 'g': ++ out_uint (pformat, prefix_len, statbuf->st_gid); ++ break; ++ case 'G': ++ gw_ent = getgrgid (statbuf->st_gid); ++ out_string (pformat, prefix_len, ++ gw_ent ? gw_ent->gr_name : "UNKNOWN"); ++ break; ++ case 'm': ++ fail |= out_mount_point (filename, pformat, prefix_len, statbuf); ++ break; ++ case 's': ++ out_int (pformat, prefix_len, statbuf->st_size); ++ break; ++ case 't': ++ out_uint_x (pformat, prefix_len, major (statbuf->st_rdev)); ++ break; ++ case 'T': ++ out_uint_x (pformat, prefix_len, minor (statbuf->st_rdev)); ++ break; ++ case 'B': ++ out_uint (pformat, prefix_len, ST_NBLOCKSIZE); ++ break; ++ case 'b': ++ out_uint (pformat, prefix_len, ST_NBLOCKS (*statbuf)); ++ break; ++ case 'o': ++ out_uint (pformat, prefix_len, ST_BLKSIZE (*statbuf)); ++ break; ++ case 'w': ++ { ++#if ! USE_STATX ++ btime = get_birthtime (fd, filename, statbuf); ++#endif ++ if (btime.tv_nsec < 0) ++ out_string (pformat, prefix_len, "-"); ++ else ++ out_string (pformat, prefix_len, human_time (btime)); ++ } ++ break; ++ case 'W': ++ { ++#if ! USE_STATX ++ btime = get_birthtime (fd, filename, statbuf); ++#endif ++ out_epoch_sec (pformat, prefix_len, neg_to_zero (btime)); ++ } ++ break; ++ case 'x': ++ out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf))); ++ break; ++ case 'X': ++ out_epoch_sec (pformat, prefix_len, get_stat_atime (statbuf)); ++ break; ++ case 'y': ++ out_string (pformat, prefix_len, human_time (get_stat_mtime (statbuf))); ++ break; ++ case 'Y': ++ out_epoch_sec (pformat, prefix_len, get_stat_mtime (statbuf)); ++ break; ++ case 'z': ++ out_string (pformat, prefix_len, human_time (get_stat_ctime (statbuf))); ++ break; ++ case 'Z': ++ out_epoch_sec (pformat, prefix_len, get_stat_ctime (statbuf)); ++ break; ++ case 'C': ++ fail |= out_file_context (pformat, prefix_len, filename); ++ break; ++ default: ++ fputc ('?', stdout); ++ break; ++ } ++ return fail; ++} + + /* Return an allocated format string in static storage that + corresponds to whether FS and TERSE options were declared. */ +@@ -1523,6 +1716,10 @@ Display file or file system status.\n\ + fputs (_("\ + -L, --dereference follow links\n\ + -f, --file-system display file system status instead of file status\n\ ++"), stdout); ++ fputs (_("\ ++ --cached=MODE specify how to use cached attributes;\n\ ++ useful on remote file systems. See MODE below\n\ + "), stdout); + fputs (_("\ + -c --format=FORMAT use the specified FORMAT instead of the default;\n\ +@@ -1535,6 +1732,13 @@ Display file or file system status.\n\ + fputs (HELP_OPTION_DESCRIPTION, stdout); + fputs (VERSION_OPTION_DESCRIPTION, stdout); + ++ fputs (_("\n\ ++The --cached MODE argument can be; always, never, or default.\n\ ++`always` will use cached attributes if available, while\n\ ++`never` will try to synchronize with the latest attributes, and\n\ ++`default` will leave it up to the underlying file system.\n\ ++"), stdout); ++ + fputs (_("\n\ + The valid format sequences for files (without --file-system):\n\ + \n\ +@@ -1668,6 +1872,23 @@ main (int argc, char *argv[]) + terse = true; + break; + ++ case 0: ++ switch (XARGMATCH ("--cached", optarg, cached_args, cached_modes)) ++ { ++ case cached_never: ++ force_sync = true; ++ dont_sync = false; ++ break; ++ case cached_always: ++ force_sync = false; ++ dont_sync = true; ++ break; ++ case cached_default: ++ force_sync = false; ++ dont_sync = false; ++ } ++ break; ++ + case_GETOPT_HELP_CHAR; + + case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); +-- +2.20.1 + + +From b9d6d0b4902cfa5ff3edf5ac7a082138f3237847 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Fri, 14 Jun 2019 14:37:43 -0400 +Subject: [PATCH 3/5] stat: fix enabling of statx logic + +* src/stat.c: STATX_INO isn't defined until stat.h is included. +Move the test down so it works properly. + +Upstream-commit: 0b9bac90d8283c1262e74f0dbda87583508de9a3 +Signed-off-by: Kamil Dudka +--- + src/stat.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/stat.c b/src/stat.c +index 32ffb6d..1d9d83a 100644 +--- a/src/stat.c ++++ b/src/stat.c +@@ -28,12 +28,6 @@ + # define USE_STATVFS 0 + #endif + +-#if HAVE_STATX && defined STATX_INO +-# define USE_STATX 1 +-#else +-# define USE_STATX 0 +-#endif +- + #include + #include + #include +@@ -80,6 +74,12 @@ + #include "find-mount-point.h" + #include "xvasprintf.h" + ++#if HAVE_STATX && defined STATX_INO ++# define USE_STATX 1 ++#else ++# define USE_STATX 0 ++#endif ++ + #if USE_STATVFS + # define STRUCT_STATXFS_F_FSID_IS_INTEGER STRUCT_STATVFS_F_FSID_IS_INTEGER + # define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATVFS_F_TYPE +-- +2.20.1 + + +From 987cb69ae212a257b5f8d1582dac03c2aa1aa399 Mon Sep 17 00:00:00 2001 +From: Andreas Dilger +Date: Thu, 27 Jun 2019 02:25:55 -0600 +Subject: [PATCH 4/5] stat: don't explicitly request file size for filenames + +When calling 'stat -c %N' to print the filename, don't explicitly +request the size of the file via statx(), as it may add overhead on +some filesystems. The size is only needed to optimize an allocation +for the relatively rare case of reading a symlink name, and the worst +effect is a somewhat-too-large temporary buffer may be allocated for +areadlink_with_size(), or internal retries if buffer is too small. + +The file size will be returned by statx() on most filesystems, even +if not requested, unless the filesystem considers this to be too +expensive for that file, in which case the tradeoff is worthwhile. + +* src/stat.c: Don't explicitly request STATX_SIZE for filenames. + +Upstream-commit: a1a5e9a32eb9525680edd02fd127240c27ba0999 +Signed-off-by: Kamil Dudka +--- + src/stat.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/stat.c b/src/stat.c +index 1d9d83a..32bb5f0 100644 +--- a/src/stat.c ++++ b/src/stat.c +@@ -1280,7 +1280,7 @@ fmt_to_mask (char fmt) + switch (fmt) + { + case 'N': +- return STATX_MODE|STATX_SIZE; ++ return STATX_MODE; + case 'd': + case 'D': + return STATX_MODE; +@@ -1352,7 +1352,7 @@ do_stat (char const *filename, char const *format, char const *format2) + int fd = STREQ (filename, "-") ? 0 : AT_FDCWD; + int flags = 0; + struct stat st; +- struct statx stx; ++ struct statx stx = { 0, }; + const char *pathname = filename; + struct print_args pa; + pa.st = &st; +-- +2.20.1 + + +From 5da6c36dacac4fd610ddad1bc0b2547a9cdfdf2f Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Thu, 19 Sep 2019 11:59:45 -0400 +Subject: [PATCH 5/5] ls: use statx instead of stat when available + +statx allows ls to indicate interest in only certain inode metadata. +This is potentially a win on networked/clustered/distributed +file systems. In cases where we'd have to do a full, heavyweight stat() +call we can now do a much lighter statx() call. + +As a real-world example, consider a file system like CephFS where one +client is actively writing to a file and another client does an +ls --color in the same directory. --color means that we need to fetch +the mode of the file. + +Doing that with a stat() call means that we have to fetch the size and +mtime in addition to the mode. The MDS in that situation will have to +revoke caps in order to ensure that it has up-to-date values to report, +which disrupts the writer. + +This has a measurable affect on performance. I ran a fio sequential +write test on one cephfs client and had a second client do "ls --color" +in a tight loop on the directory that held the file: + +Baseline -- no activity on the second client: + +WRITE: bw=76.7MiB/s (80.4MB/s), 76.7MiB/s-76.7MiB/s (80.4MB/s-80.4MB/s), + io=4600MiB (4824MB), run=60016-60016msec + +Without this patch series, we see a noticable performance hit: + +WRITE: bw=70.4MiB/s (73.9MB/s), 70.4MiB/s-70.4MiB/s (73.9MB/s-73.9MB/s), + io=4228MiB (4433MB), run=60012-60012msec + +With this patch series, we gain most of that ground back: + +WRITE: bw=75.9MiB/s (79.6MB/s), 75.9MiB/s-75.9MiB/s (79.6MB/s-79.6MB/s), + io=4555MiB (4776MB), run=60019-60019msec + +* src/stat.c: move statx to stat struct conversion to new header... +* src/statx.h: ...here. +* src/ls.c: Add wrapper functions for stat/lstat/fstat calls, +and add variants for when we are only interested in specific info. +Add statx-enabled functions and set the request mask based on the +output format and what values are needed. + +Upstream-commit: a99ab266110795ed94a9cb4d2765ddad9c4310da +Signed-off-by: Kamil Dudka +--- + src/local.mk | 1 + + src/ls.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++--- + src/stat.c | 32 +----------- + src/statx.h | 52 ++++++++++++++++++ + 4 files changed, 192 insertions(+), 38 deletions(-) + create mode 100644 src/statx.h + +diff --git a/src/local.mk b/src/local.mk +index 7a587bb..c013590 100644 +--- a/src/local.mk ++++ b/src/local.mk +@@ -58,6 +58,7 @@ noinst_HEADERS = \ + src/prog-fprintf.h \ + src/remove.h \ + src/set-fields.h \ ++ src/statx.h \ + src/system.h \ + src/uname.h + +diff --git a/src/ls.c b/src/ls.c +index bf0c594..7f68e3c 100644 +--- a/src/ls.c ++++ b/src/ls.c +@@ -114,6 +114,7 @@ + #include "xgethostname.h" + #include "c-ctype.h" + #include "canonicalize.h" ++#include "statx.h" + + /* Include last to avoid a clash of + include guards with some premature versions of libcap. +@@ -1063,6 +1064,136 @@ dired_dump_obstack (const char *prefix, struct obstack *os) + } + } + ++#if HAVE_STATX && defined STATX_INO ++static unsigned int _GL_ATTRIBUTE_PURE ++time_type_to_statx (void) ++{ ++ switch (time_type) ++ { ++ case time_ctime: ++ return STATX_CTIME; ++ case time_mtime: ++ return STATX_MTIME; ++ case time_atime: ++ return STATX_ATIME; ++ default: ++ abort (); ++ } ++ return 0; ++} ++ ++static unsigned int _GL_ATTRIBUTE_PURE ++calc_req_mask (void) ++{ ++ unsigned int mask = STATX_MODE; ++ ++ if (print_inode) ++ mask |= STATX_INO; ++ ++ if (print_block_size) ++ mask |= STATX_BLOCKS; ++ ++ if (format == long_format) { ++ mask |= STATX_NLINK | STATX_SIZE | time_type_to_statx (); ++ if (print_owner || print_author) ++ mask |= STATX_UID; ++ if (print_group) ++ mask |= STATX_GID; ++ } ++ ++ switch (sort_type) ++ { ++ case sort_none: ++ case sort_name: ++ case sort_version: ++ case sort_extension: ++ break; ++ case sort_time: ++ mask |= time_type_to_statx (); ++ break; ++ case sort_size: ++ mask |= STATX_SIZE; ++ break; ++ default: ++ abort (); ++ } ++ ++ return mask; ++} ++ ++static int ++do_statx (int fd, const char *name, struct stat *st, int flags, ++ unsigned int mask) ++{ ++ struct statx stx; ++ int ret = statx (fd, name, flags, mask, &stx); ++ if (ret >= 0) ++ statx_to_stat (&stx, st); ++ return ret; ++} ++ ++static inline int ++do_stat (const char *name, struct stat *st) ++{ ++ return do_statx (AT_FDCWD, name, st, 0, calc_req_mask ()); ++} ++ ++static inline int ++do_lstat (const char *name, struct stat *st) ++{ ++ return do_statx (AT_FDCWD, name, st, AT_SYMLINK_NOFOLLOW, calc_req_mask ()); ++} ++ ++static inline int ++stat_for_mode (const char *name, struct stat *st) ++{ ++ return do_statx (AT_FDCWD, name, st, 0, STATX_MODE); ++} ++ ++/* dev+ino should be static, so no need to sync with backing store */ ++static inline int ++stat_for_ino (const char *name, struct stat *st) ++{ ++ return do_statx (AT_FDCWD, name, st, 0, STATX_INO); ++} ++ ++static inline int ++fstat_for_ino (int fd, struct stat *st) ++{ ++ return do_statx (fd, "", st, AT_EMPTY_PATH, STATX_INO); ++} ++#else ++static inline int ++do_stat (const char *name, struct stat *st) ++{ ++ return stat (name, st); ++} ++ ++static inline int ++do_lstat (const char *name, struct stat *st) ++{ ++ return lstat (name, st); ++} ++ ++static inline int ++stat_for_mode (const char *name, struct stat *st) ++{ ++ return stat (name, st); ++} ++ ++static inline int ++stat_for_ino (const char *name, struct stat *st) ++{ ++ return stat (name, st); ++} ++ ++static inline int ++fstat_for_ino (int fd, struct stat *st) ++{ ++ return fstat (fd, st); ++} ++#endif ++ + /* Return the address of the first plain %b spec in FMT, or NULL if + there is no such spec. %5b etc. do not match, so that user + widths/flags are honored. */ +@@ -2733,10 +2864,10 @@ print_dir (char const *name, char const *realname, bool command_line_arg) + struct stat dir_stat; + int fd = dirfd (dirp); + +- /* If dirfd failed, endure the overhead of using stat. */ ++ /* If dirfd failed, endure the overhead of stat'ing by path */ + if ((0 <= fd +- ? fstat (fd, &dir_stat) +- : stat (name, &dir_stat)) < 0) ++ ? fstat_for_ino (fd, &dir_stat) ++ : stat_for_ino (name, &dir_stat)) < 0) + { + file_failure (command_line_arg, + _("cannot determine device and inode of %s"), name); +@@ -3198,7 +3329,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode, + switch (dereference) + { + case DEREF_ALWAYS: +- err = stat (full_name, &f->stat); ++ err = do_stat (full_name, &f->stat); + do_deref = true; + break; + +@@ -3207,7 +3338,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode, + if (command_line_arg) + { + bool need_lstat; +- err = stat (full_name, &f->stat); ++ err = do_stat (full_name, &f->stat); + do_deref = true; + + if (dereference == DEREF_COMMAND_LINE_ARGUMENTS) +@@ -3227,7 +3358,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode, + FALLTHROUGH; + + default: /* DEREF_NEVER */ +- err = lstat (full_name, &f->stat); ++ err = do_lstat (full_name, &f->stat); + do_deref = false; + break; + } +@@ -3316,7 +3447,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode, + they won't be traced and when no indicator is needed. */ + if (linkname + && (file_type <= indicator_style || check_symlink_color) +- && stat (linkname, &linkstats) == 0) ++ && stat_for_mode (linkname, &linkstats) == 0) + { + f->linkok = true; + +diff --git a/src/stat.c b/src/stat.c +index 32bb5f0..03fecc3 100644 +--- a/src/stat.c ++++ b/src/stat.c +@@ -73,6 +73,7 @@ + #include "strftime.h" + #include "find-mount-point.h" + #include "xvasprintf.h" ++#include "statx.h" + + #if HAVE_STATX && defined STATX_INO + # define USE_STATX 1 +@@ -1243,37 +1244,6 @@ static bool dont_sync; + static bool force_sync; + + #if USE_STATX +-/* Much of the format printing requires a struct stat or timespec */ +-static struct timespec +-statx_timestamp_to_timespec (struct statx_timestamp tsx) +-{ +- struct timespec ts; +- +- ts.tv_sec = tsx.tv_sec; +- ts.tv_nsec = tsx.tv_nsec; +- return ts; +-} +- +-static void +-statx_to_stat (struct statx *stx, struct stat *stat) +-{ +- stat->st_dev = makedev (stx->stx_dev_major, stx->stx_dev_minor); +- stat->st_ino = stx->stx_ino; +- stat->st_mode = stx->stx_mode; +- stat->st_nlink = stx->stx_nlink; +- stat->st_uid = stx->stx_uid; +- stat->st_gid = stx->stx_gid; +- stat->st_rdev = makedev (stx->stx_rdev_major, stx->stx_rdev_minor); +- stat->st_size = stx->stx_size; +- stat->st_blksize = stx->stx_blksize; +-/* define to avoid sc_prohibit_stat_st_blocks. */ +-# define SC_ST_BLOCKS st_blocks +- stat->SC_ST_BLOCKS = stx->stx_blocks; +- stat->st_atim = statx_timestamp_to_timespec (stx->stx_atime); +- stat->st_mtim = statx_timestamp_to_timespec (stx->stx_mtime); +- stat->st_ctim = statx_timestamp_to_timespec (stx->stx_ctime); +-} +- + static unsigned int + fmt_to_mask (char fmt) + { +diff --git a/src/statx.h b/src/statx.h +new file mode 100644 +index 0000000..19f3e18 +--- /dev/null ++++ b/src/statx.h +@@ -0,0 +1,52 @@ ++/* statx -> stat conversion functions for coreutils ++ Copyright (C) 2019 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 . */ ++ ++#ifndef COREUTILS_STATX_H ++# define COREUTILS_STATX_H ++ ++# if HAVE_STATX && defined STATX_INO ++/* Much of the format printing requires a struct stat or timespec */ ++static inline struct timespec ++statx_timestamp_to_timespec (struct statx_timestamp tsx) ++{ ++ struct timespec ts; ++ ++ ts.tv_sec = tsx.tv_sec; ++ ts.tv_nsec = tsx.tv_nsec; ++ return ts; ++} ++ ++static inline void ++statx_to_stat (struct statx *stx, struct stat *stat) ++{ ++ stat->st_dev = makedev (stx->stx_dev_major, stx->stx_dev_minor); ++ stat->st_ino = stx->stx_ino; ++ stat->st_mode = stx->stx_mode; ++ stat->st_nlink = stx->stx_nlink; ++ stat->st_uid = stx->stx_uid; ++ stat->st_gid = stx->stx_gid; ++ stat->st_rdev = makedev (stx->stx_rdev_major, stx->stx_rdev_minor); ++ stat->st_size = stx->stx_size; ++ stat->st_blksize = stx->stx_blksize; ++/* define to avoid sc_prohibit_stat_st_blocks. */ ++# define SC_ST_BLOCKS st_blocks ++ stat->SC_ST_BLOCKS = stx->stx_blocks; ++ stat->st_atim = statx_timestamp_to_timespec (stx->stx_atime); ++ stat->st_mtim = statx_timestamp_to_timespec (stx->stx_mtime); ++ stat->st_ctim = statx_timestamp_to_timespec (stx->stx_ctime); ++} ++# endif /* HAVE_STATX && defined STATX_INO */ ++#endif /* COREUTILS_STATX_H */ +-- +2.20.1 + diff --git a/SOURCES/coreutils-8.30-tail-use-poll.patch b/SOURCES/coreutils-8.30-tail-use-poll.patch new file mode 100644 index 0000000..804d567 --- /dev/null +++ b/SOURCES/coreutils-8.30-tail-use-poll.patch @@ -0,0 +1,469 @@ +From 95f427178720d047316e95f44777cfdf2ecf2b46 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?P=C3=A1draig=20Brady?= +Date: Fri, 4 Jan 2019 09:29:13 -0800 +Subject: [PATCH 1/4] tail: don't exit immediately with filters on AIX + +* src/tail.c: Fix the check_output_available check on AIX. +Note we don't use poll for all systems as the overhead +of adding the gnulib poll module wouldn't be worth it +just for this single use. +* tests/tail-2/pipe-f.sh: Fix the test which always passed +due to only the exit code of sleep being checked. +* NEWS: Mention the bug fix and rearrange alphabetically. +Fixes http://bugs.gnu.org/33946 + +Upstream-commit: d5ab4cbe424e3e95140eec22ef828f50b2fb3067 +Signed-off-by: Kamil Dudka +--- + src/tail.c | 13 +++++++++++++ + tests/tail-2/pipe-f.sh | 5 ++++- + 2 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/src/tail.c b/src/tail.c +index ac001d7..d63aacc 100644 +--- a/src/tail.c ++++ b/src/tail.c +@@ -30,6 +30,9 @@ + #include + #include + #include ++#ifdef _AIX ++# include ++#endif + + #include "system.h" + #include "argmatch.h" +@@ -335,6 +338,16 @@ named file in a way that accommodates renaming, removal and creation.\n\ + static void + check_output_alive (void) + { ++#ifdef _AIX ++ /* select on AIX was seen to give a readable event immediately. */ ++ struct pollfd pfd; ++ pfd.fd = STDOUT_FILENO; ++ pfd.events = POLLERR; ++ ++ if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR)) ++ raise (SIGPIPE); ++#endif ++ + if (! monitor_output) + return; + +diff --git a/tests/tail-2/pipe-f.sh b/tests/tail-2/pipe-f.sh +index 76b0d90..1126c93 100755 +--- a/tests/tail-2/pipe-f.sh ++++ b/tests/tail-2/pipe-f.sh +@@ -37,7 +37,10 @@ compare exp out || fail=1 + + # This would wait indefinitely before v8.28 due to no EPIPE being + # generated due to no data written after the first small amount +-timeout 10 tail -f $mode $fastpoll out | sleep .1 || fail=1 ++(returns_ 124 timeout 10 tail -n2 -f $mode $fastpoll out && touch timed_out) | ++ sed 2q > out2 ++test -e timed_out && fail=1 ++compare exp out2 || fail=1 + + # This would wait indefinitely before v8.28 (until first write) + (returns_ 1 timeout 10 tail -f $mode $fastpoll /dev/null >&-) || fail=1 +-- +2.31.1 + + +From 125bb79d3e9f414533b1c29237ee3f647053d0d6 Mon Sep 17 00:00:00 2001 +From: Ayappan +Date: Sun, 20 Jan 2019 00:17:33 -0800 +Subject: [PATCH 2/4] tail: fix recent ineffective AIX change + +* src/tail.c: Fix commit v8.30-40-gd5ab4cb which was ineffective. +Fixes http://bugs.gnu.org/33946 + +Upstream-commit: 17983b2cb3bccbb4fa69691178caddd99269bda9 +Signed-off-by: Kamil Dudka +--- + src/tail.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/tail.c b/src/tail.c +index d63aacc..9ed6d48 100644 +--- a/src/tail.c ++++ b/src/tail.c +@@ -338,6 +338,9 @@ named file in a way that accommodates renaming, removal and creation.\n\ + static void + check_output_alive (void) + { ++ if (! monitor_output) ++ return; ++ + #ifdef _AIX + /* select on AIX was seen to give a readable event immediately. */ + struct pollfd pfd; +@@ -346,11 +349,7 @@ check_output_alive (void) + + if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR)) + raise (SIGPIPE); +-#endif +- +- if (! monitor_output) +- return; +- ++#else + struct timeval delay; + delay.tv_sec = delay.tv_usec = 0; + +@@ -362,6 +361,7 @@ check_output_alive (void) + and implies an error condition on output like broken pipe. */ + if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1) + raise (SIGPIPE); ++#endif + } + + static bool +-- +2.31.1 + + +From 7741989c3e633aa44f01d8f91332cb65a9280ba3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?P=C3=A1draig=20Brady?= +Date: Sun, 20 Jan 2019 00:13:15 -0800 +Subject: [PATCH 3/4] tail: fix handling of broken pipes with SIGPIPE ignored + +* init.cfg (trap_sigpipe_or_skip_): A new function refactored from... +* tests/misc/printf-surprise.sh: ...here. +* tests/misc/seq-epipe.sh. Likewise. +* src/tail.c (die_pipe): Ensure we exit upon sending SIGPIPE. +* tests/tail-2/pipe-f.sh: Ensure we exit even if SIGPIPE is ignored. +* NEWS: Mention the bug fix. + +Upstream-commit: fa50623394f491b975dbd7ad73193519dd721771 +Signed-off-by: Kamil Dudka +--- + init.cfg | 6 ++++++ + src/tail.c | 14 +++++++++++--- + tests/misc/printf-surprise.sh | 4 +--- + tests/misc/seq-epipe.sh | 4 +--- + tests/tail-2/pipe-f.sh | 19 ++++++++++++++----- + 5 files changed, 33 insertions(+), 14 deletions(-) + +diff --git a/init.cfg b/init.cfg +index b6c81ab..985c8d3 100644 +--- a/init.cfg ++++ b/init.cfg +@@ -613,6 +613,12 @@ mkfifo_or_skip_() + fi + } + ++trap_sigpipe_or_skip_() ++{ ++ (trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' || ++ skip_ 'trapping SIGPIPE is not supported' ++} ++ + # Disable the current test if the working directory seems to have + # the setgid bit set. + skip_if_setgid_() +diff --git a/src/tail.c b/src/tail.c +index 9ed6d48..16e0d73 100644 +--- a/src/tail.c ++++ b/src/tail.c +@@ -333,6 +333,14 @@ named file in a way that accommodates renaming, removal and creation.\n\ + exit (status); + } + ++/* Ensure exit, either with SIGPIPE or EXIT_FAILURE status. */ ++static void ATTRIBUTE_NORETURN ++die_pipe (void) ++{ ++ raise (SIGPIPE); ++ exit (EXIT_FAILURE); ++} ++ + /* If the output has gone away, then terminate + as we would if we had written to this output. */ + static void +@@ -348,7 +356,7 @@ check_output_alive (void) + pfd.events = POLLERR; + + if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR)) +- raise (SIGPIPE); ++ die_pipe (); + #else + struct timeval delay; + delay.tv_sec = delay.tv_usec = 0; +@@ -360,7 +368,7 @@ check_output_alive (void) + /* readable event on STDOUT is equivalent to POLLERR, + and implies an error condition on output like broken pipe. */ + if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1) +- raise (SIGPIPE); ++ die_pipe (); + #endif + } + +@@ -1658,7 +1666,7 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files, + { + /* readable event on STDOUT is equivalent to POLLERR, + and implies an error on output like broken pipe. */ +- raise (SIGPIPE); ++ die_pipe (); + } + else + break; +diff --git a/tests/misc/printf-surprise.sh b/tests/misc/printf-surprise.sh +index fd88133..acac0b1 100755 +--- a/tests/misc/printf-surprise.sh ++++ b/tests/misc/printf-surprise.sh +@@ -49,9 +49,7 @@ vm=$(get_min_ulimit_v_ env $prog %20f 0) \ + # triggering the printf(3) misbehavior -- which, btw, is required by ISO C99. + + mkfifo_or_skip_ fifo +- +-(trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' || +- skip_ 'trapping SIGPIPE is not supported' ++trap_sigpipe_or_skip_ + + # Disable MALLOC_PERTURB_, to avoid triggering this bug + # https://bugs.debian.org/481543#77 +diff --git a/tests/misc/seq-epipe.sh b/tests/misc/seq-epipe.sh +index 3e89158..127d61c 100755 +--- a/tests/misc/seq-epipe.sh ++++ b/tests/misc/seq-epipe.sh +@@ -18,9 +18,7 @@ + + . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src + print_ver_ seq +- +-(trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' || +- skip_ 'trapping SIGPIPE is not supported' ++trap_sigpipe_or_skip_ + + # upon EPIPE with signals ignored, 'seq' should exit with an error. + timeout 10 sh -c \ +diff --git a/tests/tail-2/pipe-f.sh b/tests/tail-2/pipe-f.sh +index 1126c93..f734a61 100755 +--- a/tests/tail-2/pipe-f.sh ++++ b/tests/tail-2/pipe-f.sh +@@ -18,6 +18,7 @@ + + . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src + print_ver_ tail ++trap_sigpipe_or_skip_ + + # Speedup the non inotify case + fastpoll='-s.1 --max-unchanged-stats=1' +@@ -36,11 +37,19 @@ echo bar | returns_ 1 \ + compare exp out || fail=1 + + # This would wait indefinitely before v8.28 due to no EPIPE being +-# generated due to no data written after the first small amount +-(returns_ 124 timeout 10 tail -n2 -f $mode $fastpoll out && touch timed_out) | +- sed 2q > out2 +-test -e timed_out && fail=1 +-compare exp out2 || fail=1 ++# generated due to no data written after the first small amount. ++# Also check tail exits if SIGPIPE is being ignored. ++# Note 'trap - SIGPIPE' is ineffective if the initiating shell ++# has ignored SIGPIPE, but that's not the normal case. ++for disposition in '' '-'; do ++ (trap "$disposition" PIPE; ++ returns_ 124 timeout 10 \ ++ tail -n2 -f $mode $fastpoll out && touch timed_out) | ++ sed 2q > out2 ++ test -e timed_out && fail=1 ++ compare exp out2 || fail=1 ++ rm -f timed_out ++done + + # This would wait indefinitely before v8.28 (until first write) + (returns_ 1 timeout 10 tail -f $mode $fastpoll /dev/null >&-) || fail=1 +-- +2.31.1 + + +From 0f5760466d167e955d28a1250ffd0af347d48dc9 Mon Sep 17 00:00:00 2001 +From: Paul Eggert +Date: Sat, 26 Jun 2021 18:23:52 -0700 +Subject: [PATCH 4/4] tail: use poll, not select +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This fixes an unlikely stack out-of-bounds write reported by +Stepan Broz via Kamil Dudka (Bug#49209). +* src/tail.c: Do not include . +[!_AIX]: Include poll.h. +(check_output_alive) [!_AIX]: Use poll instead of select. +(tail_forever_inotify): Likewise. Simplify logic, as there is no +need for a ‘while (len <= evbuf_off)’ loop. + +Upstream-commit: da0d448bca62c6305fc432f67e2c5ccc2da75346 +Signed-off-by: Kamil Dudka +--- + src/tail.c | 101 +++++++++++++++++++++-------------------------------- + 1 file changed, 39 insertions(+), 62 deletions(-) + +diff --git a/src/tail.c b/src/tail.c +index 16e0d73..d77c660 100644 +--- a/src/tail.c ++++ b/src/tail.c +@@ -29,10 +29,8 @@ + #include + #include + #include ++#include + #include +-#ifdef _AIX +-# include +-#endif + + #include "system.h" + #include "argmatch.h" +@@ -55,8 +53,6 @@ + #if HAVE_INOTIFY + # include "hash.h" + # include +-/* 'select' is used by tail_forever_inotify. */ +-# include + + /* inotify needs to know if a file is local. */ + # include "fs.h" +@@ -349,27 +345,12 @@ check_output_alive (void) + if (! monitor_output) + return; + +-#ifdef _AIX +- /* select on AIX was seen to give a readable event immediately. */ + struct pollfd pfd; + pfd.fd = STDOUT_FILENO; + pfd.events = POLLERR; + + if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR)) + die_pipe (); +-#else +- struct timeval delay; +- delay.tv_sec = delay.tv_usec = 0; +- +- fd_set rfd; +- FD_ZERO (&rfd); +- FD_SET (STDOUT_FILENO, &rfd); +- +- /* readable event on STDOUT is equivalent to POLLERR, +- and implies an error condition on output like broken pipe. */ +- if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1) +- die_pipe (); +-#endif + } + + static bool +@@ -1609,7 +1590,7 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files, + /* Wait for inotify events and handle them. Events on directories + ensure that watched files can be re-added when following by name. + This loop blocks on the 'safe_read' call until a new event is notified. +- But when --pid=P is specified, tail usually waits via the select. */ ++ But when --pid=P is specified, tail usually waits via poll. */ + while (1) + { + struct File_spec *fspec; +@@ -1626,54 +1607,51 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files, + return false; + } + +- /* When watching a PID, ensure that a read from WD will not block +- indefinitely. */ +- while (len <= evbuf_off) ++ if (len <= evbuf_off) + { +- struct timeval delay; /* how long to wait for file changes. */ ++ /* Poll for inotify events. When watching a PID, ensure ++ that a read from WD will not block indefinitely. ++ If MONITOR_OUTPUT, also poll for a broken output pipe. */ + +- if (pid) ++ int file_change; ++ struct pollfd pfd[2]; ++ do + { +- if (writer_is_dead) +- exit (EXIT_SUCCESS); ++ /* How many ms to wait for changes. -1 means wait forever. */ ++ int delay = -1; + +- writer_is_dead = (kill (pid, 0) != 0 && errno != EPERM); +- +- if (writer_is_dead) +- delay.tv_sec = delay.tv_usec = 0; +- else ++ if (pid) + { +- delay.tv_sec = (time_t) sleep_interval; +- delay.tv_usec = 1000000 * (sleep_interval - delay.tv_sec); ++ if (writer_is_dead) ++ exit (EXIT_SUCCESS); ++ ++ writer_is_dead = (kill (pid, 0) != 0 && errno != EPERM); ++ ++ if (writer_is_dead || sleep_interval <= 0) ++ delay = 0; ++ else if (sleep_interval < INT_MAX / 1000 - 1) ++ { ++ /* delay = ceil (sleep_interval * 1000), sans libm. */ ++ double ddelay = sleep_interval * 1000; ++ delay = ddelay; ++ delay += delay < ddelay; ++ } + } ++ ++ pfd[0].fd = wd; ++ pfd[0].events = POLLIN; ++ pfd[1].fd = STDOUT_FILENO; ++ pfd[1].events = pfd[1].revents = 0; ++ file_change = poll (pfd, monitor_output + 1, delay); + } ++ while (file_change == 0); + +- fd_set rfd; +- FD_ZERO (&rfd); +- FD_SET (wd, &rfd); +- if (monitor_output) +- FD_SET (STDOUT_FILENO, &rfd); +- +- int file_change = select (MAX (wd, STDOUT_FILENO) + 1, +- &rfd, NULL, NULL, pid ? &delay: NULL); +- +- if (file_change == 0) +- continue; +- else if (file_change == -1) +- die (EXIT_FAILURE, errno, +- _("error waiting for inotify and output events")); +- else if (FD_ISSET (STDOUT_FILENO, &rfd)) +- { +- /* readable event on STDOUT is equivalent to POLLERR, +- and implies an error on output like broken pipe. */ +- die_pipe (); +- } +- else +- break; +- } ++ if (file_change < 0) ++ die (EXIT_FAILURE, errno, ++ _("error waiting for inotify and output events")); ++ if (pfd[1].revents) ++ die_pipe (); + +- if (len <= evbuf_off) +- { + len = safe_read (wd, evbuf, evlen); + evbuf_off = 0; + +@@ -2434,8 +2412,7 @@ main (int argc, char **argv) + if (forever && ignore_fifo_and_pipe (F, n_files)) + { + /* If stdout is a fifo or pipe, then monitor it +- so that we exit if the reader goes away. +- Note select() on a regular file is always readable. */ ++ so that we exit if the reader goes away. */ + struct stat out_stat; + if (fstat (STDOUT_FILENO, &out_stat) < 0) + die (EXIT_FAILURE, errno, _("standard output")); +-- +2.31.1 + diff --git a/SOURCES/coreutils-8.32-df-duplicated-entries.patch b/SOURCES/coreutils-8.32-df-duplicated-entries.patch new file mode 100644 index 0000000..5d39c1e --- /dev/null +++ b/SOURCES/coreutils-8.32-df-duplicated-entries.patch @@ -0,0 +1,72 @@ +From 0f053de4bc3ca0cfd88a42d236881dfdddb10ee9 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Wed, 30 Jun 2021 17:53:22 +0200 +Subject: [PATCH] df: fix duplicated remote entries due to bind mounts + +As originally reported in , +df invoked without -a printed duplicated entries for NFS mounts +of bind mounts. This is a regression from commit v8.25-54-g1c17f61ef99, +which introduced the use of a hash table. + +The proposed patch makes sure that the devlist entry seen the last time +is used for comparison when eliminating duplicated mount entries. This +way it worked before introducing the hash table. + +Patch co-authored by Roberto Bergantinos. + +* src/ls.c (struct devlist): Introduce the seen_last pointer. +(devlist_for_dev): Return the devlist entry seen the last time if found. +(filter_mount_list): Remember the devlist entry seen the last time for +each hashed item. +Fixes https://bugs.gnu.org/49298 + +Upstream-commit: d6125af095c9553f38cba0696f15158f5abe4ecc +Signed-off-by: Kamil Dudka +--- + src/df.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/src/df.c b/src/df.c +index 7e01839..3e9247f 100644 +--- a/src/df.c ++++ b/src/df.c +@@ -54,6 +54,7 @@ struct devlist + dev_t dev_num; + struct mount_entry *me; + struct devlist *next; ++ struct devlist *seen_last; /* valid for hashed devlist entries only */ + }; + + /* Filled with device numbers of examined file systems to avoid +@@ -689,7 +690,13 @@ devlist_for_dev (dev_t dev) + return NULL; + struct devlist dev_entry; + dev_entry.dev_num = dev; +- return hash_lookup (devlist_table, &dev_entry); ++ ++ struct devlist *found = hash_lookup (devlist_table, &dev_entry); ++ if (found == NULL) ++ return NULL; ++ ++ /* Return the last devlist entry we have seen with this dev_num */ ++ return found->seen_last; + } + + static void +@@ -807,8 +814,12 @@ filter_mount_list (bool devices_only) + devlist->dev_num = buf.st_dev; + devlist->next = device_list; + device_list = devlist; +- if (hash_insert (devlist_table, devlist) == NULL) ++ ++ struct devlist *hash_entry = hash_insert (devlist_table, devlist); ++ if (hash_entry == NULL) + xalloc_die (); ++ /* Ensure lookups use this latest devlist. */ ++ hash_entry->seen_last = devlist; + + me = me->me_next; + } +-- +2.31.1 + diff --git a/SOURCES/coreutils-8.32-fuse-portal.patch b/SOURCES/coreutils-8.32-fuse-portal.patch new file mode 100644 index 0000000..99e15e2 --- /dev/null +++ b/SOURCES/coreutils-8.32-fuse-portal.patch @@ -0,0 +1,38 @@ +From 602fb566468d3837b7871c17a0fab1a20228d119 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 7 Jun 2021 14:43:03 +0200 +Subject: [PATCH] mountlist: recognize fuse.portal as dummy file system + +This was originally proposed at: + + https://lists.gnu.org/archive/html/bug-gnulib/2021-02/msg00053.html + +As the full review might take some time, would it be possible to apply +at least the part related to fuse.portal file systems? They started to +cause problems recently: + + https://bugs.launchpad.net/ubuntu/+source/xdg-desktop-portal/+bug/1905623 + https://github.com/muesli/duf/issues/35 + https://bugzilla.redhat.com/1913358 + +Upstream-commit: 9a38d499ca16f2f4304992eb1ab0894cd0b478e1 +Signed-off-by: Kamil Dudka +--- + lib/mountlist.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/mountlist.c b/lib/mountlist.c +index e0227b7..e5f6b07 100644 +--- a/lib/mountlist.c ++++ b/lib/mountlist.c +@@ -173,6 +173,7 @@ + || strcmp (Fs_type, "debugfs") == 0 \ + || strcmp (Fs_type, "devpts") == 0 \ + || strcmp (Fs_type, "fusectl") == 0 \ ++ || strcmp (Fs_type, "fuse.portal") == 0 \ + || strcmp (Fs_type, "mqueue") == 0 \ + || strcmp (Fs_type, "rpc_pipefs") == 0 \ + || strcmp (Fs_type, "sysfs") == 0 \ +-- +2.31.1 + diff --git a/SOURCES/coreutils-8.32-rm-stray-skip.patch b/SOURCES/coreutils-8.32-rm-stray-skip.patch new file mode 100644 index 0000000..66a1efc --- /dev/null +++ b/SOURCES/coreutils-8.32-rm-stray-skip.patch @@ -0,0 +1,109 @@ +From 11b37b65d08c2a8b6d967fd866ebbdbe7e864949 Mon Sep 17 00:00:00 2001 +From: Nishant Nayan +Date: Thu, 26 Nov 2020 14:35:17 +0000 +Subject: [PATCH] rm: do not skip files upon failure to remove an empty dir + +When removing a directory fails for some reason, and that directory +is empty, the rm_fts code gets the return value of the excise call +confused with the return value of its earlier call to prompt, +causing fts_skip_tree to be called again and the next file +that rm would otherwise have deleted to survive. + +* src/remove.c (rm_fts): Ensure we only skip a single fts entry, +when processing empty dirs. I.e. only skip the entry +having successfully removed it. +* tests/rm/empty-immutable-skip.sh: New root-only test. +* tests/local.mk: Add it. +* NEWS: Mention the bug fix. +Fixes https://bugs.gnu.org/44883 + +Upstream-commit: 6bf108358a6104ec1c694c9530b3cd56b95f4b57 +Signed-off-by: Kamil Dudka +--- + src/remove.c | 3 ++- + tests/local.mk | 1 + + tests/rm/empty-immutable-skip.sh | 46 ++++++++++++++++++++++++++++++++ + 3 files changed, 49 insertions(+), 1 deletion(-) + create mode 100755 tests/rm/empty-immutable-skip.sh + +diff --git a/src/remove.c b/src/remove.c +index 2d40c55..adf9489 100644 +--- a/src/remove.c ++++ b/src/remove.c +@@ -506,7 +506,8 @@ rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x) + /* When we know (from prompt when in interactive mode) + that this is an empty directory, don't prompt twice. */ + s = excise (fts, ent, x, true); +- fts_skip_tree (fts, ent); ++ if (s == RM_OK) ++ fts_skip_tree (fts, ent); + } + + if (s != RM_OK) +diff --git a/tests/local.mk b/tests/local.mk +index 5f7f775..2aeff2b 100644 +--- a/tests/local.mk ++++ b/tests/local.mk +@@ -136,6 +136,7 @@ all_root_tests = \ + tests/rm/no-give-up.sh \ + tests/rm/one-file-system.sh \ + tests/rm/read-only.sh \ ++ tests/rm/empty-immutable-skip.sh \ + tests/tail-2/append-only.sh \ + tests/tail-2/end-of-device.sh \ + tests/touch/now-owned-by-other.sh +diff --git a/tests/rm/empty-immutable-skip.sh b/tests/rm/empty-immutable-skip.sh +new file mode 100755 +index 0000000..c91d8d4 +--- /dev/null ++++ b/tests/rm/empty-immutable-skip.sh +@@ -0,0 +1,46 @@ ++#!/bin/sh ++# Ensure that rm does not skip extra files after hitting an empty immutable dir. ++# Requires root access to do chattr +i, as well as an ext[23] or xfs file system ++ ++# Copyright (C) 2020 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 . ++ ++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src ++print_ver_ rm ++require_root_ ++ ++# These simple one-file operations are expected to work even in the ++# presence of this bug, and we need them to set up the rest of the test. ++chattr_i_works=1 ++touch f ++chattr +i f 2>/dev/null || chattr_i_works=0 ++rm f 2>/dev/null ++test -f f || chattr_i_works=0 ++chattr -i f 2>/dev/null || chattr_i_works=0 ++rm f 2>/dev/null || chattr_i_works=0 ++test -f f && chattr_i_works=0 ++ ++if test $chattr_i_works = 0; then ++ skip_ "chattr +i doesn't work on this file system" ++fi ++ ++mkdir empty || framework_failure_ ++touch x y || framework_failure_ ++chattr +i empty || framework_failure_ ++rm -rf empty x y ++{ test -f x || test -f y; } && fail=1 ++chattr -i empty ++ ++Exit $fail +-- +2.26.2 + diff --git a/SOURCES/coreutils-8.32-split-number.patch b/SOURCES/coreutils-8.32-split-number.patch new file mode 100644 index 0000000..89541bf --- /dev/null +++ b/SOURCES/coreutils-8.32-split-number.patch @@ -0,0 +1,100 @@ +From bb0e7fabcaed9a7e71e30f05e638e9f243cdb13e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?P=C3=A1draig=20Brady?= +Date: Mon, 25 Jan 2021 14:12:48 +0000 +Subject: [PATCH] split: fix --number=K/N to output correct part of file + +This functionality regressed with the adjustments +in commit v8.25-4-g62e7af032 + +* src/split.c (bytes_chunk_extract): Account for already read data +when seeking into the file. +* tests/split/b-chunk.sh: Use the hidden ---io-blksize option, +to test this functionality. +Fixes https://bugs.gnu.org/46048 + +Upstream-commit: bb21daa125aeb4e32546309d370918ca47e612db +Signed-off-by: Kamil Dudka +--- + src/split.c | 2 +- + tests/split/b-chunk.sh | 45 ++++++++++++++++++++++++------------------ + 2 files changed, 27 insertions(+), 20 deletions(-) + +diff --git a/src/split.c b/src/split.c +index 09e610b..19248f6 100644 +--- a/src/split.c ++++ b/src/split.c +@@ -1001,7 +1001,7 @@ bytes_chunk_extract (uintmax_t k, uintmax_t n, char *buf, size_t bufsize, + } + else + { +- if (lseek (STDIN_FILENO, start, SEEK_CUR) < 0) ++ if (lseek (STDIN_FILENO, start - initial_read, SEEK_CUR) < 0) + die (EXIT_FAILURE, errno, "%s", quotef (infile)); + initial_read = SIZE_MAX; + } +diff --git a/tests/split/b-chunk.sh b/tests/split/b-chunk.sh +index 864ce55..39a6799 100755 +--- a/tests/split/b-chunk.sh ++++ b/tests/split/b-chunk.sh +@@ -35,32 +35,39 @@ split -e -n 10 /dev/null || fail=1 + returns_ 1 stat x?? 2>/dev/null || fail=1 + + printf '1\n2\n3\n4\n5\n' > input || framework_failure_ ++printf '1\n2' > exp-1 || framework_failure_ ++printf '\n3\n' > exp-2 || framework_failure_ ++printf '4\n5\n' > exp-3 || framework_failure_ + + for file in input /proc/version /sys/kernel/profiling; do + test -f $file || continue + +- split -n 3 $file > out || fail=1 +- split -n 1/3 $file > b1 || fail=1 +- split -n 2/3 $file > b2 || fail=1 +- split -n 3/3 $file > b3 || fail=1 ++ for blksize in 1 2 4096; do ++ if ! test "$file" = 'input'; then ++ # For /proc like files we must be able to read all ++ # into the internal buffer to be able to determine size. ++ test "$blksize" = 4096 || continue ++ fi + +- case $file in +- input) +- printf '1\n2' > exp-1 +- printf '\n3\n' > exp-2 +- printf '4\n5\n' > exp-3 ++ split -n 3 ---io-blksize=$blksize $file > out || fail=1 ++ split -n 1/3 ---io-blksize=$blksize $file > b1 || fail=1 ++ split -n 2/3 ---io-blksize=$blksize $file > b2 || fail=1 ++ split -n 3/3 ---io-blksize=$blksize $file > b3 || fail=1 + +- compare exp-1 xaa || fail=1 +- compare exp-2 xab || fail=1 +- compare exp-3 xac || fail=1 +- ;; +- esac ++ case $file in ++ input) ++ compare exp-1 xaa || fail=1 ++ compare exp-2 xab || fail=1 ++ compare exp-3 xac || fail=1 ++ ;; ++ esac + +- compare xaa b1 || fail=1 +- compare xab b2 || fail=1 +- compare xac b3 || fail=1 +- cat xaa xab xac | compare - $file || fail=1 +- test -f xad && fail=1 ++ compare xaa b1 || fail=1 ++ compare xab b2 || fail=1 ++ compare xac b3 || fail=1 ++ cat xaa xab xac | compare - $file || fail=1 ++ test -f xad && fail=1 ++ done + done + + Exit $fail +-- +2.26.2 + diff --git a/SPECS/coreutils.spec b/SPECS/coreutils.spec index 7402268..493fc1f 100644 --- a/SPECS/coreutils.spec +++ b/SPECS/coreutils.spec @@ -1,7 +1,7 @@ Summary: A set of basic GNU tools commonly used in shell scripts Name: coreutils Version: 8.30 -Release: 8%{?dist} +Release: 12%{?dist} License: GPLv3+ Group: System Environment/Base Url: https://www.gnu.org/software/coreutils/ @@ -35,6 +35,24 @@ Patch6: coreutils-8.31-sums-man-pages.patch # df --local: recognize afs, auristorfs, and smb3 as remote fs (#1798030) Patch7: coreutils-8.30-df-local-fs.patch +# use statx instead of stat when available (#1760300) +Patch8: coreutils-8.30-statx.patch + +# rm: do not skip files upon failure to remove an empty dir (#1905481) +Patch9: coreutils-8.32-rm-stray-skip.patch + +# split: fix --number=K/N to output correct part of file (#1921246) +Patch10: coreutils-8.32-split-number.patch + +# mountlist: recognize fuse.portal as dummy file system (#1952714) +Patch11: coreutils-8.32-fuse-portal.patch + +# tail: fix stack out-of-bounds write with --follow (#1974784) +Patch12: coreutils-8.30-tail-use-poll.patch + +# df: fix duplicated remote entries due to bind mounts (#1962515) +Patch17: coreutils-8.32-df-duplicated-entries.patch + # disable the test-lock gnulib test prone to deadlock Patch100: coreutils-8.26-test-lock.patch @@ -268,6 +286,20 @@ fi %license COPYING %changelog +* Wed Jul 07 2021 Kamil Dudka - 8.30-12 +- df: fix duplicated remote entries due to bind mounts (#1962515) + +* Thu Jul 01 2021 Kamil Dudka - 8.30-11 +- tail: fix stack out-of-bounds write with --follow (#1974784) + +* Tue Jun 08 2021 Kamil Dudka - 8.30-10 +- mountlist: recognize fuse.portal as dummy file system (#1952714) + +* Fri Mar 26 2021 Kamil Dudka - 8.30-9 +- split: fix --number=K/N to output correct part of file (#1921246) +- rm: do not skip files upon failure to remove an empty dir (#1905481) +- use statx instead of stat when available (#1760300) + * Tue Apr 14 2020 Kamil Dudka - 8.30-8 - df --local: recognize afs, auristorfs, and smb3 as remote fs (#1798030) - fix formatting of sha512sum(1) man page (#1688744)