diff --git a/.gitignore b/.gitignore index 46d0f92..b8a1c39 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ -/coreutils-[0-9.]*.tar.xz -/coreutils-[0-9.]*.tar.xz.sig +/coreutils-8.10.tar.xz +/coreutils-8.11.tar.xz +/coreutils-8.12.tar.xz +/coreutils-8.13.tar.xz +/coreutils-8.14.tar.xz +/coreutils-8.15.tar.xz diff --git a/STAGE1-coreutils b/STAGE1-coreutils deleted file mode 100644 index bfe73b5..0000000 --- a/STAGE1-coreutils +++ /dev/null @@ -1,7 +0,0 @@ -srpm coreutils -mcd $BUILDDIR/$1 -(cd $SRC/${1}-*/ ; autoreconf -vif) -$SRC/${1}-*/configure $TCONFIGARGS --disable-pam -notparallel -make $J man1_MANS= V=1 -make $J man1_MANS= install DESTDIR=${ROOTFS} diff --git a/coreutils-4.5.3-langinfo.patch b/coreutils-4.5.3-langinfo.patch new file mode 100644 index 0000000..25dec6c --- /dev/null +++ b/coreutils-4.5.3-langinfo.patch @@ -0,0 +1,18 @@ +--- coreutils-5.92/src/date.c.langinfo 2005-09-16 09:06:57.000000000 +0100 ++++ coreutils-5.92/src/date.c 2005-10-24 18:09:16.000000000 +0100 +@@ -451,14 +451,7 @@ + format = DATE_FMT_LANGINFO (); + if (! *format) + { +- /* Do not wrap the following literal format string with _(...). +- For example, suppose LC_ALL is unset, LC_TIME=POSIX, +- and LANG="ko_KR". In that case, POSIX says that LC_TIME +- determines the format and contents of date and time strings +- written by date, which means "date" must generate output +- using the POSIX locale; but adding _() would cause "date" +- to use a Korean translation of the format. */ +- format = "%a %b %e %H:%M:%S %Z %Y"; ++ format = dcgettext(NULL, N_("%a %b %e %H:%M:%S %Z %Y"), LC_TIME); + } + } + diff --git a/coreutils-6.10-configuration.patch b/coreutils-6.10-configuration.patch new file mode 100644 index 0000000..1e3be91 --- /dev/null +++ b/coreutils-6.10-configuration.patch @@ -0,0 +1,136 @@ +diff -urNp coreutils-8.13-orig/gnulib-tests/gnulib.mk coreutils-8.13/gnulib-tests/gnulib.mk +--- coreutils-8.13-orig/gnulib-tests/gnulib.mk 2011-09-08 17:09:08.000000000 +0200 ++++ coreutils-8.13/gnulib-tests/gnulib.mk 2011-09-09 10:14:18.714689661 +0200 +@@ -235,9 +235,9 @@ EXTRA_DIST += nap.h test-chown.h test-ch + + ## begin gnulib module cloexec-tests + +-TESTS += test-cloexec +-check_PROGRAMS += test-cloexec +-EXTRA_DIST += test-cloexec.c macros.h ++#TESTS += test-cloexec ++#check_PROGRAMS += test-cloexec ++#EXTRA_DIST += test-cloexec.c macros.h + + ## end gnulib module cloexec-tests + +@@ -321,9 +321,9 @@ EXTRA_DIST += test-dirname.c + + ## begin gnulib module dup2-tests + +-TESTS += test-dup2 +-check_PROGRAMS += test-dup2 +-EXTRA_DIST += test-dup2.c signature.h macros.h ++#TESTS += test-dup2 ++#check_PROGRAMS += test-dup2 ++#EXTRA_DIST += test-dup2.c signature.h macros.h + + ## end gnulib module dup2-tests + +@@ -373,10 +373,10 @@ EXTRA_DIST += test-fadvise.c + + ## begin gnulib module fchdir-tests + +-TESTS += test-fchdir +-check_PROGRAMS += test-fchdir +-test_fchdir_LDADD = $(LDADD) $(LIBINTL) +-EXTRA_DIST += test-fchdir.c signature.h macros.h ++#TESTS += test-fchdir ++#check_PROGRAMS += test-fchdir ++#test_fchdir_LDADD = $(LDADD) $(LIBINTL) ++#EXTRA_DIST += test-fchdir.c signature.h macros.h + + ## end gnulib module fchdir-tests + +@@ -918,10 +918,10 @@ EXTRA_DIST += test-link.h test-link.c si + + ## begin gnulib module linkat-tests + +-TESTS += test-linkat +-check_PROGRAMS += test-linkat +-test_linkat_LDADD = $(LDADD) @LIBINTL@ +-EXTRA_DIST += test-link.h test-linkat.c signature.h macros.h ++#TESTS += test-linkat ++#check_PROGRAMS += test-linkat ++#test_linkat_LDADD = $(LDADD) @LIBINTL@ ++#EXTRA_DIST += test-link.h test-linkat.c signature.h macros.h + + ## end gnulib module linkat-tests + +@@ -1284,9 +1284,9 @@ EXTRA_DIST += test-memrchr.c zerosize-ptr.h signature.h macros.h + + ## begin gnulib module memrchr-tests + +-TESTS += test-memrchr +-check_PROGRAMS += test-memrchr +-EXTRA_DIST += test-memrchr.c zerosize-ptr.h signature.h macros.h ++#TESTS += test-memrchr ++#check_PROGRAMS += test-memrchr ++#EXTRA_DIST += test-memrchr.c zerosize-ptr.h signature.h macros.h + + ## end gnulib module memrchr-tests + +@@ -1824,9 +1824,9 @@ + + ## begin gnulib module stdalign-tests + +-TESTS += test-stdalign +-check_PROGRAMS += test-stdalign +-EXTRA_DIST += test-stdalign.c macros.h ++#TESTS += test-stdalign ++#check_PROGRAMS += test-stdalign ++#EXTRA_DIST += test-stdalign.c macros.h + + ## end gnulib module stdalign-tests + +@@ -1891,9 +1891,9 @@ EXTRA_DIST += test-uname.c signature.h m + + ## begin gnulib module unistd-safer-tests + +-TESTS += test-dup-safer +-check_PROGRAMS += test-dup-safer +-EXTRA_DIST += test-dup-safer.c macros.h ++#TESTS += test-dup-safer ++#check_PROGRAMS += test-dup-safer ++#EXTRA_DIST += test-dup-safer.c macros.h + + ## end gnulib module unistd-safer-tests + +@@ -1997,10 +1997,10 @@ EXTRA_DIST += test-usleep.c signature.h + + ## begin gnulib module utimens-tests + +-TESTS += test-utimens +-check_PROGRAMS += test-utimens +-test_utimens_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) +-EXTRA_DIST += nap.h test-futimens.h test-lutimens.h test-utimens.h test-utimens-common.h test-utimens.c macros.h ++#TESTS += test-utimens ++#check_PROGRAMS += test-utimens ++#test_utimens_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) ++#EXTRA_DIST += nap.h test-futimens.h test-lutimens.h test-utimens.h test-utimens-common.h test-utimens.c macros.h + + ## end gnulib module utimens-tests + +diff -urNp coreutils-8.13-orig/tests/Makefile.am coreutils-8.13/tests/Makefile.am +--- coreutils-8.13-orig/tests/Makefile.am 2011-09-02 14:08:40.000000000 +0200 ++++ coreutils-8.13/tests/Makefile.am 2011-09-09 10:12:56.364814725 +0200 +@@ -86,7 +86,6 @@ TESTS = \ + rm/ext3-perf \ + rm/cycle \ + cp/link-heap \ +- tail-2/inotify-hash-abuse \ + tail-2/inotify-hash-abuse2 \ + tail-2/F-vs-missing \ + tail-2/F-vs-rename \ +diff -urNp coreutils-8.13-orig/tests/touch/no-dereference coreutils-8.13/tests/touch/no-dereference +--- coreutils-8.13-orig/tests/touch/no-dereference 2011-08-08 09:42:16.000000000 +0200 ++++ coreutils-8.13/tests/touch/no-dereference 2011-09-09 10:15:21.167060702 +0200 +@@ -42,6 +42,8 @@ test -f nowhere && fail=1 + grep '^#define HAVE_UTIMENSAT 1' "$CONFIG_HEADER" > /dev/null || + grep '^#define HAVE_LUTIMES 1' "$CONFIG_HEADER" > /dev/null || + skip_ 'this system lacks the utimensat function' ++grep '^#define HAVE_WORKINGKOJI 1' "$CONFIG_HEADER" > /dev/null || ++ skip_ 'rest of the test disabled due to koji lack of utimensat function' + + # Changing time of dangling symlink is okay. + # Skip the test if this fails, but the error text corresponds to diff --git a/coreutils-6.10-manpages.patch b/coreutils-6.10-manpages.patch new file mode 100644 index 0000000..2c663f9 --- /dev/null +++ b/coreutils-6.10-manpages.patch @@ -0,0 +1,13 @@ +diff -urNp coreutils-6.12-orig/src/md5sum.c coreutils-6.12/src/md5sum.c +--- coreutils-6.12-orig/src/md5sum.c 2008-05-26 08:40:33.000000000 +0200 ++++ coreutils-6.12/src/md5sum.c 2008-10-21 16:07:28.000000000 +0200 +@@ -175,6 +175,9 @@ With no FILE, or when FILE is -, read st + fputs (_("\ + -t, --text read in text mode (default)\n\ + "), stdout); ++ fputs (_("\ ++ Note: There is no difference between binary and text mode option on GNU system.\n\ ++"), stdout); + fputs (_("\ + \n\ + The following three options are useful only when verifying checksums:\n\ diff --git a/coreutils-7.4-sttytcsadrain.patch b/coreutils-7.4-sttytcsadrain.patch new file mode 100644 index 0000000..fe83798 --- /dev/null +++ b/coreutils-7.4-sttytcsadrain.patch @@ -0,0 +1,12 @@ +diff -urNp coreutils-8.13-orig/src/stty.c coreutils-8.13/src/stty.c +--- coreutils-8.13-orig/src/stty.c 2011-07-28 12:38:27.000000000 +0200 ++++ coreutils-8.13/src/stty.c 2011-09-09 10:18:57.526687209 +0200 +@@ -1005,7 +1005,7 @@ main (int argc, char **argv) + spurious difference in an uninitialized portion of the structure. */ + struct termios new_mode = { 0, }; + +- if (tcsetattr (STDIN_FILENO, TCSADRAIN, &mode)) ++ if (tcsetattr (STDIN_FILENO, TCSANOW, &mode)) + error (EXIT_FAILURE, errno, "%s", device_name); + + /* POSIX (according to Zlotnick's book) tcsetattr returns zero if diff --git a/coreutils-8.15-cp-attribute-truncate.patch b/coreutils-8.15-cp-attribute-truncate.patch new file mode 100644 index 0000000..b7d27ef --- /dev/null +++ b/coreutils-8.15-cp-attribute-truncate.patch @@ -0,0 +1,103 @@ +From 3d53e7fe1c31aa440cc9708c7c51db6b78c07653 Mon Sep 17 00:00:00 2001 +From: =?utf8?q?P=C3=A1draig=20Brady?= +Date: Thu, 12 Apr 2012 12:47:30 +0100 +Subject: [PATCH 1/1] cp: change --attributes-only to not truncate existing files + +* src/copy.c (copy_reg): Don't truncate an existing file, +to support copying attributes between existing files. +The original use case only considered creating new files, +and it would be a very unusual use case to be relying +on the truncating behavior. +* doc/coreutils.texi (cp invocation): Mention the non +truncating behavior. +* tests/cp/attr-existing: A new test to ensure O_TRUNC skipped. +* tests/Makefile.am: Reference the new test. +--- + doc/coreutils.texi | 6 +++--- + src/copy.c | 4 +++- + tests/Makefile.am | 1 + + tests/cp/attr-existing | 29 +++++++++++++++++++++++++++++ + 4 files changed, 36 insertions(+), 4 deletions(-) + create mode 100755 tests/cp/attr-existing + +diff --git a/doc/coreutils.texi b/doc/coreutils.texi +index 510abb9..1fbf051 100644 +--- a/doc/coreutils.texi ++++ b/doc/coreutils.texi +@@ -7649,9 +7649,9 @@ Equivalent to @option{-dR --preserve=all} with the reduced diagnostics. + + @itemx --attributes-only + @opindex --attributes-only +-Preserve the specified attributes of the original files in the copy, +-but do not copy any data. See the @option{--preserve} option for +-controlling which attributes to copy. ++Copy only the specified attributes of the source file to the destination. ++If the destination already exists, do not alter its contents. ++See the @option{--preserve} option for controlling which attributes to copy. + + @item -b + @itemx @w{@kbd{--backup}[=@var{method}]} +diff --git a/src/copy.c b/src/copy.c +index f63a726..414fbe0 100644 +--- a/src/copy.c ++++ b/src/copy.c +@@ -826,7 +826,9 @@ copy_reg (char const *src_name, char const *dst_name, + by the specs for both cp and mv. */ + if (! *new_dst) + { +- dest_desc = open (dst_name, O_WRONLY | O_TRUNC | O_BINARY); ++ int open_flags = ++ O_WRONLY | O_BINARY | (x->data_copy_required ? O_TRUNC : 0); ++ dest_desc = open (dst_name, open_flags); + dest_errno = errno; + + /* When using cp --preserve=context to copy to an existing destination, +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 011051a..4d73a92 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -320,6 +320,7 @@ TESTS = \ + chown/separator \ + cp/abuse \ + cp/acl \ ++ cp/attr-existing \ + cp/backup-1 \ + cp/backup-dir \ + cp/backup-is-src \ +diff --git a/tests/cp/attr-existing b/tests/cp/attr-existing +new file mode 100755 +index 0000000..9cf0ffc +--- /dev/null ++++ b/tests/cp/attr-existing +@@ -0,0 +1,29 @@ ++#!/bin/sh ++# Make sure cp --attributes-only doesn't truncate existing data ++ ++# Copyright 2012 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=.}/init.sh"; path_prepend_ ../src ++print_ver_ cp ++ ++printf '1' > file1 ++printf '2' > file2 ++printf '2' > file2.exp ++ ++cp --attributes-only file1 file2 || fail=1 ++cmp file2 file2.exp || fail=1 ++ ++Exit $fail +-- +1.7.2.5 diff --git a/coreutils-8.15-du-x-nondir.patch b/coreutils-8.15-du-x-nondir.patch new file mode 100644 index 0000000..02d120e --- /dev/null +++ b/coreutils-8.15-du-x-nondir.patch @@ -0,0 +1,43 @@ +diff --git a/src/du.c b/src/du.c +index e4e36df..41c9535 100644 +--- a/src/du.c ++++ b/src/du.c +@@ -443,7 +443,14 @@ process_file (FTS *fts, FTSENT *ent) + return false; + } + +- if (fts->fts_options & FTS_XDEV && fts->fts_dev != sb->st_dev) ++ /* The --one-file-system (-x) option cannot exclude anything ++ specified on the command-line. By definition, it can exclude ++ a file or directory only when its device number is different ++ from that of its just-processed parent directory, and du does ++ not process the parent of a command-line argument. */ ++ if (fts->fts_options & FTS_XDEV ++ && FTS_ROOTLEVEL < ent->fts_level ++ && fts->fts_dev != sb->st_dev) + excluded = true; + } + +diff --git a/tests/du/one-file-system b/tests/du/one-file-system +index f0d264a..110080f 100755 +--- a/tests/du/one-file-system ++++ b/tests/du/one-file-system +@@ -43,7 +43,15 @@ compare exp out || fail=1 + du -xL d > u || fail=1 + sed 's/^[0-9][0-9]* //' u > out1 + echo d > exp1 || fail=1 +- + compare exp1 out1 || fail=1 + ++# With coreutils-8.15, "du -xs FILE" would print no output. ++touch f ++for opt in -x -xs; do ++ du $opt f > u || fail=1 ++ sed 's/^[0-9][0-9]* //' u > out2 ++ echo f > exp2 || fail=1 ++ compare exp2 out2 || fail=1 ++done ++ + Exit $fail +-- +cgit v0.9.0.2 diff --git a/coreutils-8.17-cp-freememoryread.patch b/coreutils-8.17-cp-freememoryread.patch new file mode 100644 index 0000000..be4a429 --- /dev/null +++ b/coreutils-8.17-cp-freememoryread.patch @@ -0,0 +1,29 @@ +diff -urNp coreutils-8.17-orig/src/extent-scan.c coreutils-8.17/src/extent-scan.c +--- coreutils-8.17-orig/src/extent-scan.c 2012-05-02 10:31:47.000000000 +0200 ++++ coreutils-8.17/src/extent-scan.c 2012-11-05 12:05:36.732370966 +0100 +@@ -89,7 +89,7 @@ extern bool + extent_scan_read (struct extent_scan *scan) + { + unsigned int si = 0; +- struct extent_info *last_ei IF_LINT ( = scan->ext_info); ++ struct extent_info *last_ei = scan->ext_info; + + while (true) + { +@@ -127,8 +127,14 @@ extent_scan_read (struct extent_scan *sc + + assert (scan->ei_count <= SIZE_MAX - fiemap->fm_mapped_extents); + scan->ei_count += fiemap->fm_mapped_extents; +- scan->ext_info = xnrealloc (scan->ext_info, scan->ei_count, +- sizeof (struct extent_info)); ++ { ++ /* last_ei points into a buffer that may be freed via xnrealloc. ++ Record its offset and adjust after allocation. */ ++ size_t prev_idx = last_ei - scan->ext_info; ++ scan->ext_info = xnrealloc (scan->ext_info, scan->ei_count, ++ sizeof (struct extent_info)); ++ last_ei = scan->ext_info + prev_idx; ++ } + + unsigned int i = 0; + for (i = 0; i < fiemap->fm_mapped_extents; i++) diff --git a/coreutils-8.17-df-duplicates.patch b/coreutils-8.17-df-duplicates.patch new file mode 100644 index 0000000..06983ad --- /dev/null +++ b/coreutils-8.17-df-duplicates.patch @@ -0,0 +1,264 @@ +diff -urNp coreutils-8.17-orig/doc/coreutils.texi coreutils-8.17/doc/coreutils.texi +--- coreutils-8.17-orig/doc/coreutils.texi 2012-05-10 09:14:30.000000000 +0200 ++++ coreutils-8.17/doc/coreutils.texi 2012-12-11 11:30:38.730760947 +0100 +@@ -10561,6 +10561,14 @@ Normally the disk space is printed in un + 1024 bytes, but this can be overridden (@pxref{Block size}). + Non-integer quantities are rounded up to the next higher unit. + ++For bind mounts and without arguments, @command{df} only outputs the statistics ++for the first occurence of that device in the list of file systems (@var{mtab}), ++i.e., it hides duplicate entries, unless the @option{-a} option is specified. ++ ++By default, @command{df} omits the early-boot pseudo file system type ++@samp{rootfs}, unless the @option{-a} option is specified or that file system ++type is explicitly to be included by using the @option{-t} option. ++ + @cindex disk device file + @cindex device file, disk + If an argument @var{file} is a disk device file containing a mounted +diff -urNp coreutils-8.17-orig/src/df.c coreutils-8.17/src/df.c +--- coreutils-8.17-orig/src/df.c 2012-05-01 22:55:08.000000000 +0200 ++++ coreutils-8.17/src/df.c 2012-12-11 11:30:38.803069545 +0100 +@@ -46,6 +46,17 @@ + /* If true, show inode information. */ + static bool inode_format; + ++/* Filled with device numbers of examined file systems to avoid ++ duplicities in output. */ ++struct devlist ++{ ++ dev_t dev_num; ++ struct devlist *next; ++}; ++ ++/* Store of already-processed device numbers. */ ++static struct devlist *devlist_head; ++ + /* If true, show even file systems with zero size or + uninteresting types. */ + static bool show_all_fs; +@@ -57,6 +68,12 @@ static bool show_local_fs; + command line argument -- even if it's a dummy (automounter) entry. */ + static bool show_listed_fs; + ++/* If true, include rootfs in the output. */ ++static bool show_rootfs; ++ ++/* The literal name of the initial root file system. */ ++static char const *ROOTFS = "rootfs"; ++ + /* Human-readable options for output. */ + static int human_output_opts; + +@@ -350,6 +367,29 @@ excluded_fstype (const char *fstype) + return false; + } + ++/* Check if the device was already examined. */ ++ ++static bool ++dev_examined (char const *mount_dir, char const *devname) ++{ ++ struct stat buf; ++ if (-1 == stat (mount_dir, &buf)) ++ return false; ++ ++ struct devlist *devlist = devlist_head; ++ for ( ; devlist; devlist = devlist->next) ++ if (devlist->dev_num == buf.st_dev) ++ return true; ++ ++ /* Add the device number to the global list devlist. */ ++ devlist = xmalloc (sizeof *devlist); ++ devlist->dev_num = buf.st_dev; ++ devlist->next = devlist_head; ++ devlist_head = devlist; ++ ++ return false; ++} ++ + /* Return true if N is a known integer value. On many file systems, + UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1 + represents unknown. Use a rule that works on AIX file systems, and +@@ -474,6 +514,15 @@ get_dev (char const *disk, char const *m + if (!selected_fstype (fstype) || excluded_fstype (fstype)) + return; + ++ if (process_all && !show_all_fs && !show_listed_fs) ++ { ++ /* No arguments nor "df -a", then check if df has to ... */ ++ if (!show_rootfs && STREQ (disk, ROOTFS)) ++ return; /* ... skip rootfs: (unless -trootfs is given. */ ++ if (dev_examined (mount_point, disk)) ++ return; /* ... skip duplicate entries (bind mounts). */ ++ } ++ + /* If MOUNT_POINT is NULL, then the file system is not mounted, and this + program reports on the file system that the special file is on. + It would be better to report on the unmounted file system, +@@ -972,6 +1021,7 @@ main (int argc, char **argv) + /* Accept -F as a synonym for -t for compatibility with Solaris. */ + case 't': + add_fs_type (optarg); ++ show_rootfs = selected_fstype (ROOTFS); + break; + + case 'v': /* For SysV compatibility. */ +@@ -1105,6 +1155,14 @@ main (int argc, char **argv) + + if (! file_systems_processed) + error (EXIT_FAILURE, 0, _("no file systems processed")); ++ IF_LINT ( ++ while (devlist_head) ++ { ++ struct devlist *devlist = devlist_head->next; ++ free (devlist_head); ++ devlist_head = devlist; ++ } ++ ); + + exit (exit_status); + } +diff -urNp coreutils-8.17-orig/tests/df/skip-duplicates coreutils-8.17/tests/df/skip-duplicates +--- coreutils-8.17-orig/tests/df/skip-duplicates 1970-01-01 01:00:00.000000000 +0100 ++++ coreutils-8.17/tests/df/skip-duplicates 2012-12-11 11:30:38.820762450 +0100 +@@ -0,0 +1,77 @@ ++#!/bin/sh ++# Test df's behavior when the mount list contains duplicate entries. ++# This test is skipped on systems that lack LD_PRELOAD support; that's fine. ++ ++# Copyright (C) 2012 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=.}/init.sh"; path_prepend_ ../src ++print_ver_ df ++ ++df || skip_ "df fails" ++ ++# Simulate an mtab file with two entries of the same device number. ++cat > k.c <<'EOF' || framework_failure_ ++#include ++#include ++ ++struct mntent *getmntent (FILE *fp) ++{ ++ /* Prove that LD_PRELOAD works. */ ++ static int done = 0; ++ if (!done) ++ { ++ fclose (fopen ("x", "w")); ++ ++done; ++ } ++ ++ static struct mntent mntent; ++ ++ while (done++ < 3) ++ { ++ mntent.mnt_fsname = "fsname"; ++ mntent.mnt_dir = "/"; ++ mntent.mnt_type = "-"; ++ ++ return &mntent; ++ } ++ return NULL; ++} ++EOF ++ ++# Then compile/link it: ++gcc --std=gnu99 -shared -fPIC -ldl -O2 k.c -o k.so \ ++ || skip_ "getmntent hack does not work on this platform" ++ ++# Test if LD_PRELOAD works: ++LD_PRELOAD=./k.so df ++test -f x || skip_ "internal test failure: maybe LD_PRELOAD doesn't work?" ++ ++# The fake mtab file should only contain 2 entries, both ++# having the same device number; thus the output should ++# consist of a header and one entry. ++LD_PRELOAD=./k.so df >out || fail=1 ++test $(wc -l out || fail=1 ++test $(wc -l out || fail=1 ++test $(wc -l . ++ ++. "${srcdir=.}/init.sh"; path_prepend_ ../src ++print_ver_ df ++ ++df || skip_ "df fails" ++ ++# Verify that rootfs is in mtab (and shown when the -a option is specified). ++df -a >out || fail=1 ++grep '^rootfs' out || skip_ "no rootfs in mtab" ++ ++# Ensure that rootfs is supressed when no options is specified. ++df >out || fail=1 ++grep '^rootfs' out && { fail=1; cat out; } ++ ++# Ensure that the rootfs is shown when explicitly specifying "-t rootfs". ++df -t rootfs >out || fail=1 ++grep '^rootfs' out || { fail=1; cat out; } ++ ++# Ensure that the rootfs is shown when explicitly specifying "-t rootfs", ++# even when the -a option is specified. ++df -t rootfs -a >out || fail=1 ++grep '^rootfs' out || { fail=1; cat out; } ++ ++# Ensure that the rootfs is omitted in all_fs mode when it is explicitly ++# black-listed. ++df -a -x rootfs >out || fail=1 ++grep '^rootfs' out && { fail=1; cat out; } ++ ++Exit $fail +diff -urNp coreutils-8.17-orig/tests/Makefile.am coreutils-8.17/tests/Makefile.am +--- coreutils-8.17-orig/tests/Makefile.am 2012-05-10 16:36:42.000000000 +0200 ++++ coreutils-8.17/tests/Makefile.am 2012-12-11 11:32:23.021760237 +0100 +@@ -373,6 +373,8 @@ TESTS = \ + cp/symlink-slash \ + cp/thru-dangling \ + df/unreadable \ ++ df/skip-duplicates \ ++ df/skip-rootfs \ + dd/direct \ + dd/misc \ + dd/nocache \ diff --git a/coreutils-8.17-sort-uniq-fmr.patch b/coreutils-8.17-sort-uniq-fmr.patch new file mode 100644 index 0000000..91873c7 --- /dev/null +++ b/coreutils-8.17-sort-uniq-fmr.patch @@ -0,0 +1,51 @@ +diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c +--- coreutils-8.17-orig/src/sort.c 2012-08-20 13:15:39.703470009 +0200 ++++ coreutils-8.17/src/sort.c 2012-08-20 13:29:47.177468563 +0200 +@@ -292,6 +292,9 @@ struct merge_node_queue + when popping. */ + }; + ++/* Used to implement --unique (-u). */ ++static struct line saved_line; ++ + /* FIXME: None of these tables work with multibyte character sets. + Also, there are many other bugs when handling multibyte characters. + One way to fix this is to rewrite `sort' to use wide characters +@@ -3943,13 +3946,12 @@ queue_pop (struct merge_node_queue *queu + static void + write_unique (struct line const *line, FILE *tfp, char const *temp_output) + { +- static struct line saved; + + if (unique) + { +- if (saved.text && ! compare (line, &saved)) ++ if (saved_line.text && ! compare (line, &saved_line)) + return; +- saved = *line; ++ saved_line = *line; + } + + write_line (line, tfp, temp_output); +@@ -4451,6 +4453,7 @@ sort (char *const *files, size_t nfiles, + break; + } + ++ saved_line.text = NULL; + line = buffer_linelim (&buf); + if (buf.eof && !nfiles && !ntemps && !buf.left) + { +diff -urNp coreutils-8.17-orig/tests/misc/sort coreutils-8.17/tests/misc/sort +--- coreutils-8.17-orig/tests/misc/sort 2012-02-03 10:22:06.000000000 +0100 ++++ coreutils-8.17/tests/misc/sort 2012-08-20 13:31:38.685565488 +0200 +@@ -226,6 +226,10 @@ my @Tests = + ["15c", '-i -u', {IN=>"a\1\na\n"}, {OUT=>"a\1\n"}], + ["15d", '-i -u', {IN=>"\1a\na\n"}, {OUT=>"\1a\n"}], + ["15e", '-i -u', {IN=>"a\n\1\1\1\1\1a\1\1\1\1\n"}, {OUT=>"a\n"}], ++# Before 8.19, this would trigger a free-memory read. ++["unique-free-mem-read", '-u --p=1 -S32b', ++ {IN=>"a\n"."b"x900 ."\n"}, ++ {OUT=>"a\n"."b"x900 ."\n"}], + + # From Erick Branderhorst -- fixed around 1.19e + ["16a", '-f', diff --git a/coreutils-8.2-uname-processortype.patch b/coreutils-8.2-uname-processortype.patch new file mode 100644 index 0000000..4c83df8 --- /dev/null +++ b/coreutils-8.2-uname-processortype.patch @@ -0,0 +1,49 @@ +diff -urNp coreutils-8.2-orig/src/uname.c coreutils-8.2/src/uname.c +--- coreutils-8.2-orig/src/uname.c 2009-09-23 10:25:44.000000000 +0200 ++++ coreutils-8.2/src/uname.c 2009-12-19 09:09:11.663607110 +0100 +@@ -301,7 +301,7 @@ main (int argc, char **argv) + + if (toprint & PRINT_PROCESSOR) + { +- char const *element = unknown; ++ char *element = unknown; + #if HAVE_SYSINFO && defined SI_ARCHITECTURE + { + static char processor[257]; +@@ -308,6 +308,12 @@ main (int argc, char **argv) + if (0 <= sysinfo (SI_ARCHITECTURE, processor, sizeof processor)) + element = processor; + } ++#else ++ { ++ static struct utsname u; ++ uname(&u); ++ element = u.machine; ++ } + #endif + #ifdef UNAME_PROCESSOR + if (element == unknown) +@@ -351,7 +357,7 @@ main (int argc, char **argv) + + if (toprint & PRINT_HARDWARE_PLATFORM) + { +- char const *element = unknown; ++ char *element = unknown; + #if HAVE_SYSINFO && defined SI_PLATFORM + { + static char hardware_platform[257]; +@@ -353,6 +359,14 @@ main (int argc, char **argv) + hardware_platform, sizeof hardware_platform)) + element = hardware_platform; + } ++#else ++ { ++ static struct utsname u; ++ uname(&u); ++ element = u.machine; ++ if(strlen(element)==4 && element[0]=='i' && element[2]=='8' && element[3]=='6') ++ element[1]='3'; ++ } + #endif + #ifdef UNAME_HARDWARE_PLATFORM + if (element == unknown) diff --git a/coreutils-8.26-selinuxenable.patch b/coreutils-8.26-selinuxenable.patch deleted file mode 100644 index d9b625a..0000000 --- a/coreutils-8.26-selinuxenable.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 6880c3dc9098b3337612850d1500b474aeb944ca Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Tue, 29 Aug 2017 17:33:51 +0200 -Subject: [PATCH] require_selinux_(): use selinuxenabled(8) if available - ---- - init.cfg | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/init.cfg b/init.cfg -index af6b581..f887b3a 100644 ---- a/init.cfg -+++ b/init.cfg -@@ -114,6 +114,9 @@ require_selinux_() - grep 'selinuxfs$' /proc/filesystems > /dev/null \ - || skip_ "this system lacks SELinux support" - -+ # use the 'selinuxenabled' utility if available -+ selinuxenabled; [ $? = 1 ] && skip_ "SELinux is disabled" -+ - # Independent of whether SELinux is enabled system-wide, - # the current file system may lack SELinux support. - # Also the current build may have SELinux support disabled. --- -2.9.5 - diff --git a/coreutils-8.26-test-lock.patch b/coreutils-8.26-test-lock.patch deleted file mode 100644 index d66928c..0000000 --- a/coreutils-8.26-test-lock.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0d04ee8ddedb2bf33d64f148f246a3b7ec4fef21 Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Mon, 23 Jan 2017 12:35:41 +0100 -Subject: [PATCH] test-lock: disable the rwlock test - -It hangs indefinitely if the system rwlock implementation does not -prevent writer starvation (and glibc does not implement it). - -Bug: http://www.mail-archive.com/bug-gnulib@gnu.org/msg33017.html ---- - gnulib-tests/test-lock.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/gnulib-tests/test-lock.c b/gnulib-tests/test-lock.c -index aa6de27..5af0a6c 100644 ---- a/gnulib-tests/test-lock.c -+++ b/gnulib-tests/test-lock.c -@@ -42,7 +42,7 @@ - Uncomment some of these, to verify that all tests crash if no locking - is enabled. */ - #define DO_TEST_LOCK 1 --#define DO_TEST_RWLOCK 1 -+#define DO_TEST_RWLOCK 0 - #define DO_TEST_RECURSIVE_LOCK 1 - #define DO_TEST_ONCE 1 - --- -2.7.4 - diff --git a/coreutils-8.32-DIR_COLORS.patch b/coreutils-8.32-DIR_COLORS.patch deleted file mode 100644 index 37ce3e6..0000000 --- a/coreutils-8.32-DIR_COLORS.patch +++ /dev/null @@ -1,100 +0,0 @@ -From bca11e30e8a6281a8cbddc9fb196dd86ab09c955 Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Fri, 17 Jun 2016 16:58:18 +0200 -Subject: [PATCH] downstream changes to default DIR_COLORS - ---- - DIR_COLORS | 9 ++++++++- - DIR_COLORS.lightbgcolor | 21 +++++++++++++++------ - 2 files changed, 23 insertions(+), 7 deletions(-) - -diff --git a/DIR_COLORS b/DIR_COLORS -index 540f6cd..b4785b6 100644 ---- a/DIR_COLORS -+++ b/DIR_COLORS -@@ -1,3 +1,7 @@ -+# This file goes in the /etc directory, and must be world readable. -+# You can override the system defaults by making a copy of this file -+# as ~/.dir_colors -+ - # Configuration file for dircolors, a utility to help you set the - # LS_COLORS environment variable used by GNU ls with the --color option. - -@@ -11,6 +15,9 @@ - - # Global config options can be specified before TERM or COLORTERM entries - -+# For compatibility, the pattern "^COLOR.*none" is recognized as a way to -+# disable colorization. See https://bugzilla.redhat.com/1349579 for details. -+ - # =================================================================== - # Terminal filters - # =================================================================== -@@ -70,7 +77,7 @@ DOOR 01;35 # door - BLK 40;33;01 # block device driver - CHR 40;33;01 # character device driver - ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file ... --MISSING 00 # ... and the files they point to -+MISSING 01;37;41 # ... and the files they point to - SETUID 37;41 # regular file that is setuid (u+s) - SETGID 30;43 # regular file that is setgid (g+s) - CAPABILITY 00 # regular file with capability (very expensive to lookup) -diff --git a/DIR_COLORS.lightbgcolor b/DIR_COLORS.lightbgcolor -index e3b0ec3..39a0a4c 100644 ---- a/DIR_COLORS.lightbgcolor -+++ b/DIR_COLORS.lightbgcolor -@@ -1,3 +1,9 @@ -+# Configuration file for the color ls utility - modified for lighter backgrounds -+ -+# This file goes in the /etc directory, and must be world readable. -+# You can override the system defaults by making a copy of this file -+# as ~/.dir_colors -+ - # Configuration file for dircolors, a utility to help you set the - # LS_COLORS environment variable used by GNU ls with the --color option. - -@@ -11,6 +17,9 @@ - - # Global config options can be specified before TERM or COLORTERM entries - -+# For compatibility, the pattern "^COLOR.*none" is recognized as a way to -+# disable colorization. See https://bugzilla.redhat.com/1349579 for details. -+ - # =================================================================== - # Terminal filters - # =================================================================== -@@ -60,17 +69,17 @@ TERM xterm* - #NORMAL 00 # no color code at all - #FILE 00 # regular file: use no color at all - RESET 0 # reset to "normal" color --DIR 01;34 # directory --LINK 01;36 # symbolic link. (If you set this to 'target' instead of a -+DIR 00;34 # directory -+LINK 00;36 # symbolic link. (If you set this to 'target' instead of a - # numerical value, the color is as for the file pointed to.) - MULTIHARDLINK 00 # regular file with more than one link - FIFO 40;33 # pipe --SOCK 01;35 # socket --DOOR 01;35 # door -+SOCK 00;35 # socket -+DOOR 00;35 # door - BLK 40;33;01 # block device driver - CHR 40;33;01 # character device driver - ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file ... --MISSING 00 # ... and the files they point to -+MISSING 01;37;41 # ... and the files they point to - SETUID 37;41 # regular file that is setuid (u+s) - SETGID 30;43 # regular file that is setgid (g+s) - CAPABILITY 00 # regular file with capability (very expensive to lookup) -@@ -79,7 +88,7 @@ OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky - STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable - - # This is for regular files with execute permission: --EXEC 01;32 -+EXEC 00;32 - - # =================================================================== - # File extension attributes --- -2.49.0 - diff --git a/coreutils-8.4-mkdir-modenote.patch b/coreutils-8.4-mkdir-modenote.patch new file mode 100644 index 0000000..3576ec6 --- /dev/null +++ b/coreutils-8.4-mkdir-modenote.patch @@ -0,0 +1,12 @@ +diff -urNp coreutils-8.4-orig/doc/coreutils.texi coreutils-8.4/doc/coreutils.texi +--- coreutils-8.4-orig/doc/coreutils.texi 2011-01-07 15:01:18.575654333 +0100 ++++ coreutils-8.4/doc/coreutils.texi 2011-01-07 15:05:38.791655243 +0100 +@@ -9058,6 +9058,8 @@ incorrect. @xref{Directory Setuid and S + set-user-ID and set-group-ID bits of directories are inherited unless + overridden in this way. + ++Note: The @option{--mode},@option{-m} option only applies to the right-most directories listed on the command line. When combined with @option{--parents}, @option{-p} option, any parent directories are created with @samp{u+wx} modified by umask. ++ + @item -p + @itemx --parents + @opindex -p diff --git a/coreutils-8.4-su-pie.patch b/coreutils-8.4-su-pie.patch new file mode 100644 index 0000000..b3fcaaf --- /dev/null +++ b/coreutils-8.4-su-pie.patch @@ -0,0 +1,11 @@ +diff -urNp coreutils-8.4-orig/src/Makefile.am coreutils-8.4/src/Makefile.am +--- coreutils-8.4-orig/src/Makefile.am 2010-09-03 17:34:43.399747649 +0200 ++++ coreutils-8.4/src/Makefile.am 2010-09-03 17:36:13.005765125 +0200 +@@ -367,6 +367,7 @@ factor_LDADD += $(LIB_GMP) + + # for crypt and pam + su_LDADD += $(LIB_CRYPT) $(PAM_LIBS) ++su_LDFLAGS = -pie -Wl,-z,relro,-z,now + + # for various ACL functions + copy_LDADD += $(LIB_ACL) diff --git a/coreutils-8.5-dircolors.patch b/coreutils-8.5-dircolors.patch new file mode 100644 index 0000000..8707c0a --- /dev/null +++ b/coreutils-8.5-dircolors.patch @@ -0,0 +1,13 @@ +diff -urNp coreutils-8.5-orig/src/dircolors.hin coreutils-8.5/src/dircolors.hin +--- coreutils-8.5-orig/src/dircolors.hin 2010-04-20 21:52:04.000000000 +0200 ++++ coreutils-8.5/src/dircolors.hin 2010-07-22 16:18:41.978036926 +0200 +@@ -127,6 +127,9 @@ EXEC 01;32 + .deb 01;31 + .rpm 01;31 + .jar 01;31 ++.war 01;31 ++.ear 01;31 ++.sar 01;31 + .rar 01;31 + .ace 01;31 + .zoo 01;31 diff --git a/coreutils-8.5-pam.patch b/coreutils-8.5-pam.patch new file mode 100644 index 0000000..8a924b2 --- /dev/null +++ b/coreutils-8.5-pam.patch @@ -0,0 +1,438 @@ +From ea2d050b1952feb99f86c98255280beb6e589d8c Mon Sep 17 00:00:00 2001 +From: Ludwig Nussel +Date: Tue, 17 Aug 2010 13:21:44 +0200 +Subject: [PATCH 1/7] pam support for su + +--- + configure.ac | 14 +++ + src/Makefile.am | 4 +- + src/su.c | 266 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 278 insertions(+), 6 deletions(-) + +diff --git a/configure.ac b/configure.ac +index b07a52b..1fb5839 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -128,6 +128,20 @@ fi + + AC_FUNC_FORK + ++AC_ARG_ENABLE(pam, AS_HELP_STRING([--disable-pam], ++ [Disable PAM support in su (default=auto)]), , [enable_pam=yes]) ++if test "x$enable_pam" != xno; then ++ AC_CHECK_LIB([pam], [pam_start], [enable_pam=yes], [enable_pam=no]) ++ AC_CHECK_LIB([pam_misc], [misc_conv], [:], [enable_pam=no]) ++ if test "x$enable_pam" != xno; then ++ AC_DEFINE(USE_PAM, 1, [Define if you want to use PAM]) ++ PAM_LIBS="-lpam -lpam_misc" ++ AC_SUBST(PAM_LIBS) ++ fi ++fi ++AC_MSG_CHECKING([whether to enable PAM support in su]) ++AC_MSG_RESULT([$enable_pam]) ++ + optional_bin_progs= + AC_CHECK_FUNCS([chroot], + gl_ADD_PROG([optional_bin_progs], [chroot])) +diff --git a/src/Makefile.am b/src/Makefile.am +index db5359b..154a5ed 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -363,8 +363,8 @@ factor_LDADD += $(LIB_GMP) + # for getloadavg + uptime_LDADD += $(GETLOADAVG_LIBS) + +-# for crypt +-su_LDADD += $(LIB_CRYPT) ++# for crypt and pam ++su_LDADD += $(LIB_CRYPT) $(PAM_LIBS) + + # for various ACL functions + copy_LDADD += $(LIB_ACL) +diff --git a/src/su.c b/src/su.c +index f8f5b61..811aad7 100644 +--- a/src/su.c ++++ b/src/su.c +@@ -37,6 +37,16 @@ + restricts who can su to UID 0 accounts. RMS considers that to + be fascist. + ++#ifdef USE_PAM ++ ++ Actually, with PAM, su has nothing to do with whether or not a ++ wheel group is enforced by su. RMS tries to restrict your access ++ to a su which implements the wheel group, but PAM considers that ++ to be fascist, and gives the user/sysadmin the opportunity to ++ enforce a wheel group by proper editing of /etc/pam.d/su ++ ++#endif ++ + Compile-time options: + -DSYSLOG_SUCCESS Log successful su's (by default, to root) with syslog. + -DSYSLOG_FAILURE Log failed su's (by default, to root) with syslog. +@@ -52,6 +62,13 @@ + #include + #include + #include ++#ifdef USE_PAM ++#include ++#include ++#include ++#include ++#include ++#endif + + #include "system.h" + #include "getpass.h" +@@ -111,7 +128,9 @@ + /* The user to become if none is specified. */ + #define DEFAULT_USER "root" + ++#ifndef USE_PAM + char *crypt (char const *key, char const *salt); ++#endif + + static void run_shell (char const *, char const *, char **, size_t) + ATTRIBUTE_NORETURN; +@@ -125,6 +144,11 @@ static bool simulate_login; + /* If true, change some environment vars to indicate the user su'd to. */ + static bool change_environment; + ++#ifdef USE_PAM ++static bool _pam_session_opened; ++static bool _pam_cred_established; ++#endif ++ + static struct option const longopts[] = + { + {"command", required_argument, NULL, 'c'}, +@@ -200,7 +224,174 @@ log_su (struct passwd const *pw, bool successful) + } + #endif + ++#ifdef USE_PAM ++#define PAM_SERVICE_NAME PROGRAM_NAME ++#define PAM_SERVICE_NAME_L PROGRAM_NAME "-l" ++static sig_atomic_t volatile caught_signal = false; ++static pam_handle_t *pamh = NULL; ++static int retval; ++static struct pam_conv conv = ++{ ++ misc_conv, ++ NULL ++}; ++ ++#define PAM_BAIL_P(a) \ ++ if (retval) \ ++ { \ ++ pam_end (pamh, retval); \ ++ a; \ ++ } ++ ++static void ++cleanup_pam (int retcode) ++{ ++ if (_pam_session_opened) ++ pam_close_session (pamh, 0); ++ ++ if (_pam_cred_established) ++ pam_setcred (pamh, PAM_DELETE_CRED | PAM_SILENT); ++ ++ pam_end(pamh, retcode); ++} ++ ++/* Signal handler for parent process. */ ++static void ++su_catch_sig (int sig) ++{ ++ caught_signal = true; ++} ++ ++/* Export env variables declared by PAM modules. */ ++static void ++export_pamenv (void) ++{ ++ char **env; ++ ++ /* This is a copy but don't care to free as we exec later anyways. */ ++ env = pam_getenvlist (pamh); ++ while (env && *env) ++ { ++ if (putenv (*env) != 0) ++ xalloc_die (); ++ env++; ++ } ++} ++ ++static void ++create_watching_parent (void) ++{ ++ pid_t child; ++ sigset_t ourset, blockset; ++ int status = 0; ++ ++ retval = pam_open_session (pamh, 0); ++ if (retval != PAM_SUCCESS) ++ { ++ cleanup_pam (retval); ++ error (EXIT_FAILURE, 0, _("cannot not open session: %s"), ++ pam_strerror (pamh, retval)); ++ } ++ else ++ _pam_session_opened = 1; ++ ++ child = fork (); ++ if (child == (pid_t) -1) ++ { ++ cleanup_pam (PAM_ABORT); ++ error (EXIT_FAILURE, errno, _("cannot create child process")); ++ } ++ ++ /* the child proceeds to run the shell */ ++ if (child == 0) ++ return; ++ ++ /* In the parent watch the child. */ ++ ++ /* su without pam support does not have a helper that keeps ++ sitting on any directory so let's go to /. */ ++ if (chdir ("/") != 0) ++ error (0, errno, _("warning: cannot change directory to %s"), "/"); ++ ++ sigfillset (&ourset); ++ if (sigprocmask (SIG_BLOCK, &ourset, NULL)) ++ { ++ error (0, errno, _("cannot block signals")); ++ caught_signal = true; ++ } ++ if (!caught_signal) ++ { ++ struct sigaction action; ++ action.sa_handler = su_catch_sig; ++ sigemptyset (&action.sa_mask); ++ action.sa_flags = 0; ++ sigemptyset (&ourset); ++ if (sigaddset (&ourset, SIGTERM) ++ || sigaddset (&ourset, SIGALRM) ++ || sigaction (SIGTERM, &action, NULL) ++ || sigprocmask (SIG_UNBLOCK, &ourset, NULL)) ++ { ++ error (0, errno, _("cannot set signal handler")); ++ caught_signal = true; ++ } ++ } ++ if (!caught_signal) ++ { ++ pid_t pid; ++ for (;;) ++ { ++ pid = waitpid (child, &status, WUNTRACED); ++ ++ if (pid != (pid_t)-1 && WIFSTOPPED (status)) ++ { ++ /* tcsh sends SIGTSTP to the process group, and so is already pending */ ++ kill (getpid (), SIGSTOP); ++ if (WSTOPSIG(status) != SIGSTOP) { ++ sigemptyset(&blockset); ++ if (sigaddset(&blockset, WSTOPSIG(status)) || ++ sigprocmask(SIG_UNBLOCK, &blockset, &ourset) || ++ sigprocmask(SIG_SETMASK, &ourset, NULL)) ++ { ++ error (0, errno, _("cannot set signal handler")); ++ } ++ } ++ /* once we get here, we must have resumed */ ++ kill (pid, SIGCONT); ++ } ++ else ++ break; ++ } ++ if (pid != (pid_t)-1) ++ if (WIFSIGNALED (status)) ++ status = WTERMSIG (status) + 128; ++ else ++ status = WEXITSTATUS (status); ++ else ++ status = 1; ++ } ++ else ++ status = 1; ++ ++ if (caught_signal) ++ { ++ fprintf (stderr, _("\nSession terminated, killing shell...")); ++ kill (child, SIGTERM); ++ } ++ ++ cleanup_pam (PAM_SUCCESS); ++ ++ if (caught_signal) ++ { ++ sleep (2); ++ kill (child, SIGKILL); ++ fprintf (stderr, _(" ...killed.\n")); ++ } ++ exit (status); ++} ++#endif ++ + /* Ask the user for a password. ++ If PAM is in use, let PAM ask for the password if necessary. + Return true if the user gives the correct password for entry PW, + false if not. Return true without asking for a password if run by UID 0 + or if PW has an empty password. */ +@@ -208,10 +399,52 @@ log_su (struct passwd const *pw, bool successful) + static bool + correct_password (const struct passwd *pw) + { ++#ifdef USE_PAM ++ const struct passwd *lpw; ++ const char *cp; ++ ++ retval = pam_start (simulate_login ? PAM_SERVICE_NAME_L : PAM_SERVICE_NAME, ++ pw->pw_name, &conv, &pamh); ++ PAM_BAIL_P (return false); ++ ++ if (isatty (0) && (cp = ttyname (0)) != NULL) ++ { ++ const char *tty; ++ ++ if (strncmp (cp, "/dev/", 5) == 0) ++ tty = cp + 5; ++ else ++ tty = cp; ++ retval = pam_set_item (pamh, PAM_TTY, tty); ++ PAM_BAIL_P (return false); ++ } ++#if 0 /* Manpage discourages use of getlogin. */ ++ cp = getlogin (); ++ if (!(cp && *cp && (lpw = getpwnam (cp)) != NULL && lpw->pw_uid == getuid ())) ++#endif ++ lpw = getpwuid (getuid ()); ++ if (lpw && lpw->pw_name) ++ { ++ retval = pam_set_item (pamh, PAM_RUSER, (const void *) lpw->pw_name); ++ PAM_BAIL_P (return false); ++ } ++ retval = pam_authenticate (pamh, 0); ++ PAM_BAIL_P (return false); ++ retval = pam_acct_mgmt (pamh, 0); ++ if (retval == PAM_NEW_AUTHTOK_REQD) ++ { ++ /* Password has expired. Offer option to change it. */ ++ retval = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK); ++ PAM_BAIL_P (return false); ++ } ++ PAM_BAIL_P (return false); ++ /* Must be authenticated if this point was reached. */ ++ return true; ++#else /* !USE_PAM */ + char *unencrypted, *encrypted, *correct; + #if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP + /* Shadow passwd stuff for SVR3 and maybe other systems. */ +- struct spwd *sp = getspnam (pw->pw_name); ++ const struct spwd *sp = getspnam (pw->pw_name); + + endspent (); + if (sp) +@@ -232,6 +465,7 @@ correct_password (const struct passwd *pw) + encrypted = crypt (unencrypted, correct); + memset (unencrypted, 0, strlen (unencrypted)); + return STREQ (encrypted, correct); ++#endif /* !USE_PAM */ + } + + /* Update `environ' for the new shell based on PW, with SHELL being +@@ -274,19 +508,41 @@ modify_environment (const struct passwd *pw, const char *shell) + } + } + } ++ ++#ifdef USE_PAM ++ export_pamenv (); ++#endif + } + + /* Become the user and group(s) specified by PW. */ + + static void +-change_identity (const struct passwd *pw) ++init_groups (const struct passwd *pw) + { + #ifdef HAVE_INITGROUPS + errno = 0; + if (initgroups (pw->pw_name, pw->pw_gid) == -1) +- error (EXIT_CANCELED, errno, _("cannot set groups")); ++ { ++#ifdef USE_PAM ++ cleanup_pam (PAM_ABORT); ++#endif ++ error (EXIT_FAILURE, errno, _("cannot set groups")); ++ } + endgrent (); + #endif ++ ++#ifdef USE_PAM ++ retval = pam_setcred (pamh, PAM_ESTABLISH_CRED); ++ if (retval != PAM_SUCCESS) ++ error (EXIT_FAILURE, 0, "%s", pam_strerror (pamh, retval)); ++ else ++ _pam_cred_established = 1; ++#endif ++} ++ ++static void ++change_identity (const struct passwd *pw) ++{ + if (setgid (pw->pw_gid)) + error (EXIT_CANCELED, errno, _("cannot set group id")); + if (setuid (pw->pw_uid)) +@@ -500,9 +756,21 @@ main (int argc, char **argv) + shell = NULL; + } + shell = xstrdup (shell ? shell : pw->pw_shell); +- modify_environment (pw, shell); ++ ++ init_groups (pw); ++ ++#ifdef USE_PAM ++ create_watching_parent (); ++ /* Now we're in the child. */ ++#endif + + change_identity (pw); ++ ++ /* Set environment after pam_open_session, which may put KRB5CCNAME ++ into the pam_env, etc. */ ++ ++ modify_environment (pw, shell); ++ + if (simulate_login && chdir (pw->pw_dir) != 0) + error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir); + +-- +1.7.1 +diff -urNp coreutils-8.7-orig/doc/coreutils.texi coreutils-8.7/doc/coreutils.texi +--- coreutils-8.7-orig/doc/coreutils.texi 2010-11-15 12:47:03.529922880 +0100 ++++ coreutils-8.7/doc/coreutils.texi 2010-11-15 12:49:55.945171380 +0100 +@@ -15180,7 +15180,9 @@ the exit status of @var{command} otherwi + + @command{su} allows one user to temporarily become another user. It runs a + command (often an interactive shell) with the real and effective user +-ID, group ID, and supplemental groups of a given @var{user}. Synopsis: ++ID, group ID, and supplemental groups of a given @var{user}. When the -l ++option is given, the su-l PAM file is used instead of the default su PAM file. ++Synopsis: + + @example + su [@var{option}]@dots{} [@var{user} [@var{arg}]@dots{}] +@@ -15259,7 +15261,8 @@ environment variables except @env{TERM}, + (which are set, even for the super-user, as described above), and set + @env{PATH} to a compiled-in default value. Change to @var{user}'s home + directory. Prepend @samp{-} to the shell's name, intended to make it +-read its login startup file(s). ++read its login startup file(s). When this option is given, /etc/pam.d/su-l ++PAM file is used instead of the default one. + + @item -m + @itemx -p diff --git a/coreutils-8.7-runuser.patch b/coreutils-8.7-runuser.patch new file mode 100644 index 0000000..c68da7c --- /dev/null +++ b/coreutils-8.7-runuser.patch @@ -0,0 +1,338 @@ +diff -urNp coreutils-8.7-orig/AUTHORS coreutils-8.7/AUTHORS +--- coreutils-8.7-orig/AUTHORS 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/AUTHORS 2010-11-15 10:08:04.222078001 +0100 +@@ -65,6 +65,7 @@ readlink: Dmitry V. Levin + rm: Paul Rubin, David MacKenzie, Richard M. Stallman, Jim Meyering + rmdir: David MacKenzie + runcon: Russell Coker ++runuser: David MacKenzie, Dan Walsh + seq: Ulrich Drepper + sha1sum: Ulrich Drepper, Scott Miller, David Madore + sha224sum: Ulrich Drepper, Scott Miller, David Madore +diff -urNp coreutils-8.7-orig/man/help2man coreutils-8.7/man/help2man +--- coreutils-8.7-orig/man/help2man 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/man/help2man 2010-11-15 10:08:51.331054884 +0100 +@@ -555,6 +555,9 @@ while (length) + $include{$sect} .= $content; + } + ++# There is no info documentation for runuser (shared with su). ++$opt_no_info = 1 if $program eq 'runuser'; ++ + # Refer to the real documentation. + unless ($opt_no_info) + { +diff -urNp coreutils-8.7-orig/man/Makefile.am coreutils-8.7/man/Makefile.am +--- coreutils-8.7-orig/man/Makefile.am 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/man/Makefile.am 2010-11-15 10:09:21.768922182 +0100 +@@ -94,6 +94,7 @@ readlink.1: $(common_dep) $(srcdir)/read + rm.1: $(common_dep) $(srcdir)/rm.x ../src/rm.c + rmdir.1: $(common_dep) $(srcdir)/rmdir.x ../src/rmdir.c + runcon.1: $(common_dep) $(srcdir)/runcon.x ../src/runcon.c ++runuser.1: $(common_dep) $(srcdir)/runuser.x ../src/su.c + seq.1: $(common_dep) $(srcdir)/seq.x ../src/seq.c + sha1sum.1: $(common_dep) $(srcdir)/sha1sum.x ../src/md5sum.c + sha224sum.1: $(common_dep) $(srcdir)/sha224sum.x ../src/md5sum.c +diff -urNp coreutils-8.7-orig/man/runuser.x coreutils-8.7/man/runuser.x +--- coreutils-8.7-orig/man/runuser.x 1970-01-01 01:00:00.000000000 +0100 ++++ coreutils-8.7/man/runuser.x 2010-11-15 10:09:57.437939015 +0100 +@@ -0,0 +1,12 @@ ++[NAME] ++runuser \- run a shell with substitute user and group IDs ++[DESCRIPTION] ++.\" Add any additional description here ++[SEE ALSO] ++.TP ++More detailed Texinfo documentation could be found by command ++.TP ++\t\fBinfo coreutils \(aqsu invocation\(aq\fR\t ++.TP ++since the command \fBrunuser\fR is trimmed down version of command \fBsu\fR. ++.br +diff -urNp coreutils-8.7-orig/README coreutils-8.7/README +--- coreutils-8.7-orig/README 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/README 2010-11-15 10:10:43.002922253 +0100 +@@ -11,8 +11,8 @@ The programs that can be built with this + factor false fmt fold groups head hostid hostname id install join kill + link ln logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl nohup + nproc od paste pathchk pinky pr printenv printf ptx pwd readlink realpath +- rm rmdir runcon seq sha1sum sha224sum sha256sum sha384sum sha512sum shred +- shuf sleep sort split stat stdbuf stty su sum sync tac tail tee test ++ rm rmdir runcon runuser seq sha1sum sha224sum sha256sum sha384sum sha512sum ++ shred shuf sleep sort split stat stdbuf stty su sum sync tac tail tee test + timeout touch tr true truncate tsort tty uname unexpand uniq unlink + uptime users vdir wc who whoami yes + +diff -urNp coreutils-8.7-orig/src/Makefile.am coreutils-8.7/src/Makefile.am +--- coreutils-8.7-orig/src/Makefile.am 2010-11-15 10:07:07.339171659 +0100 ++++ coreutils-8.7/src/Makefile.am 2010-11-15 10:12:14.847094550 +0100 +@@ -100,6 +100,7 @@ EXTRA_PROGRAMS = \ + rm \ + rmdir \ + runcon \ ++ runuser \ + seq \ + sha1sum \ + sha224sum \ +@@ -300,6 +301,10 @@ cp_LDADD += $(copy_LDADD) + ginstall_LDADD += $(copy_LDADD) + mv_LDADD += $(copy_LDADD) + ++runuser_SOURCES = su.c ++runuser_CFLAGS = -DRUNUSER -DAUTHORS="\"David MacKenzie, Dan Walsh\"" ++runuser_LDADD = $(LDADD) $(LIB_CRYPT) $(PAM_LIBS) ++ + remove_LDADD = + mv_LDADD += $(remove_LDADD) + rm_LDADD += $(remove_LDADD) +@@ -395,7 +400,7 @@ RELEASE_YEAR = \ + `sed -n '/.*COPYRIGHT_YEAR = \([0-9][0-9][0-9][0-9]\) };/s//\1/p' \ + $(top_srcdir)/lib/version-etc.c` + +-all-local: su$(EXEEXT) ++all-local: su$(EXEEXT) runuser + + installed_su = $(DESTDIR)$(bindir)/`echo su|sed '$(transform)'` + +diff -urNp coreutils-8.7-orig/src/su.c coreutils-8.7/src/su.c +--- coreutils-8.7-orig/src/su.c 2010-11-15 10:07:07.372933288 +0100 ++++ coreutils-8.7/src/su.c 2010-11-15 10:42:12.569159230 +0100 +@@ -100,9 +100,15 @@ + #include "error.h" + + /* The official name of this program (e.g., no `g' prefix). */ ++#ifndef RUNUSER + #define PROGRAM_NAME "su" ++#else ++#define PROGRAM_NAME "runuser" ++#endif + ++#ifndef AUTHORS + #define AUTHORS proper_name ("David MacKenzie") ++#endif + + #if HAVE_PATHS_H + # include +@@ -140,6 +146,9 @@ + #ifndef USE_PAM + char *crypt (char const *key, char const *salt); + #endif ++#ifndef CHECKPASSWD ++#define CHECKPASSWD 1 ++#endif + + static void run_shell (char const *, char const *, char **, size_t) + ATTRIBUTE_NORETURN; +@@ -169,6 +178,10 @@ static struct option const longopts[] = + {"login", no_argument, NULL, 'l'}, + {"preserve-environment", no_argument, NULL, 'p'}, + {"shell", required_argument, NULL, 's'}, ++#ifdef RUNUSER ++ {"group", required_argument, NULL, 'g'}, ++ {"supp-group", required_argument, NULL, 'G'}, ++#endif + {GETOPT_HELP_OPTION_DECL}, + {GETOPT_VERSION_OPTION_DECL}, + {NULL, 0, NULL, 0} +@@ -444,6 +457,11 @@ correct_password (const struct passwd *p + retval = pam_set_item (pamh, PAM_RUSER, (const void *) lpw->pw_name); + PAM_BAIL_P (return false); + } ++#ifdef RUNUSER ++ if (getuid() != geteuid()) ++ /* safety net: deny operation if we are suid by accident */ ++ error(EXIT_FAILURE, 1, "runuser may not be setuid"); ++#else + retval = pam_authenticate (pamh, 0); + PAM_BAIL_P (return false); + retval = pam_acct_mgmt (pamh, 0); +@@ -454,6 +472,7 @@ correct_password (const struct passwd *p + PAM_BAIL_P (return false); + } + PAM_BAIL_P (return false); ++#endif + /* Must be authenticated if this point was reached. */ + return true; + #else /* !USE_PAM */ +@@ -533,11 +552,22 @@ modify_environment (const struct passwd + /* Become the user and group(s) specified by PW. */ + + static void +-init_groups (const struct passwd *pw) ++init_groups (const struct passwd *pw ++#ifdef RUNUSER ++ , gid_t *groups, int num_groups ++#endif ++ ) + { + #ifdef HAVE_INITGROUPS ++ int rc = 0; + errno = 0; +- if (initgroups (pw->pw_name, pw->pw_gid) == -1) ++#ifdef RUNUSER ++ if (num_groups) ++ rc = setgroups(num_groups, groups); ++ else ++#endif ++ rc = initgroups(pw->pw_name, pw->pw_gid); ++ if (rc == -1) + { + #ifdef USE_PAM + cleanup_pam (PAM_ABORT); +@@ -639,6 +669,28 @@ usage (int status) + else + { + printf (_("Usage: %s [OPTION]... [-] [USER [ARG]...]\n"), program_name); ++#ifdef RUNUSER ++ printf (_("\ ++Change the effective user id and group id to that of USER. Only session PAM\n\ ++hooks are run, and there is no password prompt. This command is useful only\n\ ++when run as the root user. If run as a non-root user without privilege\n\ ++to set user ID, the command will fail as the binary is not setuid.\n\ ++As %s doesn't run auth and account PAM hooks, it runs with lower overhead\n\ ++than su.\n\ ++\n\ ++ -, -l, --login make the shell a login shell, uses runuser-l\n\ ++ PAM file instead of default one\n\ ++ -g --group=group specify the primary group\n\ ++ -G --supp-group=group specify a supplemental group\n\ ++ -c, --command=COMMAND pass a single COMMAND to the shell with -c\n\ ++ --session-command=COMMAND pass a single COMMAND to the shell with -c\n\ ++ and do not create a new session\n\ ++ -f, --fast pass -f to the shell (for csh or tcsh)\n\ ++ -m, --preserve-environment do not reset environment variables\n\ ++ -p same as -m\n\ ++ -s, --shell=SHELL run SHELL if /etc/shells allows it\n\ ++"), program_name); ++#else + fputs (_("\ + Change the effective user id and group id to that of USER.\n\ + \n\ +@@ -651,6 +703,7 @@ Change the effective user id and group i + -p same as -m\n\ + -s, --shell=SHELL run SHELL if /etc/shells allows it\n\ + "), stdout); ++#endif + fputs (HELP_OPTION_DESCRIPTION, stdout); + fputs (VERSION_OPTION_DESCRIPTION, stdout); + fputs (_("\ +@@ -672,6 +725,12 @@ main (int argc, char **argv) + char *shell = NULL; + struct passwd *pw; + struct passwd pw_copy; ++#ifdef RUNUSER ++ struct group *gr; ++ gid_t groups[NGROUPS_MAX]; ++ int num_supp_groups = 0; ++ int use_gid = 0; ++#endif + + initialize_main (&argc, &argv); + set_program_name (argv[0]); +@@ -686,7 +745,11 @@ main (int argc, char **argv) + simulate_login = false; + change_environment = true; + +- while ((optc = getopt_long (argc, argv, "c:flmps:", longopts, NULL)) != -1) ++ while ((optc = getopt_long (argc, argv, "c:flmps:" ++#ifdef RUNUSER ++ "g:G:" ++#endif ++ , longopts, NULL)) != -1) + { + switch (optc) + { +@@ -716,6 +779,28 @@ main (int argc, char **argv) + shell = optarg; + break; + ++#ifdef RUNUSER ++ case 'g': ++ gr = getgrnam(optarg); ++ if (!gr) ++ error (EXIT_FAILURE, 0, _("group %s does not exist"), optarg); ++ use_gid = 1; ++ groups[0] = gr->gr_gid; ++ break; ++ ++ case 'G': ++ num_supp_groups++; ++ if (num_supp_groups >= NGROUPS_MAX) ++ error (EXIT_FAILURE, 0, ++ _("Can't specify more than %d supplemental groups"), ++ NGROUPS_MAX - 1); ++ gr = getgrnam(optarg); ++ if (!gr) ++ error (EXIT_FAILURE, 0, _("group %s does not exist"), optarg); ++ groups[num_supp_groups] = gr->gr_gid; ++ break; ++#endif ++ + case_GETOPT_HELP_CHAR; + + case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); +@@ -754,7 +839,20 @@ main (int argc, char **argv) + : DEFAULT_SHELL); + endpwent (); + +- if (!correct_password (pw)) ++#ifdef RUNUSER ++ if (num_supp_groups && !use_gid) ++ { ++ pw->pw_gid = groups[1]; ++ memmove (groups, groups + 1, sizeof(gid_t) * num_supp_groups); ++ } ++ else if (use_gid) ++ { ++ pw->pw_gid = groups[0]; ++ num_supp_groups++; ++ } ++#endif ++ ++ if (CHECKPASSWD && !correct_password (pw)) + { + #ifdef SYSLOG_FAILURE + log_su (pw, false); +@@ -784,7 +882,11 @@ main (int argc, char **argv) + } + shell = xstrdup (shell ? shell : pw->pw_shell); + +- init_groups (pw); ++ init_groups (pw ++#ifdef RUNUSER ++ , groups, num_supp_groups ++#endif ++ ); + + #ifdef USE_PAM + create_watching_parent (); +diff -urNp coreutils-8.7-orig/tests/misc/help-version coreutils-8.7/tests/misc/help-version +--- coreutils-8.7-orig/tests/misc/help-version 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/tests/misc/help-version 2010-11-15 10:45:18.473682325 +0100 +@@ -32,6 +32,7 @@ expected_failure_status_nohup=125 + expected_failure_status_stdbuf=125 + expected_failure_status_su=125 + expected_failure_status_timeout=125 ++expected_failure_status_runuser=125 + expected_failure_status_printenv=2 + expected_failure_status_tty=3 + expected_failure_status_sort=2 +@@ -209,6 +210,7 @@ seq_setup () { args=10; } + sleep_setup () { args=0; } + su_setup () { args=--version; } + stdbuf_setup () { args="-oL true"; } ++runuser_setup () { args=--version; } + timeout_setup () { args=--version; } + + # I'd rather not run sync, since it spins up disks that I've +diff -urNp coreutils-8.7-orig/tests/misc/invalid-opt coreutils-8.7/tests/misc/invalid-opt +--- coreutils-8.7-orig/tests/misc/invalid-opt 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/tests/misc/invalid-opt 2010-11-15 10:45:46.451938873 +0100 +@@ -37,6 +37,7 @@ my %exit_status = + sort => 2, + stdbuf => 125, + su => 125, ++ runuser => 125, + test => 0, + timeout => 125, + true => 0, diff --git a/coreutils-9.9-fix-cut-test-aarch64.patch b/coreutils-9.9-fix-cut-test-aarch64.patch deleted file mode 100644 index 600f87b..0000000 --- a/coreutils-9.9-fix-cut-test-aarch64.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 95044cb5eaea83d02f768feb5ab79fcf5e6ad782 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?P=C3=A1draig=20Brady?= -Date: Mon, 22 Dec 2025 17:12:48 +0000 -Subject: [PATCH] tests: avoid false failure due to ulimit on aarch64 - -* tests/cut/cut-huge-range.sh: Add an extra 1MiB headroom, -which was seen with aarch64. -Reported at https://bugzilla.redhat.com/2424302 - -Cherry-picked-by: Lukáš Zaoral -Upstream-commit: 95044cb5eaea83d02f768feb5ab79fcf5e6ad782 ---- - tests/cut/cut-huge-range.sh | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/tests/cut/cut-huge-range.sh b/tests/cut/cut-huge-range.sh -index 4bd1b129d8..98d7e8f0b9 100755 ---- a/tests/cut/cut-huge-range.sh -+++ b/tests/cut/cut-huge-range.sh -@@ -22,6 +22,7 @@ getlimits_ - - vm=$(get_min_ulimit_v_ returns_ 0 cut -b1 /dev/null) \ - || skip_ 'shell lacks ulimit, or ASAN enabled' -+vm=$(($vm+1000)) # https://bugzilla.redhat.com/2424302 - - # Ensure we can cut up to our sentinel value. - # Don't use expr to subtract one, - diff --git a/coreutils-9.9-gnulib-c23.patch b/coreutils-9.9-gnulib-c23.patch deleted file mode 100644 index 82e3899..0000000 --- a/coreutils-9.9-gnulib-c23.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 891761bca1aa78336e5b18c121075b6e4696c5d4 Mon Sep 17 00:00:00 2001 -From: Paul Eggert -Date: Sun, 23 Nov 2025 00:50:40 -0800 -Subject: [PATCH] Port to C23 qualifier-generic fns like strchr -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This ports Gnulib to strict C23 platforms that reject code -like ‘char *q = strchr (P, 'x');’ when P is a pointer to const, -because in C23 strchr is a qualifier-generic function so -strchr (P, 'x') returns char const *. -This patch does not attempt to do the following two things, -which might be useful in the future: -1. When compiling on non-C23 platforms, check user code for -portability to platforms that define qualifier-generic functions. -2. Port Gnulib to platforms that have qualifier-generic functions -not listed in the C23 standard, e.g., strchrnul. I don’t know -of any such platforms. -* lib/mbschr.c (mbschr): -* lib/memchr2.c (memchr2): -Port to C23, where functions like strchr are qualifier-generic. -* lib/c++defs.h (_GL_FUNCDECL_SYS_NAME): New macro. -* lib/c++defs.h (_GL_FUNCDECL_SYS): -* lib/stdlib.in.h (bsearch): -Use it, to prevent C23 names like strchr from acting like macros. -* lib/string.in.h (memchr, strchr, strpbrk, strrchr): -Do not #undef when GNULIB_POSIXCHECK is defined, as this could -cause conforming C23 code to fail to conform. It’s not clear why -_GL_WARN_ON_USE_CXX; perhaps it was needed but isn’t any more? -But for now, limit the removal of #undef to these four functions -where #undeffing is clearly undesirable in C23. -* lib/wchar.in.h (wmemchr): Parenthesize function name in decl, -to prevent it from acting like a macro. - -Cherry-picked-by: Lukáš Zaoral -Upstream-commit: df17f4f37ed3ca373d23ad42eae51122bdb96626 ---- - lib/c++defs.h | 12 +++++++++++- - lib/mbschr.c | 2 +- - lib/memchr2.c | 2 +- - lib/stdlib.in.h | 6 +++--- - lib/string.in.h | 4 ---- - lib/wchar.in.h | 2 +- - 6 files changed, 17 insertions(+), 11 deletions(-) - -diff --git a/lib/c++defs.h b/lib/c++defs.h -index b77979a..7384457 100644 ---- a/lib/c++defs.h -+++ b/lib/c++defs.h -@@ -127,6 +127,16 @@ - #define _GL_FUNCDECL_RPL_1(rpl_func,rettype,parameters,...) \ - _GL_EXTERN_C_FUNC __VA_ARGS__ rettype rpl_func parameters - -+/* _GL_FUNCDECL_SYS_NAME (func) expands to plain func if C++, and to -+ parenthsized func otherwise. Parenthesization is needed in C23 if -+ the function is like strchr and so is a qualifier-generic macro -+ that expands to something more complicated. */ -+#ifdef __cplusplus -+# define _GL_FUNCDECL_SYS_NAME(func) func -+#else -+# define _GL_FUNCDECL_SYS_NAME(func) (func) -+#endif -+ - /* _GL_FUNCDECL_SYS (func, rettype, parameters, [attributes]); - declares the system function, named func, with the given prototype, - consisting of return type, parameters, and attributes. -@@ -139,7 +149,7 @@ - _GL_FUNCDECL_SYS (posix_openpt, int, (int flags), _GL_ATTRIBUTE_NODISCARD); - */ - #define _GL_FUNCDECL_SYS(func,rettype,parameters,...) \ -- _GL_EXTERN_C_FUNC __VA_ARGS__ rettype func parameters -+ _GL_EXTERN_C_FUNC __VA_ARGS__ rettype _GL_FUNCDECL_SYS_NAME (func) parameters - - /* _GL_CXXALIAS_RPL (func, rettype, parameters); - declares a C++ alias called GNULIB_NAMESPACE::func -diff --git a/lib/mbschr.c b/lib/mbschr.c -index c9e14b5..6582134 100644 ---- a/lib/mbschr.c -+++ b/lib/mbschr.c -@@ -65,5 +65,5 @@ mbschr (const char *string, int c) - return NULL; - } - else -- return strchr (string, c); -+ return (char *) strchr (string, c); - } -diff --git a/lib/memchr2.c b/lib/memchr2.c -index 7493823..d7724ae 100644 ---- a/lib/memchr2.c -+++ b/lib/memchr2.c -@@ -55,7 +55,7 @@ memchr2 (void const *s, int c1_in, int c2_in, size_t n) - c2 = (unsigned char) c2_in; - - if (c1 == c2) -- return memchr (s, c1, n); -+ return (void *) memchr (s, c1, n); - - /* Handle the first few bytes by reading one byte at a time. - Do this until VOID_PTR is aligned on a longword boundary. */ -diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h -index bef0aaa..fd0e1e0 100644 ---- a/lib/stdlib.in.h -+++ b/lib/stdlib.in.h -@@ -224,9 +224,9 @@ _GL_INLINE_HEADER_BEGIN - - /* Declarations for ISO C N3322. */ - #if defined __GNUC__ && __GNUC__ >= 15 && !defined __clang__ --_GL_EXTERN_C void *bsearch (const void *__key, -- const void *__base, size_t __nmemb, size_t __size, -- int (*__compare) (const void *, const void *)) -+_GL_EXTERN_C void *_GL_FUNCDECL_SYS_NAME (bsearch) -+ (const void *__key, const void *__base, size_t __nmemb, size_t __size, -+ int (*__compare) (const void *, const void *)) - _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3) _GL_ARG_NONNULL ((5)); - _GL_EXTERN_C void qsort (void *__base, size_t __nmemb, size_t __size, - int (*__compare) (const void *, const void *)) -diff --git a/lib/string.in.h b/lib/string.in.h -index fdcdd21..8b56acf 100644 ---- a/lib/string.in.h -+++ b/lib/string.in.h -@@ -409,7 +409,6 @@ _GL_CXXALIASWARN1 (memchr, void const *, - _GL_CXXALIASWARN (memchr); - # endif - #elif defined GNULIB_POSIXCHECK --# undef memchr - /* Assume memchr is always declared. */ - _GL_WARN_ON_USE (memchr, "memchr has platform-specific bugs - " - "use gnulib module memchr for portability" ); -@@ -674,7 +673,6 @@ _GL_WARN_ON_USE (stpncpy, "stpncpy is unportable - " - #if defined GNULIB_POSIXCHECK - /* strchr() does not work with multibyte strings if the locale encoding is - GB18030 and the character to be searched is a digit. */ --# undef strchr - /* Assume strchr is always declared. */ - _GL_WARN_ON_USE_CXX (strchr, - const char *, char *, (const char *, int), -@@ -981,7 +979,6 @@ _GL_CXXALIASWARN (strpbrk); - Even in this simple case, it does not work with multibyte strings if the - locale encoding is GB18030 and one of the characters to be searched is a - digit. */ --# undef strpbrk - _GL_WARN_ON_USE_CXX (strpbrk, - const char *, char *, (const char *, const char *), - "strpbrk cannot work correctly on character strings " -@@ -1011,7 +1008,6 @@ _GL_WARN_ON_USE (strspn, "strspn cannot work correctly on character strings " - #if defined GNULIB_POSIXCHECK - /* strrchr() does not work with multibyte strings if the locale encoding is - GB18030 and the character to be searched is a digit. */ --# undef strrchr - /* Assume strrchr is always declared. */ - _GL_WARN_ON_USE_CXX (strrchr, - const char *, char *, (const char *, int), -diff --git a/lib/wchar.in.h b/lib/wchar.in.h -index ab602a2..6be4515 100644 ---- a/lib/wchar.in.h -+++ b/lib/wchar.in.h -@@ -301,7 +301,7 @@ _GL_EXTERN_C int wcsncmp (const wchar_t *__s1, const wchar_t *__s2, size_t __n) - _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) - _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); - # ifndef __cplusplus --_GL_EXTERN_C wchar_t *wmemchr (const wchar_t *__s, wchar_t __wc, size_t __n) -+_GL_EXTERN_C wchar_t *(wmemchr) (const wchar_t *__s, wchar_t __wc, size_t __n) - _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3); - # endif - _GL_EXTERN_C wchar_t *wmemset (wchar_t *__s, wchar_t __wc, size_t __n) --- -2.52.0 - diff --git a/coreutils-DIR_COLORS b/coreutils-DIR_COLORS new file mode 100644 index 0000000..9c182c8 --- /dev/null +++ b/coreutils-DIR_COLORS @@ -0,0 +1,246 @@ +# Configuration file for the color ls utility +# Synchronized with coreutils 8.5 dircolors +# This file goes in the /etc directory, and must be world readable. +# You can copy this file to .dir_colors in your $HOME directory to override +# the system defaults. + +# COLOR needs one of these arguments: 'tty' colorizes output to ttys, but not +# pipes. 'all' adds color characters to all output. 'none' shuts colorization +# off. +COLOR tty + +# Extra command line options for ls go here. +# Basically these ones are: +# -F = show '/' for dirs, '*' for executables, etc. +# -T 0 = don't trust tab spacing when formatting ls output. +OPTIONS -F -T 0 + +# Below, there should be one TERM entry for each termtype that is colorizable +TERM Eterm +TERM ansi +TERM color-xterm +TERM con132x25 +TERM con132x30 +TERM con132x43 +TERM con132x60 +TERM con80x25 +TERM con80x28 +TERM con80x30 +TERM con80x43 +TERM con80x50 +TERM con80x60 +TERM cons25 +TERM console +TERM cygwin +TERM dtterm +TERM eterm-color +TERM gnome +TERM gnome-256color +TERM jfbterm +TERM konsole +TERM kterm +TERM linux +TERM linux-c +TERM mach-color +TERM mlterm +TERM putty +TERM rxvt +TERM rxvt-256color +TERM rxvt-cygwin +TERM rxvt-cygwin-native +TERM rxvt-unicode +TERM rxvt-unicode-256color +TERM rxvt-unicode256 +TERM screen +TERM screen-256color +TERM screen-256color-bce +TERM screen-bce +TERM screen-w +TERM screen.rxvt +TERM screen.linux +TERM terminator +TERM vt100 +TERM xterm +TERM xterm-16color +TERM xterm-256color +TERM xterm-88color +TERM xterm-color +TERM xterm-debian + +# EIGHTBIT, followed by '1' for on, '0' for off. (8-bit output) +EIGHTBIT 1 + +# Below are the color init strings for the basic file types. A color init +# string consists of one or more of the following numeric codes: +# Attribute codes: +# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed +# Text color codes: +# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white +# Background color codes: +# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white +#NORMAL 00 # no color code at all +#FILE 00 # normal file, use no color at all +RESET 0 # reset to "normal" color +DIR 01;34 # directory +LINK 01;36 # symbolic link (If you set this to 'target' instead of a + # numerical value, the color is as for the file pointed to.) +MULTIHARDLINK 00 # regular file with more than one link +FIFO 40;33 # pipe +SOCK 01;35 # socket +DOOR 01;35 # door +BLK 40;33;01 # block device driver +CHR 40;33;01 # character device driver +ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file +MISSING 01;05;37;41 # ... and the files they point to +SETUID 37;41 # file that is setuid (u+s) +SETGID 30;43 # file that is setgid (g+s) +CAPABILITY 30;41 # file with capability +STICKY_OTHER_WRITABLE 30;42 # dir that is sticky and other-writable (+t,o+w) +OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky +STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable + +# This is for files with execute permission: +EXEC 01;32 + +# List any file extensions like '.gz' or '.tar' that you would like ls +# to colorize below. Put the extension, a space, and the color init string. +# (and any comments you want to add after a '#') +# executables (bright green) +#.cmd 01;32 +#.exe 01;32 +#.com 01;32 +#.btm 01;32 +#.bat 01;32 +#.sh 01;32 +#.csh 01;32 + # archives or compressed (bright red) +.tar 01;31 +.tgz 01;31 +.arj 01;31 +.taz 01;31 +.lzh 01;31 +.lzma 01;31 +.tlz 01;31 +.txz 01;31 +.zip 01;31 +.z 01;31 +.Z 01;31 +.dz 01;31 +.gz 01;31 +.lz 01;31 +.xz 01;31 +.bz2 01;31 +.tbz 01;31 +.tbz2 01;31 +.bz 01;31 +.tz 01;31 +.deb 01;31 +.rpm 01;31 +.jar 01;31 +.war 01;31 +.ear 01;31 +.sar 01;31 +.rar 01;31 +.ace 01;31 +.zoo 01;31 +.cpio 01;31 +.7z 01;31 +.rz 01;31 + +# image formats (magenta) +.jpg 01;35 +.jpeg 01;35 +.gif 01;35 +.bmp 01;35 +.pbm 01;35 +.pgm 01;35 +.ppm 01;35 +.tga 01;35 +.xbm 01;35 +.xpm 01;35 +.tif 01;35 +.tiff 01;35 +.png 01;35 +.svg 01;35 +.svgz 01;35 +.mng 01;35 +.pcx 01;35 +.mov 01;35 +.mpg 01;35 +.mpeg 01;35 +.m2v 01;35 +.mkv 01;35 +.ogm 01;35 +.mp4 01;35 +.m4v 01;35 +.mp4v 01;35 +.vob 01;35 +.qt 01;35 +.nuv 01;35 +.wmv 01;35 +.asf 01;35 +.rm 01;35 +.rmvb 01;35 +.flc 01;35 +.avi 01;35 +.fli 01;35 +.flv 01;35 +.gl 01;35 +.dl 01;35 +.xcf 01;35 +.xwd 01;35 +.yuv 01;35 +.cgm 01;35 +.emf 01;35 + +# http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions +.axv 01;35 +.anx 01;35 +.ogv 01;35 +.ogx 01;35 + +# audio formats (cyan) +.aac 01;36 +.au 01;36 +.flac 01;36 +.mid 01;36 +.midi 01;36 +.mka 01;36 +.mp3 01;36 +.mpc 01;36 +.ogg 01;36 +.ra 01;36 +.wav 01;36 + +# http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions +.axa 01;36 +.oga 01;36 +.spx 01;36 +.xspf 01;36 + +# colorize basic documents (brown) +.pdf 00;33 +.ps 00;33 +.ps.gz 00;33 +.txt 00;33 +.patch 00;33 +.diff 00;33 +.log 00;33 +.tex 00;33 +.xls 00;33 +.xlsx 00;33 +.ppt 00;33 +.pptx 00;33 +.rtf 00;33 +.doc 00;33 +.docx 00;33 +.odt 00;33 +.ods 00;33 +.odp 00;33 +.xml 00;33 +.epub 00;33 +.abw 00;33 +.htm 00;33 +.html 00;33 +.shtml 00;33 +.wpd 00;33 diff --git a/coreutils-DIR_COLORS.256color b/coreutils-DIR_COLORS.256color new file mode 100644 index 0000000..1037dd5 --- /dev/null +++ b/coreutils-DIR_COLORS.256color @@ -0,0 +1,219 @@ +# Configuration file for the 256color ls utility +# This file goes in the /etc directory, and must be world readable. +# Synchronized with coreutils 8.5 dircolors +# You can copy this file to .dir_colors in your $HOME directory to override +# the system defaults. +# In the case that you are not satisfied with supplied colors, please +# submit your color configuration or attach your file with colors readable +# on ALL color background schemas (white,gray,black) to RedHat Bugzilla +# ticket on https://bugzilla.redhat.com/show_bug.cgi?id=429121 . TIA. +# Please just keep ls color conventions from 8 color scheme. + +# COLOR needs one of these arguments: 'tty' colorizes output to ttys, but not +# pipes. 'all' adds color characters to all output. 'none' shuts colorization +# off. +COLOR tty + +# Extra command line options for ls go here. +# Basically these ones are: +# -F = show '/' for dirs, '*' for executables, etc. +# -T 0 = don't trust tab spacing when formatting ls output. +OPTIONS -F -T 0 + +# Below, there should be one TERM entry for each termtype that is colorizable +TERM putty-256color +TERM rxvt-256color +TERM rxvt-unicode-256color +TERM rxvt-unicode256 +TERM screen-256color +TERM xterm-256color +TERM gnome-256color + +# EIGHTBIT, followed by '1' for on, '0' for off. (8-bit output) +EIGHTBIT 1 + +# Below are the color init strings for the basic file types. A color init +# string consists of one or more of the following numeric codes: +# Attribute codes: +# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed +# Text color(8 colors mode) codes: +# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white +# Background color(8 colors mode) codes: +# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white +# Text color(256 colors mode) codes: +# Valid syntax for text 256color is 38;5; , where color number +# is number between 0 and 255. +# You may find following command useful to search the best one for you: +# for ((x=0; x<=255; x++));do echo -e "${x}:\033[38;5;${x}mcolor\033[000m";done +# Background color(256 colors mode) codes: +# Valid syntax for background 256color is 48;5; , where +# color number is number between 0 and 255. +# You may find following command useful to search the best one for you: +# for ((x=0; x<=255; x++));do echo -e "${x}:\033[48;5;${x}mcolor\033[000m";done + +#NORMAL 00 # global default, no color code at all +#FILE 00 # normal file, use no color at all +RESET 0 # reset to "normal" color +DIR 38;5;27 # directory +LINK 38;5;51 # symbolic link (If you set this to 'target' instead of a + # numerical value, the color is as for the file pointed to.) +MULTIHARDLINK 44;38;5;15 # regular file with more than one link +FIFO 40;38;5;11 # pipe +SOCK 38;5;13 # socket +DOOR 38;5;5 # door +BLK 48;5;232;38;5;11 # block device driver +CHR 48;5;232;38;5;3 # character device driver +ORPHAN 48;5;232;38;5;9 # symlink to nonexistent file, or non-stat'able file +MISSING 05;48;5;232;38;5;15 # ... and the files they point to +SETUID 48;5;196;38;5;15 # file that is setuid (u+s) +SETGID 48;5;11;38;5;16 # file that is setgid (g+s) +CAPABILITY 48;5;196;38;5;226 # file with capability +STICKY_OTHER_WRITABLE 48;5;10;38;5;16 # dir that is sticky and other-writable (+t,o+w) +OTHER_WRITABLE 48;5;10;38;5;21 # dir that is other-writable (o+w) and not sticky +STICKY 48;5;21;38;5;15 # dir with the sticky bit set (+t) and not other-writable + +# This is for files with execute permission: +EXEC 38;5;34 + +# List any file extensions like '.gz' or '.tar' that you would like ls +# to colorize below. Put the extension, a space, and the color init string. +# (and any comments you want to add after a '#') +# executables (bright green) +#.cmd 38;5;34 +#.exe 38;5;34 +#.com 38;5;34 +#.btm 38;5;34 +#.bat 38;5;34 +#.sh 38;5;34 +#.csh 38;5;34 + # archives or compressed (bright red) +.tar 38;5;9 +.tgz 38;5;9 +.arj 38;5;9 +.taz 38;5;9 +.lzh 38;5;9 +.lzma 38;5;9 +.tlz 38;5;9 +.txz 38;5;9 +.zip 38;5;9 +.z 38;5;9 +.Z 38;5;9 +.dz 38;5;9 +.gz 38;5;9 +.lz 38;5;9 +.xz 38;5;9 +.bz2 38;5;9 +.tbz 38;5;9 +.tbz2 38;5;9 +.bz 38;5;9 +.tz 38;5;9 +.deb 38;5;9 +.rpm 38;5;9 +.jar 38;5;9 +.war 38;5;9 +.ear 38;5;9 +.sar 38;5;9 +.rar 38;5;9 +.ace 38;5;9 +.zoo 38;5;9 +.cpio 38;5;9 +.7z 38;5;9 +.rz 38;5;9 + +# image formats (magenta) +.jpg 38;5;13 +.jpeg 38;5;13 +.gif 38;5;13 +.bmp 38;5;13 +.pbm 38;5;13 +.pgm 38;5;13 +.ppm 38;5;13 +.tga 38;5;13 +.xbm 38;5;13 +.xpm 38;5;13 +.tif 38;5;13 +.tiff 38;5;13 +.png 38;5;13 +.svg 38;5;13 +.svgz 38;5;13 +.mng 38;5;13 +.pcx 38;5;13 +.mov 38;5;13 +.mpg 38;5;13 +.mpeg 38;5;13 +.m2v 38;5;13 +.mkv 38;5;13 +.ogm 38;5;13 +.mp4 38;5;13 +.m4v 38;5;13 +.mp4v 38;5;13 +.vob 38;5;13 +.qt 38;5;13 +.nuv 38;5;13 +.wmv 38;5;13 +.asf 38;5;13 +.rm 38;5;13 +.rmvb 38;5;13 +.flc 38;5;13 +.avi 38;5;13 +.fli 38;5;13 +.flv 38;5;13 +.gl 38;5;13 +.dl 38;5;13 +.xcf 38;5;13 +.xwd 38;5;13 +.yuv 38;5;13 +.cgm 38;5;13 +.emf 38;5;13 + +# http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions +.axv 38;5;13 +.anx 38;5;13 +.ogv 38;5;13 +.ogx 38;5;13 + +# audio formats (cyan) +.aac 38;5;45 +.au 38;5;45 +.flac 38;5;45 +.mid 38;5;45 +.midi 38;5;45 +.mka 38;5;45 +.mp3 38;5;45 +.mpc 38;5;45 +.ogg 38;5;45 +.ra 38;5;45 +.wav 38;5;45 + +# http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions +.axa 38;5;45 +.oga 38;5;45 +.spx 38;5;45 +.xspf 38;5;45 + +# colorize basic documents as well (brown) +.pdf 00;33 +.ps 00;33 +.ps.gz 00;33 +.txt 00;33 +.patch 00;33 +.diff 00;33 +.log 00;33 +.tex 00;33 +.xls 00;33 +.xlsx 00;33 +.ppt 00;33 +.pptx 00;33 +.rtf 00;33 +.doc 00;33 +.docx 00;33 +.odt 00;33 +.ods 00;33 +.odp 00;33 +.xml 00;33 +.epub 00;33 +.abw 00;33 +.htm 00;33 +.html 00;33 +.shtml 00;33 +.wpd 00;33 diff --git a/coreutils-DIR_COLORS.lightbgcolor b/coreutils-DIR_COLORS.lightbgcolor new file mode 100644 index 0000000..4456a8c --- /dev/null +++ b/coreutils-DIR_COLORS.lightbgcolor @@ -0,0 +1,222 @@ +# Configuration file for the color ls utility - modified for gray backgrounds +# Synchronized with coreutils 8.5 dircolors +# This file goes in the /etc directory, and must be world readable. +# You can copy this file to .dir_colors in your $HOME directory to override +# the system defaults. + +# COLOR needs one of these arguments: 'tty' colorizes output to ttys, but not +# pipes. 'all' adds color characters to all output. 'none' shuts colorization +# off. +COLOR tty + +# Extra command line options for ls go here. +# Basically these ones are: +# -F = show '/' for dirs, '*' for executables, etc. +# -T 0 = don't trust tab spacing when formatting ls output. +OPTIONS -F -T 0 + +# Below, there should be one TERM entry for each termtype that is colorizable +TERM linux +TERM console +TERM con132x25 +TERM con132x30 +TERM con132x43 +TERM con132x60 +TERM con80x25 +TERM con80x28 +TERM con80x30 +TERM con80x43 +TERM con80x50 +TERM con80x60 +TERM cons25 +TERM xterm +TERM xterm-16color +TERM xterm-88color +TERM xterm-256color +TERM rxvt +TERM rxvt-256color +TERM rxvt-unicode +TERM rxvt-unicode-256color +TERM rxvt-unicode256 +TERM xterm-color +TERM color-xterm +TERM vt100 +TERM dtterm +TERM color_xterm + +# EIGHTBIT, followed by '1' for on, '0' for off. (8-bit output) +EIGHTBIT 1 + +# Below are the color init strings for the basic file types. A color init +# string consists of one or more of the following numeric codes: +# Attribute codes: +# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed +# Text color codes: +# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white +# Background color codes: +# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white +#NORMAL 00 # no color code at all +#FILE 00 # normal file, use no color at all +RESET 0 +DIR 00;34 # directory +LINK 00;36 # symbolic link (If you set this to 'target' instead of a + # numerical value, the color is as for the file pointed to.) +MULTIHARDLINK 00 # regular file with more than one link +FIFO 40;33 # pipe +SOCK 00;35 # socket +DOOR 00;35 # door +BLK 40;33;01 # block device driver +CHR 40;33;01 # character device driver +ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file +MISSING 01;05;37;41 # ... and the files they point to +SETUID 37;41 # file that is setuid (u+s) +SETGID 30;43 # file that is setgid (g+s) +CAPABILITY 30;41 # file with capability +STICKY_OTHER_WRITABLE 30;42 # dir that is sticky and other-writable (+t,o+w) +OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky +STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable + + +# This is for files with execute permission: +EXEC 00;32 + +# List any file extensions like '.gz' or '.tar' that you would like ls +# to colorize below. Put the extension, a space, and the color init string. +# (and any comments you want to add after a '#') +#.cmd 00;32 # executables (green) +#.exe 00;32 +#.com 00;32 +#.btm 00;32 +#.bat 00;32 +#.sh 00;32 +#.csh 00;32 + # archives or compressed (red) +.tar 00;31 +.tgz 00;31 +.arj 00;31 +.taz 00;31 +.lzh 00;31 +.lzma 00;31 +.tlz 00;31 +.txz 00;31 +.zip 00;31 +.z 00;31 +.Z 00;31 +.dz 00;31 +.gz 00;31 +.lz 00;31 +.xz 00;31 +.bz2 00;31 +.tbz 00;31 +.tbz2 00;31 +.bz 00;31 +.tz 00;31 +.deb 00;31 +.rpm 00;31 +.jar 00;31 +.war 00;31 +.ear 00;31 +.sar 00;31 +.rar 00;31 +.ace 00;31 +.zoo 00;31 +.cpio 00;31 +.7z 00;31 +.rz 00;31 +# image formats (magenta) +.jpg 00;35 +.jpeg 00;35 +.gif 00;35 +.bmp 00;35 +.pbm 00;35 +.pgm 00;35 +.ppm 00;35 +.tga 00;35 +.xbm 00;35 +.xpm 00;35 +.tif 00;35 +.tiff 00;35 +.png 00;35 +.svg 00;35 +.svgz 00;35 +.mng 00;35 +.pcx 00;35 +.mov 00;35 +.mpg 00;35 +.mpeg 00;35 +.m2v 00;35 +.mkv 00;35 +.ogm 00;35 +.mp4 00;35 +.m4v 00;35 +.mp4v 00;35 +.vob 00;35 +.qt 00;35 +.nuv 00;35 +.wmv 00;35 +.asf 00;35 +.rm 00;35 +.rmvb 00;35 +.flc 00;35 +.avi 00;35 +.fli 00;35 +.flv 00;35 +.gl 00;35 +.dl 00;35 +.xcf 00;35 +.xwd 00;35 +.yuv 00;35 +.cgm 00;35 +.emf 00;35 + +# http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions +.axv 00;35 +.anx 00;35 +.ogv 00;35 +.ogx 00;35 + +# audio formats (cyan) +.aac 00;36 +.au 00;36 +.flac 00;36 +.mid 00;36 +.midi 00;36 +.mka 00;36 +.mp3 00;36 +.mpc 00;36 +.ogg 00;36 +.ra 00;36 +.wav 00;36 + +# http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions +.axa 00;36 +.oga 00;36 +.spx 00;36 +.xspf 00;36 + +# colorize basic documents (brown) +.pdf 00;33 +.ps 00;33 +.ps.gz 00;33 +.txt 00;33 +.patch 00;33 +.diff 00;33 +.log 00;33 +.tex 00;33 +.xls 00;33 +.xlsx 00;33 +.ppt 00;33 +.pptx 00;33 +.rtf 00;33 +.doc 00;33 +.docx 00;33 +.odt 00;33 +.ods 00;33 +.odp 00;33 +.xml 00;33 +.epub 00;33 +.abw 00;33 +.htm 00;33 +.html 00;33 +.shtml 00;33 +.wpd 00;33 diff --git a/coreutils-colorls.csh b/coreutils-colorls.csh index 66ec2fa..e244afb 100755 --- a/coreutils-colorls.csh +++ b/coreutils-colorls.csh @@ -1,6 +1,3 @@ -# skip everything for non-interactive shells -if (! $?prompt) exit - # color-ls initialization if ( $?USER_LS_COLORS ) then if ( "$USER_LS_COLORS" != "" ) then @@ -13,11 +10,15 @@ endif alias ll 'ls -l' alias l. 'ls -d .*' set COLORS=/etc/DIR_COLORS - if ($?TERM) then if ( -e "/etc/DIR_COLORS.$TERM" ) then set COLORS="/etc/DIR_COLORS.$TERM" endif + if ( -e "/etc/DIR_COLORS.256color" ) then + if ( "`tput colors`" == "256" ) then + set COLORS=/etc/DIR_COLORS.256color + endif + endif endif if ( -f ~/.dircolors ) set COLORS=~/.dircolors if ( -f ~/.dir_colors ) set COLORS=~/.dir_colors @@ -25,37 +26,18 @@ if ($?TERM) then if ( -f ~/.dircolors."$TERM" ) set COLORS=~/.dircolors."$TERM" if ( -f ~/.dir_colors."$TERM" ) set COLORS=~/.dir_colors."$TERM" endif -set INCLUDE="`/usr/bin/cat "$COLORS" | /usr/bin/grep '^INCLUDE' | /usr/bin/cut -d ' ' -f2-`" if ( ! -e "$COLORS" ) exit -set _tmp="`/usr/bin/mktemp .colorlsXXX -q --tmpdir=/tmp`" -#if mktemp fails, exit when include was active, otherwise use $COLORS file -if ( "$_tmp" == '' ) then - if ( "$INCLUDE" == '' ) then - eval "`/usr/bin/dircolors -c $COLORS`" - endif - goto cleanup -endif - -if ( "$INCLUDE" != '' ) /usr/bin/cat "$INCLUDE" >> $_tmp -/usr/bin/grep -v '^INCLUDE' "$COLORS" >> $_tmp - -eval "`/usr/bin/dircolors -c $_tmp`" - -/usr/bin/rm -f $_tmp +eval "`dircolors -c $COLORS`" if ( "$LS_COLORS" == '' ) exit -cleanup: -set color_none=`/usr/bin/sed -n '/^COLOR.*none/Ip' < $COLORS` +set color_none=`sed -n '/^COLOR.*none/Ip' < $COLORS` if ( "$color_none" != '' ) then unset color_none exit endif unset color_none -unset _tmp -unset INCLUDE -unset COLORS finish: alias ll 'ls -l --color=auto' diff --git a/coreutils-colorls.sh b/coreutils-colorls.sh index 5162f1e..dc5c223 100755 --- a/coreutils-colorls.sh +++ b/coreutils-colorls.sh @@ -1,53 +1,40 @@ # color-ls initialization -# Skip all for noninteractive shells. -[ ! -t 0 ] && return - #when USER_LS_COLORS defined do not override user LS_COLORS, but use them. if [ -z "$USER_LS_COLORS" ]; then alias ll='ls -l' 2>/dev/null alias l.='ls -d .*' 2>/dev/null - INCLUDE= + + # Skip the rest for noninteractive shells. + [ -z "$PS1" ] && return + COLORS= for colors in "$HOME/.dir_colors.$TERM" "$HOME/.dircolors.$TERM" \ "$HOME/.dir_colors" "$HOME/.dircolors"; do - [ -e "$colors" ] && COLORS="$colors" && \ - INCLUDE="`/usr/bin/cat "$COLORS" | /usr/bin/grep '^INCLUDE' | /usr/bin/cut -d ' ' -f2-`" && \ - break + [ -e "$colors" ] && COLORS="$colors" && break done - [ -z "$COLORS" ] && [ -e "/etc/DIR_COLORS.$TERM" ] && \ - COLORS="/etc/DIR_COLORS.$TERM" + [ -z "$COLORS" ] && [ -e "/etc/DIR_COLORS.256color" ] && \ + [ "x`tty -s && tput colors 2>/dev/null`" = "x256" ] && \ + COLORS="/etc/DIR_COLORS.256color" - [ -z "$COLORS" ] && [ -e "/etc/DIR_COLORS" ] && \ - COLORS="/etc/DIR_COLORS" + if [ -z "$COLORS" ]; then + for colors in "/etc/DIR_COLORS.$TERM" "/etc/DIR_COLORS" ; do + [ -e "$colors" ] && COLORS="$colors" && break + done + fi # Existence of $COLORS already checked above. [ -n "$COLORS" ] || return - if [ -e "$INCLUDE" ]; - then - TMP="`/usr/bin/mktemp .colorlsXXX -q --tmpdir=/tmp`" - [ -z "$TMP" ] && return - - /usr/bin/cat "$INCLUDE" >> $TMP - /usr/bin/grep -v '^INCLUDE' "$COLORS" >> $TMP - - eval "`/usr/bin/dircolors --sh $TMP 2>/dev/null`" - /usr/bin/rm -f $TMP - else - eval "`/usr/bin/dircolors --sh $COLORS 2>/dev/null`" - fi - + eval "`dircolors --sh "$COLORS" 2>/dev/null`" [ -z "$LS_COLORS" ] && return - /usr/bin/grep -qi "^COLOR.*none" $COLORS >/dev/null 2>/dev/null && return + grep -qi "^COLOR.*none" $COLORS >/dev/null 2>/dev/null && return fi -unset TMP COLORS INCLUDE - alias ll='ls -l --color=auto' 2>/dev/null alias l.='ls -d .* --color=auto' 2>/dev/null alias ls='ls --color=auto' 2>/dev/null diff --git a/coreutils-cpZ-deprecate.patch b/coreutils-cpZ-deprecate.patch new file mode 100644 index 0000000..713b7c5 --- /dev/null +++ b/coreutils-cpZ-deprecate.patch @@ -0,0 +1,23 @@ +diff -urNp coreutils-8.12-orig/src/copy.c coreutils-8.12/src/copy.c +--- coreutils-8.12-orig/src/copy.c 2011-08-11 16:05:15.432485738 +0200 ++++ coreutils-8.12/src/copy.c 2011-08-11 16:14:28.660360607 +0200 +@@ -850,7 +850,7 @@ copy_reg (char const *src_name, char con + 1) the src context may prohibit writing, and + 2) because it's more consistent to use the same context + that is used when the destination file doesn't already exist. */ +- if (x->preserve_security_context && 0 <= dest_desc) ++ if ((x->set_security_context || x->preserve_security_context) && 0 <= dest_desc) + { + bool all_errors = (!x->data_copy_required + || x->require_preserve_context); +diff -urNp coreutils-8.12-orig/src/cp.c coreutils-8.12/src/cp.c +--- coreutils-8.12-orig/src/cp.c 2011-08-11 16:05:15.435486976 +0200 ++++ coreutils-8.12/src/cp.c 2011-08-11 16:16:56.408644526 +0200 +@@ -1119,6 +1119,7 @@ main (int argc, char **argv) + exit( 1 ); + } + x.set_security_context = true; ++ (void) fprintf(stderr, _("Warning, -Z/--context option is deprecated and will be removed soon!\nPlease use 'install' utility instead of cp for this functionality.\n")); + /* if there's a security_context given set new path + components to that context, too */ + if ( setfscreatecon(optarg) < 0 ) { diff --git a/coreutils-df-direct.patch b/coreutils-df-direct.patch index 341ee2c..1bc8c40 100644 --- a/coreutils-df-direct.patch +++ b/coreutils-df-direct.patch @@ -1,77 +1,64 @@ -From 91be1a584108a6a3d96f64382bbf206c4213b3db Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Mon, 29 Mar 2010 17:20:34 +0000 -Subject: [PATCH] coreutils-df-direct.patch - ---- - doc/coreutils.texi | 7 ++++++ - src/df.c | 34 ++++++++++++++++++++++++++-- - tests/df/direct.sh | 55 ++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 94 insertions(+), 2 deletions(-) - create mode 100755 tests/df/direct.sh - -diff --git a/doc/coreutils.texi b/doc/coreutils.texi -index b420606..0ccb368 100644 ---- a/doc/coreutils.texi -+++ b/doc/coreutils.texi -@@ -12597,6 +12597,13 @@ some systems (notably Solaris), doing this yields more up to date results, - but in general this option makes @command{df} much slower, especially when - there are many or very busy file systems. +diff -urNp coreutils-8.11-orig/doc/coreutils.texi coreutils-8.11/doc/coreutils.texi +--- coreutils-8.11-orig/doc/coreutils.texi 2011-04-12 12:07:43.000000000 +0200 ++++ coreutils-8.11/doc/coreutils.texi 2011-04-14 09:53:43.764309420 +0200 +@@ -10409,6 +10409,13 @@ pseudo-file-systems, such as automounter + Scale sizes by @var{size} before printing them (@pxref{Block size}). + For example, @option{-BG} prints sizes in units of 1,073,741,824 bytes. -+@item --direct ++@itemx --direct +@opindex --direct +@cindex direct statfs for a file +Do not resolve mount point and show statistics directly for a file. It can be +especially useful for NFS mount points if there is a boundary between two +storage policies behind the mount point. + - @item --total + @itemx --total @opindex --total - @cindex grand total of file system size, usage and available space -diff --git a/src/df.c b/src/df.c -index 75e638c..ef9f0a7 100644 ---- a/src/df.c -+++ b/src/df.c -@@ -121,6 +121,9 @@ static bool print_type; + @cindex grand total of disk size, usage and available space +diff -urNp coreutils-8.11-orig/src/df.c coreutils-8.11/src/df.c +--- coreutils-8.11-orig/src/df.c 2011-04-12 12:07:43.000000000 +0200 ++++ coreutils-8.11/src/df.c 2011-04-14 10:37:44.208308771 +0200 +@@ -112,6 +112,9 @@ static bool print_type; /* If true, print a grand total at the end. */ static bool print_grand_total; +/* If true, show statistics for a file instead of mount point. */ +static bool direct_statfs; + - /* Grand total data. */ + /* Grand total data. */ static struct fs_usage grand_fsu; -@@ -248,13 +251,15 @@ enum +@@ -166,13 +169,15 @@ static size_t nrows; + enum + { NO_SYNC_OPTION = CHAR_MAX + 1, - SYNC_OPTION, - TOTAL_OPTION, -- OUTPUT_OPTION -+ OUTPUT_OPTION, +- SYNC_OPTION ++ SYNC_OPTION, + DIRECT_OPTION }; static struct option const long_options[] = { - {"all", no_argument, nullptr, 'a'}, - {"block-size", required_argument, nullptr, 'B'}, -+ {"direct", no_argument, nullptr, DIRECT_OPTION}, - {"inodes", no_argument, nullptr, 'i'}, - {"human-readable", no_argument, nullptr, 'h'}, - {"si", no_argument, nullptr, 'H'}, -@@ -571,7 +576,10 @@ get_header (void) - for (idx_t col = 0; col < ncolumns; col++) - { - char *cell; -- char const *header = _(columns[col]->caption); -+ char const *header = (columns[col]->field == TARGET_FIELD -+ && direct_statfs)? -+ _("File") : -+ _(columns[col]->caption); + {"all", no_argument, NULL, 'a'}, + {"block-size", required_argument, NULL, 'B'}, ++ {"direct", no_argument, NULL, DIRECT_OPTION}, + {"inodes", no_argument, NULL, 'i'}, + {"human-readable", no_argument, NULL, 'h'}, + {"si", no_argument, NULL, 'H'}, +@@ -259,7 +264,11 @@ get_header (void) + } - if (columns[col]->field == SIZE_FIELD - && (header_mode == DEFAULT_MODE -@@ -1446,6 +1454,17 @@ get_point (char const *point, const struct stat *statp) + char *cell = NULL; +- char const *header = _(headers[field][header_mode]); ++ ++ char const *header = (field == MNT_FIELD && direct_statfs)? ++ _("File") : ++ _(headers[field][header_mode]); ++ + if (!header) + header = _(headers[field][DEFAULT_MODE]); + +@@ -757,6 +766,17 @@ get_point (const char *point, const stru static void get_entry (char const *name, struct stat const *statp) { @@ -79,25 +66,25 @@ index 75e638c..ef9f0a7 100644 + { + char *resolved = canonicalize_file_name (name); + if (resolved) -+ { -+ get_dev (NULL, resolved, name, NULL, NULL, false, false, NULL, false); -+ free (resolved); -+ return; -+ } ++ { ++ get_dev (NULL, resolved, NULL, NULL, false, false, NULL, false); ++ free (resolved); ++ return; ++ } + } + if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode)) - && get_device (name)) + && get_disk (name)) return; -@@ -1516,6 +1535,7 @@ or all file systems by default.\n\ - -B, --block-size=SIZE scale sizes by SIZE before printing them; e.g.,\n\ - '-BM' prints sizes in units of 1,048,576 bytes;\n\ - see SIZE format below\n\ +@@ -825,6 +845,7 @@ Mandatory arguments to long options are + -B, --block-size=SIZE scale sizes by SIZE before printing them. E.g.,\n\ + `-BM' prints sizes in units of 1,048,576 bytes.\n\ + See SIZE format below.\n\ + --direct show statistics for a file instead of mount point\n\ - -h, --human-readable print sizes in powers of 1024 (e.g., 1023M)\n\ - -H, --si print sizes in powers of 1000 (e.g., 1.1G)\n\ - "), stdout); -@@ -1610,6 +1630,9 @@ main (int argc, char **argv) + --total produce a grand total\n\ + -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\ + \n\ +@@ -901,6 +922,9 @@ main (int argc, char **argv) xstrtol_fatal (e, oi, c, long_options, optarg); } break; @@ -105,27 +92,25 @@ index 75e638c..ef9f0a7 100644 + direct_statfs = true; + break; case 'i': - if (header_mode == OUTPUT_MODE) - { -@@ -1706,6 +1729,13 @@ main (int argc, char **argv) + inode_format = true; + break; +@@ -961,6 +985,13 @@ main (int argc, char **argv) } } + if (direct_statfs && show_local_fs) + { + error (0, 0, _("options --direct and --local (-l) are mutually " -+ "exclusive")); ++ "exclusive")); + usage (EXIT_FAILURE); + } + if (human_output_opts == -1) { if (posix_format) -diff --git a/tests/df/direct.sh b/tests/df/direct.sh -new file mode 100755 -index 0000000..8e4cfb8 ---- /dev/null -+++ b/tests/df/direct.sh +diff -urNp coreutils-8.11-orig/tests/df/direct coreutils-8.11/tests/df/direct +--- coreutils-8.11-orig/tests/df/direct 1970-01-01 01:00:00.000000000 +0100 ++++ coreutils-8.11/tests/df/direct 2011-04-14 09:53:43.767400034 +0200 @@ -0,0 +1,55 @@ +#!/bin/sh +# Ensure "df --direct" works as documented @@ -182,6 +167,14 @@ index 0000000..8e4cfb8 +compare file_out file_exp || fail=1 + +Exit $fail --- -2.52.0 - +diff -urNp coreutils-8.11-orig/tests/Makefile.am coreutils-8.11/tests/Makefile.am +--- coreutils-8.11-orig/tests/Makefile.am 2011-04-14 09:53:13.666324768 +0200 ++++ coreutils-8.11/tests/Makefile.am 2011-04-14 09:53:43.768432620 +0200 +@@ -362,6 +362,7 @@ TESTS = \ + dd/stderr \ + dd/unblock \ + dd/unblock-sync \ ++ df/direct \ + df/total-verify \ + du/2g \ + du/8gb \ diff --git a/coreutils-getgrouplist.patch b/coreutils-getgrouplist.patch new file mode 100644 index 0000000..86bbcef --- /dev/null +++ b/coreutils-getgrouplist.patch @@ -0,0 +1,86 @@ +diff --git a/lib/getugroups.c b/lib/getugroups.c +index 299bae6..8ece29b 100644 +--- a/lib/getugroups.c ++++ b/lib/getugroups.c +@@ -19,6 +19,9 @@ + + #include + ++/* We do not need this code if getgrouplist(3) is available. */ ++#ifndef HAVE_GETGROUPLIST ++ + #include "getugroups.h" + + #include +@@ -123,3 +126,4 @@ getugroups (int maxcount, gid_t *grouplist, char const *username, + } + + #endif /* HAVE_GRP_H */ ++#endif /* have getgrouplist */ +diff --git a/lib/mgetgroups.c b/lib/mgetgroups.c +index 76474c2..0a9d221 100644 +--- a/lib/mgetgroups.c ++++ b/lib/mgetgroups.c +@@ -115,9 +115,17 @@ mgetgroups (char const *username, gid_t gid, gid_t **groups) + /* else no username, so fall through and use getgroups. */ + #endif + +- max_n_groups = (username +- ? getugroups (0, NULL, username, gid) +- : getgroups (0, NULL)); ++ if (!username) ++ max_n_groups = getgroups(0, NULL); ++ else ++ { ++#ifdef HAVE_GETGROUPLIST ++ max_n_groups = 0; ++ getgrouplist (username, gid, NULL, &max_n_groups); ++#else ++ max_n_groups = getugroups (0, NULL, username, gid); ++#endif ++ } + + /* If we failed to count groups because there is no supplemental + group support, then return an array containing just GID. +@@ -139,10 +147,25 @@ mgetgroups (char const *username, gid_t gid, gid_t **groups) + if (g == NULL) + return -1; + +- ng = (username +- ? getugroups (max_n_groups, g, username, gid) +- : getgroups (max_n_groups - (gid != (gid_t) -1), +- g + (gid != (gid_t) -1))); ++ if (!username) ++ ng = getgroups (max_n_groups - (gid != (gid_t)-1), g + (gid != (gid_t)-1)); ++ else ++ { ++#ifdef HAVE_GETGROUPLIST ++ int e; ++ ng = max_n_groups; ++ while ((e = getgrouplist (username, gid, g, &ng)) == -1 ++ && ng > max_n_groups) ++ { ++ max_n_groups = ng; ++ g = xrealloc (g, max_n_groups * sizeof (GETGROUPS_T)); ++ } ++ if (e == -1) ++ ng = -1; ++#else ++ ng = getugroups (max_n_groups, g, username, gid); ++#endif ++ } + + if (ng < 0) + { +diff --git a/m4/jm-macros.m4 b/m4/jm-macros.m4 +index 62777c7..5180243 100644 +--- a/m4/jm-macros.m4 ++++ b/m4/jm-macros.m4 +@@ -78,6 +78,7 @@ + fchown + fchmod + ftruncate ++ getgrouplist + iswspace + mkfifo + mbrlen diff --git a/coreutils-i18n.patch b/coreutils-i18n.patch index 83579e9..55f12e7 100644 --- a/coreutils-i18n.patch +++ b/coreutils-i18n.patch @@ -1,80 +1,9 @@ -From a81b096084524e9aeef5e8b81fc829eb9efec581 Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Wed, 30 Aug 2023 17:19:58 +0200 -Subject: [PATCH] coreutils-i18n.patch - ---- - bootstrap.conf | 2 + - configure.ac | 6 + - lib/linebuffer.h | 8 + - lib/mbfile.c | 20 + - lib/mbfile.h | 283 +++++++++++++ - m4/mbfile.m4 | 16 + - src/cut.c | 508 +++++++++++++++++++++-- - src/expand-common.c | 114 ++++++ - src/expand-common.h | 12 + - src/expand.c | 90 +++- - src/local.mk | 4 +- - src/pr.c | 443 ++++++++++++++++++-- - src/sort.c | 791 +++++++++++++++++++++++++++++++++--- - src/unexpand.c | 101 ++++- - tests/Coreutils.pm | 3 + - tests/expand/mb.sh | 183 +++++++++ - tests/i18n/sort.sh | 29 ++ - tests/local.mk | 4 + - tests/misc/expand.pl | 42 ++ - tests/misc/sort-mb-tests.sh | 45 ++ - tests/misc/unexpand.pl | 39 ++ - tests/pr/pr-tests.pl | 49 +++ - tests/sort/sort-merge.pl | 42 ++ - tests/sort/sort.pl | 40 +- - tests/unexpand/mb.sh | 172 ++++++++ - 25 files changed, 2879 insertions(+), 167 deletions(-) - create mode 100644 lib/mbfile.c - create mode 100644 lib/mbfile.h - create mode 100644 m4/mbfile.m4 - create mode 100644 tests/expand/mb.sh - create mode 100644 tests/i18n/sort.sh - create mode 100644 tests/misc/sort-mb-tests.sh - create mode 100644 tests/unexpand/mb.sh - -diff --git a/bootstrap.conf b/bootstrap.conf -index ec68ac8..ec2fbbe 100644 ---- a/bootstrap.conf -+++ b/bootstrap.conf -@@ -171,6 +171,8 @@ gnulib_modules=" - malloc-gnu - manywarnings - mbbuf -+ mbchar -+ mbfile - mbrlen - mbrtoc32 - mbrtowc -diff --git a/configure.ac b/configure.ac -index 5e99ef3..ac07577 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -465,6 +465,12 @@ fi - # I'm leaving it here for now. This whole thing needs to be modernized... - gl_WINSIZE_IN_PTEM - -+gl_MBFILE -+dnl Do not use gl_MODULE_INDICATOR([mbfile]) here: we don't want 'struct mbchar' -+dnl to have a different size in lib/ than in tests/. -+AC_DEFINE([GNULIB_MBFILE], [1], -+ [Define to 1 if the gnulib module 'mbfile' is in use.]) -+ - gl_HEADER_TIOCGWINSZ_IN_TERMIOS_H - - if test $gl_cv_sys_tiocgwinsz_needs_termios_h = no && \ -diff --git a/lib/linebuffer.h b/lib/linebuffer.h -index ca56f80..509b7e6 100644 ---- a/lib/linebuffer.h -+++ b/lib/linebuffer.h -@@ -27,6 +27,11 @@ extern "C" { - #endif +diff -urNp coreutils-8.15-orig/lib/linebuffer.h coreutils-8.15/lib/linebuffer.h +--- coreutils-8.15-orig/lib/linebuffer.h 2012-01-06 10:14:31.000000000 +0100 ++++ coreutils-8.15/lib/linebuffer.h 2013-01-30 13:40:37.339145671 +0100 +@@ -21,6 +21,11 @@ + # include +/* Get mbstate_t. */ +# if HAVE_WCHAR_H @@ -84,9 +13,9 @@ index ca56f80..509b7e6 100644 /* A 'struct linebuffer' holds a line of text. */ struct linebuffer -@@ -34,6 +39,9 @@ struct linebuffer - idx_t size; /* Allocated. */ - idx_t length; /* Used. */ +@@ -28,6 +33,9 @@ struct linebuffer + size_t size; /* Allocated. */ + size_t length; /* Used. */ char *buffer; +# if HAVE_WCHAR_H + mbstate_t state; @@ -94,349 +23,11 @@ index ca56f80..509b7e6 100644 }; /* Initialize linebuffer LINEBUFFER for use. */ -diff --git a/lib/mbfile.c b/lib/mbfile.c -new file mode 100644 -index 0000000..f4e3e77 ---- /dev/null -+++ b/lib/mbfile.c -@@ -0,0 +1,20 @@ -+/* Multibyte character I/O: macros for multi-byte encodings. -+ Copyright (C) 2012-2025 Free Software Foundation, Inc. -+ -+ This file is free software: you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as -+ published by the Free Software Foundation, either version 3 of the -+ License, or (at your option) any later version. -+ -+ This file 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 Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this program. If not, see . */ -+ -+#include -+ -+#define MBFILE_INLINE _GL_EXTERN_INLINE -+#include "mbfile.h" -diff --git a/lib/mbfile.h b/lib/mbfile.h -new file mode 100644 -index 0000000..c852f31 ---- /dev/null -+++ b/lib/mbfile.h -@@ -0,0 +1,283 @@ -+/* Multibyte character I/O: macros for multi-byte encodings. -+ Copyright (C) 2001, 2005, 2009-2025 Free Software Foundation, Inc. -+ -+ This file is free software: you can redistribute it and/or modify -+ it under the terms of the GNU Lesser General Public License as -+ published by the Free Software Foundation, either version 3 of the -+ License, or (at your option) any later version. -+ -+ This file 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 Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public License -+ along with this program. If not, see . */ -+ -+/* Written by Mitsuru Chinen -+ and Bruno Haible . */ -+ -+/* The macros in this file implement multi-byte character input from a -+ stream. -+ -+ mb_file_t -+ is the type for multibyte character input stream, usable for variable -+ declarations. -+ -+ mbf_char_t -+ is the type for multibyte character or EOF, usable for variable -+ declarations. -+ -+ mbf_init (mbf, stream) -+ initializes the MB_FILE for reading from stream. -+ -+ mbf_getc (mbc, mbf) -+ reads the next multibyte character from mbf and stores it in mbc. -+ -+ mb_iseof (mbc) -+ returns true if mbc represents the EOF value. -+ -+ Here are the function prototypes of the macros. -+ -+ extern void mbf_init (mb_file_t mbf, FILE *stream); -+ extern void mbf_getc (mbf_char_t mbc, mb_file_t mbf); -+ extern bool mb_iseof (const mbf_char_t mbc); -+ */ -+ -+#ifndef _MBFILE_H -+#define _MBFILE_H 1 -+ -+/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE. */ -+#if !_GL_CONFIG_H_INCLUDED -+ #error "Please include config.h first." -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "mbchar.h" -+ -+_GL_INLINE_HEADER_BEGIN -+#ifndef MBFILE_INLINE -+# define MBFILE_INLINE _GL_INLINE -+#endif -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+ -+/* Guarantee two characters of pushback. */ -+#define MBFILE_MAX_PUSHBACK 2 -+ -+struct mbfile_multi { -+ FILE *fp; -+ bool eof_seen; -+ unsigned int pushback_count; /* <= MBFILE_MAX_PUSHBACK */ -+ mbstate_t state; -+ unsigned int bufcount; -+ char buf[MBCHAR_BUF_SIZE]; -+ struct mbchar pushback[MBFILE_MAX_PUSHBACK]; -+}; -+ -+MBFILE_INLINE void -+mbfile_multi_getc (struct mbchar *mbc, struct mbfile_multi *mbf) -+{ -+ unsigned int new_bufcount; -+ size_t bytes; -+ -+ /* Return character pushed back, if there is one. */ -+ if (mbf->pushback_count > 0) -+ { -+ mb_copy (mbc, &mbf->pushback[mbf->pushback_count - 1]); -+ mbf->pushback_count--; -+ return; -+ } -+ -+ /* If EOF has already been seen, don't use getc. This matters if -+ mbf->fp is connected to an interactive tty. */ -+ if (mbf->eof_seen) -+ goto eof; -+ -+ new_bufcount = mbf->bufcount; -+ -+ /* If mbf->state is not in an initial state, some more 32-bit wide character -+ may be hiding in the state. We need to call mbrtoc32 again. */ -+ #if GNULIB_MBRTOC32_REGULAR -+ assert (mbsinit (&mbf->state)); -+ #else -+ if (mbsinit (&mbf->state)) -+ #endif -+ { -+ /* Before using mbrtoc32, we need at least one byte. */ -+ if (new_bufcount == 0) -+ { -+ int c = getc (mbf->fp); -+ if (c == EOF) -+ { -+ mbf->eof_seen = true; -+ goto eof; -+ } -+ mbf->buf[0] = (unsigned char) c; -+ new_bufcount++; -+ } -+ -+ /* Handle most ASCII characters quickly, without calling mbrtoc32(). */ -+ if (new_bufcount == 1 && is_basic (mbf->buf[0])) -+ { -+ /* These characters are part of the POSIX portable character set. -+ For most of them, namely those in the ISO C basic character set, -+ ISO C 99 guarantees that their wide character code is identical to -+ their char code. For the few other ones, this is the case as well, -+ in all locale encodings that are in use. The 32-bit wide character -+ code is the same as well. */ -+ mbc->wc = mbc->buf[0] = mbf->buf[0]; -+ mbc->wc_valid = true; -+ mbc->ptr = &mbc->buf[0]; -+ mbc->bytes = 1; -+ mbf->bufcount = 0; -+ return; -+ } -+ } -+ -+ /* Use mbrtoc32 on an increasing number of bytes. Read only as many bytes -+ from mbf->fp as needed. This is needed to give reasonable interactive -+ behaviour when mbf->fp is connected to an interactive tty. */ -+ for (;;) -+ { -+ /* Feed the bytes one by one into mbrtoc32. */ -+ bytes = mbrtoc32 (&mbc->wc, &mbf->buf[mbf->bufcount], new_bufcount - mbf->bufcount, &mbf->state); -+ -+ if (bytes == (size_t) -1) -+ { -+ /* An invalid multibyte sequence was encountered. */ -+ mbf->bufcount = new_bufcount; -+ /* Return a single byte. */ -+ bytes = 1; -+ mbc->wc_valid = false; -+ /* Allow the next invocation to continue from a sane state. */ -+ mbszero (&mbf->state); -+ break; -+ } -+ else if (bytes == (size_t) -2) -+ { -+ /* An incomplete multibyte character. */ -+ mbf->bufcount = new_bufcount; -+ if (mbf->bufcount == MBCHAR_BUF_SIZE) -+ { -+ /* An overlong incomplete multibyte sequence was encountered. */ -+ /* Return a single byte. */ -+ bytes = 1; -+ mbc->wc_valid = false; -+ break; -+ } -+ else -+ { -+ /* Read one more byte and retry mbrtoc32. */ -+ int c = getc (mbf->fp); -+ if (c == EOF) -+ { -+ /* An incomplete multibyte character at the end. */ -+ mbf->eof_seen = true; -+ bytes = new_bufcount; -+ mbc->wc_valid = false; -+ break; -+ } -+ mbf->buf[new_bufcount] = (unsigned char) c; -+ new_bufcount++; -+ } -+ } -+ else -+ { -+ #if !GNULIB_MBRTOC32_REGULAR -+ if (bytes == (size_t) -3) -+ { -+ /* The previous multibyte sequence produced an additional 32-bit -+ wide character. */ -+ mbf->bufcount = new_bufcount; -+ bytes = 0; -+ } -+ else -+ #endif -+ { -+ bytes = mbf->bufcount + bytes; -+ mbf->bufcount = new_bufcount; -+ if (bytes == 0) -+ { -+ /* A null 32-bit wide character was encountered. */ -+ bytes = 1; -+ assert (mbf->buf[0] == '\0'); -+ assert (mbc->wc == 0); -+ } -+ } -+ mbc->wc_valid = true; -+ break; -+ } -+ } -+ -+ /* Return the multibyte sequence mbf->buf[0..bytes-1]. */ -+ mbc->ptr = &mbc->buf[0]; -+ memcpy (&mbc->buf[0], &mbf->buf[0], bytes); -+ mbc->bytes = bytes; -+ -+ mbf->bufcount -= bytes; -+ if (mbf->bufcount > 0) -+ { -+ /* It's not worth calling memmove() for so few bytes. */ -+ unsigned int count = mbf->bufcount; -+ char *p = &mbf->buf[0]; -+ -+ do -+ { -+ *p = *(p + bytes); -+ p++; -+ } -+ while (--count > 0); -+ } -+ return; -+ -+eof: -+ /* An mbchar_t with bytes == 0 is used to indicate EOF. */ -+ mbc->ptr = NULL; -+ mbc->bytes = 0; -+ mbc->wc_valid = false; -+ return; -+} -+ -+MBFILE_INLINE void -+mbfile_multi_ungetc (const struct mbchar *mbc, struct mbfile_multi *mbf) -+{ -+ if (mbf->pushback_count == MBFILE_MAX_PUSHBACK) -+ abort (); -+ mb_copy (&mbf->pushback[mbf->pushback_count], mbc); -+ mbf->pushback_count++; -+} -+ -+typedef struct mbfile_multi mb_file_t; -+ -+typedef mbchar_t mbf_char_t; -+ -+#define mbf_init(mbf, stream) \ -+ ((mbf).fp = (stream), \ -+ (mbf).eof_seen = false, \ -+ (mbf).pushback_count = 0, \ -+ mbszero (&(mbf).state), \ -+ (mbf).bufcount = 0) -+ -+#define mbf_getc(mbc, mbf) mbfile_multi_getc (&(mbc), &(mbf)) -+ -+#define mbf_ungetc(mbc, mbf) mbfile_multi_ungetc (&(mbc), &(mbf)) -+ -+#define mb_iseof(mbc) ((mbc).bytes == 0) -+ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+_GL_INLINE_HEADER_END -+ -+#endif /* _MBFILE_H */ -diff --git a/m4/mbfile.m4 b/m4/mbfile.m4 -new file mode 100644 -index 0000000..1d126e0 ---- /dev/null -+++ b/m4/mbfile.m4 -@@ -0,0 +1,16 @@ -+# mbfile.m4 -+# serial 7 -+dnl Copyright (C) 2005, 2008-2025 Free Software Foundation, Inc. -+dnl This file is free software; the Free Software Foundation -+dnl gives unlimited permission to copy and/or distribute it, -+dnl with or without modifications, as long as this notice is preserved. -+dnl This file is offered as-is, without any warranty. -+ -+dnl autoconf tests required for use of mbfile.h -+dnl From Bruno Haible. -+ -+AC_DEFUN([gl_MBFILE], -+[ -+ AC_REQUIRE([AC_TYPE_MBSTATE_T]) -+ : -+]) -diff --git a/src/cut.c b/src/cut.c -index f0effb9..36479d6 100644 ---- a/src/cut.c -+++ b/src/cut.c -@@ -27,6 +27,11 @@ - #include +diff -urNp coreutils-8.15-orig/src/cut.c coreutils-8.15/src/cut.c +--- coreutils-8.15-orig/src/cut.c 2012-01-01 10:04:06.000000000 +0100 ++++ coreutils-8.15/src/cut.c 2013-01-30 13:40:37.341145459 +0100 +@@ -28,6 +28,11 @@ + #include #include #include + @@ -446,10 +37,10 @@ index f0effb9..36479d6 100644 +#endif #include "system.h" - #include "assure.h" -@@ -35,6 +40,18 @@ - - #include "set-fields.h" + #include "error.h" +@@ -37,6 +42,18 @@ + #include "quote.h" + #include "xstrndup.h" +/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC + installation; work around this configuration error. */ @@ -463,11 +54,11 @@ index f0effb9..36479d6 100644 +# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) +#endif + - /* The official name of this program (e.g., no 'g' prefix). */ + /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "cut" -@@ -51,6 +68,52 @@ - } \ +@@ -72,6 +89,52 @@ + } \ while (0) +/* Refill the buffer BUF to get a multibyte character. */ @@ -484,7 +75,7 @@ index f0effb9..36479d6 100644 + while (0) + +/* Get wide character on BUFPOS. BUFPOS is not included after that. -+ If byte sequence is not valid as a character, CONVFAIL is true. Otherwise false. */ ++ If byte sequence is not valid as a character, CONVFAIL is 1. Otherwise 0. */ +#define GET_NEXT_WC_FROM_BUFFER(WC, BUFPOS, BUFLEN, MBLENGTH, STATE, CONVFAIL) \ + do \ + { \ @@ -497,7 +88,7 @@ index f0effb9..36479d6 100644 + } \ + \ + /* Get a wide character. */ \ -+ CONVFAIL = false; \ ++ CONVFAIL = 0; \ + state_bak = STATE; \ + MBLENGTH = mbrtowc ((wchar_t *)&WC, BUFPOS, BUFLEN, &STATE); \ + \ @@ -505,7 +96,7 @@ index f0effb9..36479d6 100644 + { \ + case (size_t)-1: \ + case (size_t)-2: \ -+ CONVFAIL = true; \ ++ CONVFAIL++; \ + STATE = state_bak; \ + /* Fall througn. */ \ + \ @@ -516,39 +107,49 @@ index f0effb9..36479d6 100644 + } \ + while (0) + - - /* Pointer inside RP. When checking if a byte or field is selected - by a finite range, we check if it is between CURRENT_RP.LO -@@ -58,6 +121,9 @@ - CURRENT_RP.HI then we make CURRENT_RP to point to the next range pair. */ - static struct field_range_pair *current_rp; - -+/* Length of the delimiter given as argument to -d. */ -+size_t delimlen; -+ - /* This buffer is used to support the semantics of the -s option - (or lack of same) when the specified field list includes (does - not include) the first field. In both of those cases, the entire -@@ -70,6 +136,29 @@ static char *field_1_buffer; + struct range_pair + { + size_t lo; +@@ -90,7 +153,7 @@ static char *field_1_buffer; /* The number of bytes allocated for FIELD_1_BUFFER. */ static size_t field_1_bufsize; -+enum operating_mode -+ { -+ undefined_mode, -+ +-/* The largest field or byte index used as an endpoint of a closed ++/* The largest byte, character or field index used as an endpoint of a closed + or degenerate range specification; this doesn't include the starting + index of right-open-ended ranges. For example, with either range spec + `2-5,9-', `2-3,5,9-' this variable would be set to 5. */ +@@ -102,10 +165,11 @@ static size_t eol_range_start; + + /* This is a bit vector. + In byte mode, which bytes to output. ++ In character mode, which characters to output. + In field mode, which DELIM-separated fields to output. +- Both bytes and fields are numbered starting with 1, ++ Bytes, characters and fields are numbered starting with 1, + so the zeroth bit of this array is unused. +- A field or byte K has been selected if ++ A byte, character or field K has been selected if + (K <= MAX_RANGE_ENDPOINT and is_printable_field(K)) + || (EOL_RANGE_START > 0 && K >= EOL_RANGE_START). */ + static unsigned char *printable_field; +@@ -114,15 +178,25 @@ enum operating_mode + { + undefined_mode, + +- /* Output characters that are in the given bytes. */ + /* Output bytes that are at the given positions. */ -+ byte_mode, -+ + byte_mode, + + /* Output characters that are at the given positions. */ + character_mode, + -+ /* Output the given delimiter-separated fields. */ -+ field_mode -+ }; -+ -+static enum operating_mode operating_mode; -+ + /* Output the given delimeter-separated fields. */ + field_mode + }; + + static enum operating_mode operating_mode; + +/* If nonzero, when in byte mode, don't split multibyte characters. */ +static int byte_mode_character_aware; + @@ -556,37 +157,20 @@ index f0effb9..36479d6 100644 + if this program runs on multibyte locale. */ +static int force_singlebyte_mode; + - /* If true, do not output lines containing no delimiter characters. + /* If true do not output lines containing no delimeter characters. Otherwise, all such lines are printed. This option is valid only with field mode. */ -@@ -81,10 +170,16 @@ static bool complement; +@@ -134,6 +208,9 @@ static bool complement; - /* The delimiter character for field mode. */ + /* The delimeter character for field mode. */ static unsigned char delim; +#if HAVE_WCHAR_H +static wchar_t wcdelim; +#endif - /* The delimiter for each line/record. */ - static unsigned char line_delim = '\n'; - -+/* True if the --output-delimiter=STRING option was specified. */ -+static bool output_delimiter_specified; -+ - /* The length of output_delimiter_string. */ - static size_t output_delimiter_length; - -@@ -92,9 +187,6 @@ static size_t output_delimiter_length; - string consisting of the input delimiter. */ - static char *output_delimiter_string; - --/* The output delimiter string contents, if the default. */ --static char output_delimiter_default[1]; -- - /* True if we have ever read standard input. */ - static bool have_read_stdin; - -@@ -148,7 +240,7 @@ Print selected parts of lines from each FILE to standard output.\n\ + /* True if the --output-delimiter=STRING option was specified. */ + static bool output_delimiter_specified; +@@ -207,7 +284,7 @@ Mandatory arguments to long options are -f, --fields=LIST select only these fields; also print any line\n\ that contains no delimiter character, unless\n\ the -s option is specified\n\ @@ -595,16 +179,54 @@ index f0effb9..36479d6 100644 "), stdout); fputs (_("\ --complement complement the set of selected bytes, characters\n\ -@@ -252,7 +344,7 @@ cut_bytes (FILE *stream) - next_item (&byte_idx); - if (print_kth (byte_idx)) - { -- if (output_delimiter_string != output_delimiter_default) -+ if (output_delimiter_specified) +@@ -366,7 +443,7 @@ set_fields (const char *fieldstr) + in_digits = false; + /* Starting a range. */ + if (dash_found) +- FATAL_ERROR (_("invalid byte or field list")); ++ FATAL_ERROR (_("invalid byte, character or field list")); + dash_found = true; + fieldstr++; + +@@ -390,14 +467,16 @@ set_fields (const char *fieldstr) + if (!rhs_specified) { - if (print_delimiter && is_range_start_index (byte_idx)) - { -@@ -271,6 +363,82 @@ cut_bytes (FILE *stream) + /* `n-'. From `initial' to end of line. */ +- eol_range_start = initial; ++ if (eol_range_start == 0 || ++ (eol_range_start != 0 && eol_range_start > initial)) ++ eol_range_start = initial; + field_found = true; + } + else + { + /* `m-n' or `-n' (1-n). */ + if (value < initial) +- FATAL_ERROR (_("invalid decreasing range")); ++ FATAL_ERROR (_("invalid byte, character or field list")); + + /* Is there already a range going to end of line? */ + if (eol_range_start != 0) +@@ -477,6 +556,9 @@ set_fields (const char *fieldstr) + if (operating_mode == byte_mode) + error (0, 0, + _("byte offset %s is too large"), quote (bad_num)); ++ else if (operating_mode == character_mode) ++ error (0, 0, ++ _("character offset %s is too large"), quote (bad_num)); + else + error (0, 0, + _("field number %s is too large"), quote (bad_num)); +@@ -487,7 +569,7 @@ set_fields (const char *fieldstr) + fieldstr++; + } + else +- FATAL_ERROR (_("invalid byte or field list")); ++ FATAL_ERROR (_("invalid byte, character or field list")); + } + + max_range_endpoint = 0; +@@ -582,6 +664,77 @@ cut_bytes (FILE *stream) } } @@ -620,7 +242,7 @@ index f0effb9..36479d6 100644 +static void +cut_characters_or_cut_bytes_no_split (FILE *stream) +{ -+ uintmax_t idx; /* number of bytes or characters in the line so far. */ ++ int idx; /* number of bytes or characters in the line so far. */ + char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */ + char *bufpos; /* Next read position of BUF. */ + size_t buflen; /* The length of the byte sequence in buf. */ @@ -628,7 +250,7 @@ index f0effb9..36479d6 100644 + size_t mblength; /* The byte size of a multibyte character which shows + as same character as WC. */ + mbstate_t state; /* State of the stream. */ -+ bool convfail = false; /* true, when conversion failed. Otherwise false. */ ++ int convfail = 0; /* 1, when conversion is failed. Otherwise 0. */ + /* Whether to begin printing delimiters between ranges for the current line. + Set after we've begun printing data corresponding to the first range. */ + bool print_delimiter = false; @@ -638,42 +260,37 @@ index f0effb9..36479d6 100644 + bufpos = buf; + memset (&state, '\0', sizeof(mbstate_t)); + -+ current_rp = frp; -+ + while (1) + { + REFILL_BUFFER (buf, bufpos, buflen, stream); + + GET_NEXT_WC_FROM_BUFFER (wc, bufpos, buflen, mblength, state, convfail); -+ (void) convfail; /* ignore unused */ + + if (wc == WEOF) + { + if (idx > 0) -+ putchar (line_delim); ++ putchar ('\n'); + break; + } -+ else if (wc == line_delim) ++ else if (wc == L'\n') + { -+ putchar (line_delim); ++ putchar ('\n'); + idx = 0; + print_delimiter = false; -+ current_rp = frp; + } + else + { -+ next_item (&idx); -+ if (print_kth (idx)) ++ bool range_start; ++ bool *rs = output_delimiter_specified ? &range_start : NULL; ++ idx += (operating_mode == byte_mode) ? mblength : 1; ++ if (print_kth (idx, rs)) + { -+ if (output_delimiter_specified) ++ if (rs && *rs && print_delimiter) + { -+ if (print_delimiter && is_range_start_index (idx)) -+ { -+ fwrite (output_delimiter_string, sizeof (char), -+ output_delimiter_length, stdout); -+ } -+ print_delimiter = true; -+ } ++ fwrite (output_delimiter_string, sizeof (char), ++ output_delimiter_length, stdout); ++ } ++ print_delimiter = true; + fwrite (bufpos, mblength, sizeof(char), stdout); + } + } @@ -687,17 +304,16 @@ index f0effb9..36479d6 100644 /* Read from stream STREAM, printing to standard output any selected fields. */ static void -@@ -433,11 +601,218 @@ cut_fields (FILE *stream) +@@ -704,13 +857,195 @@ cut_fields (FILE *stream) } } --/* Process file FILE to standard output, using CUT_STREAM. +#if HAVE_MBRTOWC +static void +cut_fields_mb (FILE *stream) +{ + int c; -+ uintmax_t field_idx; ++ unsigned int field_idx; + int found_any_selected_field; + int buffer_first_field; + int empty_input; @@ -708,9 +324,7 @@ index f0effb9..36479d6 100644 + size_t mblength; /* The byte size of a multibyte character which shows + as same character as WC. */ + mbstate_t state; /* State of the stream. */ -+ bool convfail = false; /* true, when conversion failed. Otherwise false. */ -+ -+ current_rp = frp; ++ int convfail = 0; /* 1, when conversion is failed. Otherwise 0. */ + + found_any_selected_field = 0; + field_idx = 1; @@ -734,7 +348,7 @@ index f0effb9..36479d6 100644 + and the first field has been selected, or if non-delimited lines + must be suppressed and the first field has *not* been selected. + That is because a non-delimited line has exactly one field. */ -+ buffer_first_field = (suppress_non_delimited ^ !print_kth (1)); ++ buffer_first_field = (suppress_non_delimited ^ !print_kth (1, NULL)); + + while (1) + { @@ -758,11 +372,11 @@ index f0effb9..36479d6 100644 + buflen -= mblength; + bufpos += mblength; + -+ if (!convfail && (wc == line_delim || wc == wcdelim)) ++ if (!convfail && (wc == L'\n' || wc == wcdelim)) + break; + } + -+ if (len <= 0 && wc == WEOF) ++ if (len<=0 && wc == WEOF) + break; + + /* If the first field extends to the end of line (it is not @@ -778,24 +392,24 @@ index f0effb9..36479d6 100644 + { + fwrite (field_1_buffer, sizeof (char), len, stdout); + /* Make sure the output line is newline terminated. */ -+ if (convfail || (!convfail && wc != line_delim)) -+ putchar (line_delim); ++ if (convfail || (!convfail && wc != L'\n')) ++ putchar ('\n'); + } + continue; + } + -+ if (print_kth (1)) ++ if (print_kth (1, NULL)) + { + /* Print the field, but not the trailing delimiter. */ + fwrite (field_1_buffer, sizeof (char), len - 1, stdout); + found_any_selected_field = 1; + } -+ next_item (&field_idx); ++ ++field_idx; + } + + if (wc != WEOF) + { -+ if (print_kth (field_idx)) ++ if (print_kth (field_idx, NULL)) + { + if (found_any_selected_field) + { @@ -814,14 +428,14 @@ index f0effb9..36479d6 100644 + + if (wc == WEOF) + break; -+ else if (!convfail && (wc == wcdelim || wc == line_delim)) ++ else if (!convfail && (wc == wcdelim || wc == L'\n')) + { + buflen -= mblength; + bufpos += mblength; + break; + } + -+ if (print_kth (field_idx)) ++ if (print_kth (field_idx, NULL)) + fwrite (bufpos, mblength, sizeof(char), stdout); + + buflen -= mblength; @@ -829,29 +443,30 @@ index f0effb9..36479d6 100644 + } + } + -+ if ((!convfail || wc == line_delim) && buflen < 1) ++ if ((!convfail || wc == L'\n') && buflen < 1) + wc = WEOF; + + if (!convfail && wc == wcdelim) -+ next_item (&field_idx); -+ else if (wc == WEOF || (!convfail && wc == line_delim)) ++ ++field_idx; ++ else if (wc == WEOF || (!convfail && wc == L'\n')) + { + if (found_any_selected_field + || (!empty_input && !(suppress_non_delimited && field_idx == 1))) -+ putchar (line_delim); ++ putchar ('\n'); + if (wc == WEOF) + break; + field_idx = 1; -+ current_rp = frp; + found_any_selected_field = 0; + } + } +} +#endif + -+static void -+cut_stream (FILE *stream) -+{ + static void + cut_stream (FILE *stream) + { +- if (operating_mode == byte_mode) +- cut_bytes (stream); +#if HAVE_MBRTOWC + if (MB_CUR_MAX > 1 && !force_singlebyte_mode) + { @@ -869,19 +484,6 @@ index f0effb9..36479d6 100644 + break; + + case field_mode: -+ if (delimlen == 1) -+ { -+ /* Check if we have utf8 multibyte locale, so we can use this -+ optimization because of uniqueness of characters, which is -+ not true for e.g. SJIS */ -+ char * loc = setlocale(LC_CTYPE, NULL); -+ if (loc && (strstr (loc, "UTF-8") || strstr (loc, "utf-8") || -+ strstr (loc, "UTF8") || strstr (loc, "utf8"))) -+ { -+ cut_fields (stream); -+ break; -+ } -+ } + cut_fields_mb (stream); + break; + @@ -889,7 +491,8 @@ index f0effb9..36479d6 100644 + abort (); + } + } -+ else + else +- cut_fields (stream); +#endif + { + if (operating_mode == field_mode) @@ -897,53 +500,32 @@ index f0effb9..36479d6 100644 + else + cut_bytes (stream); + } -+} -+ -+/* Process file FILE to standard output. - Return true if successful. */ + } - static bool --cut_file (char const *file, void (*cut_stream) (FILE *)) -+cut_file (char const *file) - { - FILE *stream; - -@@ -482,8 +857,8 @@ main (int argc, char **argv) - int optc; + /* Process file FILE to standard output. +@@ -762,6 +1097,8 @@ main (int argc, char **argv) bool ok; bool delim_specified = false; -- bool byte_mode = false; -- char *spec_list_string = nullptr; -+ char *spec_list_string IF_LINT ( = nullptr); + char *spec_list_string IF_LINT ( = NULL); + char mbdelim[MB_LEN_MAX + 1]; ++ size_t delimlen = 0; initialize_main (&argc, &argv); set_program_name (argv[0]); -@@ -493,6 +868,8 @@ main (int argc, char **argv) - - atexit (close_stdout); - -+ operating_mode = undefined_mode; -+ - /* By default, all non-delimited lines are printed. */ - suppress_non_delimited = false; - -@@ -505,35 +882,77 @@ main (int argc, char **argv) +@@ -784,7 +1121,6 @@ main (int argc, char **argv) switch (optc) { case 'b': - case 'c': - /* Build the byte list. */ -- byte_mode = true; -- FALLTHROUGH; -+ if (operating_mode != undefined_mode) -+ FATAL_ERROR (_("only one type of list may be specified")); -+ operating_mode = byte_mode; -+ spec_list_string = optarg; -+ break; -+ + /* Build the byte list. */ + if (operating_mode != undefined_mode) + FATAL_ERROR (_("only one type of list may be specified")); +@@ -792,6 +1128,14 @@ main (int argc, char **argv) + spec_list_string = optarg; + break; + + case 'c': -+ /* Build the character list. */ ++ /* Build the character list. */ + if (operating_mode != undefined_mode) + FATAL_ERROR (_("only one type of list may be specified")); + operating_mode = character_mode; @@ -951,18 +533,12 @@ index f0effb9..36479d6 100644 + break; + case 'f': - /* Build the field list. */ -- if (spec_list_string) -- FATAL_ERROR (_("only one list may be specified")); -+ if (operating_mode != undefined_mode) -+ FATAL_ERROR (_("only one type of list may be specified")); -+ operating_mode = field_mode; - spec_list_string = optarg; - break; - + /* Build the field list. */ + if (operating_mode != undefined_mode) +@@ -803,10 +1147,35 @@ main (int argc, char **argv) case 'd': - /* New delimiter. */ - /* Interpret -d '' to mean 'use the NUL byte as the delimiter.' */ + /* New delimiter. */ + /* Interpret -d '' to mean `use the NUL byte as the delimiter.' */ - if (optarg[0] != '\0' && optarg[1] != '\0') - FATAL_ERROR (_("the delimiter must be a single character")); - delim = optarg[0]; @@ -984,9 +560,6 @@ index f0effb9..36479d6 100644 + if (wcdelim != L'\0' && *(optarg + delimlen) != '\0') + FATAL_ERROR (_("the delimiter must be a single character")); + memcpy (mbdelim, optarg, delimlen); -+ mbdelim[delimlen] = '\0'; -+ if (delimlen == 1) -+ delim = *optarg; + } + } + @@ -1002,13 +575,7 @@ index f0effb9..36479d6 100644 break; case OUTPUT_DELIMITER_OPTION: -+ output_delimiter_specified = true; - /* Interpret --output-delimiter='' to mean - 'use the NUL byte as the delimiter.' */ - output_delimiter_length = (optarg[0] == '\0' - ? 1 : strlen (optarg)); -- output_delimiter_string = optarg; -+ output_delimiter_string = xstrdup (optarg); +@@ -819,6 +1188,7 @@ main (int argc, char **argv) break; case 'n': @@ -1016,34 +583,17 @@ index f0effb9..36479d6 100644 break; case 's': -@@ -555,40 +974,57 @@ main (int argc, char **argv) - } - } - -- if (!spec_list_string) -+ if (operating_mode == undefined_mode) +@@ -841,7 +1211,7 @@ main (int argc, char **argv) + if (operating_mode == undefined_mode) FATAL_ERROR (_("you must specify a list of bytes, characters, or fields")); -- if (byte_mode) -- { -- if (delim_specified) -- FATAL_ERROR (_("an input delimiter may be specified only\ +- if (delim != '\0' && operating_mode != field_mode) + if (delim_specified && operating_mode != field_mode) -+ FATAL_ERROR (_("an input delimiter may be specified only\ + FATAL_ERROR (_("an input delimiter may be specified only\ when operating on fields")); -- if (suppress_non_delimited) -- FATAL_ERROR (_("suppressing non-delimited lines makes sense\n\ -+ if (suppress_non_delimited && operating_mode != field_mode) -+ FATAL_ERROR (_("suppressing non-delimited lines makes sense\n\ - \tonly when operating on fields")); -- } - - set_fields (spec_list_string, -- ((byte_mode ? SETFLD_ERRMSG_USE_POS : 0) -- | (complement ? SETFLD_COMPLEMENT : 0))); -+ ( (operating_mode == field_mode) ? 0 : SETFLD_ERRMSG_USE_POS) -+ | (complement ? SETFLD_COMPLEMENT : 0) ); +@@ -868,15 +1238,34 @@ main (int argc, char **argv) + } if (!delim_specified) - delim = '\t'; @@ -1057,10 +607,12 @@ index f0effb9..36479d6 100644 +#endif + } - if (output_delimiter_string == nullptr) + if (output_delimiter_string == NULL) { -- output_delimiter_default[0] = delim; -- output_delimiter_string = output_delimiter_default; +- static char dummy[2]; +- dummy[0] = delim; +- dummy[1] = '\0'; +- output_delimiter_string = dummy; - output_delimiter_length = 1; +#ifdef HAVE_MBRTOWC + if (MB_CUR_MAX > 1 && !force_singlebyte_mode) @@ -1080,348 +632,1094 @@ index f0effb9..36479d6 100644 + } } -- void (*cut_stream) (FILE *) = byte_mode ? cut_bytes : cut_fields; if (optind == argc) -- ok = cut_file ("-", cut_stream); -+ ok = cut_file ("-"); - else - for (ok = true; optind < argc; optind++) -- ok &= cut_file (argv[optind], cut_stream); -+ ok &= cut_file (argv[optind]); - - - if (have_read_stdin && fclose (stdin) == EOF) -diff --git a/src/expand-common.c b/src/expand-common.c -index 14dd804..0d8eaaa 100644 ---- a/src/expand-common.c -+++ b/src/expand-common.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include "system.h" - #include "c-ctype.h" - #include "fadvise.h" -@@ -132,6 +133,119 @@ set_increment_size (colno tabval) - return ok; - } - -+extern int -+set_utf_locale (void) -+{ -+ /*try using some predefined locale */ -+ const char* predef_locales[] = {"C.UTF8","en_US.UTF8","en_GB.UTF8"}; -+ -+ const int predef_locales_count=3; -+ for (int i=0;ibufcount=0; -+ if (c == 0xEF) -+ { -+ c=fgetc(fp); -+ } -+ else -+ { -+ if (c != EOF) -+ { -+ ungetc(c,fp); -+ } -+ return false; -+ } -+ -+ if (c == 0xBB) -+ { -+ c=fgetc(fp); -+ } -+ else -+ { -+ if ( c!= EOF ) -+ { -+ mbf->buf[0]=(unsigned char) 0xEF; -+ mbf->bufcount=1; -+ ungetc(c,fp); -+ return false; -+ } -+ else -+ { -+ ungetc(0xEF,fp); -+ return false; -+ } -+ } -+ if (c == 0xBF) -+ { -+ mbf->bufcount=0; -+ return true; -+ } -+ else -+ { -+ if (c != EOF) -+ { -+ mbf->buf[0]=(unsigned char) 0xEF; -+ mbf->buf[1]=(unsigned char) 0xBB; -+ mbf->bufcount=2; -+ ungetc(c,fp); -+ return false; -+ } -+ else -+ { -+ mbf->buf[0]=(unsigned char) 0xEF; -+ mbf->bufcount=1; -+ ungetc(0xBB,fp); -+ return false; -+ } -+ } -+ return false; -+} -+ -+extern void -+print_bom(void) -+{ -+ putc (0xEF, stdout); -+ putc (0xBB, stdout); -+ putc (0xBF, stdout); -+} -+ - /* Add the comma or blank separated list of tab stops STOPS - to the list of tab stops. */ - extern void -diff --git a/src/expand-common.h b/src/expand-common.h -index 46ef4e3..e19469b 100644 ---- a/src/expand-common.h -+++ b/src/expand-common.h -@@ -29,6 +29,18 @@ extern idx_t max_column_width; - /* The desired exit status. */ - extern int exit_status; - -+extern int -+set_utf_locale (void); -+ -+extern bool -+check_utf_locale(void); -+ -+extern bool -+check_bom(FILE* fp, mb_file_t *mbf); -+ -+extern void -+print_bom(void); -+ - /* Add tab stop TABVAL to the end of 'tab_list'. */ - extern void - add_tab_stop (colno tabval); -diff --git a/src/expand.c b/src/expand.c -index 5ec7ce9..65ac315 100644 ---- a/src/expand.c -+++ b/src/expand.c -@@ -38,6 +38,9 @@ +diff -urNp coreutils-8.15-orig/src/expand.c coreutils-8.15/src/expand.c +--- coreutils-8.15-orig/src/expand.c 2012-01-01 10:04:06.000000000 +0100 ++++ coreutils-8.15/src/expand.c 2013-01-30 13:40:37.343145830 +0100 +@@ -38,12 +38,29 @@ #include #include #include + -+#include ++/* Get mbstate_t, mbrtowc(), wcwidth(). */ ++#if HAVE_WCHAR_H ++# include ++#endif + #include "system.h" - #include "expand-common.h" + #include "error.h" + #include "fadvise.h" + #include "quote.h" + #include "xstrndup.h" -@@ -96,19 +99,41 @@ expand (void) - { - /* Input stream. */ - FILE *fp = next_file (nullptr); -+ mb_file_t mbf; -+ mbf_char_t c; -+ /* True if the starting locale is utf8. */ -+ bool using_utf_locale; ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC ++ installation; work around this configuration error. */ ++#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 ++# define MB_LEN_MAX 16 ++#endif + -+ /* True if the first file contains BOM header. */ -+ bool found_bom; -+ using_utf_locale=check_utf_locale(); - - if (!fp) - return; -+ mbf_init (mbf, fp); -+ found_bom=check_bom(fp,&mbf); - -- while (true) -+ if (using_utf_locale == false && found_bom == true) -+ { -+ /*try using some predefined locale */ ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ ++#if HAVE_MBRTOWC && defined mbstate_t ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) ++#endif + -+ if (set_utf_locale () != 0) - { -- /* Input character, or EOF. */ -- int c; -+ error (EXIT_FAILURE, errno, _("cannot set UTF-8 locale")); -+ } -+ } -+ -+ -+ if (found_bom == true) -+ { -+ print_bom(); -+ } + /* The official name of this program (e.g., no `g' prefix). */ + #define PROGRAM_NAME "expand" -+ while (true) -+ { - /* If true, perform translations. */ - bool convert = true; - -- - /* The following variables have valid values only when CONVERT - is true: */ - -@@ -118,17 +143,48 @@ expand (void) - /* Index in TAB_LIST of next tab stop to examine. */ - idx_t tab_index = 0; - -- - /* Convert a line of text. */ - - do - { -- while ((c = getc (fp)) < 0 && (fp = next_file (fp))) -- continue; -+ while (true) { -+ mbf_getc (c, mbf); -+ if ((mb_iseof (c)) && (fp = next_file (fp))) -+ { -+ mbf_init (mbf, fp); -+ if (fp!=NULL) -+ { -+ if (check_bom(fp,&mbf)==true) -+ { -+ /*Not the first file - check BOM header*/ -+ if (using_utf_locale==false && found_bom==false) -+ { -+ /*BOM header in subsequent file but not in the first one. */ -+ error (EXIT_FAILURE, errno, _("combination of files with and without BOM header")); -+ } -+ } -+ else -+ { -+ if(using_utf_locale==false && found_bom==true) -+ { -+ /*First file conatined BOM header - locale was switched to UTF -+ *all subsequent files should contain BOM. */ -+ error (EXIT_FAILURE, errno, _("combination of files with and without BOM header")); -+ } -+ } -+ } -+ continue; -+ } -+ else -+ { -+ break; -+ } -+ } -+ - - if (convert) - { -- if (c == '\t') -+ if (mb_iseq (c, '\t')) - { - /* Column the next input tab stop is on. */ - bool last_tab; -@@ -139,31 +195,33 @@ expand (void) - if (putchar (' ') < 0) - write_error (); - -- c = ' '; -+ mb_setascii (&c, ' '); - } -- else if (c == '\b') -+ else if (mb_iseq (c, '\b')) - { - /* Go back one column, and force recalculation of the - next tab stop. */ - column -= !!column; - tab_index -= !!tab_index; - } -- else -+ /* A leading control character could make us trip over. */ -+ else if (!mb_iscntrl (c)) - { -- if (ckd_add (&column, column, 1)) -+ if (ckd_add (&column, column, mb_width (c))) - error (EXIT_FAILURE, 0, _("input line is too long")); - } - -- convert &= convert_entire_line || !! isblank (c); -+ convert &= convert_entire_line || !! mb_isblank (c); - } - -- if (c < 0) -+ if (mb_iseof (c)) - return; - -- if (putchar (c) < 0) -+ mb_putc (c, stdout); -+ if (ferror (stdout)) - write_error (); - } -- while (c != '\n'); -+ while (!mb_iseq (c, '\n')); +@@ -360,6 +377,142 @@ expand (void) } } -diff --git a/src/local.mk b/src/local.mk -index a8ad6b4..b0e61ec 100644 ---- a/src/local.mk -+++ b/src/local.mk -@@ -490,8 +490,8 @@ src_base32_CPPFLAGS = -DBASE_TYPE=32 $(AM_CPPFLAGS) - src_basenc_SOURCES = src/basenc.c - src_basenc_CPPFLAGS = -DBASE_TYPE=42 $(AM_CPPFLAGS) ++#if HAVE_MBRTOWC ++static void ++expand_multibyte (void) ++{ ++ FILE *fp; /* Input strem. */ ++ mbstate_t i_state; /* Current shift state of the input stream. */ ++ mbstate_t i_state_bak; /* Back up the I_STATE. */ ++ mbstate_t o_state; /* Current shift state of the output stream. */ ++ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */ ++ char *bufpos = buf; /* Next read position of BUF. */ ++ size_t buflen = 0; /* The length of the byte sequence in buf. */ ++ wchar_t wc; /* A gotten wide character. */ ++ size_t mblength; /* The byte size of a multibyte character ++ which shows as same character as WC. */ ++ int tab_index = 0; /* Index in `tab_list' of next tabstop. */ ++ int column = 0; /* Column on screen of the next char. */ ++ int next_tab_column; /* Column the next tab stop is on. */ ++ int convert = 1; /* If nonzero, perform translations. */ ++ ++ fp = next_file ((FILE *) NULL); ++ if (fp == NULL) ++ return; ++ ++ memset (&o_state, '\0', sizeof(mbstate_t)); ++ memset (&i_state, '\0', sizeof(mbstate_t)); ++ ++ for (;;) ++ { ++ /* Refill the buffer BUF. */ ++ if (buflen < MB_LEN_MAX && !feof(fp) && !ferror(fp)) ++ { ++ memmove (buf, bufpos, buflen); ++ buflen += fread (buf + buflen, sizeof(char), BUFSIZ, fp); ++ bufpos = buf; ++ } ++ ++ /* No character is left in BUF. */ ++ if (buflen < 1) ++ { ++ fp = next_file (fp); ++ ++ if (fp == NULL) ++ break; /* No more files. */ ++ else ++ { ++ memset (&i_state, '\0', sizeof(mbstate_t)); ++ continue; ++ } ++ } ++ ++ /* Get a wide character. */ ++ i_state_bak = i_state; ++ mblength = mbrtowc (&wc, bufpos, buflen, &i_state); ++ ++ switch (mblength) ++ { ++ case (size_t)-1: /* illegal byte sequence. */ ++ case (size_t)-2: ++ mblength = 1; ++ i_state = i_state_bak; ++ if (convert) ++ { ++ ++column; ++ if (convert_entire_line == 0 && !isblank(*bufpos)) ++ convert = 0; ++ } ++ putchar (*bufpos); ++ break; ++ ++ case 0: /* null. */ ++ mblength = 1; ++ if (convert && convert_entire_line == 0) ++ convert = 0; ++ putchar ('\0'); ++ break; ++ ++ default: ++ if (wc == L'\n') /* LF. */ ++ { ++ tab_index = 0; ++ column = 0; ++ convert = 1; ++ putchar ('\n'); ++ } ++ else if (wc == L'\t' && convert) /* Tab. */ ++ { ++ if (tab_size == 0) ++ { ++ /* Do not let tab_index == first_free_tab; ++ stop when it is 1 less. */ ++ while (tab_index < first_free_tab - 1 ++ && column >= tab_list[tab_index]) ++ tab_index++; ++ next_tab_column = tab_list[tab_index]; ++ if (tab_index < first_free_tab - 1) ++ tab_index++; ++ if (column >= next_tab_column) ++ next_tab_column = column + 1; ++ } ++ else ++ next_tab_column = column + tab_size - column % tab_size; ++ ++ while (column < next_tab_column) ++ { ++ putchar (' '); ++ ++column; ++ } ++ } ++ else /* Others. */ ++ { ++ if (convert) ++ { ++ if (wc == L'\b') ++ { ++ if (column > 0) ++ --column; ++ } ++ else ++ { ++ int width; /* The width of WC. */ ++ ++ width = wcwidth (wc); ++ column += (width > 0) ? width : 0; ++ if (convert_entire_line == 0 && !iswblank(wc)) ++ convert = 0; ++ } ++ } ++ fwrite (bufpos, sizeof(char), mblength, stdout); ++ } ++ } ++ buflen -= mblength; ++ bufpos += mblength; ++ } ++} ++#endif ++ + int + main (int argc, char **argv) + { +@@ -424,7 +577,12 @@ main (int argc, char **argv) --src_expand_SOURCES = src/expand.c src/expand-common.c --src_unexpand_SOURCES = src/unexpand.c src/expand-common.c -+src_expand_SOURCES = src/expand.c src/expand-common.c lib/mbfile.c lib/mbchar.c -+src_unexpand_SOURCES = src/unexpand.c src/expand-common.c lib/mbfile.c lib/mbchar.c + file_list = (optind < argc ? &argv[optind] : stdin_argv); + +- expand (); ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ expand_multibyte (); ++ else ++#endif ++ expand (); + + if (have_read_stdin && fclose (stdin) != 0) + error (EXIT_FAILURE, errno, "-"); +diff -urNp coreutils-8.15-orig/src/fold.c coreutils-8.15/src/fold.c +--- coreutils-8.15-orig/src/fold.c 2012-01-01 10:04:06.000000000 +0100 ++++ coreutils-8.15/src/fold.c 2013-01-30 13:40:37.344145705 +0100 +@@ -22,12 +22,34 @@ + #include + #include + ++/* Get mbstate_t, mbrtowc(), wcwidth(). */ ++#if HAVE_WCHAR_H ++# include ++#endif ++ ++/* Get iswprint(), iswblank(), wcwidth(). */ ++#if HAVE_WCTYPE_H ++# include ++#endif ++ + #include "system.h" + #include "error.h" + #include "fadvise.h" + #include "quote.h" + #include "xstrtol.h" + ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC ++ installation; work around this configuration error. */ ++#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 ++# undef MB_LEN_MAX ++# define MB_LEN_MAX 16 ++#endif ++ ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ ++#if HAVE_MBRTOWC && defined mbstate_t ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) ++#endif ++ + #define TAB_WIDTH 8 + + /* The official name of this program (e.g., no `g' prefix). */ +@@ -35,20 +57,41 @@ + + #define AUTHORS proper_name ("David MacKenzie") + ++#define FATAL_ERROR(Message) \ ++ do \ ++ { \ ++ error (0, 0, (Message)); \ ++ usage (2); \ ++ } \ ++ while (0) ++ ++enum operating_mode ++{ ++ /* Fold texts by columns that are at the given positions. */ ++ column_mode, ++ ++ /* Fold texts by bytes that are at the given positions. */ ++ byte_mode, ++ ++ /* Fold texts by characters that are at the given positions. */ ++ character_mode, ++}; ++ ++/* The argument shows current mode. (Default: column_mode) */ ++static enum operating_mode operating_mode; ++ + /* If nonzero, try to break on whitespace. */ + static bool break_spaces; + +-/* If nonzero, count bytes, not column positions. */ +-static bool count_bytes; +- + /* If nonzero, at least one of the files we read was standard input. */ + static bool have_read_stdin; + +-static char const shortopts[] = "bsw:0::1::2::3::4::5::6::7::8::9::"; ++static char const shortopts[] = "bcsw:0::1::2::3::4::5::6::7::8::9::"; + + static struct option const longopts[] = + { + {"bytes", no_argument, NULL, 'b'}, ++ {"characters", no_argument, NULL, 'c'}, + {"spaces", no_argument, NULL, 's'}, + {"width", required_argument, NULL, 'w'}, + {GETOPT_HELP_OPTION_DECL}, +@@ -78,6 +121,7 @@ Mandatory arguments to long options are + "), stdout); + fputs (_("\ + -b, --bytes count bytes rather than columns\n\ ++ -c, --characters count characters rather than columns\n\ + -s, --spaces break at spaces\n\ + -w, --width=WIDTH use WIDTH columns instead of 80\n\ + "), stdout); +@@ -95,7 +139,7 @@ Mandatory arguments to long options are + static size_t + adjust_column (size_t column, char c) + { +- if (!count_bytes) ++ if (operating_mode != byte_mode) + { + if (c == '\b') + { +@@ -118,30 +162,14 @@ adjust_column (size_t column, char c) + to stdout, with maximum line length WIDTH. + Return true if successful. */ + +-static bool +-fold_file (char const *filename, size_t width) ++static void ++fold_text (FILE *istream, size_t width, int *saved_errno) + { +- FILE *istream; + int c; + size_t column = 0; /* Screen column where next char will go. */ + size_t offset_out = 0; /* Index in `line_out' for next char. */ + static char *line_out = NULL; + static size_t allocated_out = 0; +- int saved_errno; +- +- if (STREQ (filename, "-")) +- { +- istream = stdin; +- have_read_stdin = true; +- } +- else +- istream = fopen (filename, "r"); +- +- if (istream == NULL) +- { +- error (0, errno, "%s", filename); +- return false; +- } + + fadvise (istream, FADVISE_SEQUENTIAL); + +@@ -171,6 +199,15 @@ fold_file (char const *filename, size_t + bool found_blank = false; + size_t logical_end = offset_out; + ++ /* If LINE_OUT has no wide character, ++ put a new wide character in LINE_OUT ++ if column is bigger than width. */ ++ if (offset_out == 0) ++ { ++ line_out[offset_out++] = c; ++ continue; ++ } ++ + /* Look for the last blank. */ + while (logical_end) + { +@@ -217,11 +254,221 @@ fold_file (char const *filename, size_t + line_out[offset_out++] = c; + } + +- saved_errno = errno; ++ *saved_errno = errno; + + if (offset_out) + fwrite (line_out, sizeof (char), (size_t) offset_out, stdout); + ++} ++ ++#if HAVE_MBRTOWC ++static void ++fold_multibyte_text (FILE *istream, size_t width, int *saved_errno) ++{ ++ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */ ++ size_t buflen = 0; /* The length of the byte sequence in buf. */ ++ char *bufpos = buf; /* Next read position of BUF. */ ++ wint_t wc; /* A gotten wide character. */ ++ size_t mblength; /* The byte size of a multibyte character which shows ++ as same character as WC. */ ++ mbstate_t state, state_bak; /* State of the stream. */ ++ int convfail = 0; /* 1, when conversion is failed. Otherwise 0. */ ++ ++ static char *line_out = NULL; ++ size_t offset_out = 0; /* Index in `line_out' for next char. */ ++ static size_t allocated_out = 0; ++ ++ int increment; ++ size_t column = 0; ++ ++ size_t last_blank_pos; ++ size_t last_blank_column; ++ int is_blank_seen; ++ int last_blank_increment = 0; ++ int is_bs_following_last_blank; ++ size_t bs_following_last_blank_num; ++ int is_cr_after_last_blank; ++ ++#define CLEAR_FLAGS \ ++ do \ ++ { \ ++ last_blank_pos = 0; \ ++ last_blank_column = 0; \ ++ is_blank_seen = 0; \ ++ is_bs_following_last_blank = 0; \ ++ bs_following_last_blank_num = 0; \ ++ is_cr_after_last_blank = 0; \ ++ } \ ++ while (0) ++ ++#define START_NEW_LINE \ ++ do \ ++ { \ ++ putchar ('\n'); \ ++ column = 0; \ ++ offset_out = 0; \ ++ CLEAR_FLAGS; \ ++ } \ ++ while (0) ++ ++ CLEAR_FLAGS; ++ memset (&state, '\0', sizeof(mbstate_t)); ++ ++ for (;; bufpos += mblength, buflen -= mblength) ++ { ++ if (buflen < MB_LEN_MAX && !feof (istream) && !ferror (istream)) ++ { ++ memmove (buf, bufpos, buflen); ++ buflen += fread (buf + buflen, sizeof(char), BUFSIZ, istream); ++ bufpos = buf; ++ } ++ ++ if (buflen < 1) ++ break; ++ ++ /* Get a wide character. */ ++ state_bak = state; ++ mblength = mbrtowc ((wchar_t *)&wc, bufpos, buflen, &state); ++ ++ switch (mblength) ++ { ++ case (size_t)-1: ++ case (size_t)-2: ++ convfail++; ++ state = state_bak; ++ /* Fall through. */ ++ ++ case 0: ++ mblength = 1; ++ break; ++ } ++ ++rescan: ++ if (operating_mode == byte_mode) /* byte mode */ ++ increment = mblength; ++ else if (operating_mode == character_mode) /* character mode */ ++ increment = 1; ++ else /* column mode */ ++ { ++ if (convfail) ++ increment = 1; ++ else ++ { ++ switch (wc) ++ { ++ case L'\n': ++ fwrite (line_out, sizeof(char), offset_out, stdout); ++ START_NEW_LINE; ++ continue; ++ ++ case L'\b': ++ increment = (column > 0) ? -1 : 0; ++ break; ++ ++ case L'\r': ++ increment = -1 * column; ++ break; ++ ++ case L'\t': ++ increment = 8 - column % 8; ++ break; ++ ++ default: ++ increment = wcwidth (wc); ++ increment = (increment < 0) ? 0 : increment; ++ } ++ } ++ } ++ ++ if (column + increment > width && break_spaces && last_blank_pos) ++ { ++ fwrite (line_out, sizeof(char), last_blank_pos, stdout); ++ putchar ('\n'); ++ ++ offset_out = offset_out - last_blank_pos; ++ column = column - last_blank_column + ((is_cr_after_last_blank) ++ ? last_blank_increment : bs_following_last_blank_num); ++ memmove (line_out, line_out + last_blank_pos, offset_out); ++ CLEAR_FLAGS; ++ goto rescan; ++ } ++ ++ if (column + increment > width && column != 0) ++ { ++ fwrite (line_out, sizeof(char), offset_out, stdout); ++ START_NEW_LINE; ++ goto rescan; ++ } ++ ++ if (allocated_out < offset_out + mblength) ++ { ++ line_out = X2REALLOC (line_out, &allocated_out); ++ } ++ ++ memcpy (line_out + offset_out, bufpos, mblength); ++ offset_out += mblength; ++ column += increment; ++ ++ if (is_blank_seen && !convfail && wc == L'\r') ++ is_cr_after_last_blank = 1; ++ ++ if (is_bs_following_last_blank && !convfail && wc == L'\b') ++ ++bs_following_last_blank_num; ++ else ++ is_bs_following_last_blank = 0; ++ ++ if (break_spaces && !convfail && iswblank (wc)) ++ { ++ last_blank_pos = offset_out; ++ last_blank_column = column; ++ is_blank_seen = 1; ++ last_blank_increment = increment; ++ is_bs_following_last_blank = 1; ++ bs_following_last_blank_num = 0; ++ is_cr_after_last_blank = 0; ++ } ++ } ++ ++ *saved_errno = errno; ++ ++ if (offset_out) ++ fwrite (line_out, sizeof (char), (size_t) offset_out, stdout); ++ ++} ++#endif ++ ++/* Fold file FILENAME, or standard input if FILENAME is "-", ++ to stdout, with maximum line length WIDTH. ++ Return 0 if successful, 1 if an error occurs. */ ++ ++static bool ++fold_file (char *filename, size_t width) ++{ ++ FILE *istream; ++ int saved_errno; ++ ++ if (STREQ (filename, "-")) ++ { ++ istream = stdin; ++ have_read_stdin = 1; ++ } ++ else ++ istream = fopen (filename, "r"); ++ ++ if (istream == NULL) ++ { ++ error (0, errno, "%s", filename); ++ return 1; ++ } ++ ++ /* Define how ISTREAM is being folded. */ ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ fold_multibyte_text (istream, width, &saved_errno); ++ else ++#endif ++ fold_text (istream, width, &saved_errno); ++ + if (ferror (istream)) + { + error (0, saved_errno, "%s", filename); +@@ -254,7 +501,8 @@ main (int argc, char **argv) + + atexit (close_stdout); + +- break_spaces = count_bytes = have_read_stdin = false; ++ operating_mode = column_mode; ++ break_spaces = have_read_stdin = false; + + while ((optc = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1) + { +@@ -263,7 +511,15 @@ main (int argc, char **argv) + switch (optc) + { + case 'b': /* Count bytes rather than columns. */ +- count_bytes = true; ++ if (operating_mode != column_mode) ++ FATAL_ERROR (_("only one way of folding may be specified")); ++ operating_mode = byte_mode; ++ break; ++ ++ case 'c': ++ if (operating_mode != column_mode) ++ FATAL_ERROR (_("only one way of folding may be specified")); ++ operating_mode = character_mode; + break; + + case 's': /* Break at word boundaries. */ +diff -urNp coreutils-8.15-orig/src/join.c coreutils-8.15/src/join.c +--- coreutils-8.15-orig/src/join.c 2012-01-01 10:04:06.000000000 +0100 ++++ coreutils-8.15/src/join.c 2013-01-30 15:59:19.544250392 +0100 +@@ -22,18 +22,32 @@ + #include + #include + ++/* Get mbstate_t, mbrtowc(), mbrtowc(), wcwidth(). */ ++#if HAVE_WCHAR_H ++# include ++#endif ++ ++/* Get iswblank(), towupper. */ ++#if HAVE_WCTYPE_H ++# include ++#endif ++ + #include "system.h" + #include "error.h" + #include "fadvise.h" + #include "hard-locale.h" + #include "linebuffer.h" +-#include "memcasecmp.h" + #include "quote.h" + #include "stdio--.h" + #include "xmemcoll.h" + #include "xstrtol.h" + #include "argmatch.h" + ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ ++#if HAVE_MBRTOWC && defined mbstate_t ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) ++#endif ++ + /* The official name of this program (e.g., no `g' prefix). */ + #define PROGRAM_NAME "join" + +@@ -135,10 +149,12 @@ static struct outlist outlist_head; + /* Last element in `outlist', where a new element can be added. */ + static struct outlist *outlist_end = &outlist_head; + +-/* Tab character separating fields. If negative, fields are separated +- by any nonempty string of blanks, otherwise by exactly one +- tab character whose value (when cast to unsigned char) equals TAB. */ +-static int tab = -1; ++/* Tab character separating fields. If NULL, fields are separated ++ by any nonempty string of blanks. */ ++static char *tab = NULL; ++ ++/* The number of bytes used for tab. */ ++static size_t tablen = 0; + + /* If nonzero, check that the input is correctly ordered. */ + static enum +@@ -263,13 +279,14 @@ xfields (struct line *line) + if (ptr == lim) + return; + +- if (0 <= tab && tab != '\n') ++ if (tab != NULL) + { ++ unsigned char t = tab[0]; + char *sep; +- for (; (sep = memchr (ptr, tab, lim - ptr)) != NULL; ptr = sep + 1) ++ for (; (sep = memchr (ptr, t, lim - ptr)) != NULL; ptr = sep + 1) + extract_field (line, ptr, sep - ptr); + } +- else if (tab < 0) ++ else + { + /* Skip leading blanks before the first field. */ + while (isblank (to_uchar (*ptr))) +@@ -293,6 +310,148 @@ xfields (struct line *line) + extract_field (line, ptr, lim - ptr); + } + ++#if HAVE_MBRTOWC ++static void ++xfields_multibyte (struct line *line) ++{ ++ char *ptr = line->buf.buffer; ++ char const *lim = ptr + line->buf.length - 1; ++ wchar_t wc = 0; ++ size_t mblength = 1; ++ mbstate_t state, state_bak; ++ ++ memset (&state, 0, sizeof (mbstate_t)); ++ ++ if (ptr >= lim) ++ return; ++ ++ if (tab != NULL) ++ { ++ unsigned char t = tab[0]; ++ char *sep = ptr; ++ for (; ptr < lim; ptr = sep + mblength) ++ { ++ sep = ptr; ++ while (sep < lim) ++ { ++ state_bak = state; ++ mblength = mbrtowc (&wc, sep, lim - sep + 1, &state); ++ ++ if (mblength == (size_t)-1 || mblength == (size_t)-2) ++ { ++ mblength = 1; ++ state = state_bak; ++ } ++ mblength = (mblength < 1) ? 1 : mblength; ++ ++ if (mblength == tablen && !memcmp (sep, tab, mblength)) ++ break; ++ else ++ { ++ sep += mblength; ++ continue; ++ } ++ } ++ ++ if (sep >= lim) ++ break; ++ ++ extract_field (line, ptr, sep - ptr); ++ } ++ } ++ else ++ { ++ /* Skip leading blanks before the first field. */ ++ while(ptr < lim) ++ { ++ state_bak = state; ++ mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state); ++ ++ if (mblength == (size_t)-1 || mblength == (size_t)-2) ++ { ++ mblength = 1; ++ state = state_bak; ++ break; ++ } ++ mblength = (mblength < 1) ? 1 : mblength; ++ ++ if (!iswblank(wc)) ++ break; ++ ptr += mblength; ++ } ++ ++ do ++ { ++ char *sep; ++ state_bak = state; ++ mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state); ++ if (mblength == (size_t)-1 || mblength == (size_t)-2) ++ { ++ mblength = 1; ++ state = state_bak; ++ break; ++ } ++ mblength = (mblength < 1) ? 1 : mblength; ++ ++ sep = ptr + mblength; ++ while (sep < lim) ++ { ++ state_bak = state; ++ mblength = mbrtowc (&wc, sep, lim - sep + 1, &state); ++ if (mblength == (size_t)-1 || mblength == (size_t)-2) ++ { ++ mblength = 1; ++ state = state_bak; ++ break; ++ } ++ mblength = (mblength < 1) ? 1 : mblength; ++ ++ if (iswblank (wc)) ++ break; ++ ++ sep += mblength; ++ } ++ ++ extract_field (line, ptr, sep - ptr); ++ if (sep >= lim) ++ return; ++ ++ state_bak = state; ++ mblength = mbrtowc (&wc, sep, lim - sep + 1, &state); ++ if (mblength == (size_t)-1 || mblength == (size_t)-2) ++ { ++ mblength = 1; ++ state = state_bak; ++ break; ++ } ++ mblength = (mblength < 1) ? 1 : mblength; ++ ++ ptr = sep + mblength; ++ while (ptr < lim) ++ { ++ state_bak = state; ++ mblength = mbrtowc (&wc, ptr, lim - ptr + 1, &state); ++ if (mblength == (size_t)-1 || mblength == (size_t)-2) ++ { ++ mblength = 1; ++ state = state_bak; ++ break; ++ } ++ mblength = (mblength < 1) ? 1 : mblength; ++ ++ if (!iswblank (wc)) ++ break; ++ ++ ptr += mblength; ++ } ++ } ++ while (ptr < lim); ++ } ++ ++ extract_field (line, ptr, lim - ptr); ++} ++#endif ++ + static void + freeline (struct line *line) + { +@@ -314,56 +473,129 @@ keycmp (struct line const *line1, struct + size_t jf_1, size_t jf_2) + { + /* Start of field to compare in each file. */ +- char *beg1; +- char *beg2; +- +- size_t len1; +- size_t len2; /* Length of fields to compare. */ ++ char *beg[2]; ++ char *copy[2]; ++ size_t len[2]; /* Length of fields to compare. */ + int diff; ++ int i, j; ++ int mallocd = 0; + + if (jf_1 < line1->nfields) + { +- beg1 = line1->fields[jf_1].beg; +- len1 = line1->fields[jf_1].len; ++ beg[0] = line1->fields[jf_1].beg; ++ len[0] = line1->fields[jf_1].len; + } + else + { +- beg1 = NULL; +- len1 = 0; ++ beg[0] = NULL; ++ len[0] = 0; + } + + if (jf_2 < line2->nfields) + { +- beg2 = line2->fields[jf_2].beg; +- len2 = line2->fields[jf_2].len; ++ beg[1] = line2->fields[jf_2].beg; ++ len[1] = line2->fields[jf_2].len; + } + else + { +- beg2 = NULL; +- len2 = 0; ++ beg[1] = NULL; ++ len[1] = 0; + } + +- if (len1 == 0) +- return len2 == 0 ? 0 : -1; +- if (len2 == 0) ++ if (len[0] == 0) ++ return len[1] == 0 ? 0 : -1; ++ if (len[1] == 0) + return 1; + + if (ignore_case) + { +- /* FIXME: ignore_case does not work with NLS (in particular, +- with multibyte chars). */ +- diff = memcasecmp (beg1, beg2, MIN (len1, len2)); ++#ifdef HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ { ++ size_t mblength; ++ wchar_t wc, uwc; ++ mbstate_t state, state_bak; ++ ++ memset (&state, '\0', sizeof (mbstate_t)); ++ ++ for (i = 0; i < 2; i++) ++ { ++ copy[i] = xmalloc (len[i] + 1); ++ mallocd = 1; ++ ++ for (j = 0; j < MIN (len[0], len[1]);) ++ { ++ state_bak = state; ++ mblength = mbrtowc (&wc, beg[i] + j, len[i] - j, &state); ++ ++ switch (mblength) ++ { ++ case (size_t) -1: ++ case (size_t) -2: ++ state = state_bak; ++ /* Fall through */ ++ case 0: ++ mblength = 1; ++ break; ++ ++ default: ++ uwc = towupper (wc); ++ ++ if (uwc != wc) ++ { ++ mbstate_t state_wc; ++ ++ memset (&state_wc, '\0', sizeof (mbstate_t)); ++ wcrtomb (copy[i] + j, uwc, &state_wc); ++ } ++ else ++ memcpy (copy[i] + j, beg[i] + j, mblength); ++ } ++ j += mblength; ++ } ++ copy[i][j] = '\0'; ++ } ++ } ++ else ++#endif ++ { ++ for (i = 0; i < 2; i++) ++ { ++ copy[i] = xmalloc (len[i] + 1); ++ mallocd = 1; ++ ++ for (j = 0; j < MIN (len[0], len[1]); j++) ++ copy[i][j] = toupper (beg[i][j]); ++ ++ copy[i][j] = '\0'; ++ } ++ } + } + else + { +- if (hard_LC_COLLATE) +- return xmemcoll (beg1, len1, beg2, len2); +- diff = memcmp (beg1, beg2, MIN (len1, len2)); ++ copy[0] = (unsigned char *) beg[0]; ++ copy[1] = (unsigned char *) beg[1]; ++ } ++ ++ if (hard_LC_COLLATE) ++ { ++ diff = xmemcoll ((char *) copy[0], len[0], (char *) copy[1], len[1]); ++ ++ if (mallocd) ++ for (i = 0; i < 2; i++) ++ free (copy[i]); ++ ++ return diff; + } ++ diff = memcmp (copy[0], copy[1], MIN (len[0], len[1])); ++ ++ if (mallocd) ++ for (i = 0; i < 2; i++) ++ free (copy[i]); + + if (diff) + return diff; +- return len1 < len2 ? -1 : len1 != len2; ++ return len[0] - len[1]; + } + + /* Check that successive input lines PREV and CURRENT from input file +@@ -455,6 +687,11 @@ get_line (FILE *fp, struct line **linep, + } + ++line_no[which - 1]; + ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ xfields_multibyte (line); ++ else ++#endif + xfields (line); + + if (prevline[which - 1]) +@@ -554,21 +791,28 @@ prfield (size_t n, struct line const *li + + /* Output all the fields in line, other than the join field. */ + ++#define PUT_TAB_CHAR \ ++ do \ ++ { \ ++ (tab != NULL) ? \ ++ fwrite(tab, sizeof(char), tablen, stdout) : putchar (' '); \ ++ } \ ++ while (0) ++ + static void + prfields (struct line const *line, size_t join_field, size_t autocount) + { + size_t i; + size_t nfields = autoformat ? autocount : line->nfields; +- char output_separator = tab < 0 ? ' ' : tab; + + for (i = 0; i < join_field && i < nfields; ++i) + { +- putchar (output_separator); ++ PUT_TAB_CHAR; + prfield (i, line); + } + for (i = join_field + 1; i < nfields; ++i) + { +- putchar (output_separator); ++ PUT_TAB_CHAR; + prfield (i, line); + } + } +@@ -579,7 +823,6 @@ static void + prjoin (struct line const *line1, struct line const *line2) + { + const struct outlist *outlist; +- char output_separator = tab < 0 ? ' ' : tab; + size_t field; + struct line const *line; + +@@ -613,7 +856,7 @@ prjoin (struct line const *line1, struct + o = o->next; + if (o == NULL) + break; +- putchar (output_separator); ++ PUT_TAB_CHAR; + } + putchar ('\n'); + } +@@ -1091,21 +1334,46 @@ main (int argc, char **argv) + + case 't': + { +- unsigned char newtab = optarg[0]; ++ char *newtab = NULL; ++ size_t newtablen; ++ newtab = xstrdup (optarg); ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ { ++ mbstate_t state; ++ ++ memset (&state, 0, sizeof (mbstate_t)); ++ newtablen = mbrtowc (NULL, newtab, ++ strnlen (newtab, MB_LEN_MAX), ++ &state); ++ if (newtablen == (size_t) 0 ++ || newtablen == (size_t) -1 ++ || newtablen == (size_t) -2) ++ newtablen = 1; ++ } ++ else ++#endif ++ newtablen = 1; + if (! newtab) +- newtab = '\n'; /* '' => process the whole line. */ ++ { ++ newtab = "\n"; /* '' => process the whole line. */ ++ } + else if (optarg[1]) + { +- if (STREQ (optarg, "\\0")) +- newtab = '\0'; +- else +- error (EXIT_FAILURE, 0, _("multi-character tab %s"), +- quote (optarg)); ++ if (newtablen == 1 && newtab[1]) ++ { ++ if (STREQ (newtab, "\\0")) ++ newtab[0] = '\0'; ++ } ++ } ++ if (tab != NULL && strcmp (tab, newtab)) ++ { ++ free (newtab); ++ error (EXIT_FAILURE, 0, _("incompatible tabs")); + } +- if (0 <= tab && tab != newtab) +- error (EXIT_FAILURE, 0, _("incompatible tabs")); + tab = newtab; +- } ++ tablen = newtablen; ++ } + break; + + case NOCHECK_ORDER_OPTION: +diff -urNp coreutils-8.15-orig/src/pr.c coreutils-8.15/src/pr.c +--- coreutils-8.15-orig/src/pr.c 2012-01-01 10:04:06.000000000 +0100 ++++ coreutils-8.15/src/pr.c 2013-01-30 13:40:37.350146206 +0100 +@@ -312,6 +312,32 @@ - src_wc_SOURCES = src/wc.c - if USE_AVX512_WC_LINECOUNT -diff --git a/src/pr.c b/src/pr.c -index 10b8c52..079c86c 100644 ---- a/src/pr.c -+++ b/src/pr.c -@@ -312,6 +312,24 @@ - #include #include #include + @@ -1441,13 +1739,21 @@ index 10b8c52..079c86c 100644 +#if HAVE_WCHAR_H +# include +#endif ++ ++/* Get iswprint(). -- for wcwidth(). */ ++#if HAVE_WCTYPE_H ++# include ++#endif ++#if !defined iswprint && !HAVE_ISWPRINT ++# define iswprint(wc) 1 ++#endif + #include "system.h" - #include "c-ctype.h" + #include "error.h" #include "fadvise.h" -@@ -325,6 +343,18 @@ - #include "xstrtol-error.h" - #include "xdectoint.h" +@@ -323,6 +349,18 @@ + #include "strftime.h" + #include "xstrtol.h" +/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ +#if HAVE_MBRTOWC && defined mbstate_t @@ -1461,10 +1767,10 @@ index 10b8c52..079c86c 100644 +extern int wcwidth (); +#endif + - /* The official name of this program (e.g., no 'g' prefix). */ + /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "pr" -@@ -417,7 +447,20 @@ struct COLUMN +@@ -415,7 +453,20 @@ struct COLUMN typedef struct COLUMN COLUMN; @@ -1486,23 +1792,23 @@ index 10b8c52..079c86c 100644 static bool read_line (COLUMN *p); static bool print_page (void); static bool print_stored (COLUMN *p); -@@ -428,6 +471,7 @@ static void pad_across_to (int position); +@@ -425,6 +476,7 @@ static void print_header (void); + static void pad_across_to (int position); static void add_line_number (COLUMN *p); - static int getoptnum (char const *n_str, int min, char const *errfmt); static void getoptarg (char *arg, char switch_char, char *character, + int *character_length, int *character_width, int *number); static void print_files (int number_of_files, char **av); static void init_parameters (int number_of_files); -@@ -441,7 +485,6 @@ static void store_char (char c); - static void pad_down (unsigned int lines); +@@ -438,7 +490,6 @@ static void store_char (char c); + static void pad_down (int lines); static void read_rest_of_line (COLUMN *p); static void skip_read (COLUMN *p, int column_number); -static void print_char (char c); static void cleanup (void); static void print_sep_string (void); - static void separator_string (char const *optarg_S); -@@ -453,7 +496,7 @@ static COLUMN *column_vector; + static void separator_string (const char *optarg_S); +@@ -450,7 +501,7 @@ static COLUMN *column_vector; we store the leftmost columns contiguously in buff. To print a line from buff, get the index of the first character from line_vector[i], and print up to line_vector[i + 1]. */ @@ -1511,7 +1817,7 @@ index 10b8c52..079c86c 100644 /* Index of the position in buff where the next character will be stored. */ -@@ -557,7 +600,7 @@ static int chars_per_column; +@@ -554,7 +605,7 @@ static int chars_per_column; static bool untabify_input = false; /* (-e) The input tab character. */ @@ -1520,7 +1826,7 @@ index 10b8c52..079c86c 100644 /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ... where the leftmost column is 1. */ -@@ -567,7 +610,10 @@ static int chars_per_input_tab = 8; +@@ -564,7 +615,10 @@ static int chars_per_input_tab = 8; static bool tabify_output = false; /* (-i) The output tab character. */ @@ -1532,7 +1838,7 @@ index 10b8c52..079c86c 100644 /* (-i) The width of the output tab. */ static int chars_per_output_tab = 8; -@@ -637,7 +683,13 @@ static int line_number; +@@ -638,7 +692,13 @@ static int power_10; static bool numbered_lines = false; /* (-n) Character which follows each line number. */ @@ -1547,18 +1853,18 @@ index 10b8c52..079c86c 100644 /* (-n) line counting starts with 1st line of input file (not with 1st line of 1st page printed). */ -@@ -690,6 +742,7 @@ static bool use_col_separator = false; - -a|COLUMN|-m is a 'space' and with the -J option a 'tab'. */ - static char const *col_sep_string = ""; +@@ -691,6 +751,7 @@ static bool use_col_separator = false; + -a|COLUMN|-m is a `space' and with the -J option a `tab'. */ + static char *col_sep_string = (char *) ""; static int col_sep_length = 0; +static int col_sep_width = 0; static char *column_separator = (char *) " "; static char *line_separator = (char *) "\t"; -@@ -852,6 +905,13 @@ separator_string (char const *optarg_S) - integer_overflow (); - col_sep_length = len; - col_sep_string = optarg_S; +@@ -847,6 +908,13 @@ separator_string (const char *optarg_S) + col_sep_length = (int) strlen (optarg_S); + col_sep_string = xmalloc (col_sep_length + 1); + strcpy (col_sep_string, optarg_S); + +#if HAVE_MBRTOWC + if (MB_CUR_MAX > 1) @@ -1569,7 +1875,7 @@ index 10b8c52..079c86c 100644 } int -@@ -876,6 +936,21 @@ main (int argc, char **argv) +@@ -871,6 +939,21 @@ main (int argc, char **argv) atexit (close_stdout); @@ -1590,8 +1896,8 @@ index 10b8c52..079c86c 100644 + n_files = 0; file_names = (argc > 1 - ? xnmalloc (argc - 1, sizeof (char *)) -@@ -952,8 +1027,12 @@ main (int argc, char **argv) + ? xmalloc ((argc - 1) * sizeof (char *)) +@@ -947,8 +1030,12 @@ main (int argc, char **argv) break; case 'e': if (optarg) @@ -1606,7 +1912,7 @@ index 10b8c52..079c86c 100644 /* Could check tab width > 0. */ untabify_input = true; break; -@@ -966,8 +1045,12 @@ main (int argc, char **argv) +@@ -961,8 +1048,12 @@ main (int argc, char **argv) break; case 'i': if (optarg) @@ -1621,7 +1927,7 @@ index 10b8c52..079c86c 100644 /* Could check tab width > 0. */ tabify_output = true; break; -@@ -986,8 +1069,8 @@ main (int argc, char **argv) +@@ -989,8 +1080,8 @@ main (int argc, char **argv) case 'n': numbered_lines = true; if (optarg) @@ -1632,15 +1938,16 @@ index 10b8c52..079c86c 100644 break; case 'N': skip_count = false; -@@ -1013,6 +1096,7 @@ main (int argc, char **argv) +@@ -1029,7 +1120,7 @@ main (int argc, char **argv) + old_s = false; /* Reset an additional input of -s, -S dominates -s */ - col_sep_string = ""; - col_sep_length = 0; -+ col_sep_width = 0; + col_sep_string = bad_cast (""); +- col_sep_length = 0; ++ col_sep_length = col_sep_width = 0; use_col_separator = true; if (optarg) separator_string (optarg); -@@ -1168,7 +1252,8 @@ getoptnum (char const *n_str, int min, char const *err) +@@ -1186,10 +1277,45 @@ main (int argc, char **argv) a number. */ static void @@ -1648,12 +1955,7 @@ index 10b8c52..079c86c 100644 +getoptarg (char *arg, char switch_char, char *character, int *character_length, + int *character_width, int *number) { - if (!*arg) - { -@@ -1177,7 +1262,41 @@ getoptarg (char *arg, char switch_char, char *character, int *number) - } - - if (!c_isdigit (*arg)) + if (!ISDIGIT (*arg)) - *character = *arg++; + { +#ifdef HAVE_MBRTOWC @@ -1693,7 +1995,7 @@ index 10b8c52..079c86c 100644 if (*arg) { long int tmp_long; -@@ -1206,6 +1325,11 @@ static void +@@ -1211,6 +1337,11 @@ static void init_parameters (int number_of_files) { int chars_used_by_number = 0; @@ -1705,7 +2007,7 @@ index 10b8c52..079c86c 100644 lines_per_body = lines_per_page - lines_per_header - lines_per_footer; if (lines_per_body <= 0) -@@ -1243,7 +1367,7 @@ init_parameters (int number_of_files) +@@ -1248,7 +1379,7 @@ init_parameters (int number_of_files) else col_sep_string = column_separator; @@ -1714,39 +2016,39 @@ index 10b8c52..079c86c 100644 use_col_separator = true; } /* It's rather pointless to define a TAB separator with column -@@ -1275,11 +1399,11 @@ init_parameters (int number_of_files) - + TAB_WIDTH (chars_per_input_tab, chars_per_number); */ +@@ -1279,11 +1410,11 @@ init_parameters (int number_of_files) + TAB_WIDTH (chars_per_input_tab, chars_per_number); */ /* Estimate chars_per_text without any margin and keep it constant. */ - if (number_separator == '\t') + if (number_separator[0] == '\t') - number_width = (chars_per_number - + TAB_WIDTH (chars_per_default_tab, chars_per_number)); + number_width = chars_per_number + + TAB_WIDTH (chars_per_default_tab, chars_per_number); else - number_width = chars_per_number + 1; + number_width = chars_per_number + number_separator_width; /* The number is part of the column width unless we are printing files in parallel. */ -@@ -1288,7 +1412,7 @@ init_parameters (int number_of_files) +@@ -1298,7 +1429,7 @@ init_parameters (int number_of_files) } - int sep_chars, useful_chars; -- if (ckd_mul (&sep_chars, columns - 1, col_sep_length)) -+ if (ckd_mul (&sep_chars, columns - 1, col_sep_width)) - sep_chars = INT_MAX; - if (ckd_sub (&useful_chars, chars_per_line - chars_used_by_number, - sep_chars)) -@@ -1311,7 +1435,7 @@ init_parameters (int number_of_files) + chars_per_column = (chars_per_line - chars_used_by_number - +- (columns - 1) * col_sep_length) / columns; ++ (columns - 1) * col_sep_width) / columns; + + if (chars_per_column < 1) + error (EXIT_FAILURE, 0, _("page width too narrow")); +@@ -1315,7 +1446,7 @@ init_parameters (int number_of_files) We've to use 8 as the lower limit, if we use chars_per_default_tab = 8 to expand a tab which is not an input_tab-char. */ free (clump_buff); - clump_buff = xmalloc (MAX (8, chars_per_input_tab)); + clump_buff = xmalloc (mb_len * MAX (8, chars_per_input_tab)); } - + /* Open the necessary files, -@@ -1417,7 +1541,7 @@ init_funcs (void) +@@ -1423,7 +1554,7 @@ init_funcs (void) /* Enlarge p->start_position of first column to use the same form of padding_not_printed with all columns. */ @@ -1755,7 +2057,7 @@ index 10b8c52..079c86c 100644 /* This loop takes care of all but the rightmost column. */ -@@ -1451,7 +1575,7 @@ init_funcs (void) +@@ -1457,7 +1588,7 @@ init_funcs (void) } else { @@ -1764,21 +2066,21 @@ index 10b8c52..079c86c 100644 h_next = h + chars_per_column; } } -@@ -1751,9 +1875,9 @@ static void +@@ -1748,9 +1879,9 @@ static void align_column (COLUMN *p) { padding_not_printed = p->start_position; -- if (col_sep_length < padding_not_printed) -+ if (col_sep_width < padding_not_printed) +- if (padding_not_printed - col_sep_length > 0) ++ if (padding_not_printed - col_sep_width > 0) { - pad_across_to (padding_not_printed - col_sep_length); + pad_across_to (padding_not_printed - col_sep_width); padding_not_printed = ANYWHERE; } -@@ -2030,13 +2154,13 @@ store_char (char c) +@@ -2021,13 +2152,13 @@ store_char (char c) /* May be too generous. */ - buff = xpalloc (buff, &buff_allocated, 1, -1, sizeof *buff); + buff = X2REALLOC (buff, &buff_allocated); } - buff[buff_current++] = c; + buff[buff_current++] = (unsigned char) c; @@ -1790,11 +2092,11 @@ index 10b8c52..079c86c 100644 - int i; + int i, j; char *s; - int num_width; + int left_cut; -@@ -2053,22 +2177,24 @@ add_line_number (COLUMN *p) +@@ -2050,22 +2181,24 @@ add_line_number (COLUMN *p) /* Tabification is assumed for multiple columns, also for n-separators, - but 'default n-separator = TAB' hasn't been given priority over + but `default n-separator = TAB' hasn't been given priority over equal column_width also specified by POSIX. */ - if (number_separator == '\t') + if (number_separator[0] == '\t') @@ -1821,7 +2123,7 @@ index 10b8c52..079c86c 100644 output_position = POS_AFTER_TAB (chars_per_output_tab, output_position); } -@@ -2227,7 +2353,7 @@ print_white_space (void) +@@ -2226,7 +2359,7 @@ print_white_space (void) while (goal - h_old > 1 && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal) { @@ -1830,15 +2132,15 @@ index 10b8c52..079c86c 100644 h_old = h_new; } while (++h_old <= goal) -@@ -2247,6 +2373,7 @@ print_sep_string (void) +@@ -2246,6 +2379,7 @@ print_sep_string (void) { - char const *s = col_sep_string; + char *s; int l = col_sep_length; + int not_space_flag; - if (separators_not_printed <= 0) - { -@@ -2258,6 +2385,7 @@ print_sep_string (void) + s = col_sep_string; + +@@ -2259,6 +2393,7 @@ print_sep_string (void) { for (; separators_not_printed > 0; --separators_not_printed) { @@ -1846,7 +2148,7 @@ index 10b8c52..079c86c 100644 while (l-- > 0) { /* 3 types of sep_strings: spaces only, spaces and chars, -@@ -2271,12 +2399,15 @@ print_sep_string (void) +@@ -2272,12 +2407,15 @@ print_sep_string (void) } else { @@ -1863,7 +2165,7 @@ index 10b8c52..079c86c 100644 /* sep_string ends with some spaces */ if (spaces_not_printed > 0) print_white_space (); -@@ -2307,7 +2438,7 @@ print_clump (COLUMN *p, int n, char *clump) +@@ -2305,7 +2443,7 @@ print_clump (COLUMN *p, int n, char *clu required number of tabs and spaces. */ static void @@ -1872,7 +2174,7 @@ index 10b8c52..079c86c 100644 { if (tabify_output) { -@@ -2331,6 +2462,74 @@ print_char (char c) +@@ -2329,6 +2467,74 @@ print_char (char c) putchar (c); } @@ -1947,49 +2249,31 @@ index 10b8c52..079c86c 100644 /* Skip to page PAGE before printing. PAGE may be larger than total number of pages. */ -@@ -2507,9 +2706,9 @@ read_line (COLUMN *p) +@@ -2508,9 +2714,9 @@ read_line (COLUMN *p) align_empty_cols = false; } -- if (col_sep_length < padding_not_printed) -+ if (col_sep_width < padding_not_printed) +- if (padding_not_printed - col_sep_length > 0) ++ if (padding_not_printed - col_sep_width > 0) { - pad_across_to (padding_not_printed - col_sep_length); + pad_across_to (padding_not_printed - col_sep_width); padding_not_printed = ANYWHERE; } -@@ -2578,7 +2777,7 @@ print_stored (COLUMN *p) - COLUMN *q; - - int line = p->current_line++; -- char *first = &buff[line_vector[line]]; -+ unsigned char *first = &buff[line_vector[line]]; - /* FIXME - UMR: Uninitialized memory read: - * This is occurring while in: -@@ -2590,7 +2789,7 @@ print_stored (COLUMN *p) - xmalloc [xmalloc.c:94] - init_store_cols [pr.c:1648] - */ -- char *last = &buff[line_vector[line + 1]]; -+ unsigned char *last = &buff[line_vector[line + 1]]; - - pad_vertically = true; - -@@ -2610,9 +2809,9 @@ print_stored (COLUMN *p) +@@ -2611,9 +2817,9 @@ print_stored (COLUMN *p) } } -- if (col_sep_length < padding_not_printed) -+ if (col_sep_width < padding_not_printed) +- if (padding_not_printed - col_sep_length > 0) ++ if (padding_not_printed - col_sep_width > 0) { - pad_across_to (padding_not_printed - col_sep_length); + pad_across_to (padding_not_printed - col_sep_width); padding_not_printed = ANYWHERE; } -@@ -2625,8 +2824,8 @@ print_stored (COLUMN *p) +@@ -2626,8 +2832,8 @@ print_stored (COLUMN *p) if (spaces_not_printed == 0) { output_position = p->start_position + end_vector[line]; @@ -2000,7 +2284,7 @@ index 10b8c52..079c86c 100644 } return true; -@@ -2645,7 +2844,7 @@ print_stored (COLUMN *p) +@@ -2646,7 +2852,7 @@ print_stored (COLUMN *p) number of characters is 1.) */ static int @@ -2009,7 +2293,7 @@ index 10b8c52..079c86c 100644 { unsigned char uc = c; char *s = clump_buff; -@@ -2655,10 +2854,10 @@ char_to_clump (char c) +@@ -2656,10 +2862,10 @@ char_to_clump (char c) int chars; int chars_per_c = 8; @@ -2022,7 +2306,7 @@ index 10b8c52..079c86c 100644 { width = TAB_WIDTH (chars_per_c, input_position); -@@ -2739,6 +2938,164 @@ char_to_clump (char c) +@@ -2740,6 +2946,154 @@ char_to_clump (char c) return chars; } @@ -2169,17 +2453,7 @@ index 10b8c52..079c86c 100644 + mbc_pos -= mblength; + } + -+ /* Too many backspaces must put us in position 0 -- never negative. */ -+ if (width < 0 && input_position == 0) -+ { -+ chars = 0; -+ input_position = 0; -+ } -+ else if (width < 0 && input_position <= -width) -+ input_position = 0; -+ else -+ input_position += width; -+ ++ input_position += width; + return chars; +} +#endif @@ -2187,15 +2461,19 @@ index 10b8c52..079c86c 100644 /* We've just printed some files and need to clean up things before looking for more options and printing the next batch of files. -diff --git a/src/sort.c b/src/sort.c -index 05d00cc..eb51f20 100644 ---- a/src/sort.c -+++ b/src/sort.c -@@ -30,6 +30,15 @@ +diff -urNp coreutils-8.15-orig/src/sort.c coreutils-8.15/src/sort.c +--- coreutils-8.15-orig/src/sort.c 2013-01-30 13:39:59.892046631 +0100 ++++ coreutils-8.15/src/sort.c 2013-01-30 15:56:48.675032507 +0100 +@@ -22,11 +22,20 @@ + + #include + ++#include + #include + #include + #include #include #include - #include -+ +#if HAVE_WCHAR_H +# include +#endif @@ -2206,14 +2484,9 @@ index 05d00cc..eb51f20 100644 + #include "system.h" #include "argmatch.h" - #include "assure.h" -@@ -160,14 +169,39 @@ static int thousands_sep; - /* We currently ignore multi-byte grouping chars. */ - static bool thousands_sep_ignored; + #include "error.h" +@@ -167,12 +176,34 @@ static int thousands_sep; -+/* True if -f is specified. */ -+static bool folding; -+ /* Nonzero if the corresponding locales are hard. */ static bool hard_LC_COLLATE; -#if HAVE_NL_LANGINFO @@ -2248,9 +2521,9 @@ index 05d00cc..eb51f20 100644 /* The kind of blanks for '-b' to skip in various options. */ enum blanktype { bl_start, bl_end, bl_both }; -@@ -344,13 +378,11 @@ static bool stable; - /* An int value outside char range. */ - enum { NON_CHAR = CHAR_MAX + 1 }; +@@ -346,13 +377,11 @@ static bool reverse; + they were read if all keys compare equal. */ + static bool stable; -/* If TAB has this value, blanks separate fields. */ -enum { TAB_DEFAULT = CHAR_MAX + 1 }; @@ -2265,9 +2538,9 @@ index 05d00cc..eb51f20 100644 /* Flag to remove consecutive duplicate lines from the output. Only the last of a sequence of equal lines will be output. */ -@@ -386,6 +418,46 @@ struct tempnode - static struct tempnode *volatile temphead; - static struct tempnode *volatile *temptail = &temphead; +@@ -786,6 +815,46 @@ reap_all (void) + reap (-1); + } +/* Function pointers. */ +static void @@ -2305,14 +2578,14 @@ index 05d00cc..eb51f20 100644 + } + + *length = (mblength < 1) ? 1 : mblength; -+ return iswblank (wc) || wc == '\n'; ++ return iswblank (wc); +} +#endif + /* Clean up any remaining temporary files. */ static void -@@ -1343,7 +1415,7 @@ zaptemp (char const *name) +@@ -1218,7 +1287,7 @@ zaptemp (char const *name) free (node); } @@ -2321,7 +2594,7 @@ index 05d00cc..eb51f20 100644 static int struct_month_cmp (void const *m1, void const *m2) -@@ -1358,7 +1430,7 @@ struct_month_cmp (void const *m1, void const *m2) +@@ -1233,7 +1302,7 @@ struct_month_cmp (void const *m1, void c /* Initialize the character class tables. */ static void @@ -2330,7 +2603,7 @@ index 05d00cc..eb51f20 100644 { size_t i; -@@ -1370,7 +1442,7 @@ inittables (void) +@@ -1245,7 +1314,7 @@ inittables (void) fold_toupper[i] = toupper (i); } @@ -2339,7 +2612,7 @@ index 05d00cc..eb51f20 100644 /* If we're not in the "C" locale, read different names for months. */ if (hard_LC_TIME) { -@@ -1450,6 +1522,84 @@ specify_nmerge (int oi, char c, char const *s) +@@ -1327,6 +1396,84 @@ specify_nmerge (int oi, char c, char con xstrtol_fatal (e, oi, c, long_options, s); } @@ -2424,7 +2697,7 @@ index 05d00cc..eb51f20 100644 /* Specify the amount of main memory to use when sorting. */ static void specify_sort_size (int oi, char c, char const *s) -@@ -1676,7 +1826,7 @@ buffer_linelim (struct buffer const *buf) +@@ -1555,7 +1702,7 @@ buffer_linelim (struct buffer const *buf by KEY in LINE. */ static char * @@ -2433,7 +2706,7 @@ index 05d00cc..eb51f20 100644 { char *ptr = line->text, *lim = ptr + line->length - 1; size_t sword = key->sword; -@@ -1685,10 +1835,10 @@ begfield (struct line const *line, struct keyfield const *key) +@@ -1564,10 +1711,10 @@ begfield (struct line const *line, struc /* The leading field separator itself is included in a field when -t is absent. */ @@ -2446,7 +2719,7 @@ index 05d00cc..eb51f20 100644 ++ptr; if (ptr < lim) ++ptr; -@@ -1718,12 +1868,71 @@ begfield (struct line const *line, struct keyfield const *key) +@@ -1593,11 +1740,70 @@ begfield (struct line const *line, struc return ptr; } @@ -2512,16 +2785,15 @@ index 05d00cc..eb51f20 100644 /* Return the limit of (a pointer to the first character after) the field in LINE specified by KEY. */ - ATTRIBUTE_PURE static char * -limfield (struct line const *line, struct keyfield const *key) -+limfield_uni (struct line const *line, struct keyfield const *key) ++limfield_uni (const struct line *line, const struct keyfield *key) { char *ptr = line->text, *lim = ptr + line->length - 1; size_t eword = key->eword, echar = key->echar; -@@ -1738,10 +1947,10 @@ limfield (struct line const *line, struct keyfield const *key) - 'beginning' is the first character following the delimiting TAB. - Otherwise, leave PTR pointing at the first 'blank' character after +@@ -1612,10 +1818,10 @@ limfield (struct line const *line, struc + `beginning' is the first character following the delimiting TAB. + Otherwise, leave PTR pointing at the first `blank' character after the preceding field. */ - if (tab != TAB_DEFAULT) + if (tab_length) @@ -2532,7 +2804,7 @@ index 05d00cc..eb51f20 100644 ++ptr; if (ptr < lim && (eword || echar)) ++ptr; -@@ -1787,10 +1996,10 @@ limfield (struct line const *line, struct keyfield const *key) +@@ -1661,10 +1867,10 @@ limfield (struct line const *line, struc */ /* Make LIM point to the end of (one byte past) the current field. */ @@ -2545,12 +2817,12 @@ index 05d00cc..eb51f20 100644 if (newlim) lim = newlim; } -@@ -1825,6 +2034,130 @@ limfield (struct line const *line, struct keyfield const *key) +@@ -1695,6 +1901,130 @@ limfield (struct line const *line, struc return ptr; } +#if HAVE_MBRTOWC -+static char * _GL_ATTRIBUTE_PURE ++static char * +limfield_mb (const struct line *line, const struct keyfield *key) +{ + char *ptr = line->text, *lim = ptr + line->length - 1; @@ -2634,7 +2906,7 @@ index 05d00cc..eb51f20 100644 + { + /* If we're skipping leading blanks, don't start counting characters + * until after skipping past any leading blanks. */ -+ if (key->skipeblanks) ++ if (key->skipsblanks) + while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength)) + ptr += mblength; + @@ -2676,7 +2948,7 @@ index 05d00cc..eb51f20 100644 /* Fill BUF reading from FP, moving buf->left bytes from the end of buf->buf to the beginning first. If EOF is reached and the file wasn't terminated by a newline, supply one. Set up BUF's line -@@ -1911,8 +2244,22 @@ fillbuf (struct buffer *buf, FILE *fp, char const *file) +@@ -1781,8 +2111,22 @@ fillbuf (struct buffer *buf, FILE *fp, c else { if (key->skipsblanks) @@ -2701,32 +2973,16 @@ index 05d00cc..eb51f20 100644 line->keybeg = line_start; } } -@@ -2050,12 +2397,10 @@ find_unit_order (char const *number) +@@ -1903,7 +2247,7 @@ human_numcompare (char const *a, char co + hideously fast. */ - ATTRIBUTE_PURE - static int --human_numcompare (char const *a, char const *b) -+human_numcompare (char *a, char *b) - { -- while (blanks[to_uchar (*a)]) -- a++; -- while (blanks[to_uchar (*b)]) -- b++; -+ skipblanks(&a, a + strlen(a)); -+ skipblanks(&b, b + strlen(b)); - - int diff = find_unit_order (a) - find_unit_order (b); - return (diff ? diff : strnumcmp (a, b, decimal_point, thousands_sep)); -@@ -2067,7 +2412,7 @@ human_numcompare (char const *a, char const *b) - - ATTRIBUTE_PURE static int -numcompare (char const *a, char const *b) +numcompare_uni (const char *a, const char *b) { while (blanks[to_uchar (*a)]) a++; -@@ -2077,6 +2422,25 @@ numcompare (char const *a, char const *b) +@@ -1913,6 +2257,25 @@ numcompare (char const *a, char const *b return strnumcmp (a, b, decimal_point, thousands_sep); } @@ -2749,10 +3005,10 @@ index 05d00cc..eb51f20 100644 +} +#endif /* HAV_EMBRTOWC */ + - static int - nan_compare (long double a, long double b) - { -@@ -2118,7 +2482,7 @@ general_numcompare (char const *sa, char const *sb) + /* Work around a problem whereby the long double value returned by glibc's + strtold ("NaN", ...) contains uninitialized bits: clear all bytes of + A and B before calling strtold. FIXME: remove this function once +@@ -1963,7 +2326,7 @@ general_numcompare (char const *sa, char Return 0 if the name in S is not recognized. */ static int @@ -2761,7 +3017,7 @@ index 05d00cc..eb51f20 100644 { size_t lo = 0; size_t hi = MONTHS_PER_YEAR; -@@ -2457,15 +2821,14 @@ debug_key (struct line const *line, struct keyfield const *key) +@@ -2238,15 +2601,14 @@ debug_key (struct line const *line, stru char saved = *lim; *lim = '\0'; @@ -2779,67 +3035,17 @@ index 05d00cc..eb51f20 100644 else if (key->general_numeric) ignore_value (strtold (beg, &tighter_lim)); else if (key->numeric || key->human_numeric) -@@ -2611,7 +2974,7 @@ key_warnings (struct keyfield const *gkey, bool gkey_only) - /* Warn about significant leading blanks. */ - bool implicit_skip = key_numeric (key) || key->month; +@@ -2390,7 +2752,7 @@ key_warnings (struct keyfield const *gke + bool maybe_space_aligned = !hard_LC_COLLATE && default_key_compare (key) + && !(key->schar || key->echar); bool line_offset = key->eword == 0 && key->echar != 0; /* -k1.x,1.y */ -- if (!zero_width && !gkey_only && tab == TAB_DEFAULT && !line_offset -+ if (!zero_width && !gkey_only && !tab_length && !line_offset - && ((!key->skipsblanks && !implicit_skip) +- if (!gkey_only && tab == TAB_DEFAULT && !line_offset ++ if (!gkey_only && !tab_length && !line_offset + && ((!key->skipsblanks && !(implicit_skip || maybe_space_aligned)) || (!key->skipsblanks && key->schar) || (!key->skipeblanks && key->echar))) -@@ -2659,9 +3022,9 @@ key_warnings (struct keyfield const *gkey, bool gkey_only) - bool number_locale_warned = false; - if (basic_numeric_field_span) - { -- if (tab == TAB_DEFAULT -- ? thousands_sep != NON_CHAR && (isblank (to_uchar (thousands_sep))) -- : tab == thousands_sep) -+ if (tab_length -+ ? tab[0] == thousands_sep -+ : thousands_sep != NON_CHAR && (isblank (to_uchar (thousands_sep)))) - { - error (0, 0, - _("field separator %s is treated as a " -@@ -2672,9 +3035,9 @@ key_warnings (struct keyfield const *gkey, bool gkey_only) - } - if (basic_numeric_field_span || general_numeric_field_span) - { -- if (tab == TAB_DEFAULT -- ? thousands_sep != NON_CHAR && (isblank (to_uchar (decimal_point))) -- : tab == decimal_point) -+ if (tab_length -+ ? tab[0] == decimal_point -+ : thousands_sep != NON_CHAR && (isblank (to_uchar (decimal_point)))) - { - error (0, 0, - _("field separator %s is treated as a " -@@ -2682,19 +3045,19 @@ key_warnings (struct keyfield const *gkey, bool gkey_only) - quote (((char []) {decimal_point, 0}))); - number_locale_warned = true; - } -- else if (tab == '-') -+ else if (tab_length && tab[0] == '-') - { - error (0, 0, - _("field separator %s is treated as a " - "minus sign in numbers"), -- quote (((char []) {tab, 0}))); -+ quote (((char []) {tab[0], 0}))); - } -- else if (general_numeric_field_span && tab == '+') -+ else if (general_numeric_field_span && tab_length && tab[0] == '+') - { - error (0, 0, - _("field separator %s is treated as a " - "plus sign in numbers"), -- quote (((char []) {tab, 0}))); -+ quote (((char []) {tab[0], 0}))); - } - } - -@@ -2746,11 +3109,87 @@ diff_reversed (int diff, bool reversed) - return reversed ? _GL_CMP (0, diff) : diff; +@@ -2448,11 +2810,87 @@ key_warnings (struct keyfield const *gke + error (0, 0, _("option `-r' only applies to last-resort comparison")); } +#if HAVE_MBRTOWC @@ -2851,8 +3057,8 @@ index 05d00cc..eb51f20 100644 + register int lo = 0, hi = MONTHS_PER_YEAR, result; + char *tmp; + size_t wclength, mblength; -+ const char *pp; -+ const wchar_t *wpp; ++ const char **pp; ++ const wchar_t **wpp; + wchar_t *month_wcs; + mbstate_t state; + @@ -2865,19 +3071,17 @@ index 05d00cc..eb51f20 100644 + if (len == 0) + return 0; + -+ if (SIZE_MAX - len < 1) -+ xalloc_die (); ++ month = (char *) xmalloc (len + 1); + -+ month = (char *) xnmalloc (len + 1, MB_CUR_MAX); -+ -+ pp = tmp = (char *) xnmalloc (len + 1, MB_CUR_MAX); ++ tmp = (char *) xmalloc (len + 1); + memcpy (tmp, s, len); + tmp[len] = '\0'; -+ wpp = month_wcs = (wchar_t *) xnmalloc (len + 1, sizeof (wchar_t)); -+ memset (&state, '\0', sizeof (mbstate_t)); ++ pp = (const char **)&tmp; ++ month_wcs = (wchar_t *) xmalloc ((len + 1) * sizeof (wchar_t)); ++ memset (&state, '\0', sizeof(mbstate_t)); + -+ wclength = mbsrtowcs (month_wcs, &pp, len + 1, &state); -+ if (wclength == (size_t)-1 || pp != NULL) ++ wclength = mbsrtowcs (month_wcs, pp, len + 1, &state); ++ if (wclength == (size_t)-1 || *pp != NULL) + error (SORT_FAILURE, 0, _("Invalid multibyte input %s."), quote(s)); + + for (i = 0; i < wclength; i++) @@ -2890,8 +3094,10 @@ index 05d00cc..eb51f20 100644 + } + } + -+ mblength = wcsrtombs (month, &wpp, (len + 1) * MB_CUR_MAX, &state); -+ assert (mblength != (-1) && wpp == NULL); ++ wpp = (const wchar_t **)&month_wcs; ++ ++ mblength = wcsrtombs (month, wpp, len + 1, &state); ++ assert (mblength != (-1) && *wpp == NULL); + + do + { @@ -2908,7 +3114,7 @@ index 05d00cc..eb51f20 100644 + ? monthtab[lo].val : 0); + + if (ea && result) -+ *ea = (char*) s + strlen (monthtab[lo].name); ++ *ea = s + strlen (monthtab[lo].name); + + free (month); + free (tmp); @@ -2927,17 +3133,17 @@ index 05d00cc..eb51f20 100644 { struct keyfield *key = keylist; -@@ -2831,7 +3270,7 @@ keycompare (struct line const *a, struct line const *b) +@@ -2537,7 +2975,7 @@ keycompare (struct line const *a, struct else if (key->human_numeric) diff = human_numcompare (ta, tb); else if (key->month) -- diff = getmonth (ta, nullptr) - getmonth (tb, nullptr); -+ diff = getmonth (ta, tlena, nullptr) - getmonth (tb, tlenb, nullptr); +- diff = getmonth (ta, NULL) - getmonth (tb, NULL); ++ diff = getmonth (ta, tlena, NULL) - getmonth (tb, tlenb, NULL); else if (key->random) diff = compare_random (ta, tlena, tb, tlenb); else if (key->version) -@@ -2941,6 +3380,211 @@ keycompare (struct line const *a, struct line const *b) - return diff_reversed (diff, key->reverse); +@@ -2653,6 +3091,181 @@ keycompare (struct line const *a, struct + return key->reverse ? -diff : diff; } +#if HAVE_MBRTOWC @@ -2957,14 +3163,45 @@ index 05d00cc..eb51f20 100644 + wchar_t wc_a, wc_b; + mbstate_t state_a, state_b; + -+ int diff = 0; ++ int diff; + + memset (&state_a, '\0', sizeof(mbstate_t)); + memset (&state_b, '\0', sizeof(mbstate_t)); -+ /* Ignore keys with start after end. */ -+ if (a->keybeg - a->keylim > 0) -+ return 0; + ++ for (;;) ++ { ++ char const *translate = key->translate; ++ bool const *ignore = key->ignore; ++ ++ /* Find the lengths. */ ++ size_t lena = lima <= texta ? 0 : lima - texta; ++ size_t lenb = limb <= textb ? 0 : limb - textb; ++ ++ /* Actually compare the fields. */ ++ if (key->random) ++ diff = compare_random (texta, lena, textb, lenb); ++ else if (key->numeric | key->general_numeric | key->human_numeric) ++ { ++ char savea = *lima, saveb = *limb; ++ ++ *lima = *limb = '\0'; ++ diff = (key->numeric ? numcompare (texta, textb) ++ : key->general_numeric ? general_numcompare (texta, textb) ++ : human_numcompare (texta, textb)); ++ *lima = savea, *limb = saveb; ++ } ++ else if (key->version) ++ diff = filevercmp (texta, textb); ++ else if (key->month) ++ diff = getmonth (texta, lena, NULL) - getmonth (textb, lenb, NULL); ++ else ++ { ++ if (ignore || translate) ++ { ++ char *copy_a = (char *) xmalloc (lena + 1 + lenb + 1); ++ char *copy_b = copy_a + lena + 1; ++ size_t new_len_a, new_len_b; ++ size_t i, j; + + /* Ignore and/or translate chars before comparing. */ +# define IGNORE_CHARS(NEW_LEN, LEN, TEXT, COPY, WC, MBLENGTH, STATE) \ @@ -3032,81 +3269,19 @@ index 05d00cc..eb51f20 100644 + COPY[NEW_LEN] = '\0'; \ + } \ + while (0) -+ -+ /* Actually compare the fields. */ -+ -+ for (;;) -+ { -+ /* Find the lengths. */ -+ size_t lena = lima <= texta ? 0 : lima - texta; -+ size_t lenb = limb <= textb ? 0 : limb - textb; -+ -+ char enda IF_LINT (= 0); -+ char endb IF_LINT (= 0); -+ -+ char const *translate = key->translate; -+ bool const *ignore = key->ignore; -+ -+ if (ignore || translate) -+ { -+ if (SIZE_MAX - lenb - 2 < lena) -+ xalloc_die (); -+ char *copy_a = (char *) xnmalloc (lena + lenb + 2, MB_CUR_MAX); -+ char *copy_b = copy_a + lena * MB_CUR_MAX + 1; -+ size_t new_len_a, new_len_b; -+ size_t i, j; -+ -+ IGNORE_CHARS (new_len_a, lena, texta, copy_a, -+ wc_a, mblength_a, state_a); -+ IGNORE_CHARS (new_len_b, lenb, textb, copy_b, -+ wc_b, mblength_b, state_b); -+ texta = copy_a; textb = copy_b; -+ lena = new_len_a; lenb = new_len_b; -+ } -+ else -+ { -+ /* Use the keys in-place, temporarily null-terminated. */ -+ enda = texta[lena]; texta[lena] = '\0'; -+ endb = textb[lenb]; textb[lenb] = '\0'; -+ } -+ -+ if (key->random) -+ diff = compare_random (texta, lena, textb, lenb); -+ else if (key->numeric | key->general_numeric | key->human_numeric) -+ { -+ char savea = *lima, saveb = *limb; -+ -+ *lima = *limb = '\0'; -+ diff = (key->numeric ? numcompare (texta, textb) -+ : key->general_numeric ? general_numcompare (texta, textb) -+ : human_numcompare (texta, textb)); -+ *lima = savea, *limb = saveb; -+ } -+ else if (key->version) -+ diff = filevercmp (texta, textb); -+ else if (key->month) -+ diff = getmonth (texta, lena, NULL) - getmonth (textb, lenb, NULL); -+ else if (lena == 0) -+ diff = - NONZERO (lenb); -+ else if (lenb == 0) -+ diff = 1; -+ else if (hard_LC_COLLATE && !folding) -+ { -+ diff = xmemcoll0 (texta, lena + 1, textb, lenb + 1); -+ } -+ else -+ { -+ diff = memcmp (texta, textb, MIN (lena, lenb)); -+ if (diff == 0) -+ diff = lena < lenb ? -1 : lena != lenb; -+ } -+ -+ if (ignore || translate) -+ free (texta); -+ else -+ { -+ texta[lena] = enda; -+ textb[lenb] = endb; ++ IGNORE_CHARS (new_len_a, lena, texta, copy_a, ++ wc_a, mblength_a, state_a); ++ IGNORE_CHARS (new_len_b, lenb, textb, copy_b, ++ wc_b, mblength_b, state_b); ++ diff = xmemcoll (copy_a, new_len_a, copy_b, new_len_b); ++ free(copy_a); ++ } ++ else if (lena == 0) ++ diff = - NONZERO (lenb); ++ else if (lenb == 0) ++ goto greater; ++ else ++ diff = xmemcoll (texta, lena, textb, lenb); + } + + if (diff) @@ -3137,35 +3312,19 @@ index 05d00cc..eb51f20 100644 + } + } + ++ return 0; ++ ++greater: ++ diff = 1; +not_equal: -+ if (key && key->reverse) -+ return -diff; -+ else -+ return diff; ++ return key->reverse ? -diff : diff; +} +#endif + /* Compare two lines A and B, returning negative, zero, or positive depending on whether A compares less than, equal to, or greater than B. */ -@@ -2968,7 +3612,7 @@ compare (struct line const *a, struct line const *b) - diff = - NONZERO (blen); - else if (blen == 0) - diff = 1; -- else if (hard_LC_COLLATE) -+ else if (hard_LC_COLLATE && !folding) - { - /* xmemcoll0 is a performance enhancement as - it will not unconditionally write '\0' after the -@@ -4340,6 +4984,7 @@ set_ordering (char const *s, struct keyfield *key, enum blanktype blanktype) - break; - case 'f': - key->translate = fold_toupper; -+ folding = true; - break; - case 'g': - key->general_numeric = true; -@@ -4419,7 +5064,7 @@ main (int argc, char **argv) +@@ -4113,7 +4726,7 @@ main (int argc, char **argv) initialize_exit_failure (SORT_FAILURE); hard_LC_COLLATE = hard_locale (LC_COLLATE); @@ -3174,8 +3333,8 @@ index 05d00cc..eb51f20 100644 hard_LC_TIME = hard_locale (LC_TIME); #endif -@@ -4442,6 +5087,29 @@ main (int argc, char **argv) - thousands_sep = NON_CHAR; +@@ -4134,6 +4747,29 @@ main (int argc, char **argv) + thousands_sep = -1; } +#if HAVE_MBRTOWC @@ -3204,7 +3363,7 @@ index 05d00cc..eb51f20 100644 have_read_stdin = false; inittables (); -@@ -4717,13 +5385,34 @@ main (int argc, char **argv) +@@ -4404,13 +5040,34 @@ main (int argc, char **argv) case 't': { @@ -3237,19 +3396,20 @@ index 05d00cc..eb51f20 100644 +#endif + if (newtab_length == 1 && optarg[1]) { - if (streq (optarg, "\\0")) + if (STREQ (optarg, "\\0")) - newtab = '\0'; + newtab[0] = '\0'; else { - /* Provoke with 'sort -txx'. Complain about -@@ -4734,9 +5423,11 @@ main (int argc, char **argv) + /* Provoke with `sort -txx'. Complain about +@@ -4421,9 +5078,12 @@ main (int argc, char **argv) quote (optarg)); } } - if (tab != TAB_DEFAULT && tab != newtab) -+ if (tab_length && (tab_length != newtab_length -+ || memcmp (tab, newtab, tab_length) != 0)) ++ if (tab_length ++ && (tab_length != newtab_length ++ || memcmp (tab, newtab, tab_length) != 0)) error (SORT_FAILURE, 0, _("incompatible tabs")); - tab = newtab; + memcpy (tab, newtab, newtab_length); @@ -3257,1027 +3417,783 @@ index 05d00cc..eb51f20 100644 } break; -diff --git a/src/unexpand.c b/src/unexpand.c -index ff234d7..7c36ef6 100644 ---- a/src/unexpand.c -+++ b/src/unexpand.c -@@ -39,6 +39,9 @@ +diff -urNp coreutils-8.15-orig/src/unexpand.c coreutils-8.15/src/unexpand.c +--- coreutils-8.15-orig/src/unexpand.c 2012-01-01 10:04:06.000000000 +0100 ++++ coreutils-8.15/src/unexpand.c 2013-01-30 13:40:37.358398268 +0100 +@@ -39,12 +39,29 @@ #include #include #include + -+#include ++/* Get mbstate_t, mbrtowc(), wcwidth(). */ ++#if HAVE_WCHAR_H ++# include ++#endif + #include "system.h" - #include "expand-common.h" + #include "error.h" + #include "fadvise.h" + #include "quote.h" + #include "xstrndup.h" -@@ -105,24 +108,46 @@ unexpand (void) - { - /* Input stream. */ - FILE *fp = next_file (nullptr); -+ mb_file_t mbf; - - /* The array of pending blanks. In non-POSIX locales, blanks can - include characters other than spaces, so the blanks must be - stored, not merely counted. */ -- char *pending_blank; -+ mbf_char_t *pending_blank; -+ /* True if the starting locale is utf8. */ -+ bool using_utf_locale; ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC ++ installation; work around this configuration error. */ ++#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 ++# define MB_LEN_MAX 16 ++#endif + -+ /* True if the first file contains BOM header. */ -+ bool found_bom; -+ using_utf_locale=check_utf_locale(); - - if (!fp) - return; - -+ mbf_init (mbf, fp); -+ found_bom=check_bom(fp,&mbf); ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ ++#if HAVE_MBRTOWC && defined mbstate_t ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) ++#endif + -+ if (using_utf_locale == false && found_bom == true) + /* The official name of this program (e.g., no `g' prefix). */ + #define PROGRAM_NAME "unexpand" + +@@ -104,6 +121,208 @@ static struct option const longopts[] = + {NULL, 0, NULL, 0} + }; + ++static FILE *next_file (FILE *fp); ++ ++#if HAVE_MBRTOWC ++static void ++unexpand_multibyte (void) ++{ ++ FILE *fp; /* Input stream. */ ++ mbstate_t i_state; /* Current shift state of the input stream. */ ++ mbstate_t i_state_bak; /* Back up the I_STATE. */ ++ mbstate_t o_state; /* Current shift state of the output stream. */ ++ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */ ++ char *bufpos = buf; /* Next read position of BUF. */ ++ size_t buflen = 0; /* The length of the byte sequence in buf. */ ++ wint_t wc; /* A gotten wide character. */ ++ size_t mblength; /* The byte size of a multibyte character ++ which shows as same character as WC. */ ++ ++ /* Index in `tab_list' of next tabstop: */ ++ int tab_index = 0; /* For calculating width of pending tabs. */ ++ int print_tab_index = 0; /* For printing as many tabs as possible. */ ++ unsigned int column = 0; /* Column on screen of next char. */ ++ int next_tab_column; /* Column the next tab stop is on. */ ++ int convert = 1; /* If nonzero, perform translations. */ ++ unsigned int pending = 0; /* Pending columns of blanks. */ ++ ++ fp = next_file ((FILE *) NULL); ++ if (fp == NULL) ++ return; ++ ++ memset (&o_state, '\0', sizeof(mbstate_t)); ++ memset (&i_state, '\0', sizeof(mbstate_t)); ++ ++ for (;;) + { -+ /* Try using some predefined locale */ -+ if (set_utf_locale () != 0) ++ if (buflen < MB_LEN_MAX && !feof(fp) && !ferror(fp)) ++ { ++ memmove (buf, bufpos, buflen); ++ buflen += fread (buf + buflen, sizeof(char), BUFSIZ, fp); ++ bufpos = buf; ++ } ++ ++ /* Get a wide character. */ ++ if (buflen < 1) ++ { ++ mblength = 1; ++ wc = WEOF; ++ } ++ else ++ { ++ i_state_bak = i_state; ++ mblength = mbrtowc ((wchar_t *)&wc, bufpos, buflen, &i_state); ++ } ++ ++ if (mblength == (size_t)-1 || mblength == (size_t)-2) ++ { ++ i_state = i_state_bak; ++ wc = L'\0'; ++ } ++ ++ if (wc == L' ' && convert && column < INT_MAX) ++ { ++ ++pending; ++ ++column; ++ } ++ else if (wc == L'\t' && convert) ++ { ++ if (tab_size == 0) ++ { ++ /* Do not let tab_index == first_free_tab; ++ stop when it is 1 less. */ ++ while (tab_index < first_free_tab - 1 ++ && column >= tab_list[tab_index]) ++ tab_index++; ++ next_tab_column = tab_list[tab_index]; ++ if (tab_index < first_free_tab - 1) ++ tab_index++; ++ if (column >= next_tab_column) ++ { ++ convert = 0; /* Ran out of tab stops. */ ++ goto flush_pend_mb; ++ } ++ } ++ else ++ { ++ next_tab_column = column + tab_size - column % tab_size; ++ } ++ pending += next_tab_column - column; ++ column = next_tab_column; ++ } ++ else ++ { ++flush_pend_mb: ++ /* Flush pending spaces. Print as many tabs as possible, ++ then print the rest as spaces. */ ++ if (pending == 1) ++ { ++ putchar (' '); ++ pending = 0; ++ } ++ column -= pending; ++ while (pending > 0) ++ { ++ if (tab_size == 0) ++ { ++ /* Do not let print_tab_index == first_free_tab; ++ stop when it is 1 less. */ ++ while (print_tab_index < first_free_tab - 1 ++ && column >= tab_list[print_tab_index]) ++ print_tab_index++; ++ next_tab_column = tab_list[print_tab_index]; ++ if (print_tab_index < first_free_tab - 1) ++ print_tab_index++; ++ } ++ else ++ { ++ next_tab_column = ++ column + tab_size - column % tab_size; ++ } ++ if (next_tab_column - column <= pending) ++ { ++ putchar ('\t'); ++ pending -= next_tab_column - column; ++ column = next_tab_column; ++ } ++ else ++ { ++ --print_tab_index; ++ column += pending; ++ while (pending != 0) ++ { ++ putchar (' '); ++ pending--; ++ } ++ } ++ } ++ ++ if (wc == WEOF) ++ { ++ fp = next_file (fp); ++ if (fp == NULL) ++ break; /* No more files. */ ++ else ++ { ++ memset (&i_state, '\0', sizeof(mbstate_t)); ++ continue; ++ } ++ } ++ ++ if (mblength == (size_t)-1 || mblength == (size_t)-2) ++ { ++ if (convert) ++ { ++ ++column; ++ if (convert_entire_line == 0) ++ convert = 0; ++ } ++ mblength = 1; ++ putchar (buf[0]); ++ } ++ else if (mblength == 0) ++ { ++ if (convert && convert_entire_line == 0) ++ convert = 0; ++ mblength = 1; ++ putchar ('\0'); ++ } ++ else ++ { ++ if (convert) ++ { ++ if (wc == L'\b') ++ { ++ if (column > 0) ++ --column; ++ } ++ else ++ { ++ int width; /* The width of WC. */ ++ ++ width = wcwidth (wc); ++ column += (width > 0) ? width : 0; ++ if (convert_entire_line == 0) ++ convert = 0; ++ } ++ } ++ ++ if (wc == L'\n') ++ { ++ tab_index = print_tab_index = 0; ++ column = pending = 0; ++ convert = 1; ++ } ++ fwrite (bufpos, sizeof(char), mblength, stdout); ++ } ++ } ++ buflen -= mblength; ++ bufpos += mblength; ++ } ++} ++#endif ++ ++ + void + usage (int status) + { +@@ -526,7 +745,12 @@ main (int argc, char **argv) + + file_list = (optind < argc ? &argv[optind] : stdin_argv); + +- unexpand (); ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ unexpand_multibyte (); ++ else ++#endif ++ unexpand (); + + if (have_read_stdin && fclose (stdin) != 0) + error (EXIT_FAILURE, errno, "-"); +diff -urNp coreutils-8.15-orig/src/uniq.c coreutils-8.15/src/uniq.c +--- coreutils-8.15-orig/src/uniq.c 2012-01-01 10:04:06.000000000 +0100 ++++ coreutils-8.15/src/uniq.c 2013-01-30 15:54:04.584020982 +0100 +@@ -21,6 +21,16 @@ + #include + #include + ++/* Get mbstate_t, mbrtowc(). */ ++#if HAVE_WCHAR_H ++# include ++#endif ++ ++/* Get isw* functions. */ ++#if HAVE_WCTYPE_H ++# include ++#endif ++ + #include "system.h" + #include "argmatch.h" + #include "linebuffer.h" +@@ -32,7 +42,19 @@ + #include "stdio--.h" + #include "xmemcoll.h" + #include "xstrtol.h" +-#include "memcasecmp.h" ++#include "xmemcoll.h" ++ ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC ++ installation; work around this configuration error. */ ++#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 ++# define MB_LEN_MAX 16 ++#endif ++ ++/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ ++#if HAVE_MBRTOWC && defined mbstate_t ++# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) ++#endif ++ + + /* The official name of this program (e.g., no `g' prefix). */ + #define PROGRAM_NAME "uniq" +@@ -108,6 +130,10 @@ static enum delimit_method const delimit + /* Select whether/how to delimit groups of duplicate lines. */ + static enum delimit_method delimit_groups; + ++/* Function pointers. */ ++static char * ++(*find_field) (struct linebuffer *line); ++ + static struct option const longopts[] = + { + {"count", no_argument, NULL, 'c'}, +@@ -207,7 +233,7 @@ size_opt (char const *opt, char const *m + return a pointer to the beginning of the line's field to be compared. */ + + static char * _GL_ATTRIBUTE_PURE +-find_field (struct linebuffer const *line) ++find_field_uni (struct linebuffer *line) + { + size_t count; + char const *lp = line->buffer; +@@ -227,6 +253,83 @@ find_field (struct linebuffer const *lin + return line->buffer + i; + } + ++#if HAVE_MBRTOWC ++ ++# define MBCHAR_TO_WCHAR(WC, MBLENGTH, LP, POS, SIZE, STATEP, CONVFAIL) \ ++ do \ ++ { \ ++ mbstate_t state_bak; \ ++ \ ++ CONVFAIL = 0; \ ++ state_bak = *STATEP; \ ++ \ ++ MBLENGTH = mbrtowc (&WC, LP + POS, SIZE - POS, STATEP); \ ++ \ ++ switch (MBLENGTH) \ ++ { \ ++ case (size_t)-2: \ ++ case (size_t)-1: \ ++ *STATEP = state_bak; \ ++ CONVFAIL++; \ ++ /* Fall through */ \ ++ case 0: \ ++ MBLENGTH = 1; \ ++ } \ ++ } \ ++ while (0) ++ ++static char * ++find_field_multi (struct linebuffer *line) ++{ ++ size_t count; ++ char *lp = line->buffer; ++ size_t size = line->length - 1; ++ size_t pos; ++ size_t mblength; ++ wchar_t wc; ++ mbstate_t *statep; ++ int convfail = 0; ++ ++ pos = 0; ++ statep = &(line->state); ++ ++ /* skip fields. */ ++ for (count = 0; count < skip_fields && pos < size; count++) ++ { ++ while (pos < size) + { -+ error (EXIT_FAILURE, errno, _("cannot set UTF-8 locale")); ++ MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); ++ ++ if (convfail || !iswblank (wc)) ++ { ++ pos += mblength; ++ break; ++ } ++ pos += mblength; ++ } ++ ++ while (pos < size) ++ { ++ MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); ++ ++ if (!convfail && iswblank (wc)) ++ break; ++ ++ pos += mblength; + } + } + - /* The worst case is a non-blank character, then one blank, then a - tab stop, then MAX_COLUMN_WIDTH - 1 blanks, then a non-blank; so - allocate MAX_COLUMN_WIDTH bytes to store the blanks. */ -- pending_blank = ximalloc (max_column_width); -+ pending_blank = ximalloc (max_column_width * sizeof (mbf_char_t)); ++ /* skip fields. */ ++ for (count = 0; count < skip_chars && pos < size; count++) ++ { ++ MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); ++ pos += mblength; ++ } + -+ if (found_bom == true) -+ print_bom(); ++ return lp + pos; ++} ++#endif ++ + /* Return false if two strings OLD and NEW match, true if not. + OLD and NEW point not to the beginnings of the lines + but rather to the beginnings of the fields to compare. +@@ -235,6 +338,8 @@ find_field (struct linebuffer const *lin + static bool + different (char *old, char *new, size_t oldlen, size_t newlen) + { ++ char *copy_old, *copy_new; ++ + if (check_chars < oldlen) + oldlen = check_chars; + if (check_chars < newlen) +@@ -242,14 +347,100 @@ different (char *old, char *new, size_t - while (true) + if (ignore_case) { - /* Input character, or EOF. */ -- int c; -+ mbf_char_t c; - - /* If true, perform translations. */ - bool convert = true; -@@ -156,12 +181,44 @@ unexpand (void) - - do - { -- while ((c = getc (fp)) < 0 && (fp = next_file (fp))) -- continue; -+ while (true) { -+ mbf_getc (c, mbf); -+ if ((mb_iseof (c)) && (fp = next_file (fp))) -+ { -+ mbf_init (mbf, fp); -+ if (fp!=NULL) -+ { -+ if (check_bom(fp,&mbf)==true) -+ { -+ /*Not the first file - check BOM header*/ -+ if (using_utf_locale==false && found_bom==false) -+ { -+ /*BOM header in subsequent file but not in the first one. */ -+ error (EXIT_FAILURE, errno, _("combination of files with and without BOM header")); -+ } -+ } -+ else -+ { -+ if(using_utf_locale==false && found_bom==true) -+ { -+ /*First file conatined BOM header - locale was switched to UTF -+ *all subsequent files should contain BOM. */ -+ error (EXIT_FAILURE, errno, _("combination of files with and without BOM header")); -+ } -+ } -+ } -+ continue; -+ } -+ else -+ { -+ break; -+ } -+ } +- /* FIXME: This should invoke strcoll somehow. */ +- return oldlen != newlen || memcasecmp (old, new, oldlen); ++ size_t i; + - - if (convert) - { -- bool blank = !! isblank (c); -+ bool blank = mb_isblank (c); - - if (blank) - { -@@ -175,16 +232,16 @@ unexpand (void) - - if (convert) - { -- if (c == '\t') -+ if (mb_iseq (c, '\t')) - { - column = next_tab_column; - - if (pending) -- pending_blank[0] = '\t'; -+ mb_setascii (&pending_blank[0], '\t'); - } - else - { -- column++; -+ column += mb_width (c); - - if (! (prev_blank && column == next_tab_column)) - { -@@ -192,13 +249,14 @@ unexpand (void) - will be replaced by tabs. */ - if (column == next_tab_column) - one_blank_before_tab_stop = true; -- pending_blank[pending++] = c; -+ mb_copy (&pending_blank[pending++], &c); - prev_blank = true; - continue; - } - - /* Replace the pending blanks by a tab or two. */ -- pending_blank[0] = c = '\t'; -+ mb_setascii (&c, '\t'); -+ mb_setascii (&pending_blank[0], '\t'); - } - - /* Discard pending blanks, unless it was a single -@@ -206,7 +264,7 @@ unexpand (void) - pending = one_blank_before_tab_stop; - } - } -- else if (c == '\b') -+ else if (mb_iseq (c, '\b')) - { - /* Go back one column, and force recalculation of the - next tab stop. */ -@@ -216,16 +274,20 @@ unexpand (void) - } - else - { -- column++; -- if (!column) -+ const uintmax_t orig_column = column; -+ column += mb_width (c); -+ if (column < orig_column) - error (EXIT_FAILURE, 0, _("input line is too long")); - } - - if (pending) - { - if (pending > 1 && one_blank_before_tab_stop) -- pending_blank[0] = '\t'; -- if (fwrite (pending_blank, 1, pending, stdout) != pending) -+ mb_setascii (&pending_blank[0], '\t'); ++ copy_old = xmalloc (oldlen + 1); ++ copy_new = xmalloc (oldlen + 1); + -+ for (int n = 0; n < pending; ++n) -+ mb_putc (pending_blank[n], stdout); -+ if (ferror (stdout)) - write_error (); - pending = 0; - one_blank_before_tab_stop = false; -@@ -235,16 +297,17 @@ unexpand (void) - convert &= convert_entire_line || blank; - } - -- if (c < 0) -+ if (mb_iseof (c)) - { - free (pending_blank); - return; - } - -- if (putchar (c) < 0) -+ mb_putc (c, stdout); -+ if (ferror (stdout)) - write_error (); - } -- while (c != '\n'); -+ while (!mb_iseq (c, '\n')); ++ for (i = 0; i < oldlen; i++) ++ { ++ copy_old[i] = toupper (old[i]); ++ copy_new[i] = toupper (new[i]); ++ } ++ bool rc = xmemcoll (copy_old, oldlen, copy_new, newlen); ++ free (copy_old); ++ free (copy_new); ++ return rc; } +- else if (hard_LC_COLLATE) +- return xmemcoll (old, oldlen, new, newlen) != 0; + else +- return oldlen != newlen || memcmp (old, new, oldlen); ++ { ++ copy_old = (char *)old; ++ copy_new = (char *)new; ++ } ++ ++ return xmemcoll (copy_old, oldlen, copy_new, newlen); ++} ++ ++#if HAVE_MBRTOWC ++static int ++different_multi (const char *old, const char *new, size_t oldlen, size_t newlen, mbstate_t oldstate, mbstate_t newstate) ++{ ++ size_t i, j, chars; ++ const char *str[2]; ++ char *copy[2]; ++ size_t len[2]; ++ mbstate_t state[2]; ++ size_t mblength; ++ wchar_t wc, uwc; ++ mbstate_t state_bak; ++ ++ str[0] = old; ++ str[1] = new; ++ len[0] = oldlen; ++ len[1] = newlen; ++ state[0] = oldstate; ++ state[1] = newstate; ++ ++ for (i = 0; i < 2; i++) ++ { ++ copy[i] = xmalloc (len[i] + 1); ++ ++ for (j = 0, chars = 0; j < len[i] && chars < check_chars; chars++) ++ { ++ state_bak = state[i]; ++ mblength = mbrtowc (&wc, str[i] + j, len[i] - j, &(state[i])); ++ ++ switch (mblength) ++ { ++ case (size_t)-1: ++ case (size_t)-2: ++ state[i] = state_bak; ++ /* Fall through */ ++ case 0: ++ mblength = 1; ++ break; ++ ++ default: ++ if (ignore_case) ++ { ++ uwc = towupper (wc); ++ ++ if (uwc != wc) ++ { ++ mbstate_t state_wc; ++ ++ memset (&state_wc, '\0', sizeof(mbstate_t)); ++ wcrtomb (copy[i] + j, uwc, &state_wc); ++ } ++ else ++ memcpy (copy[i] + j, str[i] + j, mblength); ++ } ++ else ++ memcpy (copy[i] + j, str[i] + j, mblength); ++ } ++ j += mblength; ++ } ++ copy[i][j] = '\0'; ++ len[i] = j; ++ } ++ ++ int rc = xmemcoll (copy[0], len[0], copy[1], len[1]); ++ free (copy[0]); ++ free (copy[1]); ++ return rc; ++ } ++#endif -diff --git a/tests/Coreutils.pm b/tests/Coreutils.pm -index b55fb9d..ac80f49 100644 ---- a/tests/Coreutils.pm -+++ b/tests/Coreutils.pm -@@ -269,6 +269,9 @@ sub run_tests ($$$$$) - # Yes, this is an arbitrary limit. If it causes trouble, - # consider removing it. - my $max = 30; -+ # The downstream i18n multi-byte tests have a "-mb" suffix. -+ # Therefore add 3 to the maximum test name length. -+ $max += 3; - if ($max < length $test_name) + /* Output the line in linebuffer LINE to standard output + provided that the switches say it should be output. +@@ -305,15 +496,43 @@ check_file (const char *infile, const ch + { + char *prevfield IF_LINT ( = NULL); + size_t prevlen IF_LINT ( = 0); ++#if HAVE_MBRTOWC ++ mbstate_t prevstate; ++ ++ memset (&prevstate, '\0', sizeof (mbstate_t)); ++#endif + + while (!feof (stdin)) { - warn "$program_name: $test_name: test name is too long (> $max)\n"; -diff --git a/tests/expand/mb.sh b/tests/expand/mb.sh -new file mode 100644 -index 0000000..dd6007c ---- /dev/null -+++ b/tests/expand/mb.sh -@@ -0,0 +1,183 @@ -+#!/bin/sh + char *thisfield; + size_t thislen; ++#if HAVE_MBRTOWC ++ mbstate_t thisstate; ++#endif + -+# Copyright (C) 2012-2015 Free Software Foundation, Inc. + if (readlinebuffer_delim (thisline, stdin, delimiter) == 0) + break; + thisfield = find_field (thisline); + thislen = thisline->length - 1 - (thisfield - thisline->buffer); ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ { ++ thisstate = thisline->state; + -+# 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. ++ if (prevline->length == 0 || different_multi ++ (thisfield, prevfield, thislen, prevlen, thisstate, prevstate)) ++ { ++ fwrite (thisline->buffer, sizeof (char), ++ thisline->length, stdout); + -+# 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_ expand -+ -+export LC_ALL=en_US.UTF-8 -+ -+#input containing multibyte characters -+cat <<\EOF > in || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+EOF -+env printf ' äöü\t. öüä. \tä xx\n' >> in || framework_failure_ -+ -+cat <<\EOF > exp || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+ -+expand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+#multiple files as an input -+cat <<\EOF >> exp || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+ -+expand ./in ./in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+#test characters with display widths != 1 -+env printf '12345678 -+e\t|ascii(1) -+\u00E9\t|composed(1) -+e\u0301\t|decomposed(1) -+\u3000\t|ideo-space(2) -+\uFF0D\t|full-hypen(2) -+' > in || framework_failure_ -+ -+env printf '12345678 -+e |ascii(1) -+\u00E9 |composed(1) -+e\u0301 |decomposed(1) -+\u3000 |ideo-space(2) -+\uFF0D |full-hypen(2) -+' > exp || framework_failure_ -+ -+expand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+#shouldn't fail with "input line too long" -+#when a line starts with a control character -+env printf '\n' > in || framework_failure_ -+ -+expand < in > out || fail=1 -+compare in out > /dev/null 2>&1 || fail=1 -+ -+#non-Unicode characters interspersed between Unicode ones -+env printf '12345678 -+\t\xFF| -+\xFF\t| -+\t\xFFä| -+ä\xFF\t| -+\tä\xFF| -+\xFF\tä| -+äbcdef\xFF\t| -+' > in || framework_failure_ -+ -+env printf '12345678 -+ \xFF| -+\xFF | -+ \xFFä| -+ä\xFF | -+ ä\xFF| -+\xFF ä| -+äbcdef\xFF | -+' > exp || framework_failure_ -+ -+expand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+ -+ -+#BOM header test 1 -+printf "\xEF\xBB\xBF" > in; cat <<\EOF >> in || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+EOF -+env printf ' äöü\t. öüä. \tä xx\n' >> in || framework_failure_ -+ -+printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+ -+ -+expand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LANG=C expand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LC_ALL=C expand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+ -+printf '\xEF\xBB\xBF' > in1; cat <<\EOF >> in1 || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+EOF -+env printf ' äöü\t. öüä. \tä xx\n' >> in1 || framework_failure_ -+ -+ -+printf '\xEF\xBB\xBF' > exp; cat <<\EOF >> exp || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+ -+expand in1 in1 > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LANG=C expand in1 in1 > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LC_ALL=C expand in1 in1 > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+exit $fail -diff --git a/tests/i18n/sort.sh b/tests/i18n/sort.sh -new file mode 100644 -index 0000000..26c95de ---- /dev/null -+++ b/tests/i18n/sort.sh -@@ -0,0 +1,29 @@ -+#!/bin/sh -+# Verify sort's multi-byte support. -+ -+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src -+print_ver_ sort -+ -+export LC_ALL=en_US.UTF-8 -+locale -k LC_CTYPE | grep -q "charmap.*UTF-8" \ -+ || skip_ "No UTF-8 locale available" -+ -+# Enable heap consistency checkng on older systems -+export MALLOC_CHECK_=2 -+ -+ -+# check buffer overflow issue due to -+# expanding multi-byte representation due to case conversion -+# https://bugzilla.suse.com/show_bug.cgi?id=928749 -+cat < exp -+. -+ɑ -+EOF -+cat < out || fail=1 -+. -+ɑ -+EOF -+compare exp out || { fail=1; cat out; } -+ -+ -+Exit $fail -diff --git a/tests/local.mk b/tests/local.mk -index 53fc53e..0148422 100644 ---- a/tests/local.mk -+++ b/tests/local.mk -@@ -412,6 +412,8 @@ all_tests = \ - tests/sort/sort-field-limit.sh \ - tests/sort/sort-files0-from.pl \ - tests/sort/sort-float.sh \ -+ tests/misc/sort-mb-tests.sh \ -+ tests/i18n/sort.sh \ - tests/sort/sort-h-thousands-sep.sh \ - tests/sort/sort-merge.pl \ - tests/sort/sort-merge-fdlimit.sh \ -@@ -618,6 +620,7 @@ all_tests = \ - tests/du/threshold.sh \ - tests/du/trailing-slash.sh \ - tests/du/two-args.sh \ -+ tests/expand/mb.sh \ - tests/id/gnu-zero-uids.sh \ - tests/id/no-context.sh \ - tests/id/context.sh \ -@@ -774,6 +777,7 @@ all_tests = \ - tests/touch/read-only.sh \ - tests/touch/relative.sh \ - tests/touch/trailing-slash.sh \ -+ tests/unexpand/mb.sh \ - $(all_root_tests) - - # See tests/factor/create-test.sh. -diff --git a/tests/misc/expand.pl b/tests/misc/expand.pl -index 4b07210..68b9ea1 100755 ---- a/tests/misc/expand.pl -+++ b/tests/misc/expand.pl -@@ -27,6 +27,15 @@ my $prog = 'expand'; - # Turn off localization of executable's output. - @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; - -+#comment out next line to disable multibyte tests -+my $mb_locale = $ENV{LOCALE_FR_UTF8}; -+! defined $mb_locale || $mb_locale eq 'none' -+ and $mb_locale = 'C'; -+ -+my $prog = 'expand'; -+my $try = "Try \`$prog --help' for more information.\n"; -+my $inval = "$prog: invalid byte, character or field list\n$try"; -+ - my @Tests = - ( - ['t1', '--tabs=3', {IN=>"a\tb"}, {OUT=>"a b"}], -@@ -168,6 +177,8 @@ my @Tests = - - - # Test errors -+ # FIXME: The following tests contain ‘quoting’ specific to LC_MESSAGES -+ # So we force LC_MESSAGES=C to make them pass. - ['e1', '--tabs="a"', {IN=>''}, {OUT=>''}, {EXIT=>1}, - {ERR => "$prog: tab size contains invalid character(s): 'a'\n"}], - ['e2', "-t $UINTMAX_OFLOW", {IN=>''}, {OUT=>''}, {EXIT=>1}, -@@ -184,6 +195,37 @@ my @Tests = - {ERR => "$prog: '/' specifier not at start of number: '/'\n"}], - ); - -+if ($mb_locale ne 'C') -+ { -+ # Duplicate each test vector, appending "-mb" to the test name and -+ # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we -+ # provide coverage for the distro-added multi-byte code paths. -+ my @new; -+ foreach my $t (@Tests) -+ { -+ my @new_t = @$t; -+ my $test_name = shift @new_t; -+ -+ # Depending on whether expand is multi-byte-patched, -+ # it emits different diagnostics: -+ # non-MB: invalid byte or field list -+ # MB: invalid byte, character or field list -+ # Adjust the expected error output accordingly. -+ if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval} -+ (@new_t)) -+ { -+ my $sub = {ERR_SUBST => 's/, character//'}; -+ push @new_t, $sub; -+ push @$t, $sub; ++ SWAP_LINES (prevline, thisline); ++ prevfield = thisfield; ++ prevlen = thislen; ++ prevstate = thisstate; ++ } + } -+ push @new, ["$test_name-mb", @new_t, {ENV => "LANG=$mb_locale LC_MESSAGES=C"}]; -+ } -+ push @Tests, @new; -+ } -+ -+ -+@Tests = triple_test \@Tests; -+ - my $save_temps = $ENV{DEBUG}; - my $verbose = $ENV{VERBOSE}; ++ else ++#endif + if (prevline->length == 0 + || different (thisfield, prevfield, thislen, prevlen)) + { +@@ -332,17 +551,26 @@ check_file (const char *infile, const ch + size_t prevlen; + uintmax_t match_count = 0; + bool first_delimiter = true; ++#if HAVE_MBRTOWC ++ mbstate_t prevstate; ++#endif -diff --git a/tests/misc/sort-mb-tests.sh b/tests/misc/sort-mb-tests.sh -new file mode 100644 -index 0000000..11836ba ---- /dev/null -+++ b/tests/misc/sort-mb-tests.sh -@@ -0,0 +1,45 @@ -+#!/bin/sh -+# Verify sort's multi-byte support. -+ -+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src -+print_ver_ sort -+ -+export LC_ALL=en_US.UTF-8 -+locale -k LC_CTYPE | grep -q "charmap.*UTF-8" \ -+ || skip_ "No UTF-8 locale available" -+ -+ -+cat < exp -+Banana@5 -+Apple@10 -+Citrus@20 -+Cherry@30 -+EOF -+ -+cat < out || fail=1 -+Apple@10 -+Banana@5 -+Citrus@20 -+Cherry@30 -+EOF -+ -+compare exp out || { fail=1; cat out; } -+ -+ -+cat < exp -+Citrus@AA20@@5 -+Cherry@AA30@@10 -+Apple@AA10@@20 -+Banana@AA5@@30 -+EOF -+ -+cat < out || fail=1 -+Apple@AA10@@20 -+Banana@AA5@@30 -+Citrus@AA20@@5 -+Cherry@AA30@@10 -+EOF -+ -+compare exp out || { fail=1; cat out; } -+ -+Exit $fail -diff --git a/tests/misc/unexpand.pl b/tests/misc/unexpand.pl -index bb7469c..c1dec95 100755 ---- a/tests/misc/unexpand.pl -+++ b/tests/misc/unexpand.pl -@@ -27,6 +27,14 @@ my $limits = getlimits (); + if (readlinebuffer_delim (prevline, stdin, delimiter) == 0) + goto closefiles; + prevfield = find_field (prevline); + prevlen = prevline->length - 1 - (prevfield - prevline->buffer); ++#if HAVE_MBRTOWC ++ prevstate = prevline->state; ++#endif - my $prog = 'unexpand'; + while (!feof (stdin)) + { + bool match; + char *thisfield; + size_t thislen; ++#if HAVE_MBRTOWC ++ mbstate_t thisstate = thisline->state; ++#endif + if (readlinebuffer_delim (thisline, stdin, delimiter) == 0) + { + if (ferror (stdin)) +@@ -351,6 +579,14 @@ check_file (const char *infile, const ch + } + thisfield = find_field (thisline); + thislen = thisline->length - 1 - (thisfield - thisline->buffer); ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ { ++ match = !different_multi (thisfield, prevfield, ++ thislen, prevlen, thisstate, prevstate); ++ } ++ else ++#endif + match = !different (thisfield, prevfield, thislen, prevlen); + match_count += match; -+# comment out next line to disable multibyte tests -+my $mb_locale = $ENV{LOCALE_FR_UTF8}; -+! defined $mb_locale || $mb_locale eq 'none' -+ and $mb_locale = 'C'; -+ -+my $try = "Try \`$prog --help' for more information.\n"; -+my $inval = "$prog: invalid byte, character or field list\n$try"; -+ - my @Tests = - ( - ['a1', {IN=> ' 'x 1 ."y\n"}, {OUT=> ' 'x 1 ."y\n"}], -@@ -132,6 +140,37 @@ my @Tests = - ['ts2', '-t5,8', {IN=>"x\t \t y\n"}, {OUT=>"x\t\t y\n"}], - ); +@@ -383,6 +619,9 @@ check_file (const char *infile, const ch + SWAP_LINES (prevline, thisline); + prevfield = thisfield; + prevlen = thislen; ++#if HAVE_MBRTOWC ++ prevstate = thisstate; ++#endif + if (!match) + match_count = 0; + } +@@ -428,6 +667,19 @@ main (int argc, char **argv) -+if ($mb_locale ne 'C') -+ { -+ # Duplicate each test vector, appending "-mb" to the test name and -+ # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we -+ # provide coverage for the distro-added multi-byte code paths. -+ my @new; -+ foreach my $t (@Tests) -+ { -+ my @new_t = @$t; -+ my $test_name = shift @new_t; -+ -+ # Depending on whether unexpand is multi-byte-patched, -+ # it emits different diagnostics: -+ # non-MB: invalid byte or field list -+ # MB: invalid byte, character or field list -+ # Adjust the expected error output accordingly. -+ if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval} -+ (@new_t)) -+ { -+ my $sub = {ERR_SUBST => 's/, character//'}; -+ push @new_t, $sub; -+ push @$t, $sub; -+ } -+ next if ($test_name =~ 'b-1'); -+ push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}]; -+ } -+ push @Tests, @new; -+ } -+ -+@Tests = triple_test \@Tests; -+ - my $save_temps = $ENV{DEBUG}; - my $verbose = $ENV{VERBOSE}; + atexit (close_stdout); -diff --git a/tests/pr/pr-tests.pl b/tests/pr/pr-tests.pl -index 60e6106..3c64a08 100755 ---- a/tests/pr/pr-tests.pl -+++ b/tests/pr/pr-tests.pl -@@ -24,6 +24,15 @@ use strict; - my $prog = 'pr'; - my $normalize_strerror = "s/': .*/'/"; ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ { ++ find_field = find_field_multi; ++ } ++ else ++#endif ++ { ++ find_field = find_field_uni; ++ } ++ ++ ++ + skip_chars = 0; + skip_fields = 0; + check_chars = SIZE_MAX; +diff -urNp coreutils-8.15-orig/tests/Makefile.am coreutils-8.15/tests/Makefile.am +--- coreutils-8.15-orig/tests/Makefile.am 2013-01-30 13:39:59.940175847 +0100 ++++ coreutils-8.15/tests/Makefile.am 2013-01-30 13:40:37.361294753 +0100 +@@ -240,6 +240,7 @@ TESTS = \ + misc/sort-debug-keys \ + misc/sort-debug-warn \ + misc/sort-files0-from \ ++ misc/sort-mb-tests \ + misc/sort-float \ + misc/sort-merge \ + misc/sort-merge-fdlimit \ +@@ -529,6 +530,10 @@ TESTS = \ + $(root_tests) -+my $mb_locale; -+#Uncomment the following line to enable multibyte tests -+$mb_locale = $ENV{LOCALE_FR_UTF8}; -+! defined $mb_locale || $mb_locale eq 'none' -+ and $mb_locale = 'C'; -+ -+my $try = "Try \`$prog --help' for more information.\n"; -+my $inval = "$prog: invalid byte, character or field list\n$try"; -+ - my @tv = ( - - # -b option is no longer an official option. But it's still working to -@@ -515,8 +524,48 @@ push @Tests, - {IN=>"x\tx\tx\tx\tx\nx\tx\tx\tx\tx\n"}, - {OUT=>"x\tx\tx\tx\tx\tx\tx\tx\tx\tx\n"} ]; - -+# Add _POSIX2_VERSION=199209 to the environment of each test -+# that uses an old-style option like +1. -+if ($mb_locale ne 'C') -+ { -+ # Duplicate each test vector, appending "-mb" to the test name and -+ # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we -+ # provide coverage for the distro-added multi-byte code paths. -+ my @new; -+ foreach my $t (@Tests) -+ { -+ my @new_t = @$t; -+ my $test_name = shift @new_t; -+ -+ # Depending on whether pr is multi-byte-patched, -+ # it emits different diagnostics: -+ # non-MB: invalid byte or field list -+ # MB: invalid byte, character or field list -+ # Adjust the expected error output accordingly. -+ if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval} -+ (@new_t)) -+ { -+ my $sub = {ERR_SUBST => 's/, character//'}; -+ push @new_t, $sub; -+ push @$t, $sub; -+ } -+ #temporarily skip some failing tests -+ next if ($test_name =~ "col-0" or $test_name =~ "col-inval" or $test_name =~ "asan1"); -+ push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}]; -+ } -+ push @Tests, @new; -+ } -+ - @Tests = triple_test \@Tests; - -+# Remember that triple_test creates from each test with exactly one "IN" -+# file two more tests (.p and .r suffix on name) corresponding to reading -+# input from a file and from a pipe. The pipe-reading test would fail -+# due to a race condition about 1 in 20 times. -+# Remove the IN_PIPE version of the "output-is-input" test above. -+# The others aren't susceptible because they have three inputs each. -+@Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests; -+ - my $save_temps = $ENV{DEBUG}; - my $verbose = $ENV{VERBOSE}; - -diff --git a/tests/sort/sort-merge.pl b/tests/sort/sort-merge.pl -index a3204d3..40942a5 100755 ---- a/tests/sort/sort-merge.pl -+++ b/tests/sort/sort-merge.pl -@@ -26,6 +26,15 @@ my $prog = 'sort'; - # Turn off localization of executable's output. - @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; - -+my $mb_locale; -+# uncommented according to upstream commit enabling multibyte paths -+$mb_locale = $ENV{LOCALE_FR_UTF8}; -+! defined $mb_locale || $mb_locale eq 'none' -+ and $mb_locale = 'C'; -+ -+my $try = "Try \`$prog --help' for more information.\n"; -+my $inval = "$prog: invalid byte, character or field list\n$try"; -+ - # three empty files and one that says 'foo' - my @inputs = (+(map{{IN=> {"empty$_"=> ''}}}1..3), {IN=> {foo=> "foo\n"}}); - -@@ -77,6 +86,39 @@ my @Tests = - {OUT=>$big_input}], - ); - -+# Add _POSIX2_VERSION=199209 to the environment of each test -+# that uses an old-style option like +1. -+if ($mb_locale ne 'C') -+ { -+ # Duplicate each test vector, appending "-mb" to the test name and -+ # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we -+ # provide coverage for the distro-added multi-byte code paths. -+ my @new; -+ foreach my $t (@Tests) -+ { -+ my @new_t = @$t; -+ my $test_name = shift @new_t; -+ -+ # Depending on whether sort is multi-byte-patched, -+ # it emits different diagnostics: -+ # non-MB: invalid byte or field list -+ # MB: invalid byte, character or field list -+ # Adjust the expected error output accordingly. -+ if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval} -+ (@new_t)) -+ { -+ my $sub = {ERR_SUBST => 's/, character//'}; -+ push @new_t, $sub; -+ push @$t, $sub; -+ } -+ next if ($test_name =~ "nmerge-."); -+ push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}]; -+ } -+ push @Tests, @new; -+ } -+ -+@Tests = triple_test \@Tests; -+ - my $save_temps = $ENV{DEBUG}; - my $verbose = $ENV{VERBOSE}; - -diff --git a/tests/sort/sort.pl b/tests/sort/sort.pl -index 5fa9d52..a66952a 100755 ---- a/tests/sort/sort.pl -+++ b/tests/sort/sort.pl -@@ -24,10 +24,15 @@ my $prog = 'sort'; + pr_data = \ ++ misc/mb1.X \ ++ misc/mb1.I \ ++ misc/mb2.X \ ++ misc/mb2.I \ + pr/0F \ + pr/0FF \ + pr/0FFnt \ +diff -urNp coreutils-8.15-orig/tests/misc/cut coreutils-8.15/tests/misc/cut +--- coreutils-8.15-orig/tests/misc/cut 2012-01-01 10:04:06.000000000 +0100 ++++ coreutils-8.15/tests/misc/cut 2013-01-30 13:40:37.361294753 +0100 +@@ -23,14 +23,15 @@ use strict; # Turn off localization of executable's output. @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; -my $mb_locale = $ENV{LOCALE_FR_UTF8}; -+my $mb_locale; -+#Comment out next line to disable multibyte tests -+$mb_locale = $ENV{LOCALE_FR_UTF8}; - ! defined $mb_locale || $mb_locale eq 'none' - and $mb_locale = 'C'; +-! defined $mb_locale || $mb_locale eq 'none' +- and $mb_locale = 'C'; ++#my $mb_locale = $ENV{LOCALE_FR_UTF8}; ++#! defined $mb_locale || $mb_locale eq 'none' ++# and $mb_locale = 'C'; ++my $mb_locale = 'C'; -+my $try = "Try \`$prog --help' for more information.\n"; + my $prog = 'cut'; + my $try = "Try \`$prog --help' for more information.\n"; + my $from_1 = "$prog: fields and positions are numbered from 1\n$try"; +-my $inval = "$prog: invalid byte or field list\n$try"; +my $inval = "$prog: invalid byte, character or field list\n$try"; -+ - # Since each test is run with a file name and with redirected stdin, - # the name in the diagnostic is either the file name or "-". - # Normalize each diagnostic to use '-'. -@@ -428,6 +433,38 @@ foreach my $t (@Tests) - } - } + my $no_endpoint = "$prog: invalid range with no endpoint: -\n$try"; -+if ($mb_locale ne 'C') -+ { -+ # Duplicate each test vector, appending "-mb" to the test name and -+ # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we -+ # provide coverage for the distro-added multi-byte code paths. -+ my @new; -+ foreach my $t (@Tests) -+ { -+ my @new_t = @$t; -+ my $test_name = shift @new_t; -+ -+ # Depending on whether sort is multi-byte-patched, -+ # it emits different diagnostics: -+ # non-MB: invalid byte or field list -+ # MB: invalid byte, character or field list -+ # Adjust the expected error output accordingly. -+ if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval} -+ (@new_t)) -+ { -+ my $sub = {ERR_SUBST => 's/, character//'}; -+ push @new_t, $sub; -+ push @$t, $sub; -+ } -+ #disable several failing tests until investigation, disable all tests with envvars set -+ next if (grep {ref $_ eq 'HASH' && exists $_->{ENV}} (@new_t)); -+ next if ($test_name =~ "18g" or $test_name =~ "sort-numeric" or $test_name =~ "08[ab]" or $test_name =~ "03[def]" or $test_name =~ "h4" or $test_name =~ "n1" or $test_name =~ "2[01]a"); -+ next if ($test_name =~ "11[ab]"); # avoid FP: expected result differs to MB result due to collation rules. -+ push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}]; -+ } -+ push @Tests, @new; -+ } -+ - @Tests = triple_test \@Tests; + my @Tests = +@@ -147,7 +148,7 @@ my @Tests = - # Remember that triple_test creates from each test with exactly one "IN" -@@ -437,6 +474,7 @@ foreach my $t (@Tests) - # Remove the IN_PIPE version of the "output-is-input" test above. - # The others aren't susceptible because they have three inputs each. - @Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests; -+@Tests = grep {$_->[0] ne 'output-is-input-mb.p'} @Tests; - - my $save_temps = $ENV{DEBUG}; - my $verbose = $ENV{VERBOSE}; -diff --git a/tests/unexpand/mb.sh b/tests/unexpand/mb.sh -new file mode 100644 -index 0000000..8a82d74 ---- /dev/null -+++ b/tests/unexpand/mb.sh -@@ -0,0 +1,172 @@ -+#!/bin/sh -+ -+# Copyright (C) 2012-2015 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_ unexpand + # None of the following invalid ranges provoked an error up to coreutils-6.9. + ['inval1', qw(-f 2-0), {IN=>''}, {OUT=>''}, {EXIT=>1}, +- {ERR=>"$prog: invalid decreasing range\n$try"}], ++ {ERR=>"$prog: invalid byte, character or field list\n$try"}], + ['inval2', qw(-f -), {IN=>''}, {OUT=>''}, {EXIT=>1}, {ERR=>$no_endpoint}], + ['inval3', '-f', '4,-', {IN=>''}, {OUT=>''}, {EXIT=>1}, {ERR=>$no_endpoint}], + ['inval4', '-f', '1-2,-', {IN=>''}, {OUT=>''}, {EXIT=>1}, +diff -urNp coreutils-8.15-orig/tests/misc/mb1.I coreutils-8.15/tests/misc/mb1.I +--- coreutils-8.15-orig/tests/misc/mb1.I 1970-01-01 01:00:00.000000000 +0100 ++++ coreutils-8.15/tests/misc/mb1.I 2013-01-30 13:40:37.362395749 +0100 +@@ -0,0 +1,4 @@ ++Apple@10 ++Banana@5 ++Citrus@20 ++Cherry@30 +diff -urNp coreutils-8.15-orig/tests/misc/mb1.X coreutils-8.15/tests/misc/mb1.X +--- coreutils-8.15-orig/tests/misc/mb1.X 1970-01-01 01:00:00.000000000 +0100 ++++ coreutils-8.15/tests/misc/mb1.X 2013-01-30 13:40:37.363395657 +0100 +@@ -0,0 +1,4 @@ ++Banana@5 ++Apple@10 ++Citrus@20 ++Cherry@30 +diff -urNp coreutils-8.15-orig/tests/misc/mb2.I coreutils-8.15/tests/misc/mb2.I +--- coreutils-8.15-orig/tests/misc/mb2.I 1970-01-01 01:00:00.000000000 +0100 ++++ coreutils-8.15/tests/misc/mb2.I 2013-01-30 13:40:37.363395657 +0100 +@@ -0,0 +1,4 @@ ++Apple@AA10@@20 ++Banana@AA5@@30 ++Citrus@AA20@@5 ++Cherry@AA30@@10 +diff -urNp coreutils-8.15-orig/tests/misc/mb2.X coreutils-8.15/tests/misc/mb2.X +--- coreutils-8.15-orig/tests/misc/mb2.X 1970-01-01 01:00:00.000000000 +0100 ++++ coreutils-8.15/tests/misc/mb2.X 2013-01-30 13:40:37.364411214 +0100 +@@ -0,0 +1,4 @@ ++Citrus@AA20@@5 ++Cherry@AA30@@10 ++Apple@AA10@@20 ++Banana@AA5@@30 +diff -urNp coreutils-8.15-orig/tests/misc/sort-mb-tests coreutils-8.15/tests/misc/sort-mb-tests +--- coreutils-8.15-orig/tests/misc/sort-mb-tests 1970-01-01 01:00:00.000000000 +0100 ++++ coreutils-8.15/tests/misc/sort-mb-tests 2013-01-30 13:40:37.365177992 +0100 +@@ -0,0 +1,58 @@ ++#! /bin/sh ++case $# in ++ 0) xx='../src/sort';; ++ *) xx="$1";; ++esac ++test "$VERBOSE" && echo=echo || echo=: ++$echo testing program: $xx ++errors=0 ++test "$srcdir" || srcdir=. ++test "$VERBOSE" && $xx --version 2> /dev/null + +export LC_ALL=en_US.UTF-8 ++locale -k LC_CTYPE 2>&1 | grep -q charmap.*UTF-8 || exit 77 ++errors=0 + -+#input containing multibyte characters -+cat > in <<\EOF -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF ++$xx -t @ -k2 -n misc/mb1.I > misc/mb1.O ++code=$? ++if test $code != 0; then ++ $echo "Test mb1 failed: $xx return code $code differs from expected value 0" ++ errors=`expr $errors + 1` ++else ++ cmp misc/mb1.O $srcdir/misc/mb1.X > /dev/null 2>&1 ++ case $? in ++ 0) if test "$VERBOSE"; then $echo "passed mb1"; fi;; ++ 1) $echo "Test mb1 failed: files misc/mb1.O and $srcdir/misc/mb1.X differ" 1>&2 ++ (diff -c misc/mb1.O $srcdir/misc/mb1.X) 2> /dev/null ++ errors=`expr $errors + 1`;; ++ 2) $echo "Test mb1 may have failed." 1>&2 ++ $echo The command "cmp misc/mb1.O $srcdir/misc/mb1.X" failed. 1>&2 ++ errors=`expr $errors + 1`;; ++ esac ++fi + -+cat > exp <<\EOF -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF ++$xx -t @ -k4 -n misc/mb2.I > misc/mb2.O ++code=$? ++if test $code != 0; then ++ $echo "Test mb2 failed: $xx return code $code differs from expected value 0" 1>&2 ++ errors=`expr $errors + 1` ++else ++ cmp misc/mb2.O $srcdir/misc/mb2.X > /dev/null 2>&1 ++ case $? in ++ 0) if test "$VERBOSE"; then $echo "passed mb2"; fi;; ++ 1) $echo "Test mb2 failed: files misc/mb2.O and $srcdir/misc/mb2.X differ" 1>&2 ++ (diff -c misc/mb2.O $srcdir/misc/mb2.X) 2> /dev/null ++ errors=`expr $errors + 1`;; ++ 2) $echo "Test mb2 may have failed." 1>&2 ++ $echo The command "cmp misc/mb2.O $srcdir/misc/mb2.X" failed. 1>&2 ++ errors=`expr $errors + 1`;; ++ esac ++fi + -+unexpand -a < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+ -+#multiple files as an input -+cat >> exp <<\EOF -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+ -+ -+unexpand -a ./in ./in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+#test characters with a display width larger than 1 -+ -+env printf '12345678 -+e |ascii(1) -+\u00E9 |composed(1) -+e\u0301 |decomposed(1) -+\u3000 |ideo-space(2) -+\uFF0D |full-hypen(2) -+' > in || framework_failure_ -+ -+env printf '12345678 -+e\t|ascii(1) -+\u00E9\t|composed(1) -+e\u0301\t|decomposed(1) -+\u3000\t|ideo-space(2) -+\uFF0D\t|full-hypen(2) -+' > exp || framework_failure_ -+ -+unexpand -a < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+#test input where a blank of width > 1 is not being substituted -+in="$(LC_ALL=en_US.UTF-8 printf ' \u3000 ö ü ß')" -+exp='   ö ü ß' -+ -+unexpand -a < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+#non-Unicode characters interspersed between Unicode ones -+env printf '12345678 -+ \xFF| -+\xFF | -+ \xFFä| -+ä\xFF | -+ ä\xFF| -+\xFF ä| -+äbcdef\xFF | -+' > in || framework_failure_ -+ -+env printf '12345678 -+\t\xFF| -+\xFF\t| -+\t\xFFä| -+ä\xFF\t| -+\tä\xFF| -+\xFF\tä| -+äbcdef\xFF\t| -+' > exp || framework_failure_ -+ -+unexpand -a < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+#BOM header test 1 -+printf "\xEF\xBB\xBF" > in; cat <<\EOF >> in || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+env printf ' äöü\t. öüä. \tä xx\n' >> in || framework_failure_ -+ -+printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+ -+unexpand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LANG=C unexpand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LC_ALL=C unexpand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+ -+printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+ -+ -+unexpand in in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LANG=C unexpand in in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LC_ALL=C unexpand in in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 --- -2.52.0 - ++if test $errors = 0; then ++ $echo Passed all 113 tests. 1>&2 ++else ++ $echo Failed $errors tests. 1>&2 ++fi ++test $errors = 0 || errors=1 ++exit $errors diff --git a/coreutils-keyring.gpg b/coreutils-keyring.gpg deleted file mode 100644 index 003a885..0000000 --- a/coreutils-keyring.gpg +++ /dev/null @@ -1,312 +0,0 @@ -Release GPG keyring of coreutils group. - ------BEGIN PGP PUBLIC KEY BLOCK----- - -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 -ELphkzjc6eM3CaOZ73u4GVXotheeUabUHQ== -=drvb ------END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/coreutils-overflow.patch b/coreutils-overflow.patch new file mode 100644 index 0000000..0d55a6d --- /dev/null +++ b/coreutils-overflow.patch @@ -0,0 +1,11 @@ +--- coreutils-5.2.1/src/who.c.overflow 2005-05-25 09:59:06.000000000 +0100 ++++ coreutils-5.2.1/src/who.c 2005-05-25 10:00:31.000000000 +0100 +@@ -75,7 +75,7 @@ + # define UT_TYPE_NEW_TIME(U) false + #endif + +-#define IDLESTR_LEN 6 ++#define IDLESTR_LEN 10 + + #if HAVE_STRUCT_XTMP_UT_PID + # define PIDSTR_DECL_AND_INIT(Var, Utmp_ent) \ diff --git a/coreutils-python3.patch b/coreutils-python3.patch deleted file mode 100644 index 447fdbc..0000000 --- a/coreutils-python3.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 8927d505ecb5334f09c48ef98ef1f464f581d0f7 Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Tue, 2 Apr 2024 14:11:26 +0100 -Subject: [PATCH] coreutils-python3.patch - ---- - init.cfg | 4 ++-- - tests/d_type-check | 2 +- - tests/du/move-dir-while-traversing.sh | 6 +++--- - 3 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/init.cfg b/init.cfg -index ac05f7b..26d9516 100644 ---- a/init.cfg -+++ b/init.cfg -@@ -601,10 +601,10 @@ seek_data_capable_() - # Skip the current test if "." lacks d_type support. - require_dirent_d_type_() - { -- python < /dev/null \ -+ python3 < /dev/null \ - || skip_ python missing: assuming no d_type support - -- python "$abs_srcdir"/tests/d_type-check \ -+ python3 "$abs_srcdir"/tests/d_type-check \ - || skip_ requires d_type support - } - -diff --git a/tests/d_type-check b/tests/d_type-check -index 1a2f76f..42d3924 100644 ---- a/tests/d_type-check -+++ b/tests/d_type-check -@@ -1,4 +1,4 @@ --#!/usr/bin/python -+#!/usr/bin/python3 - # Exit 0 if "." and "./tempfile" have useful d_type information, else 1. - # Intended to exit 0 only on Linux/GNU systems. - import os -diff --git a/tests/du/move-dir-while-traversing.sh b/tests/du/move-dir-while-traversing.sh -index adf482b..cf9214a 100755 ---- a/tests/du/move-dir-while-traversing.sh -+++ b/tests/du/move-dir-while-traversing.sh -@@ -21,8 +21,8 @@ print_ver_ du - require_trap_signame_ - - # We use a python-inotify script, so... --python -m pyinotify -h > /dev/null \ -- || skip_ 'python inotify package not installed' -+python3 -m pyinotify -h > /dev/null \ -+ || skip_ 'python3 inotify package not installed' - - # Move a directory "up" while du is processing its sub-directories. - # While du is processing a hierarchy .../B/C/D/... this script -@@ -33,7 +33,7 @@ python -m pyinotify -h > /dev/null \ - # rename syscall before du finishes processing the subtree under D/. - - cat <<'EOF' > inotify-watch-for-dir-access.py --#!/usr/bin/env python -+#!/usr/bin/env python3 - import pyinotify as pn - import os,sys - --- -2.51.0 - diff --git a/coreutils-runuser-l.pamd b/coreutils-runuser-l.pamd new file mode 100644 index 0000000..fa1e4d8 --- /dev/null +++ b/coreutils-runuser-l.pamd @@ -0,0 +1,4 @@ +#%PAM-1.0 +auth include runuser +session optional pam_keyinit.so force revoke +session include runuser diff --git a/coreutils-runuser.pamd b/coreutils-runuser.pamd new file mode 100644 index 0000000..37f0e84 --- /dev/null +++ b/coreutils-runuser.pamd @@ -0,0 +1,5 @@ +#%PAM-1.0 +auth sufficient pam_rootok.so +session optional pam_keyinit.so revoke +session required pam_limits.so +session required pam_unix.so diff --git a/coreutils-selinux.patch b/coreutils-selinux.patch new file mode 100644 index 0000000..3e5c143 --- /dev/null +++ b/coreutils-selinux.patch @@ -0,0 +1,656 @@ +diff -urNp coreutils-8.13-orig/configure.ac coreutils-8.13/configure.ac +--- coreutils-8.13-orig/configure.ac 2011-09-09 10:29:52.584690353 +0200 ++++ coreutils-8.13/configure.ac 2011-09-09 10:30:39.524564991 +0200 +@@ -141,6 +141,13 @@ if test "$gl_gcc_warnings" = yes; then + AC_SUBST([GNULIB_TEST_WARN_CFLAGS]) + fi + ++dnl Give the chance to enable SELINUX ++AC_ARG_ENABLE(selinux, dnl ++[ --enable-selinux Enable use of the SELINUX libraries], ++[AC_DEFINE(WITH_SELINUX, 1, [Define if you want to use SELINUX]) ++LIB_SELINUX="-lselinux" ++AC_SUBST(LIB_SELINUX)]) ++ + AC_FUNC_FORK + + AC_ARG_ENABLE(pam, AS_HELP_STRING([--disable-pam], +diff -urNp coreutils-8.13-orig/man/chcon.x coreutils-8.13/man/chcon.x +--- coreutils-8.13-orig/man/chcon.x 2009-09-01 13:01:16.000000000 +0200 ++++ coreutils-8.13/man/chcon.x 2011-09-09 10:30:39.524564991 +0200 +@@ -1,4 +1,4 @@ + [NAME] +-chcon \- change file security context ++chcon \- change file SELinux security context + [DESCRIPTION] + .\" Add any additional description here +diff -urNp coreutils-8.13-orig/man/runcon.x coreutils-8.13/man/runcon.x +--- coreutils-8.13-orig/man/runcon.x 2009-09-01 13:01:16.000000000 +0200 ++++ coreutils-8.13/man/runcon.x 2011-09-09 10:30:39.544686472 +0200 +@@ -1,5 +1,5 @@ + [NAME] +-runcon \- run command with specified security context ++runcon \- run command with specified SELinux security context + [DESCRIPTION] + Run COMMAND with completely-specified CONTEXT, or with current or + transitioned security context modified by one or more of LEVEL, +diff -urNp coreutils-8.13-orig/src/chcon.c coreutils-8.13/src/chcon.c +--- coreutils-8.13-orig/src/chcon.c 2011-07-28 12:38:27.000000000 +0200 ++++ coreutils-8.13/src/chcon.c 2011-09-09 10:30:39.562561252 +0200 +@@ -356,7 +356,7 @@ Usage: %s [OPTION]... CONTEXT FILE...\n\ + "), + program_name, program_name, program_name); + fputs (_("\ +-Change the security context of each FILE to CONTEXT.\n\ ++Change the SELinux security context of each FILE to CONTEXT.\n\ + With --reference, change the security context of each FILE to that of RFILE.\n\ + \n\ + "), stdout); +diff -urNp coreutils-8.13-orig/src/copy.c coreutils-8.13/src/copy.c +--- coreutils-8.13-orig/src/copy.c 2011-07-28 12:38:27.000000000 +0200 ++++ coreutils-8.13/src/copy.c 2011-09-09 10:30:39.564562214 +0200 +@@ -2244,6 +2244,8 @@ copy_internal (char const *src_name, cha + { + /* Here, we are crossing a file system boundary and cp's -x option + is in effect: so don't copy the contents of this directory. */ ++ if (x->preserve_security_context) ++ restore_default_fscreatecon_or_die (); + } + else + { +diff -urNp coreutils-8.13-orig/src/copy.h coreutils-8.13/src/copy.h +--- coreutils-8.13-orig/src/copy.h 2011-07-28 12:38:27.000000000 +0200 ++++ coreutils-8.13/src/copy.h 2011-09-09 10:30:39.565563712 +0200 +@@ -158,6 +158,9 @@ struct cp_options + bool preserve_mode; + bool preserve_timestamps; + ++ /* If true, attempt to set specified security context */ ++ bool set_security_context; ++ + /* Enabled for mv, and for cp by the --preserve=links option. + If true, attempt to preserve in the destination files any + logical hard links between the source files. If used with cp's +diff -urNp coreutils-8.13-orig/src/cp.c coreutils-8.13/src/cp.c +--- coreutils-8.13-orig/src/cp.c 2011-07-28 12:38:27.000000000 +0200 ++++ coreutils-8.13/src/cp.c 2011-09-09 10:30:39.566562062 +0200 +@@ -141,6 +141,7 @@ static struct option const long_opts[] = + {"target-directory", required_argument, NULL, 't'}, + {"update", no_argument, NULL, 'u'}, + {"verbose", no_argument, NULL, 'v'}, ++ {"context", required_argument, NULL, 'Z'}, + {GETOPT_HELP_OPTION_DECL}, + {GETOPT_VERSION_OPTION_DECL}, + {NULL, 0, NULL, 0} +@@ -204,6 +205,9 @@ Mandatory arguments to long options are + all\n\ + "), stdout); + fputs (_("\ ++ -c same as --preserve=context\n\ ++"), stdout); ++ fputs (_("\ + --no-preserve=ATTR_LIST don't preserve the specified attributes\n\ + --parents use full source file name under DIRECTORY\n\ + "), stdout); +@@ -230,6 +234,7 @@ Mandatory arguments to long options are + destination file is missing\n\ + -v, --verbose explain what is being done\n\ + -x, --one-file-system stay on this file system\n\ ++ -Z, --context=CONTEXT set security context of copy to CONTEXT\n\ + "), stdout); + fputs (HELP_OPTION_DESCRIPTION, stdout); + fputs (VERSION_OPTION_DESCRIPTION, stdout); +@@ -786,6 +791,7 @@ cp_option_init (struct cp_options *x) + x->preserve_timestamps = false; + x->preserve_security_context = false; + x->require_preserve_context = false; ++ x->set_security_context = false; + x->preserve_xattr = false; + x->reduce_diagnostics = false; + x->require_preserve_xattr = false; +@@ -933,7 +939,7 @@ main (int argc, char **argv) + we'll actually use backup_suffix_string. */ + backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); + +- while ((c = getopt_long (argc, argv, "abdfHilLnprst:uvxPRS:T", ++ while ((c = getopt_long (argc, argv, "abcdfHilLnprst:uvxPRS:TZ:", + long_opts, NULL)) + != -1) + { +@@ -981,6 +987,16 @@ main (int argc, char **argv) + copy_contents = true; + break; + ++ case 'c': ++ if ( x.set_security_context ) { ++ (void) fprintf(stderr, "%s: cannot force target context and preserve it\n", argv[0]); ++ exit( 1 ); ++ } ++ else if (selinux_enabled) { ++ x.preserve_security_context = true; ++ x.require_preserve_context = true; ++ } ++ break; + case 'd': + x.preserve_links = true; + x.dereference = DEREF_NEVER; +@@ -1090,6 +1106,27 @@ main (int argc, char **argv) + x.one_file_system = true; + break; + ++ ++ case 'Z': ++ /* politely decline if we're not on a selinux-enabled kernel. */ ++ if( !selinux_enabled ) { ++ fprintf( stderr, "Warning: ignoring --context (-Z). " ++ "It requires a SELinux enabled kernel.\n" ); ++ break; ++ } ++ if ( x.preserve_security_context ) { ++ (void) fprintf(stderr, "%s: cannot force target context to '%s' and preserve it\n", argv[0], optarg); ++ exit( 1 ); ++ } ++ x.set_security_context = true; ++ /* if there's a security_context given set new path ++ components to that context, too */ ++ if ( setfscreatecon(optarg) < 0 ) { ++ (void) fprintf(stderr, _("cannot set default security context %s\n"), optarg); ++ exit( 1 ); ++ } ++ break; ++ + case 'S': + make_backups = true; + backup_suffix_string = optarg; +diff -urNp coreutils-8.13-orig/src/id.c coreutils-8.13/src/id.c +--- coreutils-8.13-orig/src/id.c 2011-07-28 12:38:27.000000000 +0200 ++++ coreutils-8.13/src/id.c 2011-09-09 10:30:39.567562153 +0200 +@@ -107,7 +107,7 @@ int + main (int argc, char **argv) + { + int optc; +- int selinux_enabled = (is_selinux_enabled () > 0); ++ bool selinux_enabled = (is_selinux_enabled () > 0); + + /* If true, output the list of all group IDs. -G */ + bool just_group_list = false; +diff -urNp coreutils-8.13-orig/src/install.c coreutils-8.13/src/install.c +--- coreutils-8.13-orig/src/install.c 2011-07-28 12:38:27.000000000 +0200 ++++ coreutils-8.13/src/install.c 2011-09-09 10:30:39.569562422 +0200 +@@ -261,6 +261,7 @@ cp_option_init (struct cp_options *x) + x->data_copy_required = true; + x->require_preserve = false; + x->require_preserve_context = false; ++ x->set_security_context = false; + x->require_preserve_xattr = false; + x->recursive = false; + x->sparse_mode = SPARSE_AUTO; +@@ -622,7 +623,7 @@ Mandatory arguments to long options are + -v, --verbose print the name of each directory as it is created\n\ + "), stdout); + fputs (_("\ +- --preserve-context preserve SELinux security context\n\ ++ -P, --preserve-context preserve SELinux security context\n\ + -Z, --context=CONTEXT set SELinux security context of files and directories\ + \n\ + "), stdout); +@@ -765,7 +766,7 @@ main (int argc, char **argv) + we'll actually use backup_suffix_string. */ + backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); + +- while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pt:TvS:Z:", long_options, ++ while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pPt:TvS:Z:", long_options, + NULL)) != -1) + { + switch (optc) +@@ -835,6 +836,7 @@ main (int argc, char **argv) + no_target_directory = true; + break; + ++ case 'P': + case PRESERVE_CONTEXT_OPTION: + if ( ! selinux_enabled) + { +@@ -842,6 +844,10 @@ main (int argc, char **argv) + "this kernel is not SELinux-enabled")); + break; + } ++ if ( x.set_security_context ) { ++ (void) fprintf(stderr, "%s: cannot force target context and preserve it\n", argv[0]); ++ exit( 1 ); ++ } + x.preserve_security_context = true; + use_default_selinux_context = false; + break; +@@ -853,6 +859,7 @@ main (int argc, char **argv) + break; + } + scontext = optarg; ++ x.set_security_context = true; + use_default_selinux_context = false; + break; + case_GETOPT_HELP_CHAR; +diff -urNp coreutils-8.13-orig/src/ls.c coreutils-8.13/src/ls.c +--- coreutils-8.13-orig/src/ls.c 2011-07-28 12:38:27.000000000 +0200 ++++ coreutils-8.13/src/ls.c 2011-09-09 10:30:39.575562845 +0200 +@@ -166,7 +166,8 @@ enum filetype + symbolic_link, + sock, + whiteout, +- arg_directory ++ arg_directory, ++ command_line + }; + + /* Display letters and indicators for each filetype. +@@ -282,6 +283,7 @@ + bool command_line_arg); + static void sort_files (void); + static void parse_ls_color (void); ++static void print_scontext_format (const struct fileinfo *f); + + /* Initial size of hash table. + Most hierarchies are likely to be shallower than this. */ +@@ -352,7 +354,7 @@ static struct pending *pending_dirs; + + static struct timespec current_time; + +-static bool print_scontext; ++static int print_scontext = 0; + static char UNKNOWN_SECURITY_CONTEXT[] = "?"; + + /* Whether any of the files has an ACL. This affects the width of the +@@ -392,7 +394,9 @@ enum format + one_per_line, /* -1 */ + many_per_line, /* -C */ + horizontal, /* -x */ +- with_commas /* -m */ ++ with_commas, /* -m */ ++ security_format, /* -Z */ ++ invalid_format + }; + + static enum format format; +@@ -794,6 +798,9 @@ enum + SHOW_CONTROL_CHARS_OPTION, + SI_OPTION, + SORT_OPTION, ++ CONTEXT_OPTION, ++ LCONTEXT_OPTION, ++ SCONTEXT_OPTION, + TIME_OPTION, + TIME_STYLE_OPTION + }; +@@ -839,7 +846,9 @@ static struct option const long_options[ + {"time-style", required_argument, NULL, TIME_STYLE_OPTION}, + {"color", optional_argument, NULL, COLOR_OPTION}, + {"block-size", required_argument, NULL, BLOCK_SIZE_OPTION}, +- {"context", no_argument, 0, 'Z'}, ++ {"context", no_argument, 0, CONTEXT_OPTION}, ++ {"lcontext", no_argument, 0, LCONTEXT_OPTION}, ++ {"scontext", no_argument, 0, SCONTEXT_OPTION}, + {"author", no_argument, NULL, AUTHOR_OPTION}, + {GETOPT_HELP_OPTION_DECL}, + {GETOPT_VERSION_OPTION_DECL}, +@@ -849,12 +858,12 @@ static struct option const long_options[ + static char const *const format_args[] = + { + "verbose", "long", "commas", "horizontal", "across", +- "vertical", "single-column", NULL ++ "vertical", "single-column", "context", NULL + }; + static enum format const format_types[] = + { + long_format, long_format, with_commas, horizontal, horizontal, +- many_per_line, one_per_line ++ many_per_line, one_per_line, security_format + }; + ARGMATCH_VERIFY (format_args, format_types); + +@@ -1296,7 +1305,8 @@ main (int argc, char **argv) + /* Avoid following symbolic links when possible. */ + if (is_colored (C_ORPHAN) + || (is_colored (C_EXEC) && color_symlink_as_referent) +- || (is_colored (C_MISSING) && format == long_format)) ++ || (is_colored (C_MISSING) && (format == long_format ++ || format == security_format))) + check_symlink_color = true; + + /* If the standard output is a controlling terminal, watch out +@@ -1343,7 +1353,7 @@ main (int argc, char **argv) + if (dereference == DEREF_UNDEFINED) + dereference = ((immediate_dirs + || indicator_style == classify +- || format == long_format) ++ || format == long_format || format == security_format) + ? DEREF_NEVER + : DEREF_COMMAND_LINE_SYMLINK_TO_DIR); + +@@ -1363,7 +1373,7 @@ main (int argc, char **argv) + + format_needs_stat = sort_type == sort_time || sort_type == sort_size + || format == long_format +- || print_scontext ++ || format == security_format || print_scontext + || print_block_size; + format_needs_type = (! format_needs_stat + && (recursive +@@ -1394,7 +1404,7 @@ main (int argc, char **argv) + } + else + do +- gobble_file (argv[i++], unknown, NOT_AN_INODE_NUMBER, true, ""); ++ gobble_file (argv[i++], command_line, NOT_AN_INODE_NUMBER, true, ""); + while (i < argc); + + if (cwd_n_used) +@@ -1565,7 +1575,7 @@ decode_switches (int argc, char **argv) + ignore_mode = IGNORE_DEFAULT; + ignore_patterns = NULL; + hide_patterns = NULL; +- print_scontext = false; ++ print_scontext = 0; + + /* FIXME: put this in a function. */ + { +@@ -1947,13 +1957,27 @@ decode_switches (int argc, char **argv) + break; + + case 'Z': +- print_scontext = true; ++ print_scontext = 1; ++ format = security_format; + break; + + case_GETOPT_HELP_CHAR; + + case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); + ++ case CONTEXT_OPTION: /* default security context format */ ++ print_scontext = 1; ++ format = security_format; ++ break; ++ case LCONTEXT_OPTION: /* long format plus security context */ ++ print_scontext = 1; ++ format = long_format; ++ break; ++ case SCONTEXT_OPTION: /* short form of new security format */ ++ print_scontext = 0; ++ format = security_format; ++ break; ++ + default: + usage (LS_FAILURE); + } +@@ -2757,6 +2783,7 @@ gobble_file (char const *name, enum file + memset (f, '\0', sizeof *f); + f->stat.st_ino = inode; + f->filetype = type; ++ f->scontext = NULL; + + if (command_line_arg + || format_needs_stat +@@ -2869,7 +2896,7 @@ gobble_file (char const *name, enum file + && print_with_color && is_colored (C_CAP)) + f->has_capability = has_capability (absolute_name); + +- if (format == long_format || print_scontext) ++ if (format == long_format || format == security_format || print_scontext) + { + bool have_selinux = false; + bool have_acl = false; +@@ -2892,7 +2919,7 @@ gobble_file (char const *name, enum file + err = 0; + } + +- if (err == 0 && format == long_format) ++ if (err == 0 && (format == long_format || format == security_format)) + { + int n = file_has_acl (absolute_name, &f->stat); + err = (n < 0); +@@ -2911,7 +2938,8 @@ gobble_file (char const *name, enum file + } + + if (S_ISLNK (f->stat.st_mode) +- && (format == long_format || check_symlink_color)) ++ && (format == long_format || format == security_format ++ || check_symlink_color)) + { + char *linkname; + struct stat linkstats; +@@ -2931,6 +2959,7 @@ gobble_file (char const *name, enum file + command line are automatically traced if not being + listed as files. */ + if (!command_line_arg || format == long_format ++ || format == security_format + || !S_ISDIR (linkstats.st_mode)) + { + /* Get the linked-to file's mode for the filetype indicator +@@ -2970,7 +2999,7 @@ gobble_file (char const *name, enum file + block_size_width = len; + } + +- if (format == long_format) ++ if (format == long_format || format == security_format) + { + if (print_owner) + { +@@ -3471,6 +3500,13 @@ print_current_files (void) + print_long_format (sorted_file[i]); + DIRED_PUTCHAR ('\n'); + } ++ break; ++ case security_format: ++ for (i = 0; i < cwd_n_used; i++) ++ { ++ print_scontext_format (sorted_file[i]); ++ DIRED_PUTCHAR ('\n'); ++ } + break; + } + } +@@ -3633,6 +3669,67 @@ format_inode (char *buf, size_t buflen, + : (char *) "?"); + } + ++/* Print info about f in scontext format */ ++static void ++print_scontext_format (const struct fileinfo *f) ++{ ++ char modebuf[12]; ++ ++ /* 7 fields that may require LONGEST_HUMAN_READABLE bytes, ++ 1 10-byte mode string, ++ 9 spaces, one following each of these fields, and ++ 1 trailing NUL byte. */ ++ ++ char init_bigbuf[7 * LONGEST_HUMAN_READABLE + 10 + 9 + 1]; ++ char *buf = init_bigbuf; ++ char *p; ++ ++ p = buf; ++ ++ if ( print_scontext ) { /* zero means terse listing */ ++ filemodestring (&f->stat, modebuf); ++ if (! any_has_acl) ++ modebuf[10] = '\0'; ++ else if (f->acl_type == ACL_T_SELINUX_ONLY) ++ modebuf[10] = '.'; ++ else if (f->acl_type == ACL_T_YES) ++ modebuf[10] = '+'; ++ modebuf[11] = '\0'; ++ ++ /* print mode */ ++ ++ (void) sprintf (p, "%s ", modebuf); ++ p += strlen (p); ++ ++ /* print standard user and group */ ++ ++ DIRED_FPUTS (buf, stdout, p - buf); ++ format_user (f->stat.st_uid, owner_width, f->stat_ok); ++ format_group (f->stat.st_gid, group_width, f->stat_ok); ++ p = buf; ++ } ++ ++ (void) sprintf (p, "%-32s ", f->scontext ?: ""); ++ p += strlen (p); ++ ++ DIRED_INDENT (); ++ DIRED_FPUTS (buf, stdout, p - buf); ++ size_t w = print_name_with_quoting (f, false, &dired_obstack, p - buf); ++ ++ if (f->filetype == symbolic_link) { ++ if (f->linkname) { ++ DIRED_FPUTS_LITERAL (" -> ", stdout); ++ print_name_with_quoting (f, true, NULL, (p - buf) + w + 4); ++ if (indicator_style != none) ++ print_type_indicator (f->stat_ok, f->linkmode, f->filetype); ++ } ++ } ++ else { ++ if (indicator_style != none) ++ print_type_indicator (f->stat_ok, f->stat.st_mode, f->filetype); ++ } ++} ++ + /* Print information about F in long format. */ + static void + print_long_format (const struct fileinfo *f) +@@ -3724,9 +3821,15 @@ print_long_format (const struct fileinfo + The latter is wrong when nlink_width is zero. */ + p += strlen (p); + ++ if (print_scontext) ++ { ++ sprintf (p, "%-32s ", f->scontext ? f->scontext : ""); ++ p += strlen (p); ++ } ++ + DIRED_INDENT (); + +- if (print_owner || print_group || print_author || print_scontext) ++ if (print_owner || print_group || print_author) + { + DIRED_FPUTS (buf, stdout, p - buf); + +@@ -3739,9 +3842,6 @@ print_long_format (const struct fileinfo + if (print_author) + format_user (f->stat.st_author, author_width, f->stat_ok); + +- if (print_scontext) +- format_user_or_group (f->scontext, 0, scontext_width); +- + p = buf; + } + +@@ -4086,9 +4186,6 @@ print_file_name_and_frills (const struct + : human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts, + ST_NBLOCKSIZE, output_block_size)); + +- if (print_scontext) +- printf ("%*s ", format == with_commas ? 0 : scontext_width, f->scontext); +- + size_t width = print_name_with_quoting (f, false, NULL, start_col); + + if (indicator_style != none) +@@ -4292,9 +4389,6 @@ length_of_file_name_and_frills (const st + output_block_size)) + : block_size_width); + +- if (print_scontext) +- len += 1 + (format == with_commas ? strlen (f->scontext) : scontext_width); +- + quote_name (NULL, f->name, filename_quoting_options, &name_width); + len += name_width; + +@@ -4733,9 +4827,16 @@ Mandatory arguments to long options are + -w, --width=COLS assume screen width instead of current value\n\ + -x list entries by lines instead of by columns\n\ + -X sort alphabetically by entry extension\n\ +- -Z, --context print any SELinux security context of each file\n\ + -1 list one file per line\n\ + "), stdout); ++ fputs(_("\nSELinux options:\n\n\ ++ --lcontext Display security context. Enable -l. Lines\n\ ++ will probably be too wide for most displays.\n\ ++ -Z, --context Display security context so it fits on most\n\ ++ displays. Displays only mode, user, group,\n\ ++ security context and file name.\n\ ++ --scontext Display only security context and file name.\n\ ++"), stdout); + fputs (HELP_OPTION_DESCRIPTION, stdout); + fputs (VERSION_OPTION_DESCRIPTION, stdout); + emit_size_note (); +diff -urNp coreutils-8.13-orig/src/mkdir.c coreutils-8.13/src/mkdir.c +--- coreutils-8.13-orig/src/mkdir.c 2011-07-28 12:38:27.000000000 +0200 ++++ coreutils-8.13/src/mkdir.c 2011-09-09 10:30:39.576564256 +0200 +@@ -38,6 +38,7 @@ + static struct option const longopts[] = + { + {GETOPT_SELINUX_CONTEXT_OPTION_DECL}, ++ {"context", required_argument, NULL, 'Z'}, + {"mode", required_argument, NULL, 'm'}, + {"parents", no_argument, NULL, 'p'}, + {"verbose", no_argument, NULL, 'v'}, +diff -urNp coreutils-8.13-orig/src/mknod.c coreutils-8.13/src/mknod.c +--- coreutils-8.13-orig/src/mknod.c 2011-07-28 12:38:27.000000000 +0200 ++++ coreutils-8.13/src/mknod.c 2011-09-09 10:30:39.577563177 +0200 +@@ -35,7 +35,7 @@ + + static struct option const longopts[] = + { +- {GETOPT_SELINUX_CONTEXT_OPTION_DECL}, ++ {GETOPT_SELINUX_CONTEXT_OPTION_DECL}, + {"mode", required_argument, NULL, 'm'}, + {GETOPT_HELP_OPTION_DECL}, + {GETOPT_VERSION_OPTION_DECL}, +diff -urNp coreutils-8.13-orig/src/mv.c coreutils-8.13/src/mv.c +--- coreutils-8.13-orig/src/mv.c 2011-07-28 12:38:27.000000000 +0200 ++++ coreutils-8.13/src/mv.c 2011-09-09 10:30:39.578562234 +0200 +@@ -118,6 +118,7 @@ cp_option_init (struct cp_options *x) + x->preserve_mode = true; + x->preserve_timestamps = true; + x->preserve_security_context = selinux_enabled; ++ x->set_security_context = false; + x->reduce_diagnostics = false; + x->data_copy_required = true; + x->require_preserve = false; /* FIXME: maybe make this an option */ +diff -urNp coreutils-8.13-orig/src/runcon.c coreutils-8.13/src/runcon.c +--- coreutils-8.13-orig/src/runcon.c 2011-07-28 12:38:27.000000000 +0200 ++++ coreutils-8.13/src/runcon.c 2011-09-09 10:30:39.579564283 +0200 +@@ -86,7 +86,7 @@ Usage: %s CONTEXT COMMAND [args]\n\ + or: %s [ -c ] [-u USER] [-r ROLE] [-t TYPE] [-l RANGE] COMMAND [args]\n\ + "), program_name, program_name); + fputs (_("\ +-Run a program in a different security context.\n\ ++Run a program in a different SELinux security context.\n\ + With neither CONTEXT nor COMMAND, print the current security context.\n\ + \n\ + CONTEXT Complete security context\n\ +diff -urNp coreutils-8.13-orig/tests/init.cfg coreutils-8.13/tests/init.cfg +--- coreutils-8.13-orig/tests/init.cfg 2011-09-07 18:00:55.000000000 +0200 ++++ coreutils-8.13/tests/init.cfg 2011-09-09 10:32:17.031688699 +0200 +@@ -253,8 +253,8 @@ require_selinux_() + + # Independent of whether SELinux is enabled system-wide, + # the current file system may lack SELinux support. +- case `ls -Zd .` in +- '? .'|'unlabeled .') ++ case `ls -Zd . | cut -f4 -d" "` in ++ '?'|'unlabeled') + skip_ "this system (or maybe just" \ + "the current file system) lacks SELinux support" + ;; +diff -urNp coreutils-8.13-orig/tests/misc/selinux coreutils-8.13/tests/misc/selinux +--- coreutils-8.13-orig/tests/misc/selinux 2011-08-08 09:42:16.000000000 +0200 ++++ coreutils-8.13/tests/misc/selinux 2011-09-09 10:30:39.586563144 +0200 +@@ -37,7 +37,7 @@ chcon $ctx f d p || + + # inspect that context with both ls -Z and stat. + for i in d f p; do +- c=`ls -dogZ $i|cut -d' ' -f3`; test x$c = x$ctx || fail=1 ++ c=`ls -dogZ $i|cut -d' ' -f4`; test x$c = x$ctx || fail=1 + c=`stat --printf %C $i`; test x$c = x$ctx || fail=1 + done + diff --git a/coreutils-selinuxmanpages.patch b/coreutils-selinuxmanpages.patch new file mode 100644 index 0000000..9cbc166 --- /dev/null +++ b/coreutils-selinuxmanpages.patch @@ -0,0 +1,15 @@ +diff -urNp coreutils-6.10-orig/doc/coreutils.texi coreutils-6.10/doc/coreutils.texi +--- coreutils-6.10-orig/doc/coreutils.texi 2008-04-07 17:52:11.000000000 +0200 ++++ coreutils-6.10/doc/coreutils.texi 2008-04-07 18:01:43.000000000 +0200 +@@ -6981,6 +6981,11 @@ for i; do + done + @end example + ++@item -c ++@cindex SELinux security context information, preserving ++Preserve SELinux security context of the original files if possible. ++Some file systems don't support storing of SELinux security context. ++ + @item --copy-contents + @cindex directories, copying recursively + @cindex copying directories recursively diff --git a/coreutils-setsid.patch b/coreutils-setsid.patch new file mode 100644 index 0000000..714383f --- /dev/null +++ b/coreutils-setsid.patch @@ -0,0 +1,102 @@ +diff -urNp coreutils-8.6-orig/src/su.c coreutils-8.6/src/su.c +--- coreutils-8.6-orig/src/su.c 2010-11-03 13:56:11.679069689 +0100 ++++ coreutils-8.6/src/su.c 2010-11-03 13:56:45.304325661 +0100 +@@ -153,6 +153,9 @@ static bool simulate_login; + /* If true, change some environment vars to indicate the user su'd to. */ + static bool change_environment; + ++/* If true, then don't call setsid() with a command. */ ++int same_session = 0; ++ + #ifdef USE_PAM + static bool _pam_session_opened; + static bool _pam_cred_established; +@@ -161,6 +164,7 @@ static bool _pam_cred_established; + static struct option const longopts[] = + { + {"command", required_argument, NULL, 'c'}, ++ {"session-command", required_argument, NULL, 'C'}, + {"fast", no_argument, NULL, 'f'}, + {"login", no_argument, NULL, 'l'}, + {"preserve-environment", no_argument, NULL, 'p'}, +@@ -335,14 +339,27 @@ create_watching_parent (void) + sigemptyset (&action.sa_mask); + action.sa_flags = 0; + sigemptyset (&ourset); +- if (sigaddset (&ourset, SIGTERM) +- || sigaddset (&ourset, SIGALRM) +- || sigaction (SIGTERM, &action, NULL) +- || sigprocmask (SIG_UNBLOCK, &ourset, NULL)) +- { ++ if (!same_session) ++ { ++ if (sigaddset(&ourset, SIGINT) || sigaddset(&ourset, SIGQUIT)) ++ { ++ error (0, errno, _("cannot set signal handler")); ++ caught_signal = true; ++ } ++ } ++ if (!caught_signal && (sigaddset(&ourset, SIGTERM) ++ || sigaddset(&ourset, SIGALRM) ++ || sigaction(SIGTERM, &action, NULL) ++ || sigprocmask(SIG_UNBLOCK, &ourset, NULL))) { + error (0, errno, _("cannot set signal handler")); + caught_signal = true; + } ++ if (!caught_signal && !same_session && (sigaction(SIGINT, &action, NULL) ++ || sigaction(SIGQUIT, &action, NULL))) ++ { ++ error (0, errno, _("cannot set signal handler")); ++ caught_signal = true; ++ } + } + if (!caught_signal) + { +@@ -627,6 +644,8 @@ Change the effective user id and group i + \n\ + -, -l, --login make the shell a login shell\n\ + -c, --command=COMMAND pass a single COMMAND to the shell with -c\n\ ++ --session-command=COMMAND pass a single COMMAND to the shell with -c\n\ ++ and do not create a new session\n\ + -f, --fast pass -f to the shell (for csh or tcsh)\n\ + -m, --preserve-environment do not reset environment variables\n\ + -p same as -m\n\ +@@ -649,6 +668,7 @@ main (int argc, char **argv) + int optc; + const char *new_user = DEFAULT_USER; + char *command = NULL; ++ int request_same_session = 0; + char *shell = NULL; + struct passwd *pw; + struct passwd pw_copy; +@@ -674,6 +694,11 @@ main (int argc, char **argv) + command = optarg; + break; + ++ case 'C': ++ command = optarg; ++ request_same_session = 1; ++ break; ++ + case 'f': + fast_startup = true; + break; +@@ -743,6 +768,9 @@ main (int argc, char **argv) + } + #endif + ++ if (request_same_session || !command || !pw->pw_uid) ++ same_session = 1; ++ + if (!shell && !change_environment) + shell = getenv ("SHELL"); + if (shell && getuid () != 0 && restricted_shell (pw->pw_shell)) +@@ -764,6 +792,8 @@ main (int argc, char **argv) + #endif + + change_identity (pw); ++ if (!same_session) ++ setsid (); + + /* Set environment after pam_open_session, which may put KRB5CCNAME + into the pam_env, etc. */ diff --git a/coreutils-su-l.pamd b/coreutils-su-l.pamd new file mode 100644 index 0000000..656a139 --- /dev/null +++ b/coreutils-su-l.pamd @@ -0,0 +1,6 @@ +#%PAM-1.0 +auth include su +account include su +password include su +session optional pam_keyinit.so force revoke +session include su diff --git a/coreutils-su.pamd b/coreutils-su.pamd new file mode 100644 index 0000000..030657f --- /dev/null +++ b/coreutils-su.pamd @@ -0,0 +1,14 @@ +#%PAM-1.0 +auth sufficient pam_rootok.so +# Uncomment the following line to implicitly trust users in the "wheel" group. +#auth sufficient pam_wheel.so trust use_uid +# Uncomment the following line to require a user to be in the "wheel" group. +#auth required pam_wheel.so use_uid +auth substack system-auth +auth include postlogin +account sufficient pam_succeed_if.so uid = 0 use_uid quiet +account include system-auth +password include system-auth +session include system-auth +session include postlogin +session optional pam_xauth.so diff --git a/coreutils.spec b/coreutils.spec index 6712263..067333f 100644 --- a/coreutils.spec +++ b/coreutils.spec @@ -1,1084 +1,456 @@ Summary: A set of basic GNU tools commonly used in shell scripts Name: coreutils -Version: 9.9 -Release: 2%{?dist} -# some used parts of gnulib are under various variants of LGPL -License: GPL-3.0-or-later AND GFDL-1.3-no-invariants-or-later AND LGPL-2.1-or-later AND LGPL-3.0-or-later -Url: https://www.gnu.org/software/coreutils/ -Source0: https://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.xz -Source1: https://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.xz.sig -# From https://savannah.gnu.org/project/release-gpgkeys.php?group=coreutils&download=1 -# which is linked as project keyring on https://savannah.gnu.org/projects/coreutils -Source2: coreutils-keyring.gpg -Source50: supported_utils +Version: 8.15 +Release: 10%{?dist} +License: GPLv3+ +Group: System Environment/Base +Url: http://www.gnu.org/software/coreutils/ +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +Source0: ftp://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.xz +Source101: coreutils-DIR_COLORS +Source102: coreutils-DIR_COLORS.lightbgcolor +Source103: coreutils-DIR_COLORS.256color Source105: coreutils-colorls.sh Source106: coreutils-colorls.csh +Source200: coreutils-su.pamd +Source201: coreutils-runuser.pamd +Source202: coreutils-su-l.pamd +Source203: coreutils-runuser-l.pamd -# do not make coreutils-single depend on /usr/bin/coreutils -%global __requires_exclude ^%{_bindir}/coreutils$ +# From upstream +Patch1: coreutils-8.15-cp-attribute-truncate.patch +Patch2: coreutils-8.15-du-x-nondir.patch +Patch3: coreutils-8.17-cp-freememoryread.patch +Patch4: coreutils-8.17-sort-uniq-fmr.patch +Patch5: coreutils-8.17-df-duplicates.patch -# disable the test-lock gnulib test prone to deadlock -Patch100: coreutils-8.26-test-lock.patch - -# require_selinux_(): use selinuxenabled(8) if available -Patch101: coreutils-8.26-selinuxenable.patch - -# downstream changes to default DIR_COLORS -Patch102: coreutils-8.32-DIR_COLORS.patch - -# use python3 in tests -Patch103: coreutils-python3.patch - -# df --direct +# Our patches +#general patch to workaround koji build system issues +Patch100: coreutils-6.10-configuration.patch +#add note about no difference between binary/text mode on Linux - md5sum manpage +Patch101: coreutils-6.10-manpages.patch +#temporarily workaround probable kernel issue with TCSADRAIN(#504798) +Patch102: coreutils-7.4-sttytcsadrain.patch +#do display processor type for uname -p/-i based on uname(2) syscall +Patch103: coreutils-8.2-uname-processortype.patch +#df --direct Patch104: coreutils-df-direct.patch +#add note about mkdir --mode behaviour into info documentation(#610559) +Patch107: coreutils-8.4-mkdir-modenote.patch -# gnulib C23 support -# https://github.com/coreutils/gnulib/commit/df17f4f37ed3ca373d23ad42eae51122bdb96626 -Patch105: coreutils-9.9-gnulib-c23.patch - -# fix cut test failure on aarch64 rawhide (rhbz#2424302) -# https://github.com/coreutils/coreutils/commit/95044cb5eaea83d02f768feb5ab79fcf5e6ad782 -Patch106: coreutils-9.9-fix-cut-test-aarch64.patch +# sh-utils +#add info about TZ envvar to date manpage +Patch703: sh-utils-2.0.11-dateman.patch +#set paths for su explicitly, don't get influenced by paths.h +Patch704: sh-utils-1.16-paths.patch +# RMS will never accept the PAM patch because it removes his historical +# rant about Twenex and the wheel group, so we'll continue to maintain +# it here indefinitely. Patch is now the same in Fedora and SUSE. +Patch706: coreutils-8.5-pam.patch +Patch713: coreutils-4.5.3-langinfo.patch # (sb) lin18nux/lsb compliance - multibyte functionality patch Patch800: coreutils-i18n.patch +#Call setsid() in su under some circumstances (bug #173008). +Patch900: coreutils-setsid.patch +#make runuser binary based on su.c +Patch907: coreutils-8.7-runuser.patch +#getgrouplist() patch from Ulrich Drepper. +Patch908: coreutils-getgrouplist.patch +#Prevent buffer overflow in who(1) (bug #158405). +Patch912: coreutils-overflow.patch +#compile su with pie flag and RELRO protection +Patch917: coreutils-8.4-su-pie.patch + +#SELINUX Patch - implements Redhat changes +#(upstream did some SELinux implementation unlike with RedHat patch) +Patch950: coreutils-selinux.patch +Patch951: coreutils-selinuxmanpages.patch +#Deprecate cp -Z/--context non-upstream option +Patch952: coreutils-cpZ-deprecate.patch + Conflicts: filesystem < 3 +Provides: /bin/basename +Provides: /bin/cat +Provides: /bin/chgrp +Provides: /bin/chmod +Provides: /bin/chown +Provides: /bin/cp +Provides: /bin/cut +Provides: /bin/date +Provides: /bin/dd +Provides: /bin/df +Provides: /bin/echo +Provides: /bin/env +Provides: /bin/false +Provides: /bin/ln +Provides: /bin/ls +Provides: /bin/mkdir +Provides: /bin/mknod +Provides: /bin/mktemp +Provides: /bin/mv +Provides: /bin/nice +Provides: /bin/pwd +Provides: /bin/readlink +Provides: /bin/rm +Provides: /bin/rmdir +Provides: /bin/sleep +Provides: /bin/sort +Provides: /bin/stty +Provides: /bin/su +Provides: /bin/sync +Provides: /bin/touch +Provides: /bin/true +Provides: /bin/uname +Provides: /sbin/runuser -# To avoid clobbering installs -Conflicts: coreutils-single - -BuildRequires: attr +BuildRequires: libselinux-devel +BuildRequires: libacl-devel +BuildRequires: gettext bison +BuildRequires: texinfo BuildRequires: autoconf BuildRequires: automake -BuildRequires: gcc -BuildRequires: gettext-devel -BuildRequires: gmp-devel -BuildRequires: hostname -BuildRequires: libacl-devel -BuildRequires: libattr-devel +%{?!nopam:BuildRequires: pam-devel} BuildRequires: libcap-devel -BuildRequires: libselinux-devel -BuildRequires: libselinux-utils -BuildRequires: make -BuildRequires: openssl-devel +BuildRequires: libattr-devel +BuildRequires: gmp-devel +BuildRequires: attr BuildRequires: strace -BuildRequires: systemd-devel -BuildRequires: texinfo -# For gpg verification of source tarball -BuildRequires: gnupg2 +Requires(pre): /sbin/install-info +Requires(preun): /sbin/install-info +Requires(post): /sbin/install-info +Requires(post): grep +%{?!nopam:Requires: pam >= 1.1.3-7} +Requires: ncurses +Requires: gmp -# test-only dependencies -BuildRequires: acl -BuildRequires: gdb -BuildRequires: perl-interpreter -BuildRequires: perl(FileHandle) -BuildRequires: python3 -BuildRequires: tzdata -%ifarch %valgrind_arches -BuildRequires: valgrind -%endif - -%if 0%{?fedora} -BuildRequires: perl(Expect) -BuildRequires: python3-inotify -%endif - -%if 23 < 0%{?fedora} || 7 < 0%{?rhel} -# needed by i18n test-cases -BuildRequires: glibc-langpack-en -BuildRequires: glibc-langpack-fr -BuildRequires: glibc-langpack-ko -BuildRequires: glibc-langpack-sv -%endif - -Requires: %{name}-common = %{version}-%{release} - -Provides: coreutils-full = %{version}-%{release} Provides: bundled(gnulib) -Obsoletes: %{name} < 8.24-100 +Provides: fileutils = %{version}-%{release} +Provides: sh-utils = %{version}-%{release} +Provides: stat = %{version}-%{release} +Provides: textutils = %{version}-%{release} +#old mktemp package had epoch 3, so we have to use 4 for coreutils +Provides: mktemp = 4:%{version}-%{release} +Obsoletes: mktemp < 4:%{version}-%{release} +Obsoletes: fileutils <= 4.1.9 +Obsoletes: sh-utils <= 2.0.12 +Obsoletes: stat <= 3.3 +Obsoletes: textutils <= 2.0.21 +#coreutils-libs dropped in f17 +Obsoletes: coreutils-libs < 8.13 %description These are the GNU core utilities. This package is the combination of the old GNU fileutils, sh-utils, and textutils packages. -%package single -Summary: coreutils multicall binary -Suggests: coreutils-common -Provides: coreutils = %{version}-%{release} -Provides: coreutils%{?_isa} = %{version}-%{release} -Provides: bundled(gnulib) -# To avoid clobbering installs -Conflicts: coreutils < 8.24-100 -# Note RPM doesn't support separate buildroots for %files -# http://rpm.org/ticket/874 so use RemovePathPostfixes -# (new in rpm 4.13) to support separate file sets. -RemovePathPostfixes: .single -%description single -These are the GNU core utilities, -packaged as a single multicall binary. - - -%package common -# yum obsoleting rules explained at: -# https://bugzilla.redhat.com/show_bug.cgi?id=1107973#c7 -Obsoletes: %{name} < 8.24-100 - -# Gnulib translations are maintained seprately since coreutils 9.6 (#2393892) -Requires: gnulib-l10n - -# info doc refers to "Specifying the Time Zone" from glibc-doc (#959597) -Suggests: glibc-doc - -Summary: coreutils common optional components -%description common -Optional though recommended components, -including documentation and translations. - %prep -%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' -%autosetup -N +%setup -q -# will be regenerated in the build directories -rm -f src/fs.h +# From upstream +%patch1 -p1 -b .trunc +%patch2 -p1 -b .xnondir +%patch3 -p1 -b .cpfmr +%patch4 -p1 -b .sortfmr +%patch5 -p1 -b .duplic -# will be further modified by coreutils-8.32-DIR_COLORS.patch -sed src/dircolors.hin \ - -e 's| 00;36$| 01;36|' \ - > DIR_COLORS -sed src/dircolors.hin \ - -e 's| 01;31$| 00;31|' \ - -e 's| 01;35$| 00;35|' \ - > DIR_COLORS.lightbgcolor +# Our patches +%patch100 -p1 -b .configure +%patch101 -p1 -b .manpages +%patch102 -p1 -b .tcsadrain +%patch103 -p1 -b .sysinfo +%patch104 -p1 -b .dfdirect +%patch107 -p1 -b .mkdirmode -# git add DIR_COLORS{,.lightbgcolor} -# git commit -m "clone DIR_COLORS before patching" +# sh-utils +%patch703 -p1 -b .dateman +%patch704 -p1 -b .paths +%patch706 -p1 -b .pam +%patch713 -p1 -b .langinfo -# apply all patches -%autopatch -p1 +# li18nux/lsb +%patch800 -p1 -b .i18n -(echo ">>> Fixing permissions on tests") 2>/dev/null -find tests -name '*.sh' -perm 0644 -print -exec chmod 0755 '{}' '+' -(echo "<<< done") 2>/dev/null +# Coreutils +%patch900 -p1 -b .setsid +%patch907 -p1 -b .runuser +%patch908 -p1 -b .getgrouplist +%patch912 -p1 -b .overflow +%patch917 -p1 -b .pie -# FIXME: Force a newer gettext version to workaround `autoreconf -i` errors -# with coreutils 9.6 and bundled gettext 0.19.2 from gettext-common-devel. -sed -i "s/0.19.2/$(rpm -q --queryformat '%%{VERSION}\n' gettext-devel)/" bootstrap.conf configure.ac +#SELinux +%patch950 -p1 -b .selinux +%patch951 -p1 -b .selinuxman +%patch952 -p1 -b .cpZ -autoreconf -fiv +chmod a+x tests/misc/sort-mb-tests tests/df/direct tests/cp/attr-existing || : + +#fix typos/mistakes in localized documentation(#439410, #440056) +find ./po/ -name "*.p*" | xargs \ + sed -i \ + -e 's/-dpR/-cdpR/' %build export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing -fpic" - -# Upstream suggests to build with -Dlint for static analyzers: -# https://lists.gnu.org/archive/html/coreutils/2018-06/msg00110.html -# ... and even for production binary RPMs: -# https://lists.gnu.org/archive/html/bug-gnulib/2020-05/msg00130.html -# There is currently no measurable performance drop or other known downside. -CFLAGS="$CFLAGS -Dlint" - -# make mknod work again in chroot without /proc being mounted (#1811038) -export ac_cv_func_lchmod="no" - -# needed for out-of-tree build -%global _configure ../configure - %{expand:%%global optflags %{optflags} -D_GNU_SOURCE=1} -for type in separate single; do - mkdir -p $type && \ - (cd $type || exit $? - if test $type = 'single'; then - config_single='--enable-single-binary' - config_single="$config_single --without-openssl" # smaller/slower sha*sum - config_single="$config_single --without-libgmp" # expr/factor machine ints - else - config_single='--with-openssl' # faster sha*sum - fi - %configure $config_single \ - --cache-file=../config.cache \ - --enable-install-program=arch \ - --enable-no-install-program=kill,uptime \ - --enable-systemd \ - --with-tty-group \ - DEFAULT_POSIX2_VERSION=200112 alternative=199209 || : - %make_build all V=1 +#autoreconf -i -v +touch aclocal.m4 configure config.hin Makefile.in */Makefile.in +aclocal -I m4 +autoconf --force +automake --copy --add-missing +%configure --enable-largefile %{?!nopam:--enable-pam} \ + %{?!noselinux:--enable-selinux} \ + --enable-install-program=su,hostname,arch \ + --with-tty-group \ + DEFAULT_POSIX2_VERSION=200112 alternative=199209 || : - # make sure that parse-datetime.{c,y} ends up in debuginfo (#1555079) - ln -fv ../lib/parse-datetime.{c,y} . - ) -done +# Regenerate manpages +touch man/*.x -# Get the list of supported utilities -cp %SOURCE50 . +make all %{?_smp_mflags} \ + %{?!nopam:CPPFLAGS="-DUSE_PAM"} + +# XXX docs should say /var/run/[uw]tmp not /etc/[uw]tmp +sed -i -e 's,/etc/utmp,/var/run/utmp,g;s,/etc/wtmp,/var/run/wtmp,g' doc/coreutils.texi %check -for type in separate single; do - test $type = 'single' && subdirs='SUBDIRS=.' # Only check gnulib once - (cd $type && make check %{?_smp_mflags} $subdirs) -done +make check %install -for type in separate single; do - install=install - if test $type = 'single'; then - subdir=%{_libexecdir}/%{name}; install=install-exec - fi - (cd $type && make DESTDIR=$RPM_BUILD_ROOT/$subdir $install) +rm -rf $RPM_BUILD_ROOT +make DESTDIR=$RPM_BUILD_ROOT install -%if "%{_sbindir}" != "%{_bindir}" - # chroot was in /usr/sbin : - mkdir -p $RPM_BUILD_ROOT/$subdir/%_sbindir - mv $RPM_BUILD_ROOT/$subdir/{%_bindir,%_sbindir}/chroot -%endif +# man pages are not installed with make install +make mandir=$RPM_BUILD_ROOT%{_mandir} install-man - # Move multicall variants to *.single. - # RemovePathPostfixes will strip that later. - if test $type = 'single'; then - for dir in %{_bindir} \ -%if "%{_sbindir}" != "%{_bindir}" -%{_sbindir} \ -%endif -%{_libexecdir}/%{name}; do - for bin in $RPM_BUILD_ROOT/%{_libexecdir}/%{name}/$dir/*; do - basebin=$(basename $bin) - mv $bin $RPM_BUILD_ROOT/$dir/$basebin.single - done - done - fi -done +# fix japanese catalog file +if [ -d $RPM_BUILD_ROOT%{_datadir}/locale/ja_JP.EUC/LC_MESSAGES ]; then + mkdir -p $RPM_BUILD_ROOT%{_datadir}/locale/ja/LC_MESSAGES + mv $RPM_BUILD_ROOT%{_datadir}/locale/ja_JP.EUC/LC_MESSAGES/*mo \ + $RPM_BUILD_ROOT%{_datadir}/locale/ja/LC_MESSAGES + rm -rf $RPM_BUILD_ROOT%{_datadir}/locale/ja_JP.EUC +fi + +bzip2 -9f ChangeLog + +# let be compatible with old fileutils, sh-utils and textutils packages : +mkdir -p $RPM_BUILD_ROOT{%{_bindir},%{_sbindir}} +%{?!nopam:mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/pam.d} + +# chroot was in /usr/sbin : +mv $RPM_BUILD_ROOT{%_bindir,%_sbindir}/chroot mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/profile.d -install -p -c -m644 DIR_COLORS{,.lightbgcolor} $RPM_BUILD_ROOT%{_sysconfdir} +install -p -c -m644 %SOURCE101 $RPM_BUILD_ROOT%{_sysconfdir}/DIR_COLORS +install -p -c -m644 %SOURCE102 $RPM_BUILD_ROOT%{_sysconfdir}/DIR_COLORS.lightbgcolor +install -p -c -m644 %SOURCE103 $RPM_BUILD_ROOT%{_sysconfdir}/DIR_COLORS.256color install -p -c -m644 %SOURCE105 $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/colorls.sh install -p -c -m644 %SOURCE106 $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/colorls.csh +# su +install -m 4755 src/su $RPM_BUILD_ROOT/%{_bindir} +%{?!norunuser:install -m 755 src/runuser $RPM_BUILD_ROOT/%{_sbindir}} +# do not ship runuser in /usr/bin/runuser +rm -rf $RPM_BUILD_ROOT/%{_bindir}/runuser || : + +# These come from util-linux and/or procps. +for i in hostname uptime kill ; do + rm $RPM_BUILD_ROOT{%{_bindir}/$i,%{_mandir}/man1/$i.1} +done + +%{?!nopam:install -p -m 644 %SOURCE200 $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/su} +%{?!nopam:install -p -m 644 %SOURCE202 $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/su-l} +%{?!nopam:install -p -m 644 %SOURCE201 $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/runuser} +%{?!nopam:install -p -m 644 %SOURCE203 $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/runuser-l} + +# Compress ChangeLogs from before the fileutils/textutils/etc merge +bzip2 -f9 old/*/C* + +# Use hard links instead of symbolic links for LC_TIME files (bug #246729). +find %{buildroot}%{_datadir}/locale -type l | \ +(while read link + do + target=$(readlink "$link") + rm -f "$link" + ln "$(dirname "$link")/$target" "$link" + done) + %find_lang %name -# Add the %%lang(xyz) ownership for the LC_TIME dirs as well... -grep LC_TIME %name.lang | cut -d'/' -f1-6 | sed -e 's/) /) %%dir /g' >>%name.lang # (sb) Deal with Installed (but unpackaged) file(s) found rm -f $RPM_BUILD_ROOT%{_infodir}/dir -%files -f supported_utils -%exclude %{_bindir}/*.single -%dir %{_libexecdir}/coreutils -%{_libexecdir}/coreutils/*.so +%clean +rm -rf $RPM_BUILD_ROOT -%files single -%{_bindir}/*.single -%if "%{_sbindir}" != "%{_bindir}" -%{_sbindir}/chroot.single -%endif -%dir %{_libexecdir}/coreutils -%{_libexecdir}/coreutils/*.so.single -# duplicate the license because coreutils-common does not need to be installed -%{!?_licensedir:%global license %%doc} -%license COPYING +%pre +# We must deinstall these info files since they're merged in +# coreutils.info. else their postun'll be run too late +# and install-info will fail badly because of duplicates +for file in sh-utils textutils fileutils; do + if [ -f %{_infodir}/$file.info.gz ]; then + /sbin/install-info --delete %{_infodir}/$file.info.gz --dir=%{_infodir}/dir &> /dev/null || : + fi +done -%files common -f %{name}.lang +%preun +if [ $1 = 0 ]; then + if [ -f %{_infodir}/%{name}.info.gz ]; then + /sbin/install-info --delete %{_infodir}/%{name}.info.gz %{_infodir}/dir || : + fi +fi + +%post +%{_bindir}/grep -v '(sh-utils)\|(fileutils)\|(textutils)' %{_infodir}/dir > \ + %{_infodir}/dir.rpmmodify || exit 0 + /bin/mv -f %{_infodir}/dir.rpmmodify %{_infodir}/dir +if [ -f %{_infodir}/%{name}.info.gz ]; then + /sbin/install-info %{_infodir}/%{name}.info.gz %{_infodir}/dir || : +fi + +%files -f %{name}.lang +%defattr(-,root,root,-) +%dir %{_datadir}/locale/*/LC_TIME %config(noreplace) %{_sysconfdir}/DIR_COLORS* %config(noreplace) %{_sysconfdir}/profile.d/* +%{?!nopam:%config(noreplace) %{_sysconfdir}/pam.d/su} +%{?!nopam:%config(noreplace) %{_sysconfdir}/pam.d/su-l} +%{?!nopam:%config(noreplace) %{_sysconfdir}/pam.d/runuser} +%{?!nopam:%config(noreplace) %{_sysconfdir}/pam.d/runuser-l} +%doc COPYING ABOUT-NLS ChangeLog.bz2 NEWS README THANKS TODO old/* +%{_bindir}/arch +%{_bindir}/basename +%{_bindir}/cat +%{_bindir}/chgrp +%{_bindir}/chmod +%{_bindir}/chown +%{_bindir}/cp +%{_bindir}/cut +%{_bindir}/date +%{_bindir}/dd +%{_bindir}/df +%{_bindir}/echo +%{_bindir}/env +%{_bindir}/false +%{_bindir}/link +%{_bindir}/ln +%{_bindir}/ls +%{_bindir}/mkdir +%{_bindir}/mknod +%{_bindir}/mv +%{_bindir}/nice +%{_bindir}/pwd +%{_bindir}/readlink +%{_bindir}/rm +%{_bindir}/rmdir +%{_bindir}/sleep +%{_bindir}/sort +%{_bindir}/stty +%attr(4755,root,root) %{_bindir}/su +%{_bindir}/sync +%{_bindir}/mktemp +%{_bindir}/touch +%{_bindir}/true +%{_bindir}/uname +%{_bindir}/unlink +%{_bindir}/[ +%{_bindir}/base64 +%{_bindir}/chcon +%{_bindir}/cksum +%{_bindir}/comm +%{_bindir}/csplit +%{_bindir}/dir +%{_bindir}/dircolors +%{_bindir}/dirname +%{_bindir}/du +%{_bindir}/expand +%{_bindir}/expr +%{_bindir}/factor +%{_bindir}/fmt +%{_bindir}/fold +%{_bindir}/groups +%{_bindir}/head +%{_bindir}/hostid +%{_bindir}/id +%{_bindir}/install +%{_bindir}/join +%{_bindir}/logname +%{_bindir}/md5sum +%{_bindir}/mkfifo +%{_bindir}/nl +%{_bindir}/nohup +%{_bindir}/nproc +%{_bindir}/od +%{_bindir}/paste +%{_bindir}/pathchk +%{_bindir}/pinky +%{_bindir}/pr +%{_bindir}/printenv +%{_bindir}/printf +%{_bindir}/ptx +%{_bindir}/realpath +%{_bindir}/runcon +%{_bindir}/seq +%{_bindir}/sha1sum +%{_bindir}/sha224sum +%{_bindir}/sha256sum +%{_bindir}/sha384sum +%{_bindir}/sha512sum +%{_bindir}/shred +%{_bindir}/shuf +%{_bindir}/split +%{_bindir}/stat +%{_bindir}/stdbuf +%{_bindir}/sum +%{_bindir}/tac +%{_bindir}/tail +%{_bindir}/tee +%{_bindir}/test +%{_bindir}/timeout +%{_bindir}/tr +%{_bindir}/truncate +%{_bindir}/tsort +%{_bindir}/tty +%{_bindir}/unexpand +%{_bindir}/uniq +%{_bindir}/users +%{_bindir}/vdir +%{_bindir}/wc +%{_bindir}/who +%{_bindir}/whoami +%{_bindir}/yes %{_infodir}/coreutils* +%{_libexecdir}/coreutils* %{_mandir}/man*/* -# The following go to /usr/share/doc/coreutils-common -%doc ABOUT-NLS NEWS README THANKS TODO -%license COPYING +%{_sbindir}/chroot +%{?!norunuser:%{_sbindir}/runuser} %changelog -* Tue Jan 13 2026 Lukáš Zaoral - 9.9-2 -- fix cut test failure on aarch64 rawhide (rhbz#2424302) - -* Wed Nov 26 2025 Lukáš Zaoral - 9.9-1 -- rebase to latest upstream release (rhbz#2413803) - -* Mon Sep 29 2025 Lukáš Zaoral - 9.8-3 -- require gnulib-l10n for translations of gnulib messages (rhbz#2393892) - -* Thu Sep 25 2025 Lukáš Zaoral - 9.8-2 -- tail: fix tailing larger number of lines in regular files (rhbz#2398008) - -* Wed Sep 24 2025 Lukáš Zaoral - 9.8-1 -- rebase to latest upstream release (rhbz#2397467) -- remove downstream patch for selinux options deprecated since 2009 - -* Wed Jul 23 2025 Fedora Release Engineering - 9.7-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild - -* Mon Jun 30 2025 Lukáš Zaoral - 9.7-4 -- stty: add support for arbitrary baud rates (rhbz#2375439) - -* Wed May 28 2025 Lukáš Zaoral - 9.7-3 -- sort: fix buffer under-read (CVE-2025-5278) - -* Mon May 19 2025 Lukáš Zaoral - 9.7-2 -- cp/mv: do not fail when copying of trivial NFSv4 ACLs fails (rhbz#2363149) - -* Wed Apr 09 2025 Lukáš Zaoral - 9.7-1 -- rebase to latest upstream release (rhbz#2358624) - -* Tue Feb 25 2025 Lukáš Zaoral - 9.6-2 -- fix 'who -m' with guessed tty names (rhbz#2343998) - -* Mon Jan 20 2025 Lukáš Zaoral - 9.6-1 -- rebase to latest upstream version (rhbz#2338620) -- sync i18n patch with SUSE (Kudos to Berny Völker!) - -* Thu Jan 16 2025 Fedora Release Engineering - 9.5-13 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild - -* Sun Jan 12 2025 Zbigniew Jędrzejewski-Szmek - 9.5-12 -- Rebuilt for the bin-sbin merge (2nd attempt) - -* Wed Nov 13 2024 Florian Weimer - 9.5-11 -- Affinity mask handling in nproc for large CPU counts (rhbz#2325167) - -* Fri Sep 27 2024 Lukáš Zaoral - 9.5-10 -- fix fold -b with UTF8 locale (RHEL-60295) - -* Tue Aug 27 2024 Lukáš Zaoral - 9.5-9 -- show web sessions in who output (rhbz#2307847) - -* Wed Aug 21 2024 Lukáš Zaoral - 9.5-8 -- add missing systemd-devel buildrequires - -* Wed Jul 17 2024 Fedora Release Engineering - 9.5-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild - -* Mon Jul 15 2024 Lukáš Zaoral - 9.5-6 -- Rebuilt for the bin-sbin merge - -* Mon Jul 15 2024 Sohum Mendon - 9.5-5 -- fix incorrect exit status when fold is called with a non-existent file - -* Tue Jul 09 2024 Zbigniew Jędrzejewski-Szmek - 9.5-4 -- Rebuilt for the bin-sbin merge - -* Thu Jul 04 2024 Lukáš Zaoral - 9.5-3 -- do not buildrequire perl(Expect) on ELN - -* Tue Jun 04 2024 Lukáš Zaoral - 9.5-2 -- enable LTO on ppc64le - -* Tue Apr 02 2024 Lukáš Zaoral - 9.5-1 -- rebase to latest upstream version (rhbz#2272063) -- sync i18n patch with SUSE (Kudos to Berny Völker!) -- add some test dependencies to execute additional part of the upstream test-suite - -* Mon Jan 29 2024 Lukáš Zaoral - 9.4-6 -- fix tail on kernels with 64k page sizes (RHEL-22866) - -* Wed Jan 24 2024 Fedora Release Engineering - 9.4-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Fri Jan 19 2024 Fedora Release Engineering - 9.4-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Thu Jan 18 2024 Lukáš Zaoral - 9.4-3 -- fix compilation on i686 - -* Thu Jan 18 2024 Lukáš Zaoral - 9.4-2 -- fix buffer overflow in split (CVE-2024-0684) - -* Fri Sep 15 2023 Lukáš Zaoral - 9.4-1 -- new upstream release 9.4 (#2235759) -- enable integration with systemd -- fix the license field - -* Wed Jul 19 2023 Fedora Release Engineering - 9.3-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild - -* Tue Apr 18 2023 Kamil Dudka - 9.3-1 -- remove obsolete Provides for absolute paths -- new upstream release 9.3 - -* Tue Apr 11 2023 Lukáš Zaoral - 9.2-4 -- migrate to SPDX license format - -* Fri Mar 24 2023 Kamil Dudka - 9.2-3 -- copy: fix --reflink=auto to fallback in more cases (#2180056) -- cksum: fix reporting of failed checks (#2180056) - -* Wed Mar 22 2023 Kamil Dudka - 9.2-2 -- coreutils-getgrouplist.patch: drop a patch no longer needed - -* Wed Mar 22 2023 Kamil Dudka - 9.2-1 -- new upstream release 9.2 - -* Thu Jan 19 2023 Fedora Release Engineering -- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild - -* Mon Jan 02 2023 Kamil Dudka - 9.1-10 -- drop obsolete downstream-only extension of date(1) man page -- undocument downstream SELinux options deprecated since 2009 - -* Mon Jan 02 2023 Kamil Dudka - 9.1-9 -- basic support for checking NFSv4 ACLs (#2137866) - -* Mon Sep 19 2022 Kamil Dudka - 9.1-8 -- remove obsolete extension of mkdir(1) info documentation - -* Tue Aug 23 2022 Kamil Dudka - 9.1-7 -- remove non-upstream patch for uname -i/-p (#548834) - -* Mon Aug 08 2022 Kamil Dudka - 9.1-6 -- improve wording of a comment in /etc/DIR_COLORS (#2112593) - -* Mon Aug 08 2022 Kamil Dudka - 9.1-5 -- improve handling of control characters in unexpand (#2112870) - -* Mon Aug 01 2022 Kamil Dudka - 9.1-4 -- prevent unexpand from failing on control characters (#2112870) - -* Wed Jul 20 2022 Fedora Release Engineering -- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild - -* Sat Apr 23 2022 Pádraig Brady - 9.1-2 -- make simple backups in correct dir; broken in 9.1 - -* Tue Apr 19 2022 Kamil Dudka - 9.1-1 -- new upstream release 9.1 - -* Mon Mar 21 2022 Kamil Dudka - 9.0-5 -- ls, stat: avoid triggering automounts (#2044981) - -* Tue Mar 01 2022 Kamil Dudka - 9.0-4 -- make `df --direct` work again (#2058686) - -* Wed Jan 19 2022 Fedora Release Engineering -- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild - -* Mon Oct 04 2021 Kamil Dudka - 9.0-2 -- chmod: fix exit status when ignoring symlinks - -* Sun Sep 26 2021 Kamil Dudka - 9.0-1 -- new upstream release 9.0 - -* Tue Sep 14 2021 Sahana Prasad -- Rebuilt with OpenSSL 3.0.0 - -* Wed Jul 21 2021 Fedora Release Engineering -- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild - -* Wed Jul 07 2021 Kamil Dudka - 8.32-30 -- df: fix duplicated remote entries due to bind mounts (#1979814) - -* Thu Jul 01 2021 Kamil Dudka - 8.32-28 -- tail: fix stack out-of-bounds write with --follow - -* Tue Jun 08 2021 Kamil Dudka - 8.32-27 -- mountlist: recognize fuse.portal as dummy file system (#1913358) - -* Mon May 17 2021 Kamil Dudka - 8.32-26 -- cp: pick additional copy_file_range()-related fixes from upstream - -* Mon May 03 2021 Kamil Dudka - 8.32-24 -- copy: ensure we enforce --reflink=never (#1956080) - -* Tue Apr 27 2021 Kamil Dudka - 8.32-23 -- copy: do not refuse to copy a swap file - -* Fri Apr 09 2021 Kamil Dudka - 8.32-22 -- weaken the dependency on glibc-doc to reduce minimal installations -- drop the last use of ncurses no longer needed (#1830318) -- utimens: fix confusing arg type in internal func - -* Fri Mar 26 2021 Kamil Dudka - 8.32-21 -- hostname,ln: fix memory leaks detected by Coverity - -* Wed Mar 24 2021 Kamil Dudka - 8.32-20 -- cp: use copy_file_range if available - -* Thu Feb 18 2021 Kamil Dudka - 8.32-19 -- stat: add support for the exfat file system (#1921427) - -* Wed Feb 03 2021 Kamil Dudka - 8.32-18 -- make coreutils-common recommend glibc-doc for info doc refs (#959597) - -* Tue Feb 02 2021 Kamil Dudka - 8.32-17 -- ls: fix crash printing SELinux context for unstatable files (#1921249) -- split: fix --number=K/N to output correct part of file (#1921246) -- expr: fix invalid read with unmatched \(...\) (#1919775) - -* Tue Jan 26 2021 Fedora Release Engineering -- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild - -* Tue Dec 08 2020 Kamil Dudka - 8.32-15 -- rm: do not skip files upon failure to remove an empty dir (#1905481) - -* Tue Nov 03 2020 Kamil Dudka - 8.32-14 -- df,stat,tail: recognize more file system types - -* Wed Oct 14 2020 Kamil Dudka - 8.32-13 -- make the %%build section idempotent - -* Mon Aug 17 2020 Kamil Dudka - 8.32-12 -- do not install /etc/DIR_COLORS.256color (#1830318) - -* Thu Jul 30 2020 Kamil Dudka - 8.32-11 -- cp: default to --reflink=auto (#1861108) - -* Mon Jul 27 2020 Fedora Release Engineering -- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild - -* Fri Jul 24 2020 Kamil Dudka - 8.32-9 -- disable -flto on ppc64le to make test-float pass (#1789115) - -* Mon Jul 13 2020 Tom Stellard - 8.32-8 -- Use make macros -- https://fedoraproject.org/wiki/Changes/UseMakeBuildInstallMacro - -* Fri Jun 26 2020 James Cassell - 8.32-7 -- move ncurses to -common package since it's needed for colorls.sh -- make ncurses optional - -* Fri May 15 2020 Kamil Dudka - 8.32-6 -- compile with -Dlint to enable optional initialization and cleanup code - -* Thu Apr 23 2020 Kamil Dudka - 8.32-5 -- du: simplify leaf optimization for XFS (#1823247) - -* Fri Apr 17 2020 Tom Stellard - 8.32-4 -- Fix missing inline function definition - -* Wed Mar 11 2020 Kamil Dudka - 8.32-3 -- uniq: remove collation handling as required by newer POSIX - -* Mon Mar 09 2020 Kamil Dudka - 8.32-2 -- make mknod work again in chroot without /proc being mounted (#1811038) -- ls: restore 8.31 behavior on removed directories - -* Thu Mar 05 2020 Kamil Dudka - 8.32-1 -- new upstream release 8.32 - -* Tue Feb 11 2020 Kamil Dudka - 8.31-10 -- make upstream test-suite work with root privileges (#1800597) - -* Wed Feb 05 2020 Kamil Dudka - 8.31-9 -- use upstream fix the cp/proc-short-read test - -* Thu Jan 30 2020 Kamil Dudka - 8.31-8 -- skip a test that relies on /proc/kallsyms having immutable content - -* Tue Jan 28 2020 Fedora Release Engineering -- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild - -* Thu Oct 17 2019 Kamil Dudka - 8.31-6 -- temporarily disable the use of statx (#1760300) - -* Fri Oct 11 2019 Kamil Dudka - 8.31-5 -- use statx instead of stat when available (#1760300) - -* Wed Jul 24 2019 Fedora Release Engineering -- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild - -* Tue Jul 16 2019 Kamil Dudka - 8.31-3 -- disable flashing in ls colors for broken symbolic links (#1728986) - -* Mon Mar 18 2019 Kamil Dudka - 8.31-2 -- fix formatting of sha512sum(1) man page (#1688740) - -* Mon Mar 11 2019 Kamil Dudka - 8.31-1 -- new upstream release 8.31 - -* Thu Jan 31 2019 Fedora Release Engineering -- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild - -* Wed Nov 07 2018 Kamil Dudka - 8.30-8 -- sync: fix open() fallback bug -- fix implicit declaration warning in coreutils-getgrouplist.patch - -* Sat Nov 03 2018 Kevin Fenzi - 8.30-7 -- Also remove Requires pre/post used by info scriptlets. - -* Sat Nov 03 2018 Kevin Fenzi - 8.30-6 -- Remove no longer needed info scriptlets - -* Thu Oct 11 2018 Kamil Dudka - 8.30-5 -- fix heap-based buffer overflow in vasnprintf() (CVE-2018-17942) - -* Thu Jul 12 2018 Fedora Release Engineering - 8.30-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild - -* Tue Jul 10 2018 Kamil Dudka - 8.30-3 -- rename gnulib's renameat2 to renameatu to avoid clash with glibc (#1598518) - -* Wed Jul 04 2018 Kamil Dudka - 8.30-2 -- sync i18n patches with Suse (patch by Bernhard Voelker) - -* Mon Jul 02 2018 Kamil Dudka - 8.30-1 -- new upstream release 8.30 - -* Wed May 30 2018 Kamil Dudka - 8.29-12 -- add provides to coreutils-single to make it a drop-in replacement - -* Mon May 28 2018 Kamil Dudka - 8.29-11 -- ls: increase the allowed abmon width from 5 to 12 (#1577872) -- date, ls: pick strftime fixes from glibc to improve locale support (#1577872) - -* Fri Apr 20 2018 Kamil Dudka - 8.29-10 -- fix crash caused by mistakenly enabled leaf optimization (#1558249) - -* Fri Mar 23 2018 Kamil Dudka - 8.29-9 -- make it possible to install the latest available Adobe Reader RPM for Linux - -* Mon Mar 19 2018 Kamil Dudka - 8.29-8 -- drop BR for bison, which is not used during the build - -* Fri Mar 16 2018 Kamil Dudka - 8.29-7 -- make sure that parse-datetime.{c,y} ends up in debuginfo (#1555079) - -* Tue Mar 06 2018 Kamil Dudka - 8.29-6 -- fix build failure with glibc-2.28 - -* Mon Feb 26 2018 Igor Gnatenko - 8.29-5 -- Remove /bin/* Provides - -* Mon Feb 19 2018 Kamil Dudka - 8.29-4 -- add explicit BR for the gcc compiler - -* Wed Feb 07 2018 Fedora Release Engineering - 8.29-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild - -* Tue Jan 23 2018 Kamil Dudka - 8.29-2 -- doc: warn about following symlinks recursively in chown/chgrp (CVE-2017-18018) -- mv -n: do not overwrite the destination - -* Tue Jan 02 2018 Kamil Dudka - 8.29-1 -- new upstream release 8.29 - -* Tue Nov 07 2017 Igor Gnatenko - 8.28-2 -- Remove very old Provides (mktemp, sh-utils, textwrap, fileutils, stat) - -* Mon Sep 04 2017 Kamil Dudka - 8.28-1 -- new upstream release 8.28 - -* Tue Aug 22 2017 Ville Skyttä - 8.27-16 -- Own the %%{_libexecdir}/coreutils dir - -* Fri Aug 18 2017 Kamil Dudka - 8.27-15 -- ptx: fix a possible crash caused by integer overflow (#1482445) - -* Wed Aug 02 2017 Fedora Release Engineering - 8.27-14 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild - -* Fri Jul 28 2017 Igor Gnatenko - 8.27-13 -- Enable separate debuginfo back - -* Wed Jul 26 2017 Kamil Dudka - 8.27-12 -- avoid build failure caused broken RPM code that produces debuginfo packages - -* Wed Jul 26 2017 Fedora Release Engineering - 8.27-11 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild - -* Tue May 30 2017 Sebastian Kisela - 8.27-10 -- doc: mention `setpriv --no-new-privs` feature in runcon info - -* Tue May 16 2017 Kamil Dudka - 8.27-9 -- add coreutils-full provides for coreutils to make it explicitly installable - -* Wed May 03 2017 Kamil Dudka - 8.27-8 -- drop coreutils-overflow.patch no longer needed (#158405) - -* Wed May 03 2017 Kamil Dudka - 8.27-7 -- drop workaround for already fixed rpm-build bug (#1306559) - -* Wed May 03 2017 Kamil Dudka - 8.27-6 -- do not mention a deprecated option in localized man pages -- drop workaround no longer needed for 10 years old rpm-build bug (#246729) -- drop unnecessary uses of %%defattr - -* Fri Apr 28 2017 Sebastian Kisela - 8.27-5 -- tail: revert to polling if a followed directory is replaced (#1283760) - -* Thu Apr 27 2017 Kamil Dudka - 8.27-4 -- date, touch: fix out-of-bounds write via large TZ variable (CVE-2017-7476) - -* Tue Apr 25 2017 Kamil Dudka - 8.27-3 -- do not obsolete coreutils-single, so it can be installed by DNF2 (#1444802) - -* Wed Mar 15 2017 Kamil Dudka - 8.27-2 -- fix spurious build failure caused by the misc/date-debug test - -* Thu Mar 09 2017 Kamil Dudka - 8.27-1 -- new upstream release 8.27 - -* Fri Feb 10 2017 Fedora Release Engineering - 8.26-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild - -* Fri Feb 03 2017 Kamil Dudka - 8.26-6 -- fold: preserve new-lines in mutlibyte text (#1418505) - -* Mon Jan 23 2017 Kamil Dudka - 8.26-5 -- date: fix TZ= regression (patch by Pádraig Brady) - -* Mon Jan 02 2017 Kamil Dudka - 8.26-4 -- use upstream patch for gnulib's test-lock (instead of disabling it) - -* Thu Dec 15 2016 Kamil Dudka - 8.26-3 -- drop build fixes no longer needed - -* Fri Dec 02 2016 Kamil Dudka - 8.26-2 -- apply patches automatically to ease maintenance - -* Thu Dec 01 2016 Kamil Dudka - 8.26-1 -- new upstream release 8.26 - -* Mon Oct 31 2016 Kamil Dudka - 8.25-17 -- md5sum,sha*sum: fix --ignore-missing with checksums starting with 00 - -* Tue Oct 11 2016 Tomáš Mráz - 8.25-16 -- rebuild with OpenSSL 1.1.0 - -* Wed Sep 07 2016 Kamil Dudka - 8.25-15 -- ls: allow interruption when reading slow directories (#1365933) - -* Tue Jul 19 2016 Kamil Dudka - 8.25-14 -- run autoreconf in %%prep -- drop post-install fix for Japanese locales that no longer applies -- fix 'sort -h -k' in locales that use blank as thousands separator (#1355780) - -* Thu Jul 14 2016 Kamil Dudka - 8.25-13 -- make 'sort -h' work for arbitrary column even when using UTF-8 locales - -* Mon Jul 11 2016 Kamil Dudka - 8.25-12 -- install -Z now sets default SELinux context for created directories (#1339135) -- drop the %%pre scriptlet, which is no longer needed (#1354078) -- clarify recognition of "^COLOR.*none" in /etc/DIR_COLORS (#1349579) - -* Thu Jul 07 2016 Jakub Martisko - 8.25-11 -- switch to UTF8 locale when (un)expand input contains BOM header - (#1158494) -- fixed regression where (un)expand would end with "long input line" - error when BOM header is present - -* Fri Jun 24 2016 Ondrej Vasik - 8.25-10 -- change way of detection of interactive shell in colorls.sh script - (#1321648) - -* Mon Jun 20 2016 Kamil Dudka - 8.25-9 -- add BR for glibc-langpack-en to prevent the expand/mb test from failing -- do not use /bin/mv in %%post to avoid a circular dependency (#1348043) - -* Fri Jun 17 2016 Kamil Dudka - 8.25-8 -- sync /etc/DIR_COLORS with latest upstream (#1335320) - -* Wed Jun 15 2016 Kamil Dudka - 8.25-7 -- handle info doc in RPM scriptlets of coreutils-common, which provides it -- make sure that the license file is installed, even if coreutils-common is not - -* Thu Jun 09 2016 Jakub Martisko - 8.25-6 -- (un)expand: fix regression in handling input files, where only - the first file was processed. - -* Sat Mar 05 2016 Ondrej Vasik - 8.25-5 -- cut: move back to the old i18n implementation (#1314722) - -* Mon Feb 15 2016 Ondrej Vasik - 8.25-4 -- cut: fix regression in handling fields for lines wider - than 64 chars (#1304839) - -* Thu Feb 11 2016 Lubomir Rintel - 8.25-3 -- Fix a regression in unexpand empty line handling - -* Thu Jan 21 2016 Ondrej Vasik - 8.25-2 -- Adjust the i18n patch for coreutils-8.25 -- add new base32 binary - -* Wed Jan 20 2016 Ondrej Vasik - 8.25-1 -- new upstream release(#1300282) - -* Fri Jan 15 2016 Ondrej Oprala - 8.24-108 -- cut: be MB for ALL archs - -* Fri Jan 15 2016 Ondrej Oprala - 8.24-107 -- Use the new i18n implementation for the cut utility - -* Wed Jan 13 2016 Ondrej Vasik - 8.24-106 -- mv: prevent dataloss when source dir is specified multiple - times (#1297464, by P.Brady) - -* Mon Dec 14 2015 Pádraig Brady - 8.24-105 -- Give explicit priority to coreutils over coreutils-single - -* Thu Dec 03 2015 Pádraig Brady - 8.24-104 -- Avoid libgmp and libcrypto dependencies from coreutils-single - -* Thu Dec 03 2015 Pádraig Brady - 8.24-103 -- Remove erroneous /usr/bin/kill from coreutils-single - -* Tue Dec 01 2015 Ondrej Oprala - 8.24-102 -- Use the new i18n implementation for expand/unexpand - -* Mon Nov 30 2015 Ondrej Vasik - 8.24-101 -- coreutils-single should provide versioned coreutils (#1286338) - -* Wed Nov 18 2015 Pádraig Brady - 8.24-100 -- Split package to more easily support smaller installs - -* Wed Sep 16 2015 Kamil Dudka - 8.24-4 -- fix memory leak in sort/I18N (patches written by Pádraig, #1259942) - -* Sat Sep 12 2015 Ondrej Vasik 8.24-3 -- fix one still existing occurance of non-full path in colorls.sh - -* Thu Jul 16 2015 Ondrej Vasik 8.24-2 -- use newer version of sort/I18N fix for CVE-2015-4041 - and CVE-2015-4042 - -* Sun Jul 05 2015 Ondrej Vasik 8.24-1 -- new upstream release 8.24 - -* Sat Jul 4 2015 Peter Robinson 8.23-14 -- Disable failing test-update-copyright to fix FTBFS - -* Wed Jun 17 2015 Fedora Release Engineering - 8.23-13 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild - -* Thu Jun 04 2015 Ondrej Vasik - 8.23-12 -- call utilities in colorls.* scripts with full path (#1222140) - -* Thu May 14 2015 Kamil Dudka - 8.23-11 -- run 'make check' in parallel to speed up the build - -* Wed May 13 2015 Ondrej Oprala - 8.23-10 -- sort - fix buffer overflow in some case conversions - - patch by Pádraig Brady - -* Mon Apr 20 2015 Pádraig Brady - 8.23-9 -- Adjust LS_COLORS in 256 color mode; brighten some, remove hardlink colors (#1196642) - -* Sun Mar 22 2015 Peter Robinson 8.23-8 -- Drop large ancient docs - -* Sat Feb 21 2015 Till Maas - 8.23-7 -- Rebuilt for Fedora 23 Change - https://fedoraproject.org/wiki/Changes/Harden_all_packages_with_position-independent_code - -* Mon Dec 01 2014 Ondrej Vasik - 8.23-6 -- have the LC_TIME subdirs with lang macro (#1169027) - -* Wed Oct 15 2014 Ondrej Vasik - 8.23-5 -- handle situation with ro /tmp in colorls scripts (#1149761) - -* Wed Oct 01 2014 Ondrej Vasik - 8.23-4 -- fix the sorting in multibyte locales (NUL-terminate sort keys) - - patch by Andreas Schwab (#1146185) - -* Sat Aug 16 2014 Fedora Release Engineering - 8.23-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild - -* Tue Aug 05 2014 Ondrej Vasik - 8.23-2 -- enable smp_flags again (by B.Voelker) -- fix regression in chroot - -* Tue Jul 22 2014 Ondrej Vasik - 8.23-1 -- new upstream release 8.23 -- synchronize the old differences in ls SELinux options - with upstream -- skip df/skip-duplicates.sh test for now (passing locally, failing in koji) - -* Fri Jul 11 2014 Tom Callaway - 8.22-17 -- fix license handling - -* Mon Jun 23 2014 Jakub Čajka - 8.22-16 -- fix failed tests on ppc(backport from gnulib upstream) - -* Sat Jun 07 2014 Fedora Release Engineering - 8.22-15 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild - -* Sat Apr 12 2014 Ondrej Vasik 8.22-14 -- fix dd sparse test failure on xfs filesystem(#1085727, - by P.Brady) - -* Wed Mar 05 2014 Ondrej Vasik 8.22-13 -- drop the util-linux requirements (smaller docker images), - drop ancient obsoletes of -libs subpackage - -* Sun Mar 02 2014 Ondrej Vasik 8.22-12 -- fix the date crash or infloop in TZ="" parsing (#1069657) - -* Mon Jan 13 2014 Ondrej Vasik 8.22-11 -- cp/mv/install: do not crash when getfscreatecon() is - returning a NULL context - -* Mon Jan 13 2014 Ondrej Vasik 8.22-10 -- unset the unnecessary envvars after colorls scripts(#1051703) -- improve the limitation (check for both utf8 and utf-8) - -* Fri Jan 10 2014 Ondrej Oprala 8.22-9 -- Limit the cut optimizations to UTF-8 locales only - -* Wed Jan 08 2014 Ondrej Oprala 8.22-8 -- Don't use cut mb path if not necessary (#1021403, #499220) -- several i18n patch improvements merged from OpenSUSE (fixed - compilation warnings, simplify mb handling in uniq) - -* Mon Jan 06 2014 Ondrej Oprala 8.22-7 -- Fix sorting by non-first field (#1003544) - -* Fri Jan 03 2014 Ondrej Vasik 8.22-6 -- do not modify SELinux contexts of existing parent - directories when copying files (fix by P.Brady, #1045122) - -* Thu Jan 02 2014 Ondrej Oprala 8.22-5 -- reverted an old change and constricted it's condition -- turned off two multibyte tests (wrong strcoll return value) - -* Mon Dec 23 2013 Ondrej Vasik 8.22-4 -- skip even the ls aliases in noninteractive mode - (suggested by T. Cordes, #988152) - -* Sun Dec 22 2013 Ondrej Vasik 8.22-3 -- reset buffer before copying to prevent some rare cases of - invalid output in join and uniq(#1036289) - -* Sat Dec 14 2013 Ondrej Vasik 8.22-1 -- new upstream version 8.22 -- temporarily disable multibyte cut.pl part and df symlink - tests - -* Thu Dec 12 2013 Ondrej Vasik 8.21-23 -- skip output-is-input-mb.p test - failing on armv7l (reported - by B.Voelker) - -* Mon Dec 9 2013 Peter Robinson 8.21-22 -- Add upstream patch to fix test failures on aarch64 - -* Thu Nov 28 2013 Ondrej Vasik 8.21-21 -- turn on the multibyte path in the testsuite to cover - i18n regressions - -* Wed Nov 06 2013 Ondrej Vasik 8.21-20 -- fix possible colorls.csh script errors for tcsh with - noclobber set and entered include file (#1027279) - -* Mon Oct 14 2013 Ondrej Vasik 8.21-19 -- cp: correct error message for invalid arguments - of '--no-preserve' (#1018206) - -* Thu Aug 15 2013 Ondrej Vasik 8.21-18 -- pr -e, with a mix of backspaces and TABs, could corrupt the heap - in multibyte locales (analyzed by J.Koncicky) - -* Wed Aug 14 2013 Ondrej Oprala 8.21-17 -- Fix sort multibyte incompatibilities - -* Sat Aug 03 2013 Fedora Release Engineering - 8.21-16 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild - -* Wed Jul 17 2013 Ondrej Oprala 8.21-15 -- change the TMP variable name in colorls.csh to _tmp (#981373) - -* Fri May 17 2013 Ondrej Vasik 8.21-10 -- DIR_COLORS.$TERM should have higher priority than - DIR_COLORS.256color (#921651) - -* Mon Mar 11 2013 Ondrej Oprala 8.21-9 -- add support for INCLUDE in colorls scripts (#818069) - -* Mon Mar 04 2013 Ondrej Vasik 8.21-8 -- fix factor on AArch64 (M.Salter, #917735) - -* Fri Mar 01 2013 Ondrej Vasik 8.21-7 -- ls: colorize several new archive/compressed types (#868510) - -* Sat Feb 23 2013 Ondrej Vasik 8.21-6 -- install: do proper cleanup when strip fails - (O.Oprala, B.Voekler, #632444) - -* Wed Feb 20 2013 Ondrej Vasik 8.21-5 -- fix multibyte issue in unexpand(by R.Kollar, #821262) - -* Mon Feb 18 2013 Ondrej Oprala 8.21-4 -- fix sort-mb-tests.sh test (B.Voelker) - -* Mon Feb 18 2013 Mark Wielaard 8.21-3 -- fix coreutils-i18n.patch to terminate mbdelim string (#911929) - -* Mon Feb 18 2013 Ondrej Vasik 8.21-2 -- remove unnecessary powerpc factor patch - -* Fri Feb 15 2013 Ondrej Vasik 8.21-1 -- new upstream release 8.21, update patches - -* Thu Feb 07 2013 Ondrej Oprala 8.20-8 -- add missing sort-mb-tests.sh to local.mk - -* Tue Feb 05 2013 Ondrej Vasik 8.20-7 -- add support for DTR/DSR control flow in stty(#445213) - -* Wed Jan 23 2013 Ondrej Vasik 8.20-6 +* Wed Jan 30 2013 Ondrej Vasik 8.15-10 - fix multiple segmantation faults in i18n patch (by SUSE) - (#869442, #902917) + (#869442, #902917)- CVE2013-0223/CVE2013-0221/CVE2013-0222 -* Thu Dec 20 2012 Ondrej Vasik 8.20-5 -- seq: fix newline output when -s specified (upstream) - -* Mon Dec 10 2012 Ondrej Vasik 8.20-4 +* Wed Dec 12 2012 Ondrej Vasik 8.15-9 - fix showing duplicates in df (#709351, O.Oprala, B.Voelker) -* Thu Dec 06 2012 Ondrej Vasik 8.20-3 -- fix factor on 32bit powerpc (upstream, #884715) +* Mon Nov 05 2012 Ondrej Vasik 8.15-8 +- fix support for ecryptfs mount of "Private" in su (#722323) +- cp: avoid data-corrupting free-memory-read (upstream fix) +- fix possible free memory read and dataloss in sort -u + (upstream fix) +- multibyte fixes in cut and expand (by M.Briza, #821260) -* Mon Nov 05 2012 Ondrej Vasik 8.20-2 -- disable the temporary O_SYNC fix (glibc is fixed - #872366) - -* Sat Oct 27 2012 Ondrej Vasik 8.20-1 -- new upstream release 8.20 -- Temporarily require util-linux >= 2.22.1-3 (to prevent missing - su/runuser on system) - -* Mon Aug 20 2012 Ondrej Vasik 8.19-1 -- new upstream release 8.19 -- fix multibyte issues in cut and expand (M.Briza, #821260) - -* Sun Aug 12 2012 Ondrej Vasik 8.18-1 -- new upstream release 8.18 -- su/runuser moved to util-linux - -* Wed Jul 18 2012 Fedora Release Engineering - 8.17-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild - -* Tue May 15 2012 Ondrej Vasik 8.17-3 -- add virtual provides for bundled(gnulib) copylib (#821748) - -* Fri May 11 2012 Ondrej Vasik 8.17-2 -- ls: upstream fix - correctly show symlinks in / - -* Fri May 11 2012 Ondrej Vasik 8.17-1 -- new upstream release 8.17 - -* Fri May 04 2012 Ondrej Vasik 8.16-3 -- add .htm and .shtml to colorized DIR_COLORS document - type (#817218) - -* Mon Apr 16 2012 Ondrej Vasik 8.16-2 +* Fri Jul 13 2012 Ondrej Vasik 8.15-7 - fix the tcsh colorls.csh behaviour in non-interactive mode (#804604) - -* Mon Mar 26 2012 Ondrej Vasik 8.16-1 -- new upstream release 8.16 -- defuzz patches, remove already applied patches - -* Thu Mar 08 2012 Ondrej Vasik 8.15-8 +- add .htm and .shtml to colorized DIR_COLORS document + type (#817218) - fix regression in du -x with nondir argument (by J.Meyering) - -* Wed Mar 07 2012 Ondrej Vasik 8.15-7 - fix sort segfault with multibyte locales (by P.Brady) +- add virtual provides for bundled(gnulib) copylib (#821748) +- cp: change --attribute-only to not truncate existing files + (#811746) * Fri Feb 10 2012 Harald Hoyer 8.15-6 - turn on testsuite again @@ -1231,7 +603,7 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir - change assertion failure for invalid multibyte input in sort to less confusing error message(#591352) -* Wed Sep 08 2010 Ondrej Vasik - 8.5-7 +* Wed Sep 09 2010 Ondrej Vasik - 8.5-7 - add RELRO protection to su as well (#630017) * Mon Sep 06 2010 Ondrej Vasik - 8.5-6 @@ -1403,7 +775,7 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir - do not ignore sort's version sort for multibyte locales (#509688) -* Thu Jun 18 2009 Ondrej Vasik 7.4-2 +* Thu Jun 16 2009 Ondrej Vasik 7.4-2 - temporarily workaround probable kernel issue with TCSADRAIN(#504798) @@ -1496,7 +868,7 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir * Mon Nov 03 2008 Ondrej Vasik - 6.12-17 - Requires: ncurses (#469277) -* Wed Oct 22 2008 Ondrej Vasik - 6.12-16 +* Wed Oct 21 2008 Ondrej Vasik - 6.12-16 - make possible to disable capability in ls due to performance impact when not cached(#467508) - do not patch generated manpages - generate them at build @@ -1539,7 +911,7 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir * Mon Aug 04 2008 Kamil Dudka - 6.12-8 - ls -U1 now uses constant memory -* Wed Jul 23 2008 Kamil Dudka - 6.12-7 +* Wed Jul 24 2008 Kamil Dudka - 6.12-7 - dd: iflag=fullblock now read full blocks if possible (#431997, #449263) - ls: --color now highlights files with capabilities (#449985) @@ -1941,11 +1313,11 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir - Parametrize SELinux (bug #174067). - Fix runuser.pamd (bug #173807). -* Thu Nov 24 2005 Tim Waugh 5.93-4 +* Thu Nov 25 2005 Tim Waugh 5.93-4 - Rebuild to pick up new glibc *at functions. - Apply runuser PAM patch from bug #173807. Ship runuser PAM file. -* Tue Nov 15 2005 Dan Walsh 5.93-3 +* Tue Nov 14 2005 Dan Walsh 5.93-3 - Remove multiple from su.pamd * Mon Nov 14 2005 Tim Waugh 5.93-2 @@ -1985,7 +1357,7 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir - Allow id to run even when SELinux security context can not be run - Change chcon to use raw functions. -* Tue Jun 28 2005 Tim Waugh +* Thu Jun 28 2005 Tim Waugh - Corrected comments in DIR_COLORS.xterm (bug #161711). * Wed Jun 22 2005 Tim Waugh 5.2.1-52 @@ -2023,7 +1395,7 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir * Thu Mar 24 2005 Tim Waugh 5.2.1-43 - Removed patch that adds -C option to install(1). -* Wed Mar 16 2005 Tim Waugh 5.2.1-42 +* Wed Mar 14 2005 Tim Waugh 5.2.1-42 - Fixed pam patch. - Fixed broken configure test. - Fixed build with GCC 4 (bug #151045). @@ -2040,7 +1412,7 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir * Thu Jan 13 2005 Tim Waugh 5.2.1-37 - Fixed zh_CN translation (bug #144845). Patch from Mitrophan Chin. -* Tue Dec 28 2004 Dan Walsh 5.2.1-36 +* Mon Dec 28 2004 Dan Walsh 5.2.1-36 - Fix to only setdefaultfilecon if not overridden by command line * Mon Dec 27 2004 Dan Walsh 5.2.1-35 @@ -2336,7 +1708,7 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir * Mon Jul 28 2003 Tim Waugh 5.0-8 - Actually use the ACL patch (bug #100519). -* Wed Jul 16 2003 Dan Walsh 5.0-7 +* Wed Jul 18 2003 Dan Walsh 5.0-7 - Convert to SELinux * Mon Jun 9 2003 Tim Waugh diff --git a/sh-utils-1.16-paths.patch b/sh-utils-1.16-paths.patch new file mode 100644 index 0000000..00efc67 --- /dev/null +++ b/sh-utils-1.16-paths.patch @@ -0,0 +1,18 @@ +--- sh-utils-1.16/src/su.c.badpaths Mon Apr 14 14:26:55 1997 ++++ sh-utils-1.16/src/su.c Sun Aug 17 14:11:31 EDT 2003 +@@ -147,6 +147,15 @@ + # define DEFAULT_ROOT_LOGIN_PATH "/usr/ucb:/bin:/usr/bin:/etc" + #endif + ++/* The default paths which get set are both bogus and oddly influenced ++ by and -D on the commands line. Just to be clear, we'll set ++ these explicitly. -ewt */ ++#undef DEFAULT_LOGIN_PATH ++#undef DEFAULT_ROOT_LOGIN_PATH ++#define DEFAULT_LOGIN_PATH "/usr/local/bin:/bin:/usr/bin" ++#define DEFAULT_ROOT_LOGIN_PATH \ ++ "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" ++ + /* The shell to run if none is given in the user's passwd entry. */ + #define DEFAULT_SHELL "/bin/sh" + diff --git a/sh-utils-2.0.11-dateman.patch b/sh-utils-2.0.11-dateman.patch new file mode 100644 index 0000000..8684dc7 --- /dev/null +++ b/sh-utils-2.0.11-dateman.patch @@ -0,0 +1,12 @@ +diff -urNp coreutils-5.97-orig/man/date.x coreutils-5.97/man/date.x +--- coreutils-5.97-orig/man/date.x 1999-11-02 15:07:36.000000000 +0100 ++++ coreutils-5.97/man/date.x 2008-10-15 10:13:31.000000000 +0200 +@@ -11,3 +11,8 @@ + relative date, and numbers. An empty string indicates the beginning + of the day. The date string format is more complex than is easily + documented here but is fully described in the info documentation. ++[ENVIRONMENT] ++.TP ++TZ ++Specifies the timezone, unless overridden by command line parameters. ++If neither is specified, the setting from /etc/localtime is used. diff --git a/sources b/sources index 0952ab1..db9edbd 100644 --- a/sources +++ b/sources @@ -1,2 +1 @@ -SHA512 (coreutils-9.9.tar.xz.sig) = 0a3dfdfa6b4234e2e1d42142269f959bdf3cf8f6605a50270a27eff84dd22588f182121f7dd3eeb04be45f5109d02690215065b3d3b43882874d0e165a1435d0 -SHA512 (coreutils-9.9.tar.xz) = e7b0e59f7732d2c098ea4934014f470248bd5c4764210e9200a698010a8e3b95bbb26e543f0cd73ed5a4b8e1f8cda932c73f39954d68175e4deaa47526610c65 +094909fafa86110140b32e4948941545 coreutils-8.15.tar.xz diff --git a/supported_utils b/supported_utils deleted file mode 100644 index 6db4fb5..0000000 --- a/supported_utils +++ /dev/null @@ -1,105 +0,0 @@ -%{_bindir}/arch -%{_bindir}/b2sum -%{_bindir}/basename -%{_bindir}/basenc -%{_bindir}/cat -%{_bindir}/chgrp -%{_bindir}/chmod -%{_bindir}/chown -%{_bindir}/cp -%{_bindir}/cut -%{_bindir}/date -%{_bindir}/dd -%{_bindir}/df -%{_bindir}/echo -%{_bindir}/env -%{_bindir}/false -%{_bindir}/link -%{_bindir}/ln -%{_bindir}/ls -%{_bindir}/mkdir -%{_bindir}/mknod -%{_bindir}/mv -%{_bindir}/nice -%{_bindir}/pwd -%{_bindir}/readlink -%{_bindir}/rm -%{_bindir}/rmdir -%{_bindir}/sleep -%{_bindir}/sort -%{_bindir}/stty -%{_bindir}/sync -%{_bindir}/mktemp -%{_bindir}/touch -%{_bindir}/true -%{_bindir}/uname -%{_bindir}/unlink -%{_bindir}/[ -%{_bindir}/base32 -%{_bindir}/base64 -%{_bindir}/chcon -%{_bindir}/cksum -%{_bindir}/comm -%{_bindir}/csplit -%{_bindir}/dir -%{_bindir}/dircolors -%{_bindir}/dirname -%{_bindir}/du -%{_bindir}/expand -%{_bindir}/expr -%{_bindir}/factor -%{_bindir}/fmt -%{_bindir}/fold -%{_bindir}/groups -%{_bindir}/head -%{_bindir}/hostid -%{_bindir}/id -%{_bindir}/install -%{_bindir}/join -%{_bindir}/logname -%{_bindir}/md5sum -%{_bindir}/mkfifo -%{_bindir}/nl -%{_bindir}/nohup -%{_bindir}/nproc -%{_bindir}/numfmt -%{_bindir}/od -%{_bindir}/paste -%{_bindir}/pathchk -%{_bindir}/pinky -%{_bindir}/pr -%{_bindir}/printenv -%{_bindir}/printf -%{_bindir}/ptx -%{_bindir}/realpath -%{_bindir}/runcon -%{_bindir}/seq -%{_bindir}/sha1sum -%{_bindir}/sha224sum -%{_bindir}/sha256sum -%{_bindir}/sha384sum -%{_bindir}/sha512sum -%{_bindir}/shred -%{_bindir}/shuf -%{_bindir}/split -%{_bindir}/stat -%{_bindir}/stdbuf -%{_bindir}/sum -%{_bindir}/tac -%{_bindir}/tail -%{_bindir}/tee -%{_bindir}/test -%{_bindir}/timeout -%{_bindir}/tr -%{_bindir}/truncate -%{_bindir}/tsort -%{_bindir}/tty -%{_bindir}/unexpand -%{_bindir}/uniq -%{_bindir}/users -%{_bindir}/vdir -%{_bindir}/wc -%{_bindir}/who -%{_bindir}/whoami -%{_bindir}/yes -%{_sbindir}/chroot diff --git a/upstream-key.gpg b/upstream-key.gpg new file mode 100644 index 0000000..dc6dc1d --- /dev/null +++ b/upstream-key.gpg @@ -0,0 +1,123 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.6 (GNU/Linux) + +mQGiBDftyYoRBACvICTt5AWe7kdbRtJ37IZ+ED5tBA/IbISfqUPO+HmL/J9JSfkV +QHbdQR5dj5mrU6BY5YOY7L4KOS6lH3AgvsZ/NhkDBraBPgnMkpDqFb7z4keCIebb +AmlcBL2VQNTo0Lczo319YoZ+UaNH53OddlBY944qBTa0AlcJuS1SgEp7pwCg+CUj +4SjVzqZh5lgPTS0bnYvF/n0D/iItZ7WAm37KW+9UjArWZD6NO+mVMNq4GWmhcSBD +uyJOZFxFQWXdFRdM9sNO7lkWYVCxpXyFzmQcBzdrAt+zx/3QadEbduGAqEKAROQU +gSDlMITWGK97/Cadn1YRSDcGKNlJX9jlJvt5Q/xh+CnJ8HTwO0PF9A5N/phFuMMB +UH0pA/0e5eIBsr2Wvxy39+nGnNv5b+5tHkGXSSHKyI7+zOdIBTtRQO7lwTG9ioKg +/yMqb9NCSf4GdyZiFJsQ+TWoSyk1bvFHt7YUOhTeii7Zgbk7Due2q+b9KzzyH/r2 +kf+fLh0lgiy/LfBhvsfO8M9dji3XDyZpBLRO6gda9M9NqzEfgbQfSmltIE1leWVy +aW5nIDxqaW1AbWV5ZXJpbmcubmV0PohGBBARAgAGBQI9TvsUAAoJENoowjp5/0R0 +NTIAn2qpRF9QVupw/gz4UN5d5MKurlOMAKDNXKfXzWClHRq5ufCdwZead3WMMYhG +BBARAgAGBQJCk1gpAAoJEIvYLm8wuUtcqlIAn0KbOC5YSkgqhfhM1uRlHnvHB74A +AJ4qbzrkw7iitd1CH1eoMoFiP5CI14hGBBARAgAGBQJDYmg2AAoJELk/YMa1xM4T +ct0AoJIkdqI6dhTUDOVwiZRxaCKVYaoNAJsG8I+OPhhRhe7ZgN5iN3xlRfkhTohG +BBARAgAGBQJECHuEAAoJEFQUZr6xLcGbUyQAnRmg070gGrZ5E4ZPJRqL/DUoB7hN +AKCj7uAIpcRdrBAQW8PKiOWcPRvxjohGBBIRAgAGBQI/bJ2IAAoJEA6nVrUUSEP1 +QXoAoJ6dMlvbJUep2l5N8G0XFmRyxTrIAJ0bn5IYu7RMxqI0vv6DHn2VgEQLeohG +BBIRAgAGBQI/vFVMAAoJENKUXDvBNlC2gtYAn1zlWvzZaC2lxRXuW7fMWpB/5uVJ +AJ9RFEFFzl8BktsnskYJUIvrx5zVL4hGBBMRAgAGBQI/UFjyAAoJEDhZwDsuI25H +z80An0G2Xm22lMc7ThGGgKeovGP0GzPIAKCHFH2aY2Dv6XOYomNB1yvW7MU0ZIhG +BBMRAgAGBQI/cfsiAAoJEA3cqjJ41SZOmcoAoKulkHQ6TUVORoSN77UYtrdCKy0I +AKC5qT7peM0Jd6I9wPLwc7Fc65xraIhGBBMRAgAGBQJAmOELAAoJEAu1FKXQbtaf +ysgAoL7Zl3BSH+/F9ouPCXkduzIywdx9AJ9OevRoJwxpER+SwSiLnw9Q7fVmcYhX +BBMRAgAXBQI66oJOBQsHCgMEAxUDAgMWAgECF4AACgkQ/dLerNMzy6HlawCg5UXJ +LGWj9P0SuJKcGm+mqKb1J2MAn3YrgB3duqFNs/yS4mvxM74TzI5miFoEExECABoF +CwcKAwQDFQMCAxYCAQIXgAIZAQUCOuqCTwAKCRD90t6s0zPLoaVVAJ0UZOyi+B+q +cNTEDSDrc3Oc1MzZrQCg0UONeu4Dv4N5ZLI6lZBMZETaCmKIXwQTEQIAFwUCOuqC +TgULBwoDBAMVAwIDFgIBAheAABIJEP3S3qzTM8uhB2VHUEcAAQHlawCg5UXJLGWj +9P0SuJKcGm+mqKb1J2MAn3YrgB3duqFNs/yS4mvxM74TzI5miGIEExECABoFCwcK +AwQDFQMCAxYCAQIXgAIZAQUCOuqCTwASCRD90t6s0zPLoQdlR1BHAAEBpVUAnRRk +7KL4H6pw1MQNIOtzc5zUzNmtAKDRQ4167gO/g3lksjqVkExkRNoKYrQfSmltIE1l +eWVyaW5nIDxtZXllcmluZ0BnbnUub3JnPohGBBARAgAGBQJCk1gsAAoJEIvYLm8w +uUtcHS0AoIO9LsaLdn6aH3fskRVZ4qhpRBXbAJ0drV2s3abBKhkhUui7kpF87MTD ++4hGBBARAgAGBQJDYmg8AAoJELk/YMa1xM4TdT4Ani/0ORxwCzqGT0+BG2thzbO7 +aFkuAKCoKP+u6WhYYOBdEcaM6T5QLN56H4hGBBARAgAGBQJECHuHAAoJEFQUZr6x +LcGbrKEAoLef0BqLLpNGhAFJKSAvWEWOiGcxAJ9w7F7MtsDoegKeQ44yYiPX5jEu +5ohGBBIRAgAGBQI/bJ2IAAoJEA6nVrUUSEP13sUAn3IWX1RWnH50v+DZKcqzCaSA +oqHbAKCVvtirU/A3FJLnuyIBv+lguddi2IhGBBIRAgAGBQI/vFVRAAoJENKUXDvB +NlC2D68AnAzm1iw0YSQ1GuPaU3lG8n72p5EBAJ4pNBP+RFWjvZSfcUYhZAFhq8CB +QYhGBBMRAgAGBQI/cfslAAoJEA3cqjJ41SZO8asAnRsJcSER+vpIIzM/et8PakIC +ZJxsAJ9LjdnHkb+Zr9YDXzKXu6OTiJvIh4hGBBMRAgAGBQJAmOEOAAoJEAu1FKXQ +btafLL8AoJask7aB+OfOQgS/kMlKXAA25Hl3AKC/3XJeRRR0ze508VcIhx7EhYVV +84heBBMRAgAeBQI/UFjBAhsDBgsJCAcDAgMVAgMDFgIBAh4BAheAAAoJEP3S3qzT +M8uh8gwAoLfqQt7QgzavHlD44LxmAXovm5t0AJ4m8EQC+N9oJyODmpLbfQKNL6pq +zohmBBMRAgAeBQI/UFjBAhsDBgsJCAcDAgMVAgMDFgIBAh4BAheAABIJEP3S3qzT +M8uhB2VHUEcAAQHyDACgt+pC3tCDNq8eUPjgvGYBei+bm3QAnibwRAL432gnI4Oa +ktt9Ao0vqmrOtCFKaW0gTWV5ZXJpbmcgPG1leWVyaW5nQHBvYm94LmNvbT6IRgQQ +EQIABgUCQpNYLAAKCRCL2C5vMLlLXP7FAKCodISH72q8e30TxLwdoOh7hDjehACf +U97FCEOWICQaEI2BvOzGzn6yrO6IRgQQEQIABgUCQ2JoPAAKCRC5P2DGtcTOE0Gk +AJ43felw+/nxzJ7DVJYZ0tbASZ3BcACeNf2nXMkqkwrBZZ9DDMUGQ6tIB3GIRgQQ +EQIABgUCRAh7hwAKCRBUFGa+sS3Bm1nUAJ0foaMmGWqugETz37RZ2XpCfdQIlQCe +N50WxYPBxrGGmhhGOVbji1uhVSmIRgQSEQIABgUCP2ydiAAKCRAOp1a1FEhD9T73 +AJ4/51C6L0lHrX77DFXVJrB02yybsACgi/9TewF7HaF3x8fdMEZxsRK1HR+IRgQS +EQIABgUCP7xVUQAKCRDSlFw7wTZQtvjnAJ9FM83LyrTs2Dk/T7kOcSFTfjXqegCe +OlpOQ/sB4EtoHxrTSCy3OhToVsmIRgQTEQIABgUCP1BY+wAKCRA4WcA7LiNuR5yI +AJ9F3RsjjwtYX2rSx+j5o4+y4Dyl9wCfVR9uTBDLDP3kOaDrTT/H9XHTf6uIRgQT +EQIABgUCP3H7JQAKCRAN3KoyeNUmTv4eAJ9rCBUUXWYFUrjUayOenPULMW1BhACg +ncwdeTN+SGy8lX3zoo1vdNv+vTKIRgQTEQIABgUCQJjhDgAKCRALtRSl0G7WnyNP +AJ9Gn9yRup0zePUPMex36fX94o+i8wCggdDgtpKjzcaQ83o8VBiemFeiss+IXAQT +EQIAHAUCPjpzhwIbAwQLBwMCAxUCAwMWAgECHgECF4AACgkQ/dLerNMzy6FG5gCg +99D5pDqSRuZP2QJAT8LNiCZlRGgAn25OTXbNlHkM+gYFj0fyo+Ikj+T5iGQEExEC +ABwFAj46c4cCGwMECwcDAgMVAgMDFgIBAh4BAheAABIJEP3S3qzTM8uhB2VHUEcA +AQFG5gCg99D5pDqSRuZP2QJAT8LNiCZlRGgAn25OTXbNlHkM+gYFj0fyo+Ikj+T5 +tCJKaW0gTWV5ZXJpbmcgPG1leWVyaW5nQGFzY2VuZC5jb20+iEYEEBECAAYFAkKT +WCwACgkQi9gubzC5S1zwAQCgnPUCCl1g6eJdI5ZViACDiaaULAAAn19sIyQmkiaU +45QVcDtYuQTNSh/QiEYEEBECAAYFAkNiaDwACgkQuT9gxrXEzhP+igCfc526l8n/ +q8zVhIe9NonG+jVlrEoAnRXKebriKwmvVSdqbY8khlbJjB/ziEYEEBECAAYFAkQI +e4cACgkQVBRmvrEtwZs2owCgwzEOLdyXa2JGA/xkpBluqa8/UyMAnjZyxESMAj/A +2rUg3IvgtBmaetE4iEYEEhECAAYFAj+8VVEACgkQ0pRcO8E2ULaqIQCfQlbRoDOL +Hv+9YVxPgD8yhwFB850AnRTmAG4Z57YD92s4o1ne9sgaufmdiEYEExECAAYFAj9Q +WPsACgkQOFnAOy4jbkfOoQCgwfC1mkANwR+vv9TVlYkmoZ6wNL8An0dql+uy5ic1 +YpyKfV7g7MMuEMDwiEYEExECAAYFAj9x+yUACgkQDdyqMnjVJk6QCwCglS7PPvFR +HoOZxl7XgpVbAK6vZQgAniVxncBgSu06lmsDNHiJpiDMIZkkiEYEExECAAYFAkCY +4Q4ACgkQC7UUpdBu1p+QqwCeNzsozeUjiCFQBBiR+gCBnvZhQqgAnj4ImXyp45hs +fc3dZHP3qB1Ws5UjiFUEExECABUFAjftyYoDCwoDAxUDAgMWAgECF4AACgkQ/dLe +rNMzy6HnugCePkbs7JcEo0837WNqdoGf2WXL3vIAoK0cStFCa4zj4FV/SoG9cDZP +JOzfiF0EExECABUFAjftyYoDCwoDAxUDAgMWAgECF4AAEgkQ/dLerNMzy6EHZUdQ +RwABAee6AJ4+RuzslwSjTzftY2p2gZ/ZZcve8gCgrRxK0UJrjOPgVX9Kgb1wNk8k +7N+0IkppbSBNZXllcmluZyA8bWV5ZXJpbmdAbHVjZW50LmNvbT6IRQQTEQIABgUC +QJjhDgAKCRALtRSl0G7Wn/YLAJdAhf8twtaImmHzRT7eaUIf0b4+AJ9hRfAjWrRp +UF5cW5AzZsVwEW7Vc4hGBBARAgAGBQJCk1gsAAoJEIvYLm8wuUtceyMAoJGYrqPm +T+ThNBRLt5aIq/p3yBHmAJ0V0tEMjdIafWlY6IDZkst2VXBPFohGBBARAgAGBQJD +Ymg8AAoJELk/YMa1xM4TTxEAnAtkRTdyDNdPn5kW3HMKcQp9S02vAJ9wiBJbBeaB +jGcQ4zoafo0vw8ZMi4hGBBARAgAGBQJECHuHAAoJEFQUZr6xLcGbZi4AoK2Th3Pi +pC+CWdYDCA9qNa+uUkHsAKCHUU/oOSEqvjEHoYs22RZzVGbbVohGBBIRAgAGBQI/ +vFVRAAoJENKUXDvBNlC2qQ0An3hiEeuqRgzbuY6YLqiA9FH0GHEEAJ4j2O8AjZFq +Vc8RL32KA6nuwfJ28ohGBBMRAgAGBQI/UFj7AAoJEDhZwDsuI25HPicAoJOlcGaT +t5dvksbBg00BNCyZl8odAJ0UCIFlFzzB/x050scZKMrvquc2T4hGBBMRAgAGBQI/ +cfslAAoJEA3cqjJ41SZO5mQAoLTvGtjJxspvgEg3z3T/q6iI/FdxAJ4wgnqQjRvm +AHAWMibcDupPA10u+ohVBBMRAgAVBQI37e/HAwsKAwMVAwIDFgIBAheAAAoJEP3S +3qzTM8uh8vAAn23cUtWPdFr4wIwUNo9bsY1CUHMNAKCoHS3nayqM/WUfihcZJoOs +kQA22ohdBBMRAgAVBQI37e/HAwsKAwMVAwIDFgIBAheAABIJEP3S3qzTM8uhB2VH +UEcAAQHy8ACfbdxS1Y90WvjAjBQ2j1uxjUJQcw0AoKgdLedrKoz9ZR+KFxkmg6yR +ADbatCdKaW0gTWV5ZXJpbmcgPG1leWVyaW5nQG5hLW5ldC5vcm5sLmdvdj6IRgQQ +EQIABgUCPU77FAAKCRDaKMI6ef9EdBjQAJ41hqQaE3W2dHgN9otb7fL0n6U1YACg +kI9DvFQ1YmpLI8jdGwbDxDodAeOIRgQQEQIABgUCQpNYLAAKCRCL2C5vMLlLXMrg +AJ90LwV+nd+U4GEvzYixFvksHvtFGgCggD3NDeGXlgUhPB+nqyBq2QKfZxKIRgQQ +EQIABgUCQ2JoPAAKCRC5P2DGtcTOE4WfAJ4uxTyLyO4NCBk/IlTM0NAKLFHJgwCc +DP0YQC0oDm5uJ8/ZIkl0MUrzKXGIRgQQEQIABgUCRAh7hwAKCRBUFGa+sS3BmyTW +AJ4+X1CGNorq+Nme5tTIVskgYKH7wQCcD7UpPt2+r+NcGSYftkKk3O8R8TKIRgQS +EQIABgUCP7xVUQAKCRDSlFw7wTZQtolWAJ98yLyyC6jzrF/YG5kqeGqHSNdKtQCd +EdCDkGG09QJX8gFfZ/r8lWlflj+IRgQTEQIABgUCP1BY+wAKCRA4WcA7LiNuR4mz +AKC/1XBB9cBCs8X/KvoLLQP75q0i2QCbBb0UoVSUYgsdETzujbTwg+0HLseIRgQT +EQIABgUCP3H7JQAKCRAN3KoyeNUmTql1AJsEhcfoOC2U4JjHR6rWzqinaIxcNgCg +lmdHMQ3L8zCfNzD7lehquPy2P0eIRgQTEQIABgUCQJjhDgAKCRALtRSl0G7Wn+1r +AJ4nUVrAEtL+XBp2UU1QmVCxa7lcSwCfT8ds7xZ++aZomPK2Xvz230WnUsGIVQQT +EQIAFQUCN+3v9gMLCgMDFQMCAxYCAQIXgAAKCRD90t6s0zPLocAwAKCJ4wBEND4W +mzs6Sp47mWBsp96HRACfTH+SGkDfLqgkZ7JgEgzSDKGl4TyIXQQTEQIAFQUCN+3v +9gMLCgMDFQMCAxYCAQIXgAASCRD90t6s0zPLoQdlR1BHAAEBwDAAoInjAEQ0Phab +OzpKnjuZYGyn3odEAJ9Mf5IaQN8uqCRnsmASDNIMoaXhPLkBDQQ37cmSEAQAx3xz +BZlJikWJaiZGru3cEKYYnRFp8No2b4jhBwY9nKn8UIxuY5aQN4ka/k81wqjlC6cT +wn5R7kg2ha8eGXpwYhKGwn5MGvIxqfoj2tsQ76uluTowHA4seoavi7RGEDzm4Vpt +8Nua8krrZ2QPtLA86gkzL1QG5Bbv/o2Ldx8HHNcAAwcEAKcK2tj2X8RPgUarczXv +rdXMteeSFnI7fagbLpEfaTI2xa1ADLg5UO4M9Erz9m6k6xV6loxcBB9H5Ljm9GWf +el4T4p1lwzi3Lu5hKzIiFs+5vsy+fyEai4e5f6v9Ww3Q3Ec6UZpPZGyN+PDPlZxe +rf3ZIMogSGrrEBhprhLHReudiE4EGBECAAYFAjftyZIAEgkQ/dLerNMzy6EHZUdQ +RwABAQXiAKCilmALgD6mhccl4ISaUB5LfW74BQCgqd7wIfbV2+NKqf1Yuj75sryW +Ke4= +=zRdO +-----END PGP PUBLIC KEY BLOCK-----