-@@ -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
new file mode 100644
index 0000000..600f87b
--- /dev/null
+++ b/coreutils-9.9-fix-cut-test-aarch64.patch
@@ -0,0 +1,28 @@
+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
new file mode 100644
index 0000000..82e3899
--- /dev/null
+++ b/coreutils-9.9-gnulib-c23.patch
@@ -0,0 +1,169 @@
+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
deleted file mode 100644
index 5683e39..0000000
--- a/coreutils-DIR_COLORS
+++ /dev/null
@@ -1,248 +0,0 @@
-# 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 binary documents (brown)
-#.pdf 00;33
-#.ps 00;33
-#.ps.gz 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
-#.epub 00;33
-#.abw 00;33
-#.wpd 00;33
-#
-# colorize text documents (brown)
-#.txt 00;33
-#.patch 00;33
-#.diff 00;33
-#.log 00;33
-#.htm 00;33
-#.html 00;33
-#.shtml 00;33
-#.xml 00;33
diff --git a/coreutils-DIR_COLORS.256color b/coreutils-DIR_COLORS.256color
deleted file mode 100644
index 14e27d4..0000000
--- a/coreutils-DIR_COLORS.256color
+++ /dev/null
@@ -1,221 +0,0 @@
-# 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 binary documents (brown)
-#.pdf 00;33
-#.ps 00;33
-#.ps.gz 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
-#.epub 00;33
-#.abw 00;33
-#.wpd 00;33
-#
-# colorize text documents (brown)
-#.txt 00;33
-#.patch 00;33
-#.diff 00;33
-#.log 00;33
-#.htm 00;33
-#.html 00;33
-#.shtml 00;33
-#.xml 00;33
diff --git a/coreutils-DIR_COLORS.lightbgcolor b/coreutils-DIR_COLORS.lightbgcolor
deleted file mode 100644
index ac46288..0000000
--- a/coreutils-DIR_COLORS.lightbgcolor
+++ /dev/null
@@ -1,224 +0,0 @@
-# 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 binary documents (brown)
-#.pdf 00;33
-#.ps 00;33
-#.ps.gz 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
-#.epub 00;33
-#.abw 00;33
-#.wpd 00;33
-#
-# colorize text documents (brown)
-#.txt 00;33
-#.patch 00;33
-#.diff 00;33
-#.log 00;33
-#.htm 00;33
-#.html 00;33
-#.shtml 00;33
-#.xml 00;33
diff --git a/coreutils-colorls.csh b/coreutils-colorls.csh
index e244afb..66ec2fa 100755
--- a/coreutils-colorls.csh
+++ b/coreutils-colorls.csh
@@ -1,3 +1,6 @@
+# skip everything for non-interactive shells
+if (! $?prompt) exit
+
# color-ls initialization
if ( $?USER_LS_COLORS ) then
if ( "$USER_LS_COLORS" != "" ) then
@@ -10,15 +13,11 @@ 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
@@ -26,18 +25,37 @@ 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
-eval "`dircolors -c $COLORS`"
+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
if ( "$LS_COLORS" == '' ) exit
-set color_none=`sed -n '/^COLOR.*none/Ip' < $COLORS`
+cleanup:
+set color_none=`/usr/bin/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 dc5c223..5162f1e 100755
--- a/coreutils-colorls.sh
+++ b/coreutils-colorls.sh
@@ -1,40 +1,53 @@
# 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
-
- # Skip the rest for noninteractive shells.
- [ -z "$PS1" ] && return
-
+ INCLUDE=
COLORS=
for colors in "$HOME/.dir_colors.$TERM" "$HOME/.dircolors.$TERM" \
"$HOME/.dir_colors" "$HOME/.dircolors"; do
- [ -e "$colors" ] && COLORS="$colors" && break
+ [ -e "$colors" ] && COLORS="$colors" && \
+ INCLUDE="`/usr/bin/cat "$COLORS" | /usr/bin/grep '^INCLUDE' | /usr/bin/cut -d ' ' -f2-`" && \
+ break
done
- [ -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.$TERM" ] && \
+ COLORS="/etc/DIR_COLORS.$TERM"
- if [ -z "$COLORS" ]; then
- for colors in "/etc/DIR_COLORS.$TERM" "/etc/DIR_COLORS" ; do
- [ -e "$colors" ] && COLORS="$colors" && break
- done
- fi
+ [ -z "$COLORS" ] && [ -e "/etc/DIR_COLORS" ] && \
+ COLORS="/etc/DIR_COLORS"
# Existence of $COLORS already checked above.
[ -n "$COLORS" ] || return
- eval "`dircolors --sh "$COLORS" 2>/dev/null`"
+ 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
+
[ -z "$LS_COLORS" ] && return
- grep -qi "^COLOR.*none" $COLORS >/dev/null 2>/dev/null && return
+ /usr/bin/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
deleted file mode 100644
index 713b7c5..0000000
--- a/coreutils-cpZ-deprecate.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-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 14d1c44..341ee2c 100644
--- a/coreutils-df-direct.patch
+++ b/coreutils-df-direct.patch
@@ -1,64 +1,77 @@
-diff -urNp coreutils-8.16-orig/doc/coreutils.texi coreutils-8.16/doc/coreutils.texi
---- coreutils-8.16-orig/doc/coreutils.texi 2012-03-26 07:38:37.000000000 +0200
-+++ coreutils-8.16/doc/coreutils.texi 2012-03-26 17:31:31.101014556 +0200
-@@ -10584,6 +10584,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.
+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.
-+@itemx --direct
++@item --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.
+
- @itemx --total
+ @item --total
@opindex --total
- @cindex grand total of disk size, usage and available space
-diff -urNp coreutils-8.16-orig/src/df.c coreutils-8.16/src/df.c
---- coreutils-8.16-orig/src/df.c 2012-03-24 21:26:51.000000000 +0100
-+++ coreutils-8.16/src/df.c 2012-03-26 17:31:31.102014797 +0200
-@@ -113,6 +113,9 @@ static bool print_type;
+ @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;
/* 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;
-@@ -167,13 +170,15 @@ static size_t nrows;
- enum
- {
+@@ -248,13 +251,15 @@ enum
NO_SYNC_OPTION = CHAR_MAX + 1,
-- SYNC_OPTION
-+ SYNC_OPTION,
+ SYNC_OPTION,
+ TOTAL_OPTION,
+- OUTPUT_OPTION
++ OUTPUT_OPTION,
+ DIRECT_OPTION
};
static struct option const long_options[] =
{
- {"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'},
-@@ -260,7 +265,11 @@ get_header (void)
- }
+ {"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);
- 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]);
-
-@@ -790,6 +799,17 @@ get_point (const char *point, const stru
+ if (columns[col]->field == SIZE_FIELD
+ && (header_mode == DEFAULT_MODE
+@@ -1446,6 +1454,17 @@ get_point (char const *point, const struct stat *statp)
static void
get_entry (char const *name, struct stat const *statp)
{
@@ -66,25 +79,25 @@ diff -urNp coreutils-8.16-orig/src/df.c coreutils-8.16/src/df.c
+ {
+ char *resolved = canonicalize_file_name (name);
+ if (resolved)
-+ {
-+ get_dev (NULL, resolved, NULL, NULL, false, false, NULL, false);
-+ free (resolved);
-+ return;
-+ }
++ {
++ get_dev (NULL, resolved, name, NULL, NULL, false, false, NULL, false);
++ free (resolved);
++ return;
++ }
+ }
+
if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))
- && get_disk (name))
+ && get_device (name))
return;
-@@ -857,6 +877,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\
+@@ -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\
+ --direct show statistics for a file instead of mount point\n\
- --total produce a grand total\n\
- -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\
- \n\
-@@ -933,6 +954,9 @@ main (int argc, char **argv)
+ -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)
xstrtol_fatal (e, oi, c, long_options, optarg);
}
break;
@@ -92,25 +105,27 @@ diff -urNp coreutils-8.16-orig/src/df.c coreutils-8.16/src/df.c
+ direct_statfs = true;
+ break;
case 'i':
- inode_format = true;
- break;
-@@ -993,6 +1017,13 @@ main (int argc, char **argv)
+ if (header_mode == OUTPUT_MODE)
+ {
+@@ -1706,6 +1729,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 -urNp coreutils-8.16-orig/tests/df/direct coreutils-8.16/tests/df/direct
---- coreutils-8.16-orig/tests/df/direct 1970-01-01 01:00:00.000000000 +0100
-+++ coreutils-8.16/tests/df/direct 2012-03-26 17:31:31.102897406 +0200
+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
@@ -0,0 +1,55 @@
+#!/bin/sh
+# Ensure "df --direct" works as documented
@@ -167,14 +182,6 @@ diff -urNp coreutils-8.16-orig/tests/df/direct coreutils-8.16/tests/df/direct
+compare file_out file_exp || fail=1
+
+Exit $fail
-diff -urNp coreutils-8.16-orig/tests/Makefile.am coreutils-8.16/tests/Makefile.am
---- coreutils-8.16-orig/tests/Makefile.am 2012-03-26 17:31:08.642764437 +0200
-+++ coreutils-8.16/tests/Makefile.am 2012-03-26 17:31:31.104015483 +0200
-@@ -379,6 +379,7 @@ TESTS = \
- dd/stderr \
- dd/unblock \
- dd/unblock-sync \
-+ df/direct \
- df/total-verify \
- du/2g \
- du/8gb \
+--
+2.52.0
+
diff --git a/coreutils-getgrouplist.patch b/coreutils-getgrouplist.patch
deleted file mode 100644
index 86bbcef..0000000
--- a/coreutils-getgrouplist.patch
+++ /dev/null
@@ -1,86 +0,0 @@
-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 704941f..83579e9 100644
--- a/coreutils-i18n.patch
+++ b/coreutils-i18n.patch
@@ -1,9 +1,80 @@
-diff -urNp coreutils-8.17-orig/lib/linebuffer.h coreutils-8.17/lib/linebuffer.h
---- coreutils-8.17-orig/lib/linebuffer.h 2012-01-06 10:14:31.000000000 +0100
-+++ coreutils-8.17/lib/linebuffer.h 2013-01-24 17:11:53.530457138 +0100
-@@ -21,6 +21,11 @@
+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
- # include
+/* Get mbstate_t. */
+# if HAVE_WCHAR_H
@@ -13,9 +84,9 @@ diff -urNp coreutils-8.17-orig/lib/linebuffer.h coreutils-8.17/lib/linebuffer.h
/* A 'struct linebuffer' holds a line of text. */
struct linebuffer
-@@ -28,6 +33,9 @@ struct linebuffer
- size_t size; /* Allocated. */
- size_t length; /* Used. */
+@@ -34,6 +39,9 @@ struct linebuffer
+ idx_t size; /* Allocated. */
+ idx_t length; /* Used. */
char *buffer;
+# if HAVE_WCHAR_H
+ mbstate_t state;
@@ -23,11 +94,349 @@ diff -urNp coreutils-8.17-orig/lib/linebuffer.h coreutils-8.17/lib/linebuffer.h
};
/* Initialize linebuffer LINEBUFFER for use. */
-diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
---- coreutils-8.17-orig/src/cut.c 2012-05-02 10:31:47.000000000 +0200
-+++ coreutils-8.17/src/cut.c 2013-01-24 17:11:53.532456847 +0100
-@@ -28,6 +28,11 @@
- #include
+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
#include
#include
+
@@ -37,10 +446,10 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+#endif
#include "system.h"
- #include "error.h"
-@@ -37,6 +42,18 @@
- #include "quote.h"
- #include "xstrndup.h"
+ #include "assure.h"
+@@ -35,6 +40,18 @@
+
+ #include "set-fields.h"
+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC
+ installation; work around this configuration error. */
@@ -57,8 +466,8 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "cut"
-@@ -72,6 +89,52 @@
- } \
+@@ -51,6 +68,52 @@
+ } \
while (0)
+/* Refill the buffer BUF to get a multibyte character. */
@@ -75,7 +484,7 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ while (0)
+
+/* Get wide character on BUFPOS. BUFPOS is not included after that.
-+ If byte sequence is not valid as a character, CONVFAIL is 1. Otherwise 0. */
++ If byte sequence is not valid as a character, CONVFAIL is true. Otherwise false. */
+#define GET_NEXT_WC_FROM_BUFFER(WC, BUFPOS, BUFLEN, MBLENGTH, STATE, CONVFAIL) \
+ do \
+ { \
@@ -88,7 +497,7 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ } \
+ \
+ /* Get a wide character. */ \
-+ CONVFAIL = 0; \
++ CONVFAIL = false; \
+ state_bak = STATE; \
+ MBLENGTH = mbrtowc ((wchar_t *)&WC, BUFPOS, BUFLEN, &STATE); \
+ \
@@ -96,7 +505,7 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ { \
+ case (size_t)-1: \
+ case (size_t)-2: \
-+ CONVFAIL++; \
++ CONVFAIL = true; \
+ STATE = state_bak; \
+ /* Fall througn. */ \
+ \
@@ -107,49 +516,39 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ } \
+ while (0)
+
- struct range_pair
- {
- size_t lo;
-@@ -90,7 +153,7 @@ static char *field_1_buffer;
+
+ /* 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;
/* The number of bytes allocated for FIELD_1_BUFFER. */
static size_t field_1_bufsize;
--/* 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. */
++enum operating_mode
++ {
++ undefined_mode,
++
+ /* 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 delimeter-separated fields. */
- field_mode
- };
-
- static enum operating_mode operating_mode;
-
++ /* Output the given delimiter-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;
+
@@ -157,20 +556,37 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ if this program runs on multibyte locale. */
+static int force_singlebyte_mode;
+
- /* If true do not output lines containing no delimeter characters.
+ /* If true, do not output lines containing no delimiter characters.
Otherwise, all such lines are printed. This option is valid only
with field mode. */
-@@ -134,6 +208,9 @@ static bool complement;
+@@ -81,10 +170,16 @@ static bool complement;
- /* The delimeter character for field mode. */
+ /* The delimiter character for field mode. */
static unsigned char delim;
+#if HAVE_WCHAR_H
+static wchar_t wcdelim;
+#endif
- /* True if the --output-delimiter=STRING option was specified. */
- static bool output_delimiter_specified;
-@@ -206,7 +283,7 @@ Mandatory arguments to long options are
+ /* 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\
-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\
@@ -179,54 +595,16 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
"), stdout);
fputs (_("\
--complement complement the set of selected bytes, characters\n\
-@@ -365,7 +442,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++;
-
-@@ -389,14 +466,16 @@ set_fields (const char *fieldstr)
- if (!rhs_specified)
+@@ -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)
{
- /* '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)
-@@ -476,6 +555,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));
-@@ -486,7 +568,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;
-@@ -581,6 +663,77 @@ cut_bytes (FILE *stream)
+ if (print_delimiter && is_range_start_index (byte_idx))
+ {
+@@ -271,6 +363,82 @@ cut_bytes (FILE *stream)
}
}
@@ -242,7 +620,7 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+static void
+cut_characters_or_cut_bytes_no_split (FILE *stream)
+{
-+ int idx; /* number of bytes or characters in the line so far. */
++ uintmax_t 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. */
@@ -250,7 +628,7 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ size_t mblength; /* The byte size of a multibyte character which shows
+ as same character as WC. */
+ mbstate_t state; /* State of the stream. */
-+ int convfail = 0; /* 1, when conversion is failed. Otherwise 0. */
++ bool convfail = false; /* true, when conversion failed. Otherwise false. */
+ /* 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;
@@ -260,37 +638,42 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ 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 ('\n');
++ putchar (line_delim);
+ break;
+ }
-+ else if (wc == L'\n')
++ else if (wc == line_delim)
+ {
-+ putchar ('\n');
++ putchar (line_delim);
+ idx = 0;
+ print_delimiter = false;
++ current_rp = frp;
+ }
+ else
+ {
-+ bool range_start;
-+ bool *rs = output_delimiter_specified ? &range_start : NULL;
-+ idx += (operating_mode == byte_mode) ? mblength : 1;
-+ if (print_kth (idx, rs))
++ next_item (&idx);
++ if (print_kth (idx))
+ {
-+ if (rs && *rs && print_delimiter)
++ if (output_delimiter_specified)
+ {
-+ fwrite (output_delimiter_string, sizeof (char),
-+ output_delimiter_length, stdout);
-+ }
-+ print_delimiter = true;
++ if (print_delimiter && is_range_start_index (idx))
++ {
++ fwrite (output_delimiter_string, sizeof (char),
++ output_delimiter_length, stdout);
++ }
++ print_delimiter = true;
++ }
+ fwrite (bufpos, mblength, sizeof(char), stdout);
+ }
+ }
@@ -304,16 +687,17 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
/* Read from stream STREAM, printing to standard output any selected fields. */
static void
-@@ -703,13 +856,195 @@ cut_fields (FILE *stream)
+@@ -433,11 +601,218 @@ 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;
-+ unsigned int field_idx;
++ uintmax_t field_idx;
+ int found_any_selected_field;
+ int buffer_first_field;
+ int empty_input;
@@ -324,7 +708,9 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ size_t mblength; /* The byte size of a multibyte character which shows
+ as same character as WC. */
+ mbstate_t state; /* State of the stream. */
-+ int convfail = 0; /* 1, when conversion is failed. Otherwise 0. */
++ bool convfail = false; /* true, when conversion failed. Otherwise false. */
++
++ current_rp = frp;
+
+ found_any_selected_field = 0;
+ field_idx = 1;
@@ -348,7 +734,7 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ 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, NULL));
++ buffer_first_field = (suppress_non_delimited ^ !print_kth (1));
+
+ while (1)
+ {
@@ -372,11 +758,11 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ buflen -= mblength;
+ bufpos += mblength;
+
-+ if (!convfail && (wc == L'\n' || wc == wcdelim))
++ if (!convfail && (wc == line_delim || 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
@@ -392,24 +778,24 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ {
+ fwrite (field_1_buffer, sizeof (char), len, stdout);
+ /* Make sure the output line is newline terminated. */
-+ if (convfail || (!convfail && wc != L'\n'))
-+ putchar ('\n');
++ if (convfail || (!convfail && wc != line_delim))
++ putchar (line_delim);
+ }
+ continue;
+ }
+
-+ if (print_kth (1, NULL))
++ if (print_kth (1))
+ {
+ /* Print the field, but not the trailing delimiter. */
+ fwrite (field_1_buffer, sizeof (char), len - 1, stdout);
+ found_any_selected_field = 1;
+ }
-+ ++field_idx;
++ next_item (&field_idx);
+ }
+
+ if (wc != WEOF)
+ {
-+ if (print_kth (field_idx, NULL))
++ if (print_kth (field_idx))
+ {
+ if (found_any_selected_field)
+ {
@@ -428,14 +814,14 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+
+ if (wc == WEOF)
+ break;
-+ else if (!convfail && (wc == wcdelim || wc == L'\n'))
++ else if (!convfail && (wc == wcdelim || wc == line_delim))
+ {
+ buflen -= mblength;
+ bufpos += mblength;
+ break;
+ }
+
-+ if (print_kth (field_idx, NULL))
++ if (print_kth (field_idx))
+ fwrite (bufpos, mblength, sizeof(char), stdout);
+
+ buflen -= mblength;
@@ -443,30 +829,29 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ }
+ }
+
-+ if ((!convfail || wc == L'\n') && buflen < 1)
++ if ((!convfail || wc == line_delim) && buflen < 1)
+ wc = WEOF;
+
+ if (!convfail && wc == wcdelim)
-+ ++field_idx;
-+ else if (wc == WEOF || (!convfail && wc == L'\n'))
++ next_item (&field_idx);
++ else if (wc == WEOF || (!convfail && wc == line_delim))
+ {
+ if (found_any_selected_field
+ || (!empty_input && !(suppress_non_delimited && field_idx == 1)))
-+ putchar ('\n');
++ putchar (line_delim);
+ if (wc == WEOF)
+ break;
+ field_idx = 1;
++ current_rp = frp;
+ found_any_selected_field = 0;
+ }
+ }
+}
+#endif
+
- static void
- cut_stream (FILE *stream)
- {
-- if (operating_mode == byte_mode)
-- cut_bytes (stream);
++static void
++cut_stream (FILE *stream)
++{
+#if HAVE_MBRTOWC
+ if (MB_CUR_MAX > 1 && !force_singlebyte_mode)
+ {
@@ -484,6 +869,19 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ 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;
+
@@ -491,8 +889,7 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ abort ();
+ }
+ }
- else
-- cut_fields (stream);
++ else
+#endif
+ {
+ if (operating_mode == field_mode)
@@ -500,32 +897,53 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ else
+ cut_bytes (stream);
+ }
- }
++}
++
++/* Process file FILE to standard output.
+ Return true if successful. */
- /* Process file FILE to standard output.
-@@ -761,6 +1096,8 @@ main (int argc, char **argv)
+ 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;
bool ok;
bool delim_specified = false;
- char *spec_list_string IF_LINT ( = NULL);
+- bool byte_mode = false;
+- char *spec_list_string = nullptr;
++ char *spec_list_string IF_LINT ( = nullptr);
+ char mbdelim[MB_LEN_MAX + 1];
-+ size_t delimlen = 0;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
-@@ -783,7 +1120,6 @@ main (int argc, char **argv)
+@@ -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)
switch (optc)
{
case 'b':
- case 'c':
- /* Build the byte list. */
- if (operating_mode != undefined_mode)
- FATAL_ERROR (_("only one type of list may be specified"));
-@@ -791,6 +1127,14 @@ main (int argc, char **argv)
- spec_list_string = optarg;
- break;
-
+ /* 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;
++
+ 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;
@@ -533,11 +951,17 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ break;
+
case 'f':
- /* Build the field list. */
- if (operating_mode != undefined_mode)
-@@ -802,10 +1146,35 @@ main (int argc, char **argv)
+ /* 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;
+
case 'd':
- /* New 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"));
@@ -560,6 +984,9 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ 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;
+ }
+ }
+
@@ -575,7 +1002,13 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
break;
case OUTPUT_DELIMITER_OPTION:
-@@ -818,6 +1187,7 @@ main (int argc, char **argv)
++ 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);
break;
case 'n':
@@ -583,17 +1016,34 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
break;
case 's':
-@@ -840,7 +1210,7 @@ main (int argc, char **argv)
- if (operating_mode == undefined_mode)
+@@ -555,40 +974,57 @@ main (int argc, char **argv)
+ }
+ }
+
+- if (!spec_list_string)
++ if (operating_mode == undefined_mode)
FATAL_ERROR (_("you must specify a list of bytes, characters, or fields"));
-- if (delim != '\0' && operating_mode != field_mode)
+- if (byte_mode)
+- {
+- if (delim_specified)
+- FATAL_ERROR (_("an input delimiter may be specified only\
+ 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"));
-@@ -867,15 +1237,34 @@ main (int argc, char **argv)
- }
+- 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) );
if (!delim_specified)
- delim = '\t';
@@ -607,12 +1057,10 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+#endif
+ }
- if (output_delimiter_string == NULL)
+ if (output_delimiter_string == nullptr)
{
-- static char dummy[2];
-- dummy[0] = delim;
-- dummy[1] = '\0';
-- output_delimiter_string = dummy;
+- output_delimiter_default[0] = delim;
+- output_delimiter_string = output_delimiter_default;
- output_delimiter_length = 1;
+#ifdef HAVE_MBRTOWC
+ if (MB_CUR_MAX > 1 && !force_singlebyte_mode)
@@ -632,1095 +1080,348 @@ diff -urNp coreutils-8.17-orig/src/cut.c coreutils-8.17/src/cut.c
+ }
}
+- void (*cut_stream) (FILE *) = byte_mode ? cut_bytes : cut_fields;
if (optind == argc)
-diff -urNp coreutils-8.17-orig/src/expand.c coreutils-8.17/src/expand.c
---- coreutils-8.17-orig/src/expand.c 2012-05-01 22:55:08.000000000 +0200
-+++ coreutils-8.17/src/expand.c 2013-01-24 17:11:53.534459250 +0100
-@@ -37,12 +37,29 @@
+- 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 @@
#include
#include
#include
+
-+/* Get mbstate_t, mbrtowc(), wcwidth(). */
-+#if HAVE_WCHAR_H
-+# include
-+#endif
++#include
+
#include "system.h"
- #include "error.h"
- #include "fadvise.h"
- #include "quote.h"
- #include "xstrndup.h"
+ #include "expand-common.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 "expand"
-
-@@ -358,6 +375,142 @@ expand (void)
- }
- }
-
-+#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)
+@@ -96,19 +99,41 @@ expand (void)
{
-@@ -422,7 +575,12 @@ main (int argc, char **argv)
+ /* 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;
++
++ /* True if the first file contains BOM header. */
++ bool found_bom;
++ using_utf_locale=check_utf_locale();
- 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.17-orig/src/fold.c coreutils-8.17/src/fold.c
---- coreutils-8.17-orig/src/fold.c 2012-04-29 13:45:30.000000000 +0200
-+++ coreutils-8.17/src/fold.c 2013-01-24 17:11:53.535456924 +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},
-@@ -77,6 +120,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);
-@@ -94,7 +138,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')
- {
-@@ -117,30 +161,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);
-
-@@ -170,6 +198,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)
- {
-@@ -216,11 +253,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);
-@@ -253,7 +500,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)
- {
-@@ -262,7 +510,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.17-orig/src/join.c coreutils-8.17/src/join.c
---- coreutils-8.17-orig/src/join.c 2012-05-02 10:31:47.000000000 +0200
-+++ coreutils-8.17/src/join.c 2013-01-24 17:11:53.537387892 +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
-@@ -262,13 +278,14 @@ xfields (struct line *line)
- if (ptr == lim)
+ if (!fp)
return;
++ mbf_init (mbf, fp);
++ found_bom=check_bom(fp,&mbf);
-- if (0 <= tab && tab != '\n')
-+ if (tab != NULL)
+- while (true)
++ if (using_utf_locale == false && found_bom == true)
++ {
++ /*try using some predefined locale */
++
++ if (set_utf_locale () != 0)
{
-+ 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)))
-@@ -292,6 +309,148 @@ xfields (struct line *line)
- extract_field (line, ptr, lim - ptr);
- }
+- /* Input character, or EOF. */
+- int c;
++ error (EXIT_FAILURE, errno, _("cannot set UTF-8 locale"));
++ }
++ }
++
++
++ if (found_bom == true)
++ {
++ print_bom();
++ }
-+#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)
++ while (true)
+ {
-+ 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)
- {
-@@ -313,56 +472,130 @@ 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;
+ /* If true, perform translations. */
+ bool convert = true;
+
-
-- 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;
+ /* The following variables have valid values only when CONVERT
+ is true: */
- 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;
- }
+@@ -118,17 +143,48 @@ expand (void)
+ /* Index in TAB_LIST of next tab stop to examine. */
+ idx_t tab_index = 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;
- }
+-
+ /* Convert a line of text. */
-- 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++)
-+ {
-+ mallocd = 1;
-+ copy[i] = xmalloc (len[i] + 1);
-+
-+ for (j = 0; j < MIN (len[0], len[1]);)
+ 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)))
+ {
-+ state_bak = state;
-+ mblength = mbrtowc (&wc, beg[i] + j, len[i] - j, &state);
-+
-+ switch (mblength)
++ mbf_init (mbf, fp);
++ if (fp!=NULL)
++ {
++ if (check_bom(fp,&mbf)==true)
+ {
-+ 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);
++ /*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"));
++ }
+ }
-+ j += mblength;
-+ }
-+ copy[i][j] = '\0';
-+ }
-+ }
-+ else
-+#endif
-+ {
-+ for (i = 0; i < 2; i++)
-+ {
-+ mallocd = 1;
-+ copy[i] = xmalloc (len[i] + 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
-@@ -454,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])
-@@ -553,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);
- }
- }
-@@ -578,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;
-
-@@ -612,7 +856,7 @@ prjoin (struct line const *line1, struct
- o = o->next;
- if (o == NULL)
- break;
-- putchar (output_separator);
-+ PUT_TAB_CHAR;
- }
- putchar ('\n');
- }
-@@ -1090,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
++ {
++ 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
-+#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;
++ break;
++ }
++ }
++
- case NOCHECK_ORDER_OPTION:
-diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
---- coreutils-8.17-orig/src/pr.c 2012-05-10 09:14:30.000000000 +0200
-+++ coreutils-8.17/src/pr.c 2013-01-24 17:11:53.543389383 +0100
-@@ -312,6 +312,32 @@
+ 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'));
+ }
+ }
+
+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)
+
+-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
+
+ 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
+
@@ -1740,21 +1441,13 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
+#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 "error.h"
+ #include "c-ctype.h"
#include "fadvise.h"
-@@ -323,6 +349,18 @@
- #include "strftime.h"
- #include "xstrtol.h"
+@@ -325,6 +343,18 @@
+ #include "xstrtol-error.h"
+ #include "xdectoint.h"
+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
+#if HAVE_MBRTOWC && defined mbstate_t
@@ -1771,7 +1464,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "pr"
-@@ -415,7 +453,20 @@ struct COLUMN
+@@ -417,7 +447,20 @@ struct COLUMN
typedef struct COLUMN COLUMN;
@@ -1793,23 +1486,23 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
static bool read_line (COLUMN *p);
static bool print_page (void);
static bool print_stored (COLUMN *p);
-@@ -425,6 +476,7 @@ static void print_header (void);
- static void pad_across_to (int position);
+@@ -428,6 +471,7 @@ 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);
-@@ -438,7 +490,6 @@ static void store_char (char c);
- static void pad_down (int lines);
+@@ -441,7 +485,6 @@ static void store_char (char c);
+ static void pad_down (unsigned 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 (const char *optarg_S);
-@@ -450,7 +501,7 @@ static COLUMN *column_vector;
+ static void separator_string (char const *optarg_S);
+@@ -453,7 +496,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]. */
@@ -1818,7 +1511,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
/* Index of the position in buff where the next character
will be stored. */
-@@ -554,7 +605,7 @@ static int chars_per_column;
+@@ -557,7 +600,7 @@ static int chars_per_column;
static bool untabify_input = false;
/* (-e) The input tab character. */
@@ -1827,7 +1520,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
/* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ...
where the leftmost column is 1. */
-@@ -564,7 +615,10 @@ static int chars_per_input_tab = 8;
+@@ -567,7 +610,10 @@ static int chars_per_input_tab = 8;
static bool tabify_output = false;
/* (-i) The output tab character. */
@@ -1839,7 +1532,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
/* (-i) The width of the output tab. */
static int chars_per_output_tab = 8;
-@@ -638,7 +692,13 @@ static int power_10;
+@@ -637,7 +683,13 @@ static int line_number;
static bool numbered_lines = false;
/* (-n) Character which follows each line number. */
@@ -1854,18 +1547,18 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
/* (-n) line counting starts with 1st line of input file (not with 1st
line of 1st page printed). */
-@@ -691,6 +751,7 @@ static bool use_col_separator = false;
+@@ -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 *col_sep_string = (char *) "";
+ static char const *col_sep_string = "";
static int col_sep_length = 0;
+static int col_sep_width = 0;
static char *column_separator = (char *) " ";
static char *line_separator = (char *) "\t";
-@@ -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);
+@@ -852,6 +905,13 @@ separator_string (char const *optarg_S)
+ integer_overflow ();
+ col_sep_length = len;
+ col_sep_string = optarg_S;
+
+#if HAVE_MBRTOWC
+ if (MB_CUR_MAX > 1)
@@ -1876,7 +1569,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
}
int
-@@ -871,6 +939,21 @@ main (int argc, char **argv)
+@@ -876,6 +936,21 @@ main (int argc, char **argv)
atexit (close_stdout);
@@ -1897,8 +1590,8 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
+
n_files = 0;
file_names = (argc > 1
- ? xmalloc ((argc - 1) * sizeof (char *))
-@@ -947,8 +1030,12 @@ main (int argc, char **argv)
+ ? xnmalloc (argc - 1, sizeof (char *))
+@@ -952,8 +1027,12 @@ main (int argc, char **argv)
break;
case 'e':
if (optarg)
@@ -1913,7 +1606,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
/* Could check tab width > 0. */
untabify_input = true;
break;
-@@ -961,8 +1048,12 @@ main (int argc, char **argv)
+@@ -966,8 +1045,12 @@ main (int argc, char **argv)
break;
case 'i':
if (optarg)
@@ -1928,7 +1621,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
/* Could check tab width > 0. */
tabify_output = true;
break;
-@@ -989,8 +1080,8 @@ main (int argc, char **argv)
+@@ -986,8 +1069,8 @@ main (int argc, char **argv)
case 'n':
numbered_lines = true;
if (optarg)
@@ -1939,16 +1632,15 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
break;
case 'N':
skip_count = false;
-@@ -1029,7 +1120,7 @@ main (int argc, char **argv)
- old_s = false;
+@@ -1013,6 +1096,7 @@ main (int argc, char **argv)
/* Reset an additional input of -s, -S dominates -s */
- col_sep_string = bad_cast ("");
-- col_sep_length = 0;
-+ col_sep_length = col_sep_width = 0;
+ col_sep_string = "";
+ col_sep_length = 0;
++ col_sep_width = 0;
use_col_separator = true;
if (optarg)
separator_string (optarg);
-@@ -1186,10 +1277,45 @@ main (int argc, char **argv)
+@@ -1168,7 +1252,8 @@ getoptnum (char const *n_str, int min, char const *err)
a number. */
static void
@@ -1956,7 +1648,12 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
+getoptarg (char *arg, char switch_char, char *character, int *character_length,
+ int *character_width, int *number)
{
- if (!ISDIGIT (*arg))
+ if (!*arg)
+ {
+@@ -1177,7 +1262,41 @@ getoptarg (char *arg, char switch_char, char *character, int *number)
+ }
+
+ if (!c_isdigit (*arg))
- *character = *arg++;
+ {
+#ifdef HAVE_MBRTOWC
@@ -1996,7 +1693,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
if (*arg)
{
long int tmp_long;
-@@ -1211,6 +1337,11 @@ static void
+@@ -1206,6 +1325,11 @@ static void
init_parameters (int number_of_files)
{
int chars_used_by_number = 0;
@@ -2008,7 +1705,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
lines_per_body = lines_per_page - lines_per_header - lines_per_footer;
if (lines_per_body <= 0)
-@@ -1248,7 +1379,7 @@ init_parameters (int number_of_files)
+@@ -1243,7 +1367,7 @@ init_parameters (int number_of_files)
else
col_sep_string = column_separator;
@@ -2017,7 +1714,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
use_col_separator = true;
}
/* It's rather pointless to define a TAB separator with column
-@@ -1279,11 +1410,11 @@ init_parameters (int number_of_files)
+@@ -1275,11 +1399,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. */
@@ -2031,25 +1728,25 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
/* The number is part of the column width unless we are
printing files in parallel. */
-@@ -1298,7 +1429,7 @@ init_parameters (int number_of_files)
+@@ -1288,7 +1412,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)
+ 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)
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,
-@@ -1423,7 +1554,7 @@ init_funcs (void)
+@@ -1417,7 +1541,7 @@ init_funcs (void)
/* Enlarge p->start_position of first column to use the same form of
padding_not_printed with all columns. */
@@ -2058,7 +1755,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
/* This loop takes care of all but the rightmost column. */
-@@ -1457,7 +1588,7 @@ init_funcs (void)
+@@ -1451,7 +1575,7 @@ init_funcs (void)
}
else
{
@@ -2067,21 +1764,21 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
h_next = h + chars_per_column;
}
}
-@@ -1748,9 +1879,9 @@ static void
+@@ -1751,9 +1875,9 @@ static void
align_column (COLUMN *p)
{
padding_not_printed = p->start_position;
-- if (padding_not_printed - col_sep_length > 0)
-+ if (padding_not_printed - col_sep_width > 0)
+- if (col_sep_length < padding_not_printed)
++ if (col_sep_width < padding_not_printed)
{
- pad_across_to (padding_not_printed - col_sep_length);
+ pad_across_to (padding_not_printed - col_sep_width);
padding_not_printed = ANYWHERE;
}
-@@ -2021,13 +2152,13 @@ store_char (char c)
+@@ -2030,13 +2154,13 @@ store_char (char c)
/* May be too generous. */
- buff = X2REALLOC (buff, &buff_allocated);
+ buff = xpalloc (buff, &buff_allocated, 1, -1, sizeof *buff);
}
- buff[buff_current++] = c;
+ buff[buff_current++] = (unsigned char) c;
@@ -2093,9 +1790,9 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
- int i;
+ int i, j;
char *s;
- int left_cut;
+ int num_width;
-@@ -2050,22 +2181,24 @@ add_line_number (COLUMN *p)
+@@ -2053,22 +2177,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
equal column_width also specified by POSIX. */
@@ -2124,7 +1821,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
output_position = POS_AFTER_TAB (chars_per_output_tab,
output_position);
}
-@@ -2226,7 +2359,7 @@ print_white_space (void)
+@@ -2227,7 +2353,7 @@ print_white_space (void)
while (goal - h_old > 1
&& (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal)
{
@@ -2133,15 +1830,15 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
h_old = h_new;
}
while (++h_old <= goal)
-@@ -2246,6 +2379,7 @@ print_sep_string (void)
+@@ -2247,6 +2373,7 @@ print_sep_string (void)
{
- char *s;
+ char const *s = col_sep_string;
int l = col_sep_length;
+ int not_space_flag;
- s = col_sep_string;
-
-@@ -2259,6 +2393,7 @@ print_sep_string (void)
+ if (separators_not_printed <= 0)
+ {
+@@ -2258,6 +2385,7 @@ print_sep_string (void)
{
for (; separators_not_printed > 0; --separators_not_printed)
{
@@ -2149,7 +1846,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
while (l-- > 0)
{
/* 3 types of sep_strings: spaces only, spaces and chars,
-@@ -2272,12 +2407,15 @@ print_sep_string (void)
+@@ -2271,12 +2399,15 @@ print_sep_string (void)
}
else
{
@@ -2166,7 +1863,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
/* sep_string ends with some spaces */
if (spaces_not_printed > 0)
print_white_space ();
-@@ -2305,7 +2443,7 @@ print_clump (COLUMN *p, int n, char *clu
+@@ -2307,7 +2438,7 @@ print_clump (COLUMN *p, int n, char *clump)
required number of tabs and spaces. */
static void
@@ -2175,7 +1872,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
{
if (tabify_output)
{
-@@ -2329,6 +2467,74 @@ print_char (char c)
+@@ -2331,6 +2462,74 @@ print_char (char c)
putchar (c);
}
@@ -2250,31 +1947,49 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
/* Skip to page PAGE before printing.
PAGE may be larger than total number of pages. */
-@@ -2508,9 +2714,9 @@ read_line (COLUMN *p)
+@@ -2507,9 +2706,9 @@ read_line (COLUMN *p)
align_empty_cols = false;
}
-- if (padding_not_printed - col_sep_length > 0)
-+ if (padding_not_printed - col_sep_width > 0)
+- if (col_sep_length < padding_not_printed)
++ if (col_sep_width < padding_not_printed)
{
- pad_across_to (padding_not_printed - col_sep_length);
+ pad_across_to (padding_not_printed - col_sep_width);
padding_not_printed = ANYWHERE;
}
-@@ -2611,9 +2817,9 @@ print_stored (COLUMN *p)
+@@ -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)
}
}
-- if (padding_not_printed - col_sep_length > 0)
-+ if (padding_not_printed - col_sep_width > 0)
+- if (col_sep_length < padding_not_printed)
++ if (col_sep_width < padding_not_printed)
{
- pad_across_to (padding_not_printed - col_sep_length);
+ pad_across_to (padding_not_printed - col_sep_width);
padding_not_printed = ANYWHERE;
}
-@@ -2626,8 +2832,8 @@ print_stored (COLUMN *p)
+@@ -2625,8 +2824,8 @@ print_stored (COLUMN *p)
if (spaces_not_printed == 0)
{
output_position = p->start_position + end_vector[line];
@@ -2285,7 +2000,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
}
return true;
-@@ -2646,7 +2852,7 @@ print_stored (COLUMN *p)
+@@ -2645,7 +2844,7 @@ print_stored (COLUMN *p)
number of characters is 1.) */
static int
@@ -2294,7 +2009,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
{
unsigned char uc = c;
char *s = clump_buff;
-@@ -2656,10 +2862,10 @@ char_to_clump (char c)
+@@ -2655,10 +2854,10 @@ char_to_clump (char c)
int chars;
int chars_per_c = 8;
@@ -2307,7 +2022,7 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
{
width = TAB_WIDTH (chars_per_c, input_position);
-@@ -2740,6 +2946,154 @@ char_to_clump (char c)
+@@ -2739,6 +2938,164 @@ char_to_clump (char c)
return chars;
}
@@ -2454,7 +2169,17 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
+ mbc_pos -= mblength;
+ }
+
-+ input_position += width;
++ /* 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;
++
+ return chars;
+}
+#endif
@@ -2462,20 +2187,15 @@ diff -urNp coreutils-8.17-orig/src/pr.c coreutils-8.17/src/pr.c
/* 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 -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
---- coreutils-8.17-orig/src/sort.c 2013-01-24 17:03:36.008333014 +0100
-+++ coreutils-8.17/src/sort.c 2013-01-24 17:11:53.549332078 +0100
-@@ -22,12 +22,21 @@
-
- #include
-
-+#include
- #include
- #include
- #include
- #include
+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 @@
#include
#include
+ #include
++
+#if HAVE_WCHAR_H
+# include
+#endif
@@ -2486,9 +2206,14 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
+
#include "system.h"
#include "argmatch.h"
- #include "error.h"
-@@ -165,12 +174,34 @@ static int thousands_sep;
+ #include "assure.h"
+@@ -160,14 +169,39 @@ static int thousands_sep;
+ /* We currently ignore multi-byte grouping chars. */
+ static bool thousands_sep_ignored;
++/* True if -f is specified. */
++static bool folding;
++
/* Nonzero if the corresponding locales are hard. */
static bool hard_LC_COLLATE;
-#if HAVE_NL_LANGINFO
@@ -2523,9 +2248,9 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
/* The kind of blanks for '-b' to skip in various options. */
enum blanktype { bl_start, bl_end, bl_both };
-@@ -344,13 +375,11 @@ static bool reverse;
- they were read if all keys compare equal. */
- static bool stable;
+@@ -344,13 +378,11 @@ static bool stable;
+ /* An int value outside char range. */
+ enum { NON_CHAR = CHAR_MAX + 1 };
-/* If TAB has this value, blanks separate fields. */
-enum { TAB_DEFAULT = CHAR_MAX + 1 };
@@ -2540,9 +2265,9 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
/* Flag to remove consecutive duplicate lines from the output.
Only the last of a sequence of equal lines will be output. */
-@@ -783,6 +812,46 @@ reap_all (void)
- reap (-1);
- }
+@@ -386,6 +418,46 @@ struct tempnode
+ static struct tempnode *volatile temphead;
+ static struct tempnode *volatile *temptail = &temphead;
+/* Function pointers. */
+static void
@@ -2580,14 +2305,14 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
+ }
+
+ *length = (mblength < 1) ? 1 : mblength;
-+ return iswblank (wc);
++ return iswblank (wc) || wc == '\n';
+}
+#endif
+
/* Clean up any remaining temporary files. */
static void
-@@ -1215,7 +1284,7 @@ zaptemp (char const *name)
+@@ -1343,7 +1415,7 @@ zaptemp (char const *name)
free (node);
}
@@ -2596,7 +2321,7 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
static int
struct_month_cmp (void const *m1, void const *m2)
-@@ -1230,7 +1299,7 @@ struct_month_cmp (void const *m1, void c
+@@ -1358,7 +1430,7 @@ struct_month_cmp (void const *m1, void const *m2)
/* Initialize the character class tables. */
static void
@@ -2605,7 +2330,7 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
{
size_t i;
-@@ -1242,7 +1311,7 @@ inittables (void)
+@@ -1370,7 +1442,7 @@ inittables (void)
fold_toupper[i] = toupper (i);
}
@@ -2614,7 +2339,7 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
/* If we're not in the "C" locale, read different names for months. */
if (hard_LC_TIME)
{
-@@ -1324,6 +1393,84 @@ specify_nmerge (int oi, char c, char con
+@@ -1450,6 +1522,84 @@ specify_nmerge (int oi, char c, char const *s)
xstrtol_fatal (e, oi, c, long_options, s);
}
@@ -2699,7 +2424,7 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
/* Specify the amount of main memory to use when sorting. */
static void
specify_sort_size (int oi, char c, char const *s)
-@@ -1552,7 +1699,7 @@ buffer_linelim (struct buffer const *buf
+@@ -1676,7 +1826,7 @@ buffer_linelim (struct buffer const *buf)
by KEY in LINE. */
static char *
@@ -2708,7 +2433,7 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
{
char *ptr = line->text, *lim = ptr + line->length - 1;
size_t sword = key->sword;
-@@ -1561,10 +1708,10 @@ begfield (struct line const *line, struc
+@@ -1685,10 +1835,10 @@ begfield (struct line const *line, struct keyfield const *key)
/* The leading field separator itself is included in a field when -t
is absent. */
@@ -2721,7 +2446,7 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
++ptr;
if (ptr < lim)
++ptr;
-@@ -1590,11 +1737,70 @@ begfield (struct line const *line, struc
+@@ -1718,12 +1868,71 @@ begfield (struct line const *line, struct keyfield const *key)
return ptr;
}
@@ -2787,13 +2512,14 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
/* 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 (const struct line *line, const struct keyfield *key)
++limfield_uni (struct line const *line, struct keyfield const *key)
{
char *ptr = line->text, *lim = ptr + line->length - 1;
size_t eword = key->eword, echar = key->echar;
-@@ -1609,10 +1815,10 @@ limfield (struct line const *line, struc
+@@ -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
the preceding field. */
@@ -2806,7 +2532,7 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
++ptr;
if (ptr < lim && (eword || echar))
++ptr;
-@@ -1658,10 +1864,10 @@ limfield (struct line const *line, struc
+@@ -1787,10 +1996,10 @@ limfield (struct line const *line, struct keyfield const *key)
*/
/* Make LIM point to the end of (one byte past) the current field. */
@@ -2819,12 +2545,12 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
if (newlim)
lim = newlim;
}
-@@ -1692,6 +1898,130 @@ limfield (struct line const *line, struc
+@@ -1825,6 +2034,130 @@ limfield (struct line const *line, struct keyfield const *key)
return ptr;
}
+#if HAVE_MBRTOWC
-+static char *
++static char * _GL_ATTRIBUTE_PURE
+limfield_mb (const struct line *line, const struct keyfield *key)
+{
+ char *ptr = line->text, *lim = ptr + line->length - 1;
@@ -2908,7 +2634,7 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
+ {
+ /* If we're skipping leading blanks, don't start counting characters
+ * until after skipping past any leading blanks. */
-+ if (key->skipsblanks)
++ if (key->skipeblanks)
+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength))
+ ptr += mblength;
+
@@ -2950,7 +2676,7 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
/* 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
-@@ -1778,8 +2108,22 @@ fillbuf (struct buffer *buf, FILE *fp, c
+@@ -1911,8 +2244,22 @@ fillbuf (struct buffer *buf, FILE *fp, char const *file)
else
{
if (key->skipsblanks)
@@ -2975,16 +2701,32 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
line->keybeg = line_start;
}
}
-@@ -1900,7 +2244,7 @@ human_numcompare (char const *a, char co
- hideously fast. */
+@@ -2050,12 +2397,10 @@ find_unit_order (char const *number)
+ 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++;
-@@ -1910,6 +2254,25 @@ numcompare (char const *a, char const *b
+@@ -2077,6 +2422,25 @@ numcompare (char const *a, char const *b)
return strnumcmp (a, b, decimal_point, thousands_sep);
}
@@ -3007,10 +2749,10 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
+}
+#endif /* HAV_EMBRTOWC */
+
- /* 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
-@@ -1960,7 +2323,7 @@ general_numcompare (char const *sa, char
+ static int
+ nan_compare (long double a, long double b)
+ {
+@@ -2118,7 +2482,7 @@ general_numcompare (char const *sa, char const *sb)
Return 0 if the name in S is not recognized. */
static int
@@ -3019,7 +2761,7 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
{
size_t lo = 0;
size_t hi = MONTHS_PER_YEAR;
-@@ -2235,15 +2598,14 @@ debug_key (struct line const *line, stru
+@@ -2457,15 +2821,14 @@ debug_key (struct line const *line, struct keyfield const *key)
char saved = *lim;
*lim = '\0';
@@ -3037,17 +2779,67 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
else if (key->general_numeric)
ignore_value (strtold (beg, &tighter_lim));
else if (key->numeric || key->human_numeric)
-@@ -2387,7 +2749,7 @@ key_warnings (struct keyfield const *gke
- bool maybe_space_aligned = !hard_LC_COLLATE && default_key_compare (key)
- && !(key->schar || key->echar);
+@@ -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;
bool line_offset = key->eword == 0 && key->echar != 0; /* -k1.x,1.y */
-- if (!gkey_only && tab == TAB_DEFAULT && !line_offset
-+ if (!gkey_only && !tab_length && !line_offset
- && ((!key->skipsblanks && !(implicit_skip || maybe_space_aligned))
+- if (!zero_width && !gkey_only && tab == TAB_DEFAULT && !line_offset
++ if (!zero_width && !gkey_only && !tab_length && !line_offset
+ && ((!key->skipsblanks && !implicit_skip)
|| (!key->skipsblanks && key->schar)
|| (!key->skipeblanks && key->echar)))
-@@ -2445,11 +2807,87 @@ key_warnings (struct keyfield const *gke
- error (0, 0, _("option '-r' only applies to last-resort comparison"));
+@@ -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;
}
+#if HAVE_MBRTOWC
@@ -3059,8 +2851,8 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
+ 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;
+
@@ -3073,17 +2865,19 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
+ if (len == 0)
+ return 0;
+
-+ month = (char *) xmalloc (len + 1);
++ if (SIZE_MAX - len < 1)
++ xalloc_die ();
+
-+ tmp = (char *) xmalloc (len + 1);
++ month = (char *) xnmalloc (len + 1, MB_CUR_MAX);
++
++ pp = tmp = (char *) xnmalloc (len + 1, MB_CUR_MAX);
+ memcpy (tmp, s, len);
+ tmp[len] = '\0';
-+ pp = (const char **)&tmp;
-+ month_wcs = (wchar_t *) xmalloc ((len + 1) * sizeof (wchar_t));
-+ memset (&state, '\0', sizeof(mbstate_t));
++ wpp = month_wcs = (wchar_t *) xnmalloc (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++)
@@ -3096,10 +2890,8 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
+ }
+ }
+
-+ wpp = (const wchar_t **)&month_wcs;
-+
-+ mblength = wcsrtombs (month, wpp, len + 1, &state);
-+ assert (mblength != (-1) && *wpp == NULL);
++ mblength = wcsrtombs (month, &wpp, (len + 1) * MB_CUR_MAX, &state);
++ assert (mblength != (-1) && wpp == NULL);
+
+ do
+ {
@@ -3116,7 +2908,7 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
+ ? monthtab[lo].val : 0);
+
+ if (ea && result)
-+ *ea = s + strlen (monthtab[lo].name);
++ *ea = (char*) s + strlen (monthtab[lo].name);
+
+ free (month);
+ free (tmp);
@@ -3135,17 +2927,17 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
{
struct keyfield *key = keylist;
-@@ -2534,7 +2972,7 @@ keycompare (struct line const *a, struct
+@@ -2831,7 +3270,7 @@ keycompare (struct line const *a, struct line const *b)
else if (key->human_numeric)
diff = human_numcompare (ta, tb);
else if (key->month)
-- diff = getmonth (ta, NULL) - getmonth (tb, NULL);
-+ diff = getmonth (ta, tlena, NULL) - getmonth (tb, tlenb, NULL);
+- diff = getmonth (ta, nullptr) - getmonth (tb, nullptr);
++ diff = getmonth (ta, tlena, nullptr) - getmonth (tb, tlenb, nullptr);
else if (key->random)
diff = compare_random (ta, tlena, tb, tlenb);
else if (key->version)
-@@ -2650,6 +3088,181 @@ keycompare (struct line const *a, struct
- return key->reverse ? -diff : diff;
+@@ -2941,6 +3380,211 @@ keycompare (struct line const *a, struct line const *b)
+ return diff_reversed (diff, key->reverse);
}
+#if HAVE_MBRTOWC
@@ -3165,45 +2957,14 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
+ wchar_t wc_a, wc_b;
+ mbstate_t state_a, state_b;
+
-+ int diff;
++ int diff = 0;
+
+ 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) \
@@ -3271,19 +3032,81 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
+ COPY[NEW_LEN] = '\0'; \
+ } \
+ while (0)
-+ 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);
++
++ /* 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;
+ }
+
+ if (diff)
@@ -3314,19 +3137,35 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
+ }
+ }
+
-+ return 0;
-+
-+greater:
-+ diff = 1;
+not_equal:
-+ return key->reverse ? -diff : diff;
++ if (key && key->reverse)
++ return -diff;
++ else
++ return 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. */
-@@ -4110,7 +4723,7 @@ main (int argc, char **argv)
+@@ -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)
initialize_exit_failure (SORT_FAILURE);
hard_LC_COLLATE = hard_locale (LC_COLLATE);
@@ -3335,8 +3174,8 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
hard_LC_TIME = hard_locale (LC_TIME);
#endif
-@@ -4131,6 +4744,29 @@ main (int argc, char **argv)
- thousands_sep = -1;
+@@ -4442,6 +5087,29 @@ main (int argc, char **argv)
+ thousands_sep = NON_CHAR;
}
+#if HAVE_MBRTOWC
@@ -3365,7 +3204,7 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
have_read_stdin = false;
inittables ();
-@@ -4401,13 +5037,34 @@ main (int argc, char **argv)
+@@ -4717,13 +5385,34 @@ main (int argc, char **argv)
case 't':
{
@@ -3398,20 +3237,19 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
+#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
-@@ -4418,9 +5075,12 @@ main (int argc, char **argv)
+@@ -4734,9 +5423,11 @@ 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);
@@ -3419,783 +3257,1027 @@ diff -urNp coreutils-8.17-orig/src/sort.c coreutils-8.17/src/sort.c
}
break;
-diff -urNp coreutils-8.17-orig/src/unexpand.c coreutils-8.17/src/unexpand.c
---- coreutils-8.17-orig/src/unexpand.c 2012-05-01 22:55:08.000000000 +0200
-+++ coreutils-8.17/src/unexpand.c 2013-01-24 17:11:53.551335712 +0100
-@@ -38,12 +38,29 @@
+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 @@
#include
#include
#include
+
-+/* Get mbstate_t, mbrtowc(), wcwidth(). */
-+#if HAVE_WCHAR_H
-+# include
-+#endif
++#include
+
#include "system.h"
- #include "error.h"
- #include "fadvise.h"
- #include "quote.h"
- #include "xstrndup.h"
+ #include "expand-common.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 "unexpand"
+@@ -105,24 +108,46 @@ unexpand (void)
+ {
+ /* Input stream. */
+ FILE *fp = next_file (nullptr);
++ mb_file_t mbf;
-@@ -103,6 +120,208 @@ static struct option const longopts[] =
- {NULL, 0, NULL, 0}
- };
+ /* 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;
++
++ /* True if the first file contains BOM header. */
++ bool found_bom;
++ using_utf_locale=check_utf_locale();
-+static FILE *next_file (FILE *fp);
+ if (!fp)
+ return;
+
++ mbf_init (mbf, fp);
++ found_bom=check_bom(fp,&mbf);
+
-+#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 (;;)
++ if (using_utf_locale == false && found_bom == true)
+ {
-+ 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)
- {
-@@ -524,7 +743,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.17-orig/src/uniq.c coreutils-8.17/src/uniq.c
---- coreutils-8.17-orig/src/uniq.c 2012-05-01 22:55:08.000000000 +0200
-+++ coreutils-8.17/src/uniq.c 2013-01-24 17:11:53.552332659 +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'},
-@@ -206,7 +232,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;
-@@ -226,6 +252,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)
++ /* Try using some predefined locale */
++ if (set_utf_locale () != 0)
+ {
-+ 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;
++ error (EXIT_FAILURE, errno, _("cannot set UTF-8 locale"));
+ }
+ }
+
-+ /* skip fields. */
-+ for (count = 0; count < skip_chars && pos < size; count++)
-+ {
-+ MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail);
-+ 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));
+
-+ 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.
-@@ -234,6 +337,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)
-@@ -241,14 +346,100 @@ different (char *old, char *new, size_t
++ if (found_bom == true)
++ print_bom();
- if (ignore_case)
+ while (true)
{
-- /* FIXME: This should invoke strcoll somehow. */
-- return oldlen != newlen || memcasecmp (old, new, oldlen);
-+ size_t i;
-+
-+ copy_old = xmalloc (oldlen + 1);
-+ copy_new = xmalloc (oldlen + 1);
-+
-+ 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
+ /* Input character, or EOF. */
+- int c;
++ mbf_char_t c;
- /* Output the line in linebuffer LINE to standard output
- provided that the switches say it should be output.
-@@ -304,15 +495,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
+ /* If true, perform translations. */
+ bool convert = true;
+@@ -156,12 +181,44 @@ unexpand (void)
- while (!feof (stdin))
+ do
{
- char *thisfield;
- size_t thislen;
-+#if HAVE_MBRTOWC
-+ mbstate_t thisstate;
-+#endif
-+
- 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;
-+
-+ if (prevline->length == 0 || different_multi
-+ (thisfield, prevfield, thislen, prevlen, thisstate, prevstate))
+- while ((c = getc (fp)) < 0 && (fp = next_file (fp)))
+- continue;
++ while (true) {
++ mbf_getc (c, mbf);
++ if ((mb_iseof (c)) && (fp = next_file (fp)))
+ {
-+ fwrite (thisline->buffer, sizeof (char),
-+ thisline->length, stdout);
-+
-+ SWAP_LINES (prevline, thisline);
-+ prevfield = thisfield;
-+ prevlen = thislen;
-+ prevstate = thisstate;
++ 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;
+ }
-+ }
-+ else
-+#endif
- if (prevline->length == 0
- || different (thisfield, prevfield, thislen, prevlen))
- {
-@@ -331,17 +550,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
-
- 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
-
- 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))
-@@ -350,6 +578,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;
++
-@@ -382,6 +618,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;
+ 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');
++
++ 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;
}
-@@ -427,6 +666,19 @@ main (int argc, char **argv)
- atexit (close_stdout);
+- if (c < 0)
++ if (mb_iseof (c))
+ {
+ free (pending_blank);
+ return;
+ }
-+#if HAVE_MBRTOWC
-+ if (MB_CUR_MAX > 1)
-+ {
-+ find_field = find_field_multi;
-+ }
-+ else
-+#endif
-+ {
-+ find_field = find_field_uni;
-+ }
+- if (putchar (c) < 0)
++ mb_putc (c, stdout);
++ if (ferror (stdout))
+ write_error ();
+ }
+- while (c != '\n');
++ while (!mb_iseq (c, '\n'));
+ }
+ }
+
+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)
+ {
+ 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
++
++# 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_ 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
+
+
+
- skip_chars = 0;
- skip_fields = 0;
- check_chars = SIZE_MAX;
-diff -urNp coreutils-8.17-orig/tests/Makefile.am coreutils-8.17/tests/Makefile.am
---- coreutils-8.17-orig/tests/Makefile.am 2013-01-24 17:03:36.144332400 +0100
-+++ coreutils-8.17/tests/Makefile.am 2013-01-24 17:11:53.554331990 +0100
-@@ -246,6 +246,7 @@ TESTS = \
- misc/sort-debug-warn \
- misc/sort-discrim \
- misc/sort-files0-from \
-+ misc/sort-mb-tests \
- misc/sort-float \
- misc/sort-merge \
- misc/sort-merge-fdlimit \
-@@ -545,6 +546,10 @@ TESTS = \
- $(root_tests)
++#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)
- pr_data = \
-+ misc/mb1.X \
-+ misc/mb1.I \
-+ misc/mb2.X \
-+ misc/mb2.I \
- pr/0F \
- pr/0FF \
- pr/0FFnt \
-diff -urNp coreutils-8.17-orig/tests/misc/cut coreutils-8.17/tests/misc/cut
---- coreutils-8.17-orig/tests/misc/cut 2012-02-03 10:22:06.000000000 +0100
-+++ coreutils-8.17/tests/misc/cut 2013-01-24 17:11:53.555332032 +0100
-@@ -23,14 +23,15 @@ use strict;
+ # 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;
++ }
++ 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};
+
+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 ();
+
+ my $prog = 'unexpand';
+
++# 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"}],
+ );
+
++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};
+
+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/': .*/'/";
+
++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';
# Turn off localization of executable's output.
@ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
-my $mb_locale = $ENV{LOCALE_FR_UTF8};
--! 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 $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';
- 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 $try = "Try \`$prog --help' for more information.\n";
+my $inval = "$prog: invalid byte, character or field list\n$try";
- my $no_endpoint = "$prog: invalid range with no endpoint: -\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 @Tests =
-@@ -147,7 +148,7 @@ my @Tests =
++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;
- # 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.17-orig/tests/misc/mb1.I coreutils-8.17/tests/misc/mb1.I
---- coreutils-8.17-orig/tests/misc/mb1.I 1970-01-01 01:00:00.000000000 +0100
-+++ coreutils-8.17/tests/misc/mb1.I 2013-01-24 17:11:53.555332032 +0100
-@@ -0,0 +1,4 @@
-+Apple@10
-+Banana@5
-+Citrus@20
-+Cherry@30
-diff -urNp coreutils-8.17-orig/tests/misc/mb1.X coreutils-8.17/tests/misc/mb1.X
---- coreutils-8.17-orig/tests/misc/mb1.X 1970-01-01 01:00:00.000000000 +0100
-+++ coreutils-8.17/tests/misc/mb1.X 2013-01-24 17:11:53.556332141 +0100
-@@ -0,0 +1,4 @@
-+Banana@5
-+Apple@10
-+Citrus@20
-+Cherry@30
-diff -urNp coreutils-8.17-orig/tests/misc/mb2.I coreutils-8.17/tests/misc/mb2.I
---- coreutils-8.17-orig/tests/misc/mb2.I 1970-01-01 01:00:00.000000000 +0100
-+++ coreutils-8.17/tests/misc/mb2.I 2013-01-24 17:11:53.556332141 +0100
-@@ -0,0 +1,4 @@
-+Apple@AA10@@20
-+Banana@AA5@@30
-+Citrus@AA20@@5
-+Cherry@AA30@@10
-diff -urNp coreutils-8.17-orig/tests/misc/mb2.X coreutils-8.17/tests/misc/mb2.X
---- coreutils-8.17-orig/tests/misc/mb2.X 1970-01-01 01:00:00.000000000 +0100
-+++ coreutils-8.17/tests/misc/mb2.X 2013-01-24 17:11:53.557333171 +0100
-@@ -0,0 +1,4 @@
-+Citrus@AA20@@5
-+Cherry@AA30@@10
-+Apple@AA10@@20
-+Banana@AA5@@30
-diff -urNp coreutils-8.17-orig/tests/misc/sort-mb-tests coreutils-8.17/tests/misc/sort-mb-tests
---- coreutils-8.17-orig/tests/misc/sort-mb-tests 1970-01-01 01:00:00.000000000 +0100
-+++ coreutils-8.17/tests/misc/sort-mb-tests 2013-01-24 17:11:53.557333171 +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
+ # 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
+
+export LC_ALL=en_US.UTF-8
-+locale -k LC_CTYPE 2>&1 | grep -q charmap.*UTF-8 || exit 77
-+errors=0
+
-+$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
++#input containing multibyte characters
++cat > in <<\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
++cat > exp <<\EOF
++1234567812345678123456781
++. . . .
++a b c d
++. . . .
++ä ö ü ß
++. . . .
++ äöü . öüä. ä xx
++EOF
+
-+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
++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
+
diff --git a/coreutils-keyring.gpg b/coreutils-keyring.gpg
new file mode 100644
index 0000000..003a885
--- /dev/null
+++ b/coreutils-keyring.gpg
@@ -0,0 +1,312 @@
+Release GPG keyring of coreutils group.
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+ELphkzjc6eM3CaOZ73u4GVXotheeUabUHQ==
+=drvb
+-----END PGP PUBLIC KEY BLOCK-----
\ No newline at end of file
diff --git a/coreutils-overflow.patch b/coreutils-overflow.patch
deleted file mode 100644
index 0d55a6d..0000000
--- a/coreutils-overflow.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- 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
new file mode 100644
index 0000000..447fdbc
--- /dev/null
+++ b/coreutils-python3.patch
@@ -0,0 +1,65 @@
+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
deleted file mode 100644
index fa1e4d8..0000000
--- a/coreutils-runuser-l.pamd
+++ /dev/null
@@ -1,4 +0,0 @@
-#%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
deleted file mode 100644
index 37f0e84..0000000
--- a/coreutils-runuser.pamd
+++ /dev/null
@@ -1,5 +0,0 @@
-#%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
deleted file mode 100644
index 501b33e..0000000
--- a/coreutils-selinux.patch
+++ /dev/null
@@ -1,656 +0,0 @@
-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_cache (absolute_name, f);
-
-- 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_cache (absolute_name, f);
- 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))
- {
- 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.17-orig/tests/init.cfg coreutils-8.17/tests/init.cfg
---- coreutils-8.17-orig/tests/init.cfg
-+++ coreutils-8.17/tests/init.cfg
-@@ -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.17-orig/tests/misc/selinux coreutils-8.17/tests/misc/selinux
---- coreutils-8.17-orig/tests/misc/selinux
-+++ coreutils-8.17/tests/misc/selinux
-@@ -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
deleted file mode 100644
index 9cbc166..0000000
--- a/coreutils-selinuxmanpages.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-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
deleted file mode 100644
index 714383f..0000000
--- a/coreutils-setsid.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-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
deleted file mode 100644
index 656a139..0000000
--- a/coreutils-su-l.pamd
+++ /dev/null
@@ -1,6 +0,0 @@
-#%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
deleted file mode 100644
index 030657f..0000000
--- a/coreutils-su.pamd
+++ /dev/null
@@ -1,14 +0,0 @@
-#%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 880319c..6712263 100644
--- a/coreutils.spec
+++ b/coreutils.spec
@@ -1,445 +1,1054 @@
Summary: A set of basic GNU tools commonly used in shell scripts
Name: coreutils
-Version: 8.17
-Release: 8%{?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
+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
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
-# From upstream
-Patch1: coreutils-8.17-ls-rootdir-symlink.patch
-Patch2: coreutils-8.17-sort-uniq-fmr.patch
-Patch3: coreutils-8.17-cp-freememoryread.patch
-Patch4: coreutils-8.17-df-duplicates.patch
+# do not make coreutils-single depend on /usr/bin/coreutils
+%global __requires_exclude ^%{_bindir}/coreutils$
-# 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
+# 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
Patch104: coreutils-df-direct.patch
-#add note about mkdir --mode behaviour into info documentation(#610559)
-Patch107: coreutils-8.4-mkdir-modenote.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
+# 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
# (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
-BuildRequires: libselinux-devel
-BuildRequires: libacl-devel
-BuildRequires: gettext bison
-BuildRequires: texinfo
+# To avoid clobbering installs
+Conflicts: coreutils-single
+
+BuildRequires: attr
BuildRequires: autoconf
BuildRequires: automake
-%{?!nopam:BuildRequires: pam-devel}
-BuildRequires: libcap-devel
-BuildRequires: libattr-devel
+BuildRequires: gcc
+BuildRequires: gettext-devel
BuildRequires: gmp-devel
-BuildRequires: attr
+BuildRequires: hostname
+BuildRequires: libacl-devel
+BuildRequires: libattr-devel
+BuildRequires: libcap-devel
+BuildRequires: libselinux-devel
+BuildRequires: libselinux-utils
+BuildRequires: make
+BuildRequires: openssl-devel
BuildRequires: strace
+BuildRequires: systemd-devel
+BuildRequires: texinfo
-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
+# For gpg verification of source tarball
+BuildRequires: gnupg2
-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}
+# 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: 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
+Obsoletes: %{name} < 8.24-100
%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
-%setup -q
+%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}'
+%autosetup -N
-# From upstream
-%patch1 -p1 -b .roodirsymlink
-%patch2 -p1 -b .fmr
-%patch3 -p1 -b .freememoryread
-%patch4 -p1 -b .duplic
+# will be regenerated in the build directories
+rm -f src/fs.h
-# 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
+# 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
-# sh-utils
-%patch703 -p1 -b .dateman
-%patch704 -p1 -b .paths
-%patch706 -p1 -b .pam
-%patch713 -p1 -b .langinfo
+# git add DIR_COLORS{,.lightbgcolor}
+# git commit -m "clone DIR_COLORS before patching"
-# li18nux/lsb
-%patch800 -p1 -b .i18n
+# apply all patches
+%autopatch -p1
-# Coreutils
-%patch900 -p1 -b .setsid
-%patch907 -p1 -b .runuser
-%patch908 -p1 -b .getgrouplist
-%patch912 -p1 -b .overflow
-%patch917 -p1 -b .pie
+(echo ">>> Fixing permissions on tests") 2>/dev/null
+find tests -name '*.sh' -perm 0644 -print -exec chmod 0755 '{}' '+'
+(echo "<<< done") 2>/dev/null
-#SELinux
-%patch950 -p1 -b .selinux
-%patch951 -p1 -b .selinuxman
-%patch952 -p1 -b .cpZ
+# 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
-chmod a+x tests/misc/sort-mb-tests tests/df/direct tests/df/skip-duplicates tests/df/skip-rootfs || :
-
-#fix typos/mistakes in localized documentation(#439410, #440056)
-find ./po/ -name "*.p*" | xargs \
- sed -i \
- -e 's/-dpR/-cdpR/'
+autoreconf -fiv
%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}
-#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 || :
+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
-# Regenerate manpages
-touch man/*.x
+ # make sure that parse-datetime.{c,y} ends up in debuginfo (#1555079)
+ ln -fv ../lib/parse-datetime.{c,y} .
+ )
+done
-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
+# Get the list of supported utilities
+cp %SOURCE50 .
%check
-make check
+for type in separate single; do
+ test $type = 'single' && subdirs='SUBDIRS=.' # Only check gnulib once
+ (cd $type && make check %{?_smp_mflags} $subdirs)
+done
%install
-rm -rf $RPM_BUILD_ROOT
-make DESTDIR=$RPM_BUILD_ROOT 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)
-# man pages are not installed with make install
-make mandir=$RPM_BUILD_ROOT%{_mandir} install-man
+%if "%{_sbindir}" != "%{_bindir}"
+ # chroot was in /usr/sbin :
+ mkdir -p $RPM_BUILD_ROOT/$subdir/%_sbindir
+ mv $RPM_BUILD_ROOT/$subdir/{%_bindir,%_sbindir}/chroot
+%endif
-# 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
+ # 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
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/profile.d
-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 DIR_COLORS{,.lightbgcolor} $RPM_BUILD_ROOT%{_sysconfdir}
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
-%clean
-rm -rf $RPM_BUILD_ROOT
+%files -f supported_utils
+%exclude %{_bindir}/*.single
+%dir %{_libexecdir}/coreutils
+%{_libexecdir}/coreutils/*.so
-%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 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
-%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
+%files common -f %{name}.lang
%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*/*
-%{_sbindir}/chroot
-%{?!norunuser:%{_sbindir}/runuser}
+# The following go to /usr/share/doc/coreutils-common
+%doc ABOUT-NLS NEWS README THANKS TODO
+%license COPYING
%changelog
-* Thu Jan 24 2013 Ondrej Vasik 8.17-8
-- fix multiple segmantation faults in i18n patch (by SUSE)
- (#869442, #902917)- CVE2013-0223/CVE2013-0221/CVE2013-0222
+* Tue Jan 13 2026 Lukáš Zaoral - 9.9-2
+- fix cut test failure on aarch64 rawhide (rhbz#2424302)
-* Tue Dec 11 2012 Ondrej Vasik 8.17-7
+* 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