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-----
-
-mQINBE58fE4BEADGS6VzDkx2OOQMPQedsmBtRs3S5sz9tzO51EwkS779js3Sjt96
-KlQM0SbwtbUxOFor42LRXJKUU9T/Jl3v3+onASvoHAUcuAL15WAhnY9cuQeFOvZP
-/iy0I1+bV0CILrz364T6vL614obnBBdTg8ZqSZM+csRlpGwXJiuY6mkrsPLXakxA
-35n/nAgQOcQPj36CuuvpCH4JKPkzklwUMqueDzXkYMNSdWmVnI+ZSfDmeiwzAbFY
-tE5uGW+c3DzD98RGCLt3FLr86n24IDlaTZSsaWbTJVsur9s4sbp6rST3pspDSQYF
-ShhJ5aqqEYIvPp5kXj2CZJjOFBnIkn+0aDSps+XrnZjJn/f8f9lIAg0/0JjmytHY
-yopo6HFZMdtOvklmnsIuJ/fdyk7761+necYHf5dopVuv29PSu62+A/gnKGfGaqtY
-AjXFfsiLp/+iTQ+LNV4hWFbFKHHZOn4G194pWl6nY1gArwQKPZ5p6uy5EXgiNPRs
-C1CcuVZNJp1RiayhTI68uuI+cldBU6N7+yZKGhjDUQKjIZ3eDB8X7vsCC9S1GgvX
-Hcv8mjcMcHtnoC0w0FiW35JYtAu9mY4+uQhoRPTyPHh+ufX+OdKf7q5BKCppY1r7
-HF1VRFKjSybhEwMeGBdj1EEY413/A8ynpgpHLosPT36n8HtAWUGu+TadZQARAQAB
-tCFQw6FkcmFpZyBCcmFkeSA8UEBkcmFpZ0JyYWR5LmNvbT6JAjsEEwECACUCGwMG
-CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheABQJOfIDXAhkBAAoJEN9v2XEwYDfZ4AEP
-/jr6zmXUVhNiVCtqiHqc4jOs1OPC51iEcMUwpeaEEWHq17uMMIqz+nd8B7CAyjzw
-FJIW4gtwPS3uTsXR2+KOl1VnMS5O/M9suyG5eM+fpCWkzyTC1He/1M9iaRMGY8u2
-wOjZoeY40QFN5fvL/BuC8GLBefI0rTzMaYO0WFlVWTpaemj4pL1Z4JoQdmR49H6O
-qI155jfsXuv2VWjN1NoYT8w3FEugc7rdNWe4dmscU5H54JEQMuFd34X7Ja2S9YnQ
-OdqO/nVQGm3te2X6ElOBoA68HyuXcEozf0KgKkcPrBEV/tjQrzn5Mc7jOgeCDDV3
-7MFwBZUi+z69jjOc85tNYf/FHRfUFnBLPC1HrOIlrraaqydPfvHBRTybTJVhXlQW
-b9kqfrT1HU8UGfwP+5cwTy2WjZecxvozZakYBO4cdcmsSNE5jM8Tp7EU7ktxPXg1
-IQwZ8sEFJN6HRhRVmhK1FyR1hrwdcvfYrFmoYbyWUCW1RNuGw3RXdjXjGSl6VxzC
-vrWXjeiMyLQQ7l7IneFaIPV22quPi/NVJbNeT5DqKa58kYgEVASfZVZkL7S3PJvj
-fEqhw5jTi3l84AHtYNNo95UXWQQCWhpYjZ3q61satme++Eth552VAGP+JK4634mj
-vVViYmWAnjs0efSN9yCOWKDKBONviW5WGZwi7MVtgF6uiQIcBBMBCAAGBQJOhIiA
-AAoJEH/Z/MsAC+7uW3YP/RJlgRTkRa8t0t4oK06zg+jSMMQ3ZFsiipQEBMzJfCXy
-C9pG+gU/mgcOoqnpxY6iA9ufY0dLOJYhMPsSLtrkjwMAIU54UY+WRpaTcXB+5Zma
-1OoA/Oh6wcZHy61PEUkSfoiQ8vtXhzqQn7PAUbi7ds5ecn0hy8E6KKEEysFt+Say
-zrINiCeO3wr6LUqUtpxdo8JGaHhdXGZsk5OMARnYlC/rzZxFKsie3+FKO7KNFoNr
-edIElFKdx6b7r4CXqfK9XpZr8SaM+f3wh8mBCK4W2Re50/6inHAnTYwW0octwr0b
-AtlHOY2myauBdj+19IWntZnhoKxuhVPLaEoG8j26k+LIP6h8fB8GoRh5oUarLiCk
-fahDRNY/bPFtBnsE6Co5OTTy41CFkGX0JbguTpL0uPQxygIKz7x29P509fMpq5t8
-z0hcVYJ5/cXiNjFLid2JsWugKAWe5k53E7qQKR+jLSvPtZ2oOHAMUzu6hOnwDY4Q
-5r+j6t81tFAlS6P4fcpVU+alUwvVNdXc6MSkfmK9ahumjYnLKy0uo242U1wuBZgN
-adr6pFxKrMiC/0PVJz+ZQOZU4OUt/t4E9KpyUEasfOl1z4r+q+6dZffRbrP5CCIQ
-M6A01GRbEufrcXjgYnmaDncV8JnmLbHOoZ8WF+xczywFg45ULSt0N5ZiS/BbatuO
-iEYEExECAAYFAlE+Z4wACgkQFg9ft4s9SAbl2ACgqTFvvpXJzTpZrKrisKY2i9RR
-dNsAoJt0xI/urG+JIn5kUJobcPsZtY62iQIcBBMBAgAGBQJRY/sdAAoJEGiHnitP
-7eG+NrgP/iKO5+3ytwRYwwbtQNROUQSbLwpUN2N3S3XH9lRV2NGEx5nx9Yn0l22w
-gRMbULeFk4S1Ak3mR16D/mlnfPMyVqrJotp/E4rkK5OzjIsy58vL6B4PLgut2Xlw
-Clg+XklxkQDfT4m/QtLGJYOnx/AjBn6ABu2zD4FWsn7hIMdXDq9bpr9IT96iqd1P
-MYogglYK5OBFIGefjf+Sut7i3vuwJcjuNdL79tIbn5yple96EOL6eoHSRv5ndcoS
-mxHtmin0lVeQ1ajoBETNh/E6/yItZNtc7BKbttYF/tN0GYpQB+dcCeiXLAOJ9n/2
-ET0gAWMP+kHzdcl3mdfw+KiZOK0gak0cu6LW+3GGAXXZkFYh7I70Y7K0wYNNgy3W
-rzlISbAeC0zKOzpJJ2eQWJAs13FyinUPEyKRorRSubajbhJzHa4t3SwevR9DExnG
-DL23UWreDO4ElDbvT3MzMA7ifaVSLFR/Rxu/6xsK1lPs2NygmGpdDnPjJung9CTa
-1yyadMi3Cfgggu5IuUaKtzW61lbD8sMXqLRoFIIkZjcQagS/ybGeKIAedCE6pqMh
-MViSIVi2G/F1wVaahfhjvaj87yYPxUuHq4hHwx2RE1EjP66a1IoR4key/eZDWfHi
-th2VeeaVnma12NTl1GzfaEig3mzgtB7lM50/qJ7ml+MeE5agga7oiQIcBBABCgAG
-BQJVfds0AAoJECFMgsI2H9co0u0QAK+EhLBUwJJ1XfuheL8pXSJ7FxaicSPk9dKL
-Fbhc2oIAItqGSAsBRncYH8jYAPSwtCq1whATbyPgoEDm5G8KQEdAZ4bA6mhXw7Nj
-UgHtkbnm1bIbavM/lhZLdNi+H0ZV4w5G4e47/zMLbwK84ZhiArRdklq58200CmPB
-qNnfaxRxxkJBA6Bn6Cnv0FUSRvHUlSXgOw+pZXGNFZpzi50d38L1na7iCxrfyxH1
-sS3Nhn3zTf8BCKDcCVyP8UeBP9Fb2+fYJ/f3/KN0C12Hnbqc9WsYvFSYWq6u+I8/
-GP0oQohe3Fv5S1VEHWB1feCNmvVtV50J7hukTBojERhC07Z+2T5G2aw1Cc4zxkOA
-uwOBTzuij53sErn5o+hca/pJTlXz8jJ8OxSFY8FT1QGVlLAN10yl9mDsdnZb2VSn
-bQdqYG/qfbdC2cm2rCrhcKFpierXURLr14UC1O7tbDmLFYXDxvQfjtj9GSo4NHrK
-wlTvfHi+3x6fGyx+Auulcjt65A5kQ3mycOc5paZhTdIKhS5mFdQoKw1Sg6RPiRIy
-OH5fx8ob6I7gN+bcuX3r8KCH1FcIiyZd3WsVQlI1EfnpujkFo1O2xDVpm/D9IjAO
-MRqKTtnHbCjaPUrsRRysAharr47YuzQUYGaMmIJfSN3kP4U2OukYmVFSUpxrlNep
-M7LGQsmdiQIzBBMBCAAdFiEEP0srMOiHNvRbOiwMIhOnPE4lafEFAlimlJcACgkQ
-IhOnPE4lafEZRA//bTNw4mi9B04yacqaFlJ5f3i9v0fWnsSXNEkW5wslhbjoD8Ab
-PpVNrrw7Jm0YTFNa5TtnNc7fcnHNNfsL0LbtCfdrZOTm7vZstFJrASHam7La5655
-RgvTbozSWuuYrfLyKAituRmhJyv3ntpP9K6yUAAuJjxR3ny1sn8KNIFX7g49emlC
-k5eIEujcmaVJp1l8wbnf/jioKr6QeXz0cxWUUFXolR0AUt8Vy11V+qRQb9Iw902y
-2gmbMun4HjYEtCtm+eY9TRD5jY7hCHTYTFEfWITnGIRDyHyLIS9a0xql3W3EyWO0
-JkHNIm1ajqbuUp4IIxoZmIxNmEmW3aS8rsuIY1P0zXjj6j+GcRX8lZJOIhieBfWk
-ku6dZwwtv9wF3K1UQzFwRsERqiwj4CAwlUy4um1eLOcjx6ge7Ub67FQCihx0VEpO
-jnngjQN4clth8YM5nst/+lOFsZb/k2SHqTnpdE9pFl39aij5Y7nAI6xZL8xyM+CG
-9tcFMXBrmyZAmD83v0N2PyjWuLAyY2b2SSYhOXIVfonHYSfuGw27yvn6mQ0jICZu
-vdeZQASYgBAohMDXOgDgKdL6g143d96tQST72RflXAxoKTbblKK0kqxZnfdRIja6
-MTLstYJUNwWQsSD7bwcY8wnTXPK5TpPtBH4q0sjkjd1ZNNAQvbbowTlZ/smJAjME
-EwEKAB0WIQQSG9otSstjYWs2eg5Y4Rux5BTZrQUCWKj25AAKCRBY4Rux5BTZrY/1
-EACrnMsYUnN9sc9qhy67pAMPy5QaGsYY5IMOnQlTcjXYrBRBx0kEWhiMrX4USqRK
-Yj51J5U/6MIyeFbmDMaGrUQ/Ba9GxxjOnYAUri5S7lvtuYZGYsQqQc4ORgNCSRAQ
-GMiB5Q+3oWbkaoads3ezhcE+R7/0HrqgxgCRg5mzTx6up5vrkBN8kbI6BIpgoPBy
-AzTOul/EIkJuBYHg4IPt9dWOmbFbJyxMJg7kNwTS65GypIEiMeQXK4VzcdB6jr2L
-Ju77Ia+pWyzKpq323swdRZtM/hHrGJrwJDbdKMfWxoWf9e8cqvO5hIM2mzchHCQ8
-7OQSnb3JIsHQIPHCxeaxzMOS1smRNbYu4/yY/MRcWaNiScuoMJqI0gVWd+XIScwE
-PSGyKlncV8moki4pFNkseaLw3MEQDoxqf9TtxXnEB7ZduvR/UcELUB85lVjNnoiy
-GjrcagTZ4jDISxADvqBP+a02GsY28dLOk6smqPPwezbVWqV+ABPeQ+bgPd313MGl
-a22s72O4/nXzzt0rNgmgEIqMy0OkgmxAUBCSfcQp88HEnk/roHsUV4iYwAks2cOp
-CDriBnwjIywK+hVq0r8nuBNRQt0P/Yp75ZITffPRrOLVXvA8D7tV+kIm1GrjDbIZ
-OFCNpAUCHXv/cXPeUvHsSd9hmyjGbNN3UzpxhykiDF9GWYkBHAQTAQgABgUCWKaB
-cAAKCRCZRTN/KIg+y2JSCADAOSj2N7T8PriPsuGbRWehb2zvfjQ1C/IiDIWf6s7F
-QuEjfg4NuWUJ2rPl2bYFey2yzSx7Ld0yNNdzSRxng6QADHUHYAneQi2WuGlyA06P
-DDfFERlWRv6JZgnL9R7rWHB+RAa6DnPPgpxifABv9RR4caU+8uAP24KHRxCQXPx7
-LfB8hi+G8G3UYbuLnO5FTTuCObjjSh50h8qEt0f5y65R4kDDA40/L26POJNsHc5u
-EE9rZlh0c4AqmakRSmH83+Q6XRWOtn/zPggj85ir0gsxLAezZG/OtuAyXW+rOC0L
-RJDJ3JaiScUC3xewY5L/7jgg9aTcvuwxKoLBIaHOYtJQiQIzBBMBCgAdFiEE+ymK
-u+HQChyPpNwfqLUfXoAyzOQFAlimepMACgkQqLUfXoAyzOQokg/8CqbMll42B+nG
-VDdSNFCNjhjhKYctR/aZa2th7iDRwsTFuqSVHbywRL0XrkI0YOOJU57V56fBY7Uh
-kfOKc6oeL7EXxpox8ehMToWMOcLSvi37EGMmlGLXokM9bN1gxfdFIrZr1Ji1kBYX
-hvSj2Fxxi2NGRp0uy+IIOa0vB29u2xHi6GWk8U8MBMn0UcP6H053Kk6tMsMDEhF2
-rSYGpvKFSWywuFuELosSS6jG73+6pg9fMWBTDYQyWFH8YRA9AlpxWxT29gcKaftM
-SBIz86Svh3PZ7qOEDVxh+yWAQTVUTVuGzUSleDDuJt75QLSt+ZERS9iezodB6EOb
-AZr6canAJGmDwmjPTLwS0E3U197QW6encv3qUSA0Sb/QyAzr5007d2PzkIk6wJq3
-SxBdBRqCjAyR0VxZr2kE1Yr3t5rI3MOFsVWIKIpmkLzmCSPuUGFTvOZHlYVaTOKI
-x5ge8d9smXdHjpSF0iGl45e0u1UMDsiU9dpo++ygdZWAnMI12Md5MO+K2uB4gLk8
-Njln1duZ0MQP9M6swkiIwH6jig3BkRCIAIWCNhbScBWJ79+HKD4Swk92+vTKDFRV
-lrD8TQlQSbS69Lbon4/v+NwgcpHRTigY5TZZ6s4DXBUl8OIkXDs2LHeboTvm2Zu8
-gX+uWujFHr0nJmvwI1P/ih3kYoEFqLuJAjMEEwEKAB0WIQS7Pk4P+lsqogxkAaHa
-lBBIg4QoJgUCWKeHnwAKCRDalBBIg4QoJv+gD/9AygNKRsaxJ19u0wyLifpGOsi2
-a6mlmwZkLLYhomeC82iV4+7EeI++QFhLc+KlRNZtkQld9rmihbcJo9UOfqTwwG/W
-bzSF/Ed0GSFzPtS6HDjVPTn7qiKQoeat/e6g+VmYoK765wLknj75Tq0jPltX0/Yl
-78s0ZwMI+HhirTBreOS6AVPlS8wFD4ywe64PN/YjgePAEfiIEiYICXmwGUHjPBgK
-a50z9VuVs3TRLo+b00N73YDEW8tlpouhETQuL8hAYhjGgivHss0DRnuB5fNe6FgN
-vwretguK3uknup1vrvVvDXOUOIdI1UksplrJvDbjYrFJB+L4VSbyGk7Kl6oSGKiz
-YRF7gM4I+hpXlVWSKVxEdUlA9F6KPm3iqM5ld6K3Q6rDuppO/2BaqlBhinR+Z3bJ
-TLtM1uKh0IgyGUstEkML/kjF9wJcCC+z7ZmW0k2CdA9JyMiHDQdVblxZpUI//Yge
-gA4P32X1OofAFX2oXua88qehbEY2uYk3OFsR3bJwbTn40bJkxE8072IpBozYzskg
-14Q/xnUxXkIL1wqLU1GPi9l+kbuh2+8yAdlz799x7De/uZhk8IwOOC5H+2oLp+vd
-iRXDLKU1sDBiVFRJb9kosvUj7S/a15My1eqOSVP5Fa0GbXNw7ndvcpybMoFqbVSC
-lzjlN2OgZuXYEl2PU4kCMwQQAQgAHRYhBH/Z1lK/X9LsXxORsHmPHjXLTTipBQJY
-qndrAAoJEHmPHjXLTTip6uUP/j3RieBfyGnau1a4KClaXlPGHxlu9M1fFw+aRqV7
-r8ALWuQzsKlh8QlPEWhtqkty0BFXAhzRMYJd3G/5j9kaoS9NAeNpJpbZd9Gz25ZN
-k+3PCkww4XthvKNY/ONwnwGuelLpIbwa25+f7Oct55tthkyM2TWXlwkRVNpeMNhk
-uUkP4+gFnpvtzUTFqwYtaEtNY3UFw1CjmcA5xTGL6pIg2FKf6m1YyJJkDLpU2/pB
-Ca8Mk/A9wQZ/9+M/l8goNq05vsQsp8nlh9zo1XpwWYBq3OwPQKDt4d6rAwU+zMHC
-XI5MP5B2g2Pj+M5bQMNOxa4sLw71ALaCYETeHHi24Kp/ZhOWsUomwc+v7t5gApAk
-6gjxbGklMWhdJuk2I+lv796J4cFI4VZpTXAygMSnnlo+GoMiqTz0C9eElZlp8z/Z
-yy9g88Z8fBoAY1SmrroaxLOvlFKRG92xhd+JUh0kj72loB+Fozg5HV1OqkF6c2us
-w3XCoIcht87TxmZWPTXqXdPXrStS74g59vrVyGvsNN2hG/l4dPGZSEV63Kn2eiti
-Of3JPYJcy0iQpBBnhhKQwPVNgWso7NxsNsVYOUZCDeSoCFEvrdUFSr6q26IBBLcw
-itnF/KEX3MyJLGr1BjDF9KqdP3+YL5Eqrq1Zn7LtyAbC2Odo4KY6vOT3SRrSkBRH
-RRq4iQIcBBMBAgAGBQJYrLQ2AAoJEPaR/VwUa1eD1d8P/1qcubzbb/p4jpnrZsXW
-i6+CAeJuA2f2qyBJtdVPhiz2swSHMNIlhVWh20w4892yv7Mgafj6i3Zoben088Bd
-BTvCUOXRtkepCSTLTg1fTa/l3a2vNxLyK3LT6Xf8KuY5lXTH+XWn7vG/N4T6jyd2
-MQLP9VUltRkk7aNarIZvoYMd6/JVqKVhvxg42UZmcjke3PFKiHMIHBVSGBu3W1Mx
-TDNgVZqTJlsqvfShwoBjPPYLBpSVZKHKgjirsDkZTS+ufpVmt2rzlujeVyC6y5f4
-subOde/pxGnTT+sMJENe/3uJxjUIy07xyXKBRnhpPxXbpTafZCcVc688er0CLRW2
-JsL9aEmEM0FV6HlnvW4ivoW1v9mSevAxe+KvgCO2cU2+HFqN/tCtxnr8rZ2HIpf8
-00cTpdvIn7wibGP9jfwMisD2Mugx28eLrZ+1sNaRLwVmroedjo9NJr2BiyPozOEN
-lGX8V/RxQLaQfiHwyuKVpxA8rlx5evvtDE2d31ekVtdLXtN+GmCymnPhu1KbD5Mq
-+Xk+yj1t8tdMD+SiFclz1uVeAOGpX5u7GMIsy4W8yoB5JlrwrsFot6UBaVZjAVHB
-XTdMvBGsfxmimO7d0p2tBFJ1QV2lAafVhVIklCT8zXk4McqqtWxXIKWEB9dfIpbD
-/A5MPtu7X91BTISC7SmRdBjViQGcBBMBCAAGBQJYrnXHAAoJEBzIdvEMrJ+JDgAM
-AJyHN3j+g47bSERRxLevoRybp8/BoRfK/OjcLRxhOru4prOAiJEfNo77IbG9Quz3
-aBn7vRDh44BxXIR/NjI6kM3hsN40BBDVwfeFEFGKciV3cjCBqlqnhwt4MV6iDoGQ
-1CkTm4LZQvtjQN26PAXUxxl/GO39vze3a8z3QP9BatZ+KrLOp2u7pOkwHNkY3Anb
-/H0AUq0fH2Dq5omDJB8R54jlHc3/ZrLvujCVAmEuTPxK6LGl5xg4TaBtYeUgIki8
-A9iwrcFgh9OjgAuG1PFs+6RroE+nVPm/ZPDJ5l45ZHR4qQB52qp2lxf745PlSHj7
-23d6ASx/I8mDZ7bPqk2aCKXGQqkZ31b+I+Ut2ru2nEW6JAna26kgBMhNrINqLNxO
-qPXjZHqZHG1amvlTAwGpAgeW5WBPvNjFn1WNPB1+9vCPTSwkWLR8dnzy46Rsfohk
-RAGFtQjdccBxaikRHuUlIUI32M0WjKCP/sy5nVLQKrX9xqkOj+mSblmbS+u8cmIH
-0rQiUMOhZHJhaWcgQnJhZHkgPHBicmFkeUByZWRoYXQuY29tPokCHwQwAQIACQUC
-Vp+cpgIdIAAKCRDfb9lxMGA32UftD/9jYqsCfNAzb0vhDOaU1AchzaQa1pIKEjoL
-6d4AMeXFSBpMi4nYJpN+rmM8DAzcbenBcSoIqecdfENp3mY+hI8mYdnMiVpldsro
-EAl/SDxY6//pPd0Dnmoe6sNodBB2uwHxhQi9ubz72iWX5WiKP8+OUAj91cLMl9nK
-IYfcHy3iinSRqT02JP33DGDwsHCoAMmp59g6AHnf0sjCtZEtK79MtKiKTkUdMazP
-VGs81x1jCO2kvvmy0fDZxkGuyso0inae2hsaMSqqoga5lC0jQanFIXSEkLZgJglj
-LmiWPO0IGHPFth/e//51atGUmpdd2ufQ/QVoxSnQKRFQ98eO/SQ75bO5vbE8dGv8
-oX9S3M9NjKOY9VnXC/JDyMXt2aMDs9tqSo22lJuT2Wq20wM5hlszxKI7c9QphnuH
-yPNtszzXo1+5/UEuCNIQoe59MoscGmx7GN5WvlENaixGg7tzpZ+wdftN7BUcpJfC
-gsEQurHzPEIomlszp3xraX0G84plClas13Ie8CIVM7UPbF0Cwx6XwhryjaDTkq3f
-+mjQXtNJQk487q8cc9dxplslXiDqBYVngV+oDKOjrqc5PXSQm2M8EYRn9SXuFnT8
-iF5SkuFYtgOEj3KNZ04ZB1I7AQebylS2LGwWan8yWJSAs22eR9urWBVpmre6GUGZ
-fo7YBdOvbLQiUMOhZHJhaWcgQnJhZHkgPHBpeGVsYmVhdEBnbnUub3JnPokCOAQT
-AQIAIgUCTnyAtAIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ32/ZcTBg
-N9moHg/+Mjq/O1RnNg7kdUjRK1wOflym7itgE8kq4G55EJvLSxo6wIgd7ZKUj+cv
-X+iXQpGRc3bicpNTsKcW6EjDtyg+VCSWD7qJ3EtwxVf9mN3bIqWSVwP0k8kc1N+t
-p+L+/9jve+h7Hf7rXZoNo+l9h0/AIIr9YyM2r1VtiAsMNCfD/Ssvc5Yx4fZHR+2V
-kOLeVb2lqdYVe7ZrXDt8qkdBHMCtxm+9jaY3pZVDFKk19NeI74Vzr9+mYn0I0OZS
-0capUuG7+a+FGI1Dx2jn8uL+x4eLDdI3vvr/vGWparikBExGq1pAKWm5gBF10CDP
-4nx9+5hzjPipvCuQerRnjL3FQyXa6E/GpCp4Mk7SdB4zML1CmnYUzz4n0TcV5aFi
-yaMQPk5TByxzYXWUqjFJzFwmU0z8Oy/d64ZMGLyAxCly6gBc/AmXzsUhg2hJB3nG
-3JRw2WmpOIeOdYn6S3onfAFT1tGo7kWNIWYxX5fT7qAHVlnAmgjz+zvfB8Hwq/B0
-FDZPzgwYX4LeRMCj9VDspoCVnaMd4rWqbH2lKUU/k0SFRt3iAqjvT6WPbJIDtEF0
-ifU2R79laaZZU5rbYWZC52AfO7NdLP+7uwxtPYyOdP/4s0HS0e8WDuykdZbTaC9K
-HbIiKMW9YXQJRo6YupWJWOpFpPkvx9ttcQQ7C5s8YFjVR/96dYKJAhwEEwEIAAYF
-Ak6EiIAACgkQf9n8ywAL7u5OexAAjb2+LR8Pa80t3ooladI3Q1icII1hvfb6C+KB
-lzm0d8nMNqcjpPdkbppcVmjqbF3xw70uMnT9m1Y5NGMzJEZiNv6VWT3/m+VJ/aih
-ci/lccUA46pL6Edxw2F/l6ftEOcPRAefNvszCQPNSVHPoQ1m+HuweVgYs9by6s6E
-FFCG8BbqxpAxGxaByoq7ZtlxfMAjKHSPCJSJQTntj5dz79+K+eI8i6bMP8isPBvu
-HAT8ZJ8mn2kQTEpuMIyCl6GTEigKimwq21tebB666Kv7wwS/nwCzceqyPshlrXQp
-YYWoKfLd4SrC1z99//H93/IkN9dZfDJaWvMOlgO+/Tjnlr0tnVsIafnYaOA7Pb4c
-QAx/tbPeiSH3QyRQw4wD2T1CaoLGPLaS4aOCjJXbNBPk+44suO0gUkU8duBwyK0p
-fjFAJQJnJnVEsqWDh0KustQW3jdPvlqEe1eWmhnivXnmtvBk4U2BPkOG/NC9+r3n
-xIWnrRhINWZLT85wM47WtQ2l5BRK71UKrgZDixOIbAR4H54FLa+vrwub6JjpOrQM
-MYaxA/aiEv5byP38nWVvWRSaFDC+QpPyOHLnzBSoxaAHvm8bsNR+4KALcL4zyrUm
-+qqQWbaOpikgBDhYyI/qteW6REZunofpkrpXZbyE+oFUxn7Vwz1ivEkiYPrEhTWr
-HomA9eSIRgQTEQIABgUCUT5njAAKCRAWD1+3iz1IBic4AJ0VP0N+M3OHLK84zhnb
-r7NV/OsepwCghhSEutr+LFoP8SIDFZGyGwWNZkWJAhwEEwECAAYFAlFj+x0ACgkQ
-aIeeK0/t4b4XvBAAnQEaY8PFnZgegqdsNakq1gLr433h3WwQBGzba9CHhElS7VdF
-c3+VnZ031zRXFFMWSFOovvQpyuRNsuGvgmvlr93+/OgP2jBZbgPFZy0B0KaTpvuE
-3LD2XyPINajejIVJTMwNIuD2TTxz+zqRcdie4ExOdSmWHmjGNVCt2W7Xf2ZX18ex
-FdH8jOVKtI2Hdm0YdfgNrfbcSLVgGr5MJMvaifsgGyQkPS/iDXVvLZxmSJiloupJ
-ZfXrCcw5mzd8qodWwC7VJbZWIYkUBo5ir+tFAr1GuxD8D1l2U1RA3jRIgsmjd2CD
-S6eKOmBXR3UVxFypOkHqfsHlST2vzTpvWGhzeQXAbo5ahjtI6m2c5mn6Tvb0V6BA
-o6Fjw1id/iOWmfUSyI9byZkC7HJD/68jgvFha5eXixSo7v66MFptGl9B3sWG0gf5
-iSMbIj4EFzuBySv905kmXJ9VXnawQWalNC7n5JvJkIwAMC6bNU7aO84+9K7kh7bo
-rGaBkiYfD5W09BgTipJAEgq5cVKLOGKaN47DhSszu3QAXl6Wk/VL/RTJfzWWGU13
-nZ7UY7f2uavA30mHOznAn+2v1GnMwq6ZhCQt2Y37YgDowBSR2PrFFZJOzZJhd6GN
-5XWjq6A4QKZouIK19zRAA2Zsvi1TNDzUw01qGT4i+hsxPKXgEbp883D/ZMuJAhwE
-EAEKAAYFAlV92zQACgkQIUyCwjYf1yjk7w/9FyPk/VEJsUYvG6Oap8Qh+bwCQRRm
-vApZKVurqkMAXntN93GbCudWyPdt5igZDQf7CAHobvkUrn4fIGSMAUu6jmy7qoFf
-AnGNKDMWLVYIUi5T/Sb5WCoV6DGpRJ46MjEkbplbnvQyemVsUVQLkB5GrnkO1WRV
-UCk3vnsgSqrJ7B9HyLHAjsbEgm3L2OWe+1Nz9+Evg7etyVHyLLN5N2pMK3/ZMHKf
-42p9SEh5x6JL9YlcxW6EseOnoy64MHDvVvnXnuUWxuTEsEpytvRXlJ7SkG+2lLcn
-nbPNPY3zWfjOEI7j8RvXQJGU3FKt7NZNMGe/jdjq5nF1R5QtilRBnpVFboVmkWNN
-/eiOT1Xy9/PEZKe0GUHLLh2t2ffI2du4FPKKmZ3i8sl2VTh70okKEO8zxTohs+7h
-1bff6XgIFCqzpzVoiIMHLloN/Qxr27lywFzu42UISXIJBW34nSzJ1SUkaVdAdkE8
-TtXEk0xHmMkATTWTwDHoWmp0E2QcVugFpUlw85Dj1FkFNf6IvwaMw0wpE9aP9IKM
-oPmKuarKzC1PUiGqm8o66Oh8I/ycQVv70VgvazeUY1f0GXV/49nT9tyj988/XKAT
-T3OkyHmZIE0Q3HLlSK98bN1ddlVn35IABE7LSa9aJWN2QTOU0pw6D1Gc7pRD9smT
-HAxs4LUP8TXOkGWJAjMEEwEIAB0WIQQ/Sysw6Ic29Fs6LAwiE6c8TiVp8QUCWKaU
-mQAKCRAiE6c8TiVp8bY1D/476x3jkMpbkhg5wd6YlVH33kvxocqaMEdt9jIMj/Xr
-xJbMZKQgHBAESf6XiIYqLRZOsIcdi8k/0goaqP+HENnUj/lK/vBii8P7Qtcct8F5
-55UEDC6GWCFaqEZn0l2qgbHjGWcwh8toq+NZ5VniPyhQErm3b7dToauqE7sOoibm
-/RpkfwxNmtySd/nmmyanP4Q27AgZ7Csq8h68P1wiVTAnOuBJ28CW1z5XsJ5YRTq8
-ae/6kJs7g9eRoDtMkUr516EYmui10khYFUaZ87KjpsTXpgfiHUTtbbW73yGBdqwM
-QD/s10UUCrlv7j8gJ1V8Z5NRSda8kwDyeorziwD+sfGIuxK86Q7NA5tjP9QY5tJA
-m+yxgiwcv56XL12p7G82L3WRDujVm4pDs5NGFRGQNsmkb1T9DEFQMOnsBgVWH4sl
-sjPsN51YNs/wHmu0jOv3CBbVDJAELxjqIroTZuT1yjG1xV5maPTqppMr3+gT16eR
-SZ2nBy4ev8rYM4N4K9EEBjcbXWLNQOYeger1vz5S0bEzUuGeHY4ahMNB+dRTf1eN
-UjRlhSzddlWpoNMbb1+PlYwtcTEIfh2vs2iJEbhZhuETVFye2RmBQ+MQ6oXDGEcg
-fwbwrbyW0X+Z9KPIDhTRMrdXJiBui5RvQ1AxAuQ3sZglw/xySSvztqf5InRrt1lE
-N4kCMwQTAQoAHRYhBBIb2i1Ky2NhazZ6DljhG7HkFNmtBQJYqPbkAAoJEFjhG7Hk
-FNmt9cgP/2owqkabfUTz1Gf5BZn8cWlcZT0ePFJuXqceoyZfPj4VhwKSyRiXEu2U
-LGi75TSUp1ESok6w3KG7chq2GoH2EITysqUhpcroOTAT5qjWGwf1WEP/zEYrmQb2
-ayFRBHdcoNNgRnJVd2HB7FlHF6fg5aPrM3P7o8ajYDneYSDwubajN2xnUsFV8yYv
-liNV8DtFOsX2AHSf9ipsF3P5ArsjRJoMI6Z/PgZuECRiya8qzbxZoIZGgT+khcvC
-SwxsX6YXmNImwhGpugUnSrjvBPdiyN4CilTOdaiEqPLwFDpFWEkByx3ewfJYfBfH
-EOzTdSgtPEXJB0Xxb7ge5fpBtFunI45bPRwRIT6EM29WcYWwCp12HCTt4N2LHwu6
-h+JL3ikFucgtJsSO68h/oId7THD24ft4UpIfBR0zZ0/i+ier3SAB/gN0xE4Hpy4Q
-YNcl9rkt/ApuHX2hQqcN8woUhGV9HV4n07Z6FIqs3qSj+o4w2hV5xaEqOiVoKdMC
-p7DCECjR5ACmhvtLTI8ddS/2rXPK/8Kttg4e74LysK5WOSbCiX7M+GjNIuVh7aA8
-BVR7hLjQ1CRAu/c0/m6EsTEViHuNZjX4deJo/c70kWLbP5UVN9yXrJjwVXwBOz1O
-XiZzzJCl+ICT2fu8K2P7nL4yqkSAuMZHz1sQxzIvLs8hjbMYbdqMiQIzBBMBCgAd
-FiEE+ymKu+HQChyPpNwfqLUfXoAyzOQFAlimepUACgkQqLUfXoAyzOTxgA/7BZpk
-HIlTGVobZ3drVXXLRVdydLbypAJ2d6KU37hY1xuCM1bQ36H/hQKtHBgdTVc87IvB
-0iZTKfwxPHBloK4MBDl0zj0Nz+Y6OK5oaUccDCSIDyBuMnkwu+U3O94mWoftQZuB
-FH9urpElmgLftknKE1PMsPT2PVEpLVKX82yXo28+aAhXjcO7W/FYQhHX5vqPZmjC
-uJGS2DZJHUjF0Vem1Eh2a200+t47JfFSMRSFBm2S4Z1Bo5UUjSk83yJ66tCynJ3x
-D5vhMTWJXRLhZd7DXjjPBMrp6MqDElL8tNF1w86Bk4kIwX/hMre6c0/+4b5rJBwF
-mjRkAwfk/YLJPz5dfoMiTf0kqj93F86BKDnYZNQ4L0Yn1QWWKJSEf55ldmxvaxwz
-ZE3NpOALdBwkG7yjhttsHIe5kpWgluxcuYTvWpX7KGIZnt1qSl+Cv0VAOY7eo2Zl
-KTtpqAQeFqtCZL0tcLxj2Ce8LqViuraKGxNKi13FtpS74W4DgseXv8tnhdy0uqlP
-gRQ2WCHpUhXUlU/KaXtXXmS6oRFnCzXikYXzH5ZFTHzNthg1gO5Fk3y2B+5eL71V
-SHDeIpi0jTpiO3Mav6AtVlw6QRXXfn61cdF1M37k1XA5lFPb+ifkV0sF/rkFE5NL
-r0NAFqcwB3CE7K0fgOidFhdnH9zi+qcfCiyMjpGJAjMEEwEKAB0WIQS7Pk4P+lsq
-ogxkAaHalBBIg4QoJgUCWKeHoQAKCRDalBBIg4QoJnzFD/wNhcOyJURvQtQXcys2
-bSw93rubuZO2OUpIgs6CCcZgCKt4sES9Xv9Qt2qRdk6GBgnlsTdTfwDWEDla1NYf
-+/894Kf+3dLhaiTmYkWVh3UhysE6rihKZ5SHeriNCFCyaOvflOfpGQn20TX17I04
-fLBPQ2tZLIZYELpHHr5OXDm0YiBR+1Rc7mj80cTdw2+1vNa1p2r72n2GzKz76Yl4
-BI7dWud4GAEW26yrwF3VtdGFacRcDsjSM5rR5pxREY2WGzONCCD1yuaJUqk8Q+QK
-8g/2PybkAUJpzmNzWqgsn8FhPESfObl2FPuIbxIjR+N531QGeU4HcH62zJeJjCdR
-XxJk+k1VRP7SIIg310q6J4WiHa6LU79BVTFEV/0gyHh8psLpySr6nJN9TAImdekd
-2+BN6xdWcub6/JJTdJgg+g/VuD+2vUm9zPtcP7nnpadqen6k2pobiDfuGepa4k7s
-1jdgSoyKdgntJNBEpBCCx/fQQeXlR6kcscjUP1aMa+XIgpeZhyKTWWcGfbzsf58u
-YYOP2nMn1GvPvoKcW4AfbPui14eNh3m3hQ3numJKBZGLzBASJsdc10CkOJzLq448
-nhdJTp8ZLRGYl9mEbpVuHNrYQnxYe67OtGS9Nv/DlAJXR4fUiX/Yq/Z+w5zz7HMK
-Pbu/XhRIZcfJWgmRkgr3DSwGdIkCMwQQAQgAHRYhBH/Z1lK/X9LsXxORsHmPHjXL
-TTipBQJYqndrAAoJEHmPHjXLTTip1XkP/R2nPYovKt4/ytjOMRDfO7XSzpUn2d0g
-hmKRn0MHe21n3IjBzDG+BapdTMQCOc4Ucs1UicPV2lxRD8TQa8hh1MYCp9gkZ0Hx
-I9R4q8StipyPLq7B5TQJ4tsHqT4Vc8reuxRInV/2XZ6gdr412v9dsK08o9lYri59
-mv5YJaxZmdov5555oK0ieMAbIRXiSqSsONcA4ph/MPXpVRXZvmu8+IhKJZbAd0cw
-iOhjTU8z0qCBcU4vYB0nxwp2AWbQG4QDpk5lTp40Tn7A1dL1XUbiXsK9h2jAF5zn
-Rssb+drhNeafoqYfVRsB2ObZPhfqD9nq6isbj1ocDU1nQLOrFdYu1o9+JgMFs6F5
-NvavG7RY4RdVLlXDQuoMiX5e1PyGsBgLliy4Tz5gogKtqzm40nV0573pcEkUR7Um
-rNEzEuPoC8PFr7W8lYEHx70Yhql6IZ7rGXKDQNBWLp4drmPKajhdH8xPOKn1Tocr
-qdL8hkzWh6wqLcSzwhgR14/bjCZDj3AJr6bRdAAbcE1xqWt86XiJRM0upe0j/Q7E
-s2eUybhUb/YPSe++llkUsePqvLGMSY2nUN1lwHST1/yI1gjJ0qTSdrHUDd/V1KkU
-SY8CL122N61FoSAEy2Tk4hVNrSNEM0DUuYXaEFZFazJT5/QwfmCaE7lBFzHFRQFs
-mbsPONxL6qjFiQIcBBMBAgAGBQJYrLRFAAoJEPaR/VwUa1eDkbsQAKFy6zUg6GQz
-i3pSqoaWvwCh0rdQzlQJ0Rr+1k70AnGvGnPmtFpceT8AHsJkzfhH4AetZLYeuOpf
-FlcMca9267VdyWgwInob8fcvAURW1ZN4qn8MvNPOBXudj5W5+8XowWmDES4qNr1/
-2Oj4IgHDlMRgUYhsql0ybYarpfZdRxxKKj3ZW4B55Qqds2mG1w40zTSeW9ErXQvJ
-EYkqFsAhEme0Ii+tKP1oM/qRrHuCfKiQw8Zc99v0uU19KbdD2B8sCsBfgkIJpGny
-6ne8BuNAJRDJa4JhzyRu0Aw7f+U/ewn4T+GYdzgsqnsqH6nEwEabeHUtEsChXxZp
-7mu9nSww8fJUEgHuTonr/w8UcMtB7HVwhQ1/AuFxzaQx7uKkyU+uyJaElZ3LD30O
-f20p9Z0v6LXpyiqxBUUytoPCsBtRi2aPQKvNmnkPbtH4P45nz0Nc7CVaWM3tvAGR
-53WQMxowHcek/J3mtNVprhG1gn5V+NnF/a5cjVqGxQbs/G7lhqZXYBNeflW3mUFx
-7DaO5C5KcqjJBN1h9W6a48qh0sqyIbuBFlWJFNdizV0eMi1ypsHXKSZcl7SZ7PB2
-QGMVLg6VW0RneL7zzpoaLHaey97bxeccP721rA0/6w5qCE+qlTUXgV5sZSXJkj9M
-wwpVQWwqa6q/cG0G7iFCxbD+OPZ3/9jZiQGcBBMBCAAGBQJYrnXJAAoJEBzIdvEM
-rJ+J7Q4MAKz8ITE6nKeltOLAJF3xHNNcvyIHFLcOF2BI4bJTinMS7hFwEM3tg8+s
-fnClHe7Lu/YpJdtqJ+jz8+nZMEF9tpS49C4bA8sPDyBHVqBi75xivKDSchnogPql
-jctZF6NWbOt3Bf21DqbJFnrrtg/aEDrHQIDdXZUIKM66artlELC1XmFUnzfUBYNB
-vksoPD+ehG9Im4ugC5kQCGxMNDjHXGyw+DzSm5n+hyEtkjnOPq1x2uPaELrHweMZ
-c06ivHndOBp3vU2EgkyuCvRebc4OLu94RSel/ANv2VRdt3ryRQrW5tqxQJhEwPLW
-fWqNTmR3vZhuUrY5Bk/R6Spn+iNJE1qCUutbB89aIeT9KMV5Dl0Zes4gdK7PLnLJ
-5rjEMoVvJ1Tdl4LUToKZk+7el+2jEMZpkv5jnXkeRqMZAB584wWVOA7+7pKDUGL4
-r7RJByaBz6wRFCGmSJ5DIZQ8HKSeF1ikCwUHqVDYfAWmlyR/t7ZH3ZgUT1ezi67/
-PLQrM9JPbLkCDQROfHxOARAA5hb6RwSG2oH8LMWk6rmPthWH5IBE8yw4InTPpsA8
-V7LyFlNUOH+BuHI8mTpTHk4aRfg3h8wxqw9VfnncWN/H69Y6bhgYp8XZ37esQjPr
-kujaQ7QaLp9EB++96AvF+5pTvf1eBlkhprMXUolw/D3UpGnC6uXW2iCjKEjt4HGU
-G/nJQum9U9fcmZJWrtKFOW8NK/DVJ3iIdh2RmR+DceBDXUJF2qL9DEQvhEDAO5uY
-glC8CwYdHwbdQaWjgLyDMWjr65SQZGbYJ1e+ZxPGGpucfQR89lylNaZwIg/HkFgU
-bIvGnezleSwfO93ayQ34HVtpecr14TMG/jouh85xCsbsX7znnTLtCKzti+EkWRXa
-NV0D+FvaPKo4jv440vgQZajcPzD9tbYWUfylpg83URVaQqZZglg1gLPU166vkB4V
-/ov6nBjQ+Z6YxJsGvgPVhfBZth8IrckFUINyH5JKAAcwPZBtKR0QfUSHW+SxHer4
-DMLHpsjO39wHO9CIk4EcbLYUJwoEYlFpcnNWNYBwjLqAWXuMA+mE2fX/+NoMY1/c
-rOZ46y3dLq0zJfD+LBgORx10j1fFaAj9j36pg43DUewZSwLtBhlYJ/SExW0Rz0xU
-MU+C/4EJjy7+3ycLV+M8gnJGVwp2+z1H1ESe5bH6hSgARqQ4pOfP9sbM7sNX/y17
-KMEAEQEAAYkCHwQYAQIACQUCTnx8TgIbDAAKCRDfb9lxMGA32aBIEADAGhbCehSj
-Wv8SEw9gUpN+slmIDBnZ7uqQgXjWO5OnG2TrSJyPNAwfk6ESY6JeoGuiASL3EpqD
-vRTVsIvDzzqhNBwVa+mi/q3lof9yNs74dmJYsH0P20+9lVzNfWATWUDA4cVYBvON
-BloCK1cVvn9zqFvfjFBcRbZskcvMBVPxO2Fv4xAzX+omPDfCnweY8G7i71Z8Nnl/
-HVkSZMI9uXrtcde00oISHf5xUebJdx96dxnUCDLPUwPiIxxYN44KvIl3cnIB5qwu
-BV8F2XXUtBdxZDJexqsCIoAD3rhRoWq6E2fRJKeqt/4TmxwjsJ8ZODp+ilXhqRe/
-shHttoOvbo5QBZNZMujxkqxXeu+j2E3Ry5mSiGX1SewwbT1iUppwGI15Uwhthhrc
-PwbtWxxIyzPBU6awwlrTrYxNTB1n7WM99gcQctLWZpWnEaoAnEmIEcPjnM+c2NRw
-UJmE/C5h9intY4fOa2a8hpUPx6UbMkfPl0bkIA2cduvQtAFKy/G/Jm4H+0trSmrD
-c+o+rl7v9sMJ9wKkMUdAcqUgNP0TEHzDPbzvztcKBCLnNLoUTKNIN4eNJjMGk8Si
-/OgiN1NKkuVz7I3i916mVxxlFjKEyLYU4tYYXsbB+ZJy4dTP/YWHbQulJYLgju6Z
-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