From 06a642b9ff7ec76fdec1ec21f953bbe4c28208dc24ec44c0f5f9f46a9c4d9af7 Mon Sep 17 00:00:00 2001 From: OBS User unknown Date: Mon, 18 Dec 2006 23:15:28 +0000 Subject: [PATCH] OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/coreutils?expand=0&rev=1 --- _multibuild | 4 - acl-test.diff | 89 + baselibs.conf | 3 - coreutils-5.0-pam-env.patch | 38 + coreutils-5.3.0-i18n-0.1.patch | 3998 ++++++++++++ coreutils-5.3.0-pie.diff | 21 + coreutils-5.3.0-sbin4su.diff | 143 + coreutils-6.7.diff | 764 +++ coreutils-6.7.tar.bz2 | 3 + coreutils-8.32.tar.xz | 3 - coreutils-8.32.tar.xz.sig | 16 - coreutils-build-timeout-as-pie.patch | 39 - coreutils-changelog.diff | 44 + coreutils-disable_tests.patch | 23 - coreutils-getaddrinfo.patch | 21 - coreutils-gnulib-disable-test-float.patch | 25 - coreutils-i18n.patch | 5332 ----------------- coreutils-invalid-ids.patch | 30 - ...estore-8.31-behavior-on-removed-dirs.patch | 156 - coreutils-misc.patch | 61 - coreutils-remove_hostname_documentation.patch | 92 - coreutils-remove_kill_documentation.patch | 126 - coreutils-skip-gnulib-test-tls.patch | 37 - coreutils-skip-some-sort-tests-on-ppc.patch | 52 - ...ls-sysinfo.patch => coreutils-sysinfo.diff | 24 +- coreutils-test_without_valgrind.patch | 18 - ...s-tests-fix-FP-in-ls-stat-free-color.patch | 46 - ...s-tests-shorten-extreme-factor-tests.patch | 36 - coreutils-use-python3.patch | 24 - coreutils-xattr.diff | 321 + coreutils.changes | 3324 ---------- coreutils.keyring | 312 - coreutils.spec | 1003 +++- getcwd.diff | 11 + gnulib-test-avoid-FP-perror-strerror.patch | 101 - i18n-infloop.diff | 12 + i18n-uninit.diff | 25 + invalid-ids.diff | 47 + no-no.diff | 10 + ready | 0 su.default | 11 + su.pamd | 7 + 42 files changed, 6257 insertions(+), 10195 deletions(-) delete mode 100644 _multibuild create mode 100644 acl-test.diff delete mode 100644 baselibs.conf create mode 100644 coreutils-5.0-pam-env.patch create mode 100644 coreutils-5.3.0-i18n-0.1.patch create mode 100644 coreutils-5.3.0-pie.diff create mode 100644 coreutils-5.3.0-sbin4su.diff create mode 100644 coreutils-6.7.diff create mode 100644 coreutils-6.7.tar.bz2 delete mode 100644 coreutils-8.32.tar.xz delete mode 100644 coreutils-8.32.tar.xz.sig delete mode 100644 coreutils-build-timeout-as-pie.patch create mode 100644 coreutils-changelog.diff delete mode 100644 coreutils-disable_tests.patch delete mode 100644 coreutils-getaddrinfo.patch delete mode 100644 coreutils-gnulib-disable-test-float.patch delete mode 100644 coreutils-i18n.patch delete mode 100644 coreutils-invalid-ids.patch delete mode 100644 coreutils-ls-restore-8.31-behavior-on-removed-dirs.patch delete mode 100644 coreutils-misc.patch delete mode 100644 coreutils-remove_hostname_documentation.patch delete mode 100644 coreutils-remove_kill_documentation.patch delete mode 100644 coreutils-skip-gnulib-test-tls.patch delete mode 100644 coreutils-skip-some-sort-tests-on-ppc.patch rename coreutils-sysinfo.patch => coreutils-sysinfo.diff (74%) delete mode 100644 coreutils-test_without_valgrind.patch delete mode 100644 coreutils-tests-fix-FP-in-ls-stat-free-color.patch delete mode 100644 coreutils-tests-shorten-extreme-factor-tests.patch delete mode 100644 coreutils-use-python3.patch create mode 100644 coreutils-xattr.diff delete mode 100644 coreutils.keyring create mode 100644 getcwd.diff delete mode 100644 gnulib-test-avoid-FP-perror-strerror.patch create mode 100644 i18n-infloop.diff create mode 100644 i18n-uninit.diff create mode 100644 invalid-ids.diff create mode 100644 no-no.diff create mode 100644 ready create mode 100644 su.default create mode 100644 su.pamd diff --git a/_multibuild b/_multibuild deleted file mode 100644 index eb2bf3f..0000000 --- a/_multibuild +++ /dev/null @@ -1,4 +0,0 @@ - - single - testsuite - diff --git a/acl-test.diff b/acl-test.diff new file mode 100644 index 0000000..3f953b6 --- /dev/null +++ b/acl-test.diff @@ -0,0 +1,89 @@ +2006-12-13 Andreas Schwab + + * tests/mv/acl (skip): Check for acl support in the file system. + + * tests/mv/Makefile.am (XFAIL_TESTS): Remove. + (TESTS_ENVIRONMENT): Pass CONFIG_HEADER. + +2006-12-12 Jim Meyering + + * m4/acl.m4 (gl_ACL_GET_FILE): Fix logic error. + Reported by Andreas Schwab . + +diff --git a/tests/mv/Makefile.am b/tests/mv/Makefile.am +index 57581cd..0a1f2db 100644 +--- a/tests/mv/Makefile.am ++++ b/tests/mv/Makefile.am +@@ -20,7 +20,6 @@ + + AUTOMAKE_OPTIONS = 1.3 gnits + +-XFAIL_TESTS = acl + TESTS = \ + hard-verbose \ + backup-dir \ +@@ -48,4 +47,5 @@ TESTS_ENVIRONMENT = \ + PERL="$(PERL)" \ + EGREP="$(EGREP)" \ + PATH="$(VG_PATH_PREFIX)`pwd`/../../src$(PATH_SEPARATOR)$$PATH" \ ++ CONFIG_HEADER=$(CONFIG_HEADER) \ + PROG=mv +diff --git a/tests/mv/acl b/tests/mv/acl +index f570656..df3bb01 100755 +--- a/tests/mv/acl ++++ b/tests/mv/acl +@@ -24,6 +24,13 @@ + # Make sure we get English translations. + . $srcdir/../lang-default + ++# Skip this test if cp was built without ACL support: ++grep '^#define USE_ACL 0' $CONFIG_HEADER > /dev/null && \ ++ { ++ echo 1>&2 "$0: insufficient ACL support, so skipping this test" ++ (exit 77); exit 77 ++ } ++ + if test "$VERBOSE" = yes; then + set -x + mv --version +@@ -46,15 +53,26 @@ framework_failure=0 + mkdir -p $tmp || framework_failure=1 + cd $tmp || framework_failure=1 + ++touch file || framework_failure=1 ++ + if test $framework_failure = 1; then + echo 'failure in testing framework' + (exit 1); exit 1 + fi + ++skip=no ++# Ensure that setfacl and getfacl work on this file system. ++setfacl -m user:bin:rw file 2> /dev/null || skip=yes ++acl1=`getfacl file` || skip=yes ++ ++test $skip = yes && ++ { ++ echo "$0: '.' is not on a suitable file system for this test" 1>&2 ++ echo "$0: skipping this test" 1>&2 ++ (exit 77); exit 77 ++ } ++ + # move the access acl of a file +-touch file || framework_failure=1 +-setfacl -m user:bin:rw file || framework_failure=1 +-acl1=`getfacl file` || framework_failure=1 + mv file $other_partition_tmpdir || fail=1 + acl2=`cd $other_partition_tmpdir && getfacl file` || framework_failure=1 + test "$acl1" = "$acl2" || fail=1 +--- a/m4/acl.m4 ++++ b/m4/acl.m4 +@@ -53,7 +53,7 @@ + #include + ]], + [[return !! (!acl_get_file (".", ACL_TYPE_ACCESS) +- || errno == ENOENT);]])], ++ && errno == ENOENT);]])], + [gl_cv_func_working_acl_get_file=yes], + [gl_cv_func_working_acl_get_file=no], + [gl_cv_func_working_acl_get_file=cross-compiling])]) diff --git a/baselibs.conf b/baselibs.conf deleted file mode 100644 index 5b642b4..0000000 --- a/baselibs.conf +++ /dev/null @@ -1,3 +0,0 @@ -targettype x86 package coreutils - +^/bin/uname$ - prereq -glibc-x86 diff --git a/coreutils-5.0-pam-env.patch b/coreutils-5.0-pam-env.patch new file mode 100644 index 0000000..151bbb2 --- /dev/null +++ b/coreutils-5.0-pam-env.patch @@ -0,0 +1,38 @@ +--- coreutils-5.3.0/src/su.c ++++ coreutils-5.3.0/src/su.c +@@ -521,6 +521,21 @@ + } + + /* child shell */ ++ ++ /* Export env variables declared by PAM modules */ ++ { ++ const char *const *env; ++ ++ env = (const char *const *) pam_getenvlist (pamh); ++ while (env && *env) ++ { ++ ++ if (putenv (*env) != 0) ++ xalloc_die (); ++ env++; ++ } ++ } ++ + pam_end (pamh, 0); + #endif + +@@ -726,9 +741,12 @@ + shell = NULL; + } + shell = xstrdup (shell ? shell : pw->pw_shell); ++ change_identity (pw); ++ ++ /* Set environment after pam_open_session, which may put KRB5CCNAME ++ into the pam_env, etc. */ + modify_environment (pw, shell); + +- change_identity (pw); + if (simulate_login && chdir (pw->pw_dir) != 0) + error (0, errno, _("warning: cannot change directory to %s"), pw->pw_dir); + diff --git a/coreutils-5.3.0-i18n-0.1.patch b/coreutils-5.3.0-i18n-0.1.patch new file mode 100644 index 0000000..f4df397 --- /dev/null +++ b/coreutils-5.3.0-i18n-0.1.patch @@ -0,0 +1,3998 @@ +--- coreutils-6.5/lib/linebuffer.h ++++ coreutils-6.5/lib/linebuffer.h +@@ -22,6 +22,11 @@ + + # include + ++/* Get mbstate_t. */ ++# if HAVE_WCHAR_H ++# include ++# endif ++ + /* A `struct linebuffer' holds a line of text. */ + + struct linebuffer +@@ -29,6 +34,9 @@ + size_t size; /* Allocated. */ + size_t length; /* Used. */ + char *buffer; ++# if HAVE_WCHAR_H ++ mbstate_t state; ++# endif + }; + + /* Initialize linebuffer LINEBUFFER for use. */ +--- coreutils-6.5/src/cut.c ++++ coreutils-6.5/src/cut.c +@@ -29,6 +29,12 @@ + #include + #include + #include ++ ++/* Get mbstate_t, mbrtowc(). */ ++#if HAVE_WCHAR_H ++# include ++#endif ++ + #include "system.h" + + #include "error.h" +@@ -37,6 +43,13 @@ + #include "quote.h" + #include "xstrndup.h" + ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC ++ installation; work around this configuration error. */ ++#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 ++# undef MB_LEN_MAX ++# define MB_LEN_MAX 16 ++#endif ++ + /* The official name of this program (e.g., no `g' prefix). */ + #define PROGRAM_NAME "cut" + +@@ -73,6 +86,54 @@ + size_t hi; + }; + ++/* Refill the buffer BUF. */ ++#define REFILL_BUFFER(BUF, BUFPOS, BUFLEN, STREAM) \ ++ do \ ++ { \ ++ if (BUFLEN < MB_LEN_MAX && !feof (STREAM) && !ferror (STREAM)) \ ++ { \ ++ memmove (BUF, BUFPOS, BUFLEN); \ ++ BUFLEN += fread (BUF + BUFLEN, sizeof(char), BUFSIZ, STREAM); \ ++ BUFPOS = BUF; \ ++ } \ ++ } \ ++ while (0) ++ ++/* Get wide character which starts at BUFPOS. If the byte sequence is ++ not valid as a character, CONVFAIL is 1. Otherwise 0. */ ++#define GET_NEXT_WC_FROM_BUFFER(WC, BUFPOS, BUFLEN, MBLENGTH, STATE, CONVFAIL) \ ++ do \ ++ { \ ++ wchar_t tmp; \ ++ mbstate_t state_bak; \ ++ \ ++ if (BUFLEN < 1) \ ++ { \ ++ WC = WEOF; \ ++ break; \ ++ } \ ++ \ ++ /* Get a wide character. */ \ ++ CONVFAIL = 0; \ ++ state_bak = STATE; \ ++ MBLENGTH = mbrtowc (&tmp, BUFPOS, BUFLEN, &STATE); \ ++ WC = tmp; \ ++ \ ++ switch (MBLENGTH) \ ++ { \ ++ case (size_t)-1: \ ++ case (size_t)-2: \ ++ ++CONVFAIL; \ ++ STATE = state_bak; \ ++ /* Fall througn. */ \ ++ \ ++ case 0: \ ++ MBLENGTH = 1; \ ++ break; \ ++ } \ ++ } \ ++ while (0) ++ + /* 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 +@@ -85,7 +146,7 @@ + /* 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 field, character or byte 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. */ +@@ -97,10 +158,11 @@ + + /* 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; +@@ -109,9 +171,12 @@ + { + undefined_mode, + +- /* Output characters that are in the given bytes. */ ++ /* Output bytes that are in the given bytes. */ + byte_mode, + ++ /* Output characters that are at the given positions. */ ++ character_mode, ++ + /* Output the given delimeter-separated fields. */ + field_mode + }; +@@ -121,6 +186,13 @@ + + static enum operating_mode operating_mode; + ++/* If true, when in byte mode, don't split multibyte characters. */ ++static bool byte_mode_character_aware; ++ ++/* If true, the function for single byte locale is work ++ if this program runs on multibyte locale. */ ++static bool force_singlebyte_mode; ++ + /* If true do not output lines containing no delimeter characters. + Otherwise, all such lines are printed. This option is valid only + with field mode. */ +@@ -132,6 +204,9 @@ + + /* The delimeter 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; +@@ -205,7 +280,7 @@ + -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\ +- -n (ignored)\n\ ++ -n with -b: don't split multibyte characters\n\ + "), stdout); + fputs (_("\ + --complement complement the set of selected bytes, characters\n\ +@@ -360,7 +435,7 @@ + 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++; + +@@ -385,14 +460,16 @@ + if (value == 0) + { + /* `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 byte or field list")); ++ FATAL_ERROR (_("invalid byte, character or field list")); + + /* Is there already a range going to end of line? */ + if (eol_range_start != 0) +@@ -475,7 +552,7 @@ + fieldstr++; + } + else +- FATAL_ERROR (_("invalid byte or field list")); ++ FATAL_ERROR (_("invalid byte, character or field list")); + } + + max_range_endpoint = 0; +@@ -568,6 +645,81 @@ + } + } + ++#if HAVE_MBRTOWC ++/* This function is in use for the following case. ++ ++ 1. Read from the stream STREAM, printing to standard output any selected ++ characters. ++ ++ 2. Read from stream STREAM, printing to standard output any selected bytes, ++ without splitting multibyte characters. */ ++ ++static void ++cut_characters_or_cut_bytes_no_split (FILE *stream) ++{ ++ size_t idx; /* Number of bytes or characters in the line so far. */ ++ /* 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; ++ ++ 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. */ ++ 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 of the stream. */ ++ int convfail; /* 1, when conversion is failed. Otherwise 0. */ ++ ++ ++ idx = 0; ++ print_delimiter = false; ++ buflen = 0; ++ bufpos = buf; ++ memset (&state, '\0', sizeof(mbstate_t)); ++ ++ while (1) ++ { ++ REFILL_BUFFER (buf, bufpos, buflen, stream); ++ ++ GET_NEXT_WC_FROM_BUFFER (wc, bufpos, buflen, mblength, state, convfail); ++ ++ if (wc == WEOF) ++ { ++ if (idx > 0) ++ putchar ('\n'); ++ break; ++ } ++ else if (wc == L'\n') ++ { ++ putchar ('\n'); ++ idx = 0; ++ print_delimiter = false; ++ } ++ else ++ { ++ bool range_start; ++ bool *rs = output_delimiter_specified ? &range_start : NULL; ++ ++ idx += (operating_mode == byte_mode) ? mblength : 1; ++ if (print_kth (idx, rs)) ++ { ++ if (rs && *rs && print_delimiter) ++ { ++ fwrite (output_delimiter_string, sizeof (char), ++ output_delimiter_length, stdout); ++ } ++ print_delimiter = true; ++ fwrite (bufpos, mblength, sizeof (char), stdout); ++ } ++ } ++ ++ buflen -= mblength; ++ bufpos += mblength; ++ } ++} ++#endif ++ + /* Read from stream STREAM, printing to standard output any selected fields. */ + + static void +@@ -689,13 +841,190 @@ + } + } + ++#if HAVE_MBRTOWC ++static void ++cut_fields_mb (FILE *stream) ++{ ++ int c; ++ size_t field_idx = 1; ++ bool found_any_selected_field = false; ++ bool buffer_first_field; ++ int empty_input; ++ 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. */ ++ 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 of the stream. */ ++ int convfail; /* 1, when conversion is failed. Otherwise 0. */ ++ ++ bufpos = buf; ++ buflen = 0; ++ memset (&state, '\0', sizeof (mbstate_t)); ++ ++ c = getc (stream); ++ empty_input = (c == EOF); ++ if (c != EOF) ++ ungetc (c, stream); ++ else ++ wc = WEOF; ++ ++ /* To support the semantics of the -s flag, we may have to buffer ++ all of the first field to determine whether it is `delimited.' ++ But that is unnecessary if all non-delimited lines must be printed ++ 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)); ++ ++ while (1) ++ { ++ if (field_idx == 1 && buffer_first_field) ++ { ++ size_t n_bytes = 0; ++ ++ while (1) ++ { ++ REFILL_BUFFER (buf, bufpos, buflen, stream); ++ ++ GET_NEXT_WC_FROM_BUFFER ++ (wc, bufpos, buflen, mblength, state, convfail); ++ ++ if (wc == WEOF) ++ break; ++ ++ field_1_buffer = xrealloc (field_1_buffer, n_bytes + mblength); ++ memcpy (field_1_buffer + n_bytes, bufpos, mblength); ++ n_bytes += mblength; ++ buflen -= mblength; ++ bufpos += mblength; ++ ++ if (!convfail && (wc == L'\n' || wc == wcdelim)) ++ break; ++ } ++ ++ if (wc == WEOF) ++ break; ++ ++ /* If the first field extends to the end of line (it is not ++ delimited) and we are printing all non-delimited lines, ++ print this one. */ ++ if (convfail || (!convfail && wc != wcdelim)) ++ { ++ if (suppress_non_delimited) ++ { ++ /* Empty. */ ++ } ++ else ++ { ++ fwrite (field_1_buffer, sizeof (char), n_bytes, stdout); ++ /* Make sure the output line is newline terminated. */ ++ if (convfail || (!convfail && wc != L'\n')) ++ putchar ('\n'); ++ } ++ continue; ++ } ++ ++ if (print_kth (1, NULL)) ++ { ++ /* Print the field, but not the trailing delimiter. */ ++ fwrite (field_1_buffer, sizeof (char), n_bytes - 1, stdout); ++ found_any_selected_field = true; ++ } ++ ++field_idx; ++ } ++ ++ if (wc != WEOF) ++ { ++ if (print_kth (field_idx, NULL)) ++ { ++ if (found_any_selected_field) ++ { ++ fwrite (output_delimiter_string, sizeof (char), ++ output_delimiter_length, stdout); ++ } ++ found_any_selected_field = true; ++ } ++ ++ while (1) ++ { ++ REFILL_BUFFER (buf, bufpos, buflen, stream); ++ ++ GET_NEXT_WC_FROM_BUFFER ++ (wc, bufpos, buflen, mblength, state, convfail); ++ ++ if (wc == WEOF) ++ break; ++ else if (!convfail && (wc == wcdelim || wc == L'\n')) ++ { ++ buflen -= mblength; ++ bufpos += mblength; ++ break; ++ } ++ ++ if (print_kth (field_idx, NULL)) ++ fwrite (bufpos, mblength, sizeof (char), stdout); ++ ++ buflen -= mblength; ++ bufpos += mblength; ++ } ++ } ++ ++ if ((!convfail || wc == L'\n') && buflen < 1) ++ wc = WEOF; ++ ++ if (!convfail && wc == wcdelim) ++ ++field_idx; ++ else if (wc == WEOF || (!convfail && wc == L'\n')) ++ { ++ if (found_any_selected_field ++ || (!empty_input && !(suppress_non_delimited && field_idx == 1))) ++ putchar ('\n'); ++ if (wc == WEOF) ++ break; ++ field_idx = 1; ++ found_any_selected_field = false; ++ } ++ } ++} ++#endif ++ + static void + cut_stream (FILE *stream) + { +- if (operating_mode == byte_mode) +- cut_bytes (stream); ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1 && !force_singlebyte_mode) ++ { ++ switch (operating_mode) ++ { ++ case byte_mode: ++ if (byte_mode_character_aware) ++ cut_characters_or_cut_bytes_no_split (stream); ++ else ++ cut_bytes (stream); ++ break; ++ ++ case character_mode: ++ cut_characters_or_cut_bytes_no_split (stream); ++ break; ++ ++ case field_mode: ++ cut_fields_mb (stream); ++ break; ++ ++ default: ++ abort (); ++ } ++ } + else +- cut_fields (stream); ++#endif ++ { ++ if (operating_mode == field_mode) ++ cut_fields (stream); ++ else ++ cut_bytes (stream); ++ } + } + + /* Process file FILE to standard output. +@@ -745,6 +1074,8 @@ + bool ok; + bool delim_specified = false; + char *spec_list_string IF_LINT(= NULL); ++ char mbdelim[MB_LEN_MAX + 1]; ++ size_t delimlen = 0; + + initialize_main (&argc, &argv); + program_name = argv[0]; +@@ -767,7 +1098,6 @@ + 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")); +@@ -775,6 +1105,14 @@ + spec_list_string = optarg; + break; + ++ case 'c': ++ /* Build the character list. */ ++ if (operating_mode != undefined_mode) ++ FATAL_ERROR (_("only one type of list may be specified")); ++ operating_mode = character_mode; ++ spec_list_string = optarg; ++ break; ++ + case 'f': + /* Build the field list. */ + if (operating_mode != undefined_mode) +@@ -786,9 +1124,32 @@ + case 'd': + /* New delimiter. */ + /* Interpret -d '' to mean `use the NUL byte as the delimiter.' */ +- if (optarg[0] != '\0' && optarg[1] != '\0') +- FATAL_ERROR (_("the delimiter must be a single character")); +- delim = optarg[0]; ++#if HAVE_MBRTOWC ++ if(MB_CUR_MAX > 1) ++ { ++ mbstate_t state; ++ ++ memset (&state, '\0', sizeof(mbstate_t)); ++ delimlen = mbrtowc (&wcdelim, optarg, MB_LEN_MAX, &state); ++ ++ if (delimlen == (size_t)-1 || delimlen == (size_t)-2) ++ force_singlebyte_mode = true; ++ else ++ { ++ delimlen = (delimlen < 1) ? 1 : delimlen; ++ if (wcdelim != L'\0' && *(optarg + delimlen) != '\0') ++ FATAL_ERROR (_("the delimiter must be a single character")); ++ memcpy (mbdelim, optarg, delimlen); ++ } ++ } ++ ++ if (MB_CUR_MAX <= 1 || force_singlebyte_mode) ++#endif ++ { ++ if (optarg[0] != '\0' && optarg[1] != '\0') ++ FATAL_ERROR (_("the delimiter must be a single character")); ++ delim = (unsigned char) optarg[0]; ++ } + delim_specified = true; + break; + +@@ -802,6 +1163,7 @@ + break; + + case 'n': ++ byte_mode_character_aware = true; + break; + + case 's': +@@ -824,7 +1186,7 @@ + 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 (delim_specified && operating_mode != field_mode) + FATAL_ERROR (_("an input delimiter may be specified only\ + when operating on fields")); + +@@ -851,15 +1213,34 @@ + } + + if (!delim_specified) +- delim = '\t'; ++ { ++ delim = '\t'; ++#ifdef HAVE_MBRTOWC ++ wcdelim = L'\t'; ++ mbdelim[0] = '\t'; ++ mbdelim[1] = '\0'; ++ delimlen = 1; ++ } ++#endif + + if (output_delimiter_string == NULL) + { +- static char dummy[2]; +- dummy[0] = delim; +- dummy[1] = '\0'; +- output_delimiter_string = dummy; +- output_delimiter_length = 1; ++#ifdef HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1 && !force_singlebyte_mode) ++ { ++ output_delimiter_string = xstrdup (mbdelim); ++ output_delimiter_length = delimlen; ++ } ++ ++ if (MB_CUR_MAX <= 1 || force_singlebyte_mode) ++#endif ++ { ++ static char dummy[2]; ++ dummy[0] = delim; ++ dummy[1] = '\0'; ++ output_delimiter_string = dummy; ++ output_delimiter_length = 1; ++ } + } + + if (optind == argc) +--- coreutils-6.5/src/expand.c ++++ coreutils-6.5/src/expand.c +@@ -38,11 +38,31 @@ + #include + #include + #include ++ ++/* Get mbstate_t, mbrtowc, wcwidth. */ ++#if HAVE_WCHAR_H ++# include ++#endif ++#if HAVE_WCTYPE_H ++# include ++#endif ++ + #include "system.h" + #include "error.h" + #include "quote.h" + #include "xstrndup.h" + ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC ++ installation; work around this configuration error. */ ++#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" + +@@ -347,9 +367,12 @@ + } + else + { +- column++; +- if (!column) +- error (EXIT_FAILURE, 0, _("input line is too long")); ++ if (!iscntrl (c)) ++ { ++ column++; ++ if (!column) ++ error (EXIT_FAILURE, 0, _("input line is too long")); ++ } + } + + convert &= convert_entire_line | !! isblank (c); +@@ -365,6 +388,165 @@ + } + } + ++#if HAVE_MBRTOWC && HAVE_WCTYPE_H ++static void ++expand_multibyte (void) ++{ ++ /* Input stream. */ ++ FILE *fp = next_file (NULL); ++ ++ mbstate_t i_state; /* Current shift state of the input stream. */ ++ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */ ++ char *bufpos; /* Next read position of BUF. */ ++ size_t buflen = 0; /* The length of the byte sequence in buf. */ ++ ++ if (!fp) ++ return; ++ ++ memset (&i_state, '\0', sizeof (mbstate_t)); ++ ++ for (;;) ++ { ++ /* Input character, or EOF. */ ++ wint_t wc; ++ ++ /* If true, perform translations. */ ++ bool convert = true; ++ ++ ++ /* The following variables have valid values only when CONVERT ++ is true: */ ++ ++ /* Column of next input character. */ ++ uintmax_t column = 0; ++ ++ /* Index in TAB_LIST of next tab stop to examine. */ ++ size_t tab_index = 0; ++ ++ ++ /* Convert a line of text. */ ++ ++ do ++ { ++ wchar_t w; ++ size_t mblength; /* The byte size of a multibyte character ++ which shows as same character as WC. */ ++ mbstate_t i_state_bak; /* Back up the I_STATE. */ ++ ++ /* Fill buffer */ ++ if (buflen < MB_LEN_MAX) ++ { ++ if (!feof(fp) && !ferror(fp)) ++ { ++ if (buflen > 0) ++ memmove (buf, bufpos, buflen); ++ buflen += fread (buf + buflen, sizeof (char), BUFSIZ, fp); ++ bufpos = buf; ++ } ++ } ++ ++ if (buflen < 1) ++ { ++ /* Move to the next file */ ++ if (feof (fp) || ferror (fp)) ++ fp = next_file(fp); ++ if (!fp) ++ return; ++ memset (&i_state, '\0', sizeof (mbstate_t)); ++ continue; ++ } ++ ++ i_state_bak = i_state; ++ mblength = mbrtowc (&w, bufpos, buflen, &i_state); ++ wc = w; ++ ++ if (mblength == (size_t) -1 || mblength == (size_t) -2) ++ { ++ i_state = i_state_bak; ++ wc = L'\0'; ++ column += convert; ++ mblength = 1; ++ } ++ ++ if (convert) ++ { ++ if (wc == L'\t') ++ { ++ /* Column the next input tab stop is on. */ ++ uintmax_t next_tab_column; ++ ++ if (tab_size) ++ next_tab_column = column + (tab_size - column % tab_size); ++ else ++ for (;;) ++ if (tab_index == first_free_tab) ++ { ++ next_tab_column = column + 1; ++ break; ++ } ++ else ++ { ++ uintmax_t tab = tab_list[tab_index++]; ++ if (column < tab) ++ { ++ next_tab_column = tab; ++ break; ++ } ++ } ++ ++ if (next_tab_column < column) ++ error (EXIT_FAILURE, 0, _("input line is too long")); ++ ++ while (++column < next_tab_column) ++ if (putchar (' ') < 0) ++ error (EXIT_FAILURE, errno, _("write error")); ++ ++ *bufpos = ' '; ++ } ++ else if (wc == L'\b') ++ { ++ /* Go back one column, and force recalculation of the ++ next tab stop. */ ++ column -= !!column; ++ tab_index -= !!tab_index; ++ } ++ else ++ { ++ if (!iswcntrl (wc)) ++ { ++ int width = wcwidth (wc); ++ if (width > 0) ++ { ++ if (column > (column + width)) ++ error (EXIT_FAILURE, 0, _("input line is too long")); ++ column += width; ++ } ++ } ++ } ++ ++ convert &= convert_entire_line | iswblank (wc); ++ } ++ ++ if (mblength) ++ { ++ if (fwrite (bufpos, sizeof (char), mblength, stdout) < mblength) ++ error (EXIT_FAILURE, errno, _("write error")); ++ } ++ else ++ { ++ if (putchar ('\0')) ++ error (EXIT_FAILURE, errno, _("write error")); ++ mblength = 1; ++ } ++ ++ buflen -= mblength; ++ bufpos += mblength; ++ } ++ while (wc != L'\n'); ++ } ++} ++#endif ++ + int + main (int argc, char **argv) + { +@@ -429,7 +611,12 @@ + + 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, "-"); +--- coreutils-6.5/src/fold.c ++++ coreutils-6.5/src/fold.c +@@ -23,6 +23,19 @@ + #include + #include + ++/* Get MB_CUR_MAX. */ ++#include ++ ++/* Get mbrtowc, mbstate_t, wcwidth(). */ ++#if HAVE_WCHAR_H ++# include ++#endif ++ ++/* Get iswprint(), iswctype(), wctype(). */ ++#if HAVE_WCTYPE_H ++# include ++#endif ++ + #include "system.h" + #include "error.h" + #include "quote.h" +@@ -30,14 +43,57 @@ + + #define TAB_WIDTH 8 + ++/* 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 ++ ++#ifndef HAVE_DECL_WCWIDTH ++"this configure-time declaration test was not run" ++#endif ++#if !HAVE_DECL_WCWIDTH ++extern int wcwidth (); ++#endif ++ ++/* If wcwidth() doesn't exist, assume all printable characters have ++ width 1. */ ++#if !defined wcwidth && !HAVE_WCWIDTH ++# define wcwidth(wc) ((wc) == 0 ? 0 : iswprint (wc) ? 1 : -1) ++#endif ++ + /* The official name of this program (e.g., no `g' prefix). */ + #define PROGRAM_NAME "fold" + + #define AUTHORS "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 name this program was run with. */ + char *program_name; + ++/* 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; + +@@ -47,11 +103,17 @@ + /* 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::"; ++ ++/* wide character class `blank' */ ++#if HAVE_MBRTOWC ++wctype_t blank_type; ++#endif + + 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}, +@@ -81,6 +143,7 @@ + "), 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); +@@ -98,7 +161,7 @@ + static size_t + adjust_column (size_t column, char c) + { +- if (!count_bytes) ++ if (operating_mode != byte_mode) + { + if (c == '\b') + { +@@ -117,14 +180,9 @@ + return column; + } + +-/* Fold file FILENAME, or standard input if FILENAME is "-", +- to stdout, with maximum line length WIDTH. +- Return true if successful. */ +- +-static bool +-fold_file (char const *filename, size_t width) ++static int ++fold_text (FILE *istream, size_t width) + { +- 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. */ +@@ -132,20 +190,6 @@ + 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; +- } +- + while ((c = getc (istream)) != EOF) + { + if (offset_out + 1 >= allocated_out) +@@ -223,6 +267,234 @@ + if (offset_out) + fwrite (line_out, sizeof (char), (size_t) offset_out, stdout); + ++ return saved_errno; ++} ++ ++#if HAVE_MBRTOWC ++static void ++fold_multibyte_text (FILE *istream, size_t width) ++{ ++ int i; ++ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */ ++ size_t buflen; /* The length of the byte sequence in buf. */ ++ char *bufpos; /* Next read position of BUF. */ ++ wint_t wc; /* A gotten wide character. */ ++ wchar_t tmp; ++ 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; /* 1, when conversion is failed. Otherwise 0. */ ++ ++ char *line_out = NULL; ++ size_t offset_out = 0; /* Index in `line_out' for next char. */ ++ size_t allocated_out = 1024; ++ ++ int increment; ++ size_t column = 0; ++ ++ size_t last_blank_pos; ++ size_t last_blank_column; ++ int is_blank_seen; ++ int last_blank_increment; ++ 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)); ++ line_out = xmalloc (allocated_out); ++ ++ buflen = fread (buf, sizeof (char), BUFSIZ, istream); ++ bufpos = buf; ++ ++ 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. */ ++ convfail = 0; ++ state_bak = state; ++ mblength = mbrtowc (&tmp, bufpos, buflen, &state); ++ wc = tmp; ++ ++ switch (mblength) ++ { ++ case (size_t)-1: ++ case (size_t)-2: ++ convfail++; ++ state = state_bak; ++ /* Fall through. */ ++ ++ case 0: ++ mblength = 1; ++ break; ++ } ++ ++ if (!convfail && wc == L'\n') ++ { ++ if (offset_out > 0) ++ { ++ fwrite (line_out, sizeof (char), offset_out, stdout); ++ START_NEW_LINE; ++ } ++ continue; ++ } ++ ++ 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'\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 = x2nrealloc (line_out, &allocated_out, sizeof *line_out); ++ ++ for (i = 0; i < mblength; i++) ++ { ++ line_out[offset_out] = bufpos[i]; ++ ++offset_out; ++ } ++ ++ 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 && iswctype (wc, blank_type)) ++ { ++ 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; ++ } ++ } ++ ++ if (offset_out) ++ fwrite (line_out, sizeof (char), (size_t) offset_out, stdout); ++ ++ free(line_out); ++} ++#endif ++ ++/* Fold file FILENAME, or standard input if FILENAME is "-", ++ to stdout, with maximum line length WIDTH. ++ Return true if successful. */ ++ ++static bool ++fold_file (char const *filename, size_t width) ++{ ++ FILE *istream; ++ 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; ++ } ++ ++ /* Define how ISTREAM is being folded. */ ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ fold_multibyte_text (istream, width); ++ else ++#endif ++ saved_errno = fold_text (istream, width); ++ + if (ferror (istream)) + { + error (0, saved_errno, "%s", filename); +@@ -255,6 +527,10 @@ + + atexit (close_stdout); + ++#if HAVE_MBRTOWC ++ blank_type = wctype ("blank"); ++#endif ++ operating_mode = column_mode; + break_spaces = count_bytes = have_read_stdin = false; + + while ((optc = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1) +@@ -264,7 +540,15 @@ + 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': /* Count characters rather than columns. */ ++ 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. */ +--- coreutils-6.5/src/join.c ++++ coreutils-6.5/src/join.c +@@ -23,6 +23,16 @@ + #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 "hard-locale.h" +@@ -33,6 +43,11 @@ + #include "xmemcoll.h" + #include "xstrtol.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" + +@@ -104,10 +119,13 @@ + /* 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 ++/* Tab character separating fields. If NULL, 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; ++static const char *tab = NULL; ++ ++/* The number of bytes used for tab. */ ++static size_t tablen = 0; + + static struct option const longopts[] = + { +@@ -199,10 +217,10 @@ + if (ptr == lim) + return; + +- if (0 <= tab) ++ if (tab != NULL) + { + char *sep; +- for (; (sep = memchr (ptr, tab, lim - ptr)) != NULL; ptr = sep + 1) ++ for (; (sep = memchr (ptr, tab[0], lim - ptr)) != NULL; ptr = sep + 1) + extract_field (line, ptr, sep - ptr); + } + else +@@ -229,6 +247,133 @@ + extract_field (line, ptr, lim - ptr); + } + ++#if HAVE_MBRTOWC ++static void ++xfields_multibyte (struct line *line) ++{ ++ int i; ++ char *ptr0 = line->buf.buffer; ++ char *ptr; ++ char *lim; ++ wchar_t wc = 0; ++ size_t mblength; ++ mbstate_t state, state_bak; ++ ++ memset (&state, 0, sizeof (mbstate_t)); ++ ++ ptr = ptr0; ++ lim = ptr0 + line->buf.length - 1; ++ ++ if (tab == NULL) ++ { ++ /* 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; ++ } ++ } ++ ++ for (i = 0; ptr < lim; ++i) ++ { ++ if (tab != NULL) ++ { ++ char *beg = ptr; ++ 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; ++ } ++ mblength = (mblength < 1) ? 1 : mblength; ++ ++ if (mblength == tablen && !memcmp (ptr, tab, mblength)) ++ break; ++ else ++ { ++ ptr += mblength; ++ continue; ++ } ++ } ++ ++ extract_field (line, beg, ptr - beg); ++ if (ptr < lim) ++ ptr += mblength; ++ } ++ else ++ { ++ char *beg = ptr; ++ 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; ++ } ++ mblength = (mblength < 1) ? 1 : mblength; ++ ++ if (iswblank (wc)) ++ break; ++ else ++ { ++ ptr += mblength; ++ continue; ++ } ++ } ++ ++ extract_field (line, beg, ptr - beg); ++ if (ptr < lim) ++ ptr += mblength; ++ } ++ } ++ ++ if (ptr != ptr0) ++ { ++ mblength = mbrtowc (&wc, ptr - mblength, mblength, &state); ++ wc = (mbsinit (&state) && *(ptr - mblength) == '\0') ? L'\0' : wc; ++ if (tab != NULL) ++ { ++ if (mblength == (size_t) -1 || mblength == (size_t) -2) ++ mblength = 1; ++ ++ if (mblength == tablen && !memcmp (ptr - mblength, tab, mblength)) ++ /* Add one more (empty) field because the last character of ++ the line was a delimiter. */ ++ extract_field (line, NULL, 0); ++ } ++ else ++ { ++ if (mblength != (size_t) -1 && mblength != (size_t) -2) ++ { ++ if (iswblank (wc)) ++ /* Add one more (empty) field because the last character of ++ the line was a delimiter. */ ++ extract_field (line, NULL, 0); ++ } ++ } ++ } ++} ++#endif ++ + /* Read a line from FP into LINE and split it into fields. + Return true if successful. */ + +@@ -249,7 +394,13 @@ + line->nfields_allocated = 0; + line->nfields = 0; + line->fields = NULL; +- xfields (line); ++ ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ xfields_multibyte (line); ++ else ++#endif ++ xfields (line); + return true; + } + +@@ -303,56 +454,115 @@ + keycmp (struct line const *line1, struct line const *line2) + { + /* Start of field to compare in each file. */ +- char *beg1; +- char *beg2; +- +- size_t len1; +- size_t len2; /* Length of fields to compare. */ ++ char *beg[2]; ++ char *copy[2]; ++ size_t len[2]; /* Length of fields to compare. */ + int diff; ++ int i, j; + + if (join_field_1 < line1->nfields) + { +- beg1 = line1->fields[join_field_1].beg; +- len1 = line1->fields[join_field_1].len; ++ beg[0] = line1->fields[join_field_1].beg; ++ len[0] = line1->fields[join_field_1].len; + } + else + { +- beg1 = NULL; +- len1 = 0; ++ beg[0] = NULL; ++ len[0] = 0; + } + + if (join_field_2 < line2->nfields) + { +- beg2 = line2->fields[join_field_2].beg; +- len2 = line2->fields[join_field_2].len; ++ beg[1] = line2->fields[join_field_2].beg; ++ len[1] = line2->fields[join_field_2].len; + } + else + { +- beg2 = NULL; +- len2 = 0; ++ beg[1] = NULL; ++ len[1] = 0; + } + +- if (len1 == 0) +- return len2 == 0 ? 0 : -1; +- if (len2 == 0) ++ if (len[0] == 0) ++ return len[1] == 0 ? 0 : -1; ++ if (len[1] == 0) + return 1; + + if (ignore_case) + { +- /* FIXME: ignore_case does not work with NLS (in particular, +- with multibyte chars). */ +- diff = memcasecmp (beg1, beg2, MIN (len1, len2)); ++#ifdef HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ { ++ size_t mblength; ++ wchar_t wc, uwc; ++ mbstate_t state, state_bak; ++ ++ memset (&state, '\0', sizeof (mbstate_t)); ++ ++ for (i = 0; i < 2; i++) ++ { ++ copy[i] = alloca (len[i] + 1); ++ ++ for (j = 0; j < MIN (len[0], len[1]);) ++ { ++ state_bak = state; ++ mblength = mbrtowc (&wc, beg[i] + j, len[i] - j, &state); ++ ++ switch (mblength) ++ { ++ case (size_t) -1: ++ case (size_t) -2: ++ state = state_bak; ++ /* Fall through */ ++ case 0: ++ mblength = 1; ++ break; ++ ++ default: ++ uwc = towupper (wc); ++ ++ if (uwc != wc) ++ { ++ mbstate_t state_wc; ++ ++ memset (&state_wc, '\0', sizeof (mbstate_t)); ++ wcrtomb (copy[i] + j, uwc, &state_wc); ++ } ++ else ++ memcpy (copy[i] + j, beg[i] + j, mblength); ++ } ++ j += mblength; ++ } ++ copy[i][j] = '\0'; ++ } ++ return xmemcoll (copy[0], len[0], copy[1], len[1]); ++ } ++#endif ++ if (hard_LC_COLLATE) ++ { ++ for (i = 0; i < 2; i++) ++ { ++ copy[i] = alloca (len[i] + 1); ++ ++ for (j = 0; j < MIN (len[0], len[1]); j++) ++ copy[i][j] = toupper (beg[i][j]); ++ ++ copy[i][j] = '\0'; ++ } ++ return xmemcoll (copy[0], len[0], copy[1], len[1]); ++ } ++ else ++ diff = memcasecmp (beg[0], beg[1], MIN (len[0], len[1])); + } + else + { + if (hard_LC_COLLATE) +- return xmemcoll (beg1, len1, beg2, len2); +- diff = memcmp (beg1, beg2, MIN (len1, len2)); ++ return xmemcoll (beg[0], len[0], beg[1], len[1]); ++ diff = memcmp (beg[0], beg[1], MIN (len[0], len[1])); + } + + if (diff) + return diff; +- return len1 < len2 ? -1 : len1 != len2; ++ return len[0] < len[1] ? -1 : len[0] != len[1]; + } + + /* Print field N of LINE if it exists and is nonempty, otherwise +@@ -381,7 +591,8 @@ + prjoin (struct line const *line1, struct line const *line2) + { + const struct outlist *outlist; +- char output_separator = tab < 0 ? ' ' : tab; ++ const char *output_separator = tab == NULL ? " " : tab; ++ size_t output_separator_len = tab == NULL ? 1 : tablen; + + outlist = outlist_head.next; + if (outlist) +@@ -416,7 +627,7 @@ + o = o->next; + if (o == NULL) + break; +- putchar (output_separator); ++ fwrite (output_separator, 1, output_separator_len, stdout); + } + putchar ('\n'); + } +@@ -434,23 +645,23 @@ + prfield (join_field_1, line1); + for (i = 0; i < join_field_1 && i < line1->nfields; ++i) + { +- putchar (output_separator); ++ fwrite (output_separator, 1, output_separator_len, stdout); + prfield (i, line1); + } + for (i = join_field_1 + 1; i < line1->nfields; ++i) + { +- putchar (output_separator); ++ fwrite (output_separator, 1, output_separator_len, stdout); + prfield (i, line1); + } + + for (i = 0; i < join_field_2 && i < line2->nfields; ++i) + { +- putchar (output_separator); ++ fwrite (output_separator, 1, output_separator_len, stdout); + prfield (i, line2); + } + for (i = join_field_2 + 1; i < line2->nfields; ++i) + { +- putchar (output_separator); ++ fwrite (output_separator, 1, output_separator_len, stdout); + prfield (i, line2); + } + putchar ('\n'); +@@ -862,20 +1073,40 @@ + + case 't': + { +- unsigned char newtab = optarg[0]; +- if (! newtab) ++ const char *newtab = optarg; ++ size_t newtablen; ++ if (! newtab[0]) + error (EXIT_FAILURE, 0, _("empty tab")); +- if (optarg[1]) ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ { ++ mbstate_t state; ++ ++ memset (&state, 0, sizeof (mbstate_t)); ++ newtablen = mbrtowc (NULL, newtab, strlen (newtab), &state); ++ if (newtablen == (size_t) 0 ++ || newtablen == (size_t) -1 || newtablen == (size_t) -2) ++ newtablen = 1; ++ } ++ else ++#endif ++ newtablen = 1; ++ if (optarg[newtablen]) + { + if (STREQ (optarg, "\\0")) +- newtab = '\0'; ++ { ++ newtab = "\0"; ++ newtablen = 1; ++ } + else + error (EXIT_FAILURE, 0, _("multi-character tab %s"), + quote (optarg)); + } +- if (0 <= tab && tab != newtab) ++ if (tab != NULL ++ && (tablen != newtablen || memcmp (tab, newtab, tablen) != 0)) + error (EXIT_FAILURE, 0, _("incompatible tabs")); + tab = newtab; ++ tablen = newtablen; + } + break; + +--- coreutils-6.5/src/pr.c ++++ coreutils-6.5/src/pr.c +@@ -313,6 +313,32 @@ + + #include + #include ++ ++/* Get MB_LEN_MAX. */ ++#include ++/* 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 == 1 ++# define MB_LEN_MAX 16 ++#endif ++ ++/* Get MB_CUR_MAX. */ ++#include ++ ++/* Solaris 2.5 has a bug: must be included before . */ ++/* Get mbstate_t, mbrtowc(), wcwidth(). */ ++#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 "hard-locale.h" +@@ -324,6 +350,18 @@ + #include "strftime.h" + #include "xstrtol.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 ++ ++#ifndef HAVE_DECL_WCWIDTH ++"this configure-time declaration test was not run" ++#endif ++#if !HAVE_DECL_WCWIDTH ++extern int wcwidth (); ++#endif ++ + /* The official name of this program (e.g., no `g' prefix). */ + #define PROGRAM_NAME "pr" + +@@ -415,8 +453,21 @@ + typedef struct COLUMN COLUMN; + + #define NULLCOL (COLUMN *)0 ++ ++/* Funtion pointers to switch functions for single byte locale or for ++ multibyte locale. If multibyte functions do not exist in your sysytem, ++ these pointers always point the function for single byte locale. */ ++static void (*print_char) (char c); ++static int (*char_to_clump) (char c); ++ ++/* Functions for single byte locale. */ ++static void print_char_single (char c); ++static int char_to_clump_single (char c); ++ ++/* Functions for multibyte locale. */ ++static void print_char_multi (char c); ++static int char_to_clump_multi (char c); + +-static int char_to_clump (char c); + static bool read_line (COLUMN *p); + static bool print_page (void); + static bool print_stored (COLUMN *p); +@@ -426,6 +477,7 @@ + static void pad_across_to (int position); + static void add_line_number (COLUMN *p); + static void getoptarg (char *arg, char switch_char, char *character, ++ int *character_length, int *character_width, + int *number); + void usage (int status); + static void print_files (int number_of_files, char **av); +@@ -440,7 +492,6 @@ + static void pad_down (int lines); + static void read_rest_of_line (COLUMN *p); + static void skip_read (COLUMN *p, int column_number); +-static void print_char (char c); + static void cleanup (void); + static void print_sep_string (void); + static void separator_string (const char *optarg_S); +@@ -455,7 +506,7 @@ + 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]. */ +-static char *buff; ++static unsigned char *buff; + + /* Index of the position in buff where the next character + will be stored. */ +@@ -559,7 +610,7 @@ + static bool untabify_input = false; + + /* (-e) The input tab character. */ +-static char input_tab_char = '\t'; ++static char input_tab_char[MB_LEN_MAX] = "\t"; + + /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ... + where the leftmost column is 1. */ +@@ -569,7 +620,10 @@ + static bool tabify_output = false; + + /* (-i) The output tab character. */ +-static char output_tab_char = '\t'; ++static char output_tab_char[MB_LEN_MAX] = "\t"; ++ ++/* (-i) The byte length of output tab character. */ ++static int output_tab_char_length = 1; + + /* (-i) The width of the output tab. */ + static int chars_per_output_tab = 8; +@@ -643,7 +697,13 @@ + static bool numbered_lines = false; + + /* (-n) Character which follows each line number. */ +-static char number_separator = '\t'; ++static char number_separator[MB_LEN_MAX] = "\t"; ++ ++/* (-n) The byte length of the character which follows each line number. */ ++static int number_separator_length = 1; ++ ++/* (-n) The character width of the character which follows each line number. */ ++static int number_separator_width = 0; + + /* (-n) line counting starts with 1st line of input file (not with 1st + line of 1st page printed). */ +@@ -696,6 +756,7 @@ + -a|COLUMN|-m is a `space' and with the -J option a `tab'. */ + static char *col_sep_string = ""; + static int col_sep_length = 0; ++static int col_sep_width = 0; + static char *column_separator = " "; + static char *line_separator = "\t"; + +@@ -852,6 +913,13 @@ + col_sep_length = (int) strlen (optarg_S); + col_sep_string = xmalloc (col_sep_length + 1); + strcpy (col_sep_string, optarg_S); ++ ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ col_sep_width = mbswidth (col_sep_string, 0); ++ else ++#endif ++ col_sep_width = col_sep_length; + } + + int +@@ -877,6 +945,21 @@ + + atexit (close_stdout); + ++/* Define which functions are used, the ones for single byte locale or the ones ++ for multibyte locale. */ ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ { ++ print_char = print_char_multi; ++ char_to_clump = char_to_clump_multi; ++ } ++ else ++#endif ++ { ++ print_char = print_char_single; ++ char_to_clump = char_to_clump_single; ++ } ++ + n_files = 0; + file_names = (argc > 1 + ? xmalloc ((argc - 1) * sizeof (char *)) +@@ -949,8 +1032,12 @@ + break; + case 'e': + if (optarg) +- getoptarg (optarg, 'e', &input_tab_char, +- &chars_per_input_tab); ++ { ++ int dummy_length, dummy_width; ++ ++ getoptarg (optarg, 'e', input_tab_char, &dummy_length, ++ &dummy_width, &chars_per_input_tab); ++ } + /* Could check tab width > 0. */ + untabify_input = true; + break; +@@ -963,8 +1050,12 @@ + break; + case 'i': + if (optarg) +- getoptarg (optarg, 'i', &output_tab_char, +- &chars_per_output_tab); ++ { ++ int dummy_width; ++ ++ getoptarg (optarg, 'i', output_tab_char, &output_tab_char_length, ++ &dummy_width, &chars_per_output_tab); ++ } + /* Could check tab width > 0. */ + tabify_output = true; + break; +@@ -991,8 +1082,8 @@ + case 'n': + numbered_lines = true; + if (optarg) +- getoptarg (optarg, 'n', &number_separator, +- &chars_per_number); ++ getoptarg (optarg, 'n', number_separator, &number_separator_length, ++ &number_separator_width, &chars_per_number); + break; + case 'N': + skip_count = false; +@@ -1031,7 +1122,7 @@ + old_s = false; + /* Reset an additional input of -s, -S dominates -s */ + col_sep_string = ""; +- col_sep_length = 0; ++ col_sep_length = col_sep_width = 0; + use_col_separator = true; + if (optarg) + separator_string (optarg); +@@ -1188,10 +1279,45 @@ + a number. */ + + static void +-getoptarg (char *arg, char switch_char, char *character, int *number) ++getoptarg (char *arg, char switch_char, char *character, int *character_length, ++ int *character_width, int *number) + { + if (!ISDIGIT (*arg)) +- *character = *arg++; ++ { ++#ifdef HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) /* for multibyte locale. */ ++ { ++ wchar_t wc; ++ size_t mblength; ++ int width; ++ mbstate_t state = {'\0'}; ++ ++ mblength = mbrtowc (&wc, arg, strlen (arg), &state); ++ ++ if (mblength == (size_t) -1 || mblength == (size_t) -2) ++ { ++ *character_length = 1; ++ *character_width = 1; ++ } ++ else ++ { ++ *character_length = (mblength < 1) ? 1 : mblength; ++ width = wcwidth (wc); ++ *character_width = (width < 0) ? 0 : width; ++ } ++ ++ strncpy (character, arg, *character_length); ++ arg += *character_length; ++ } ++ else /* for single byte locale. */ ++#endif ++ { ++ *character = *arg++; ++ *character_length = 1; ++ *character_width = 1; ++ } ++ } ++ + if (*arg) + { + long int tmp_long; +@@ -1256,7 +1382,7 @@ + else + col_sep_string = column_separator; + +- col_sep_length = 1; ++ col_sep_length = col_sep_width = 1; + use_col_separator = true; + } + /* It's rather pointless to define a TAB separator with column +@@ -1288,11 +1414,11 @@ + TAB_WIDTH (chars_per_input_tab, chars_per_number); */ + + /* Estimate chars_per_text without any margin and keep it constant. */ +- if (number_separator == '\t') ++ if (number_separator[0] == '\t') + number_width = chars_per_number + + TAB_WIDTH (chars_per_default_tab, chars_per_number); + else +- number_width = chars_per_number + 1; ++ number_width = chars_per_number + number_separator_width; + + /* The number is part of the column width unless we are + printing files in parallel. */ +@@ -1307,7 +1433,7 @@ + } + + 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")); +@@ -1432,7 +1558,7 @@ + + /* Enlarge p->start_position of first column to use the same form of + padding_not_printed with all columns. */ +- h = h + col_sep_length; ++ h = h + col_sep_width; + + /* This loop takes care of all but the rightmost column. */ + +@@ -1466,7 +1592,7 @@ + } + else + { +- h = h_next + col_sep_length; ++ h = h_next + col_sep_width; + h_next = h + chars_per_column; + } + } +@@ -1756,9 +1882,9 @@ + 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) + { +- pad_across_to (padding_not_printed - col_sep_length); ++ pad_across_to (padding_not_printed - col_sep_width); + padding_not_printed = ANYWHERE; + } + +@@ -2029,13 +2155,13 @@ + /* May be too generous. */ + buff = X2REALLOC (buff, &buff_allocated); + } +- buff[buff_current++] = c; ++ buff[buff_current++] = (unsigned char) c; + } + + static void + add_line_number (COLUMN *p) + { +- int i; ++ int i, j; + char *s; + int left_cut; + +@@ -2058,22 +2184,24 @@ + /* 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. */ +- if (number_separator == '\t') ++ if (number_separator[0] == '\t') + { + i = number_width - chars_per_number; + while (i-- > 0) + (p->char_func) (' '); + } + else +- (p->char_func) (number_separator); ++ for (j = 0; j < number_separator_length; j++) ++ (p->char_func) (number_separator[j]); + } + else + /* To comply with POSIX, we avoid any expansion of default TAB + separator with a single column output. No column_width requirement + has to be considered. */ + { +- (p->char_func) (number_separator); +- if (number_separator == '\t') ++ for (j = 0; j < number_separator_length; j++) ++ (p->char_func) (number_separator[j]); ++ if (number_separator[0] == '\t') + output_position = POS_AFTER_TAB (chars_per_output_tab, + output_position); + } +@@ -2234,7 +2362,7 @@ + while (goal - h_old > 1 + && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal) + { +- putchar (output_tab_char); ++ fwrite (output_tab_char, 1, output_tab_char_length, stdout); + h_old = h_new; + } + while (++h_old <= goal) +@@ -2254,6 +2382,7 @@ + { + char *s; + int l = col_sep_length; ++ int not_space_flag; + + s = col_sep_string; + +@@ -2267,6 +2396,7 @@ + { + for (; separators_not_printed > 0; --separators_not_printed) + { ++ not_space_flag = 0; + while (l-- > 0) + { + /* 3 types of sep_strings: spaces only, spaces and chars, +@@ -2280,12 +2410,15 @@ + } + else + { ++ not_space_flag = 1; + if (spaces_not_printed > 0) + print_white_space (); + putchar (*s++); +- ++output_position; + } + } ++ if (not_space_flag) ++ output_position += col_sep_width; ++ + /* sep_string ends with some spaces */ + if (spaces_not_printed > 0) + print_white_space (); +@@ -2312,8 +2445,9 @@ + a nonspace is encountered, call print_white_space() to print the + required number of tabs and spaces. */ + ++ + static void +-print_char (char c) ++print_char_single (char c) + { + if (tabify_output) + { +@@ -2337,6 +2471,75 @@ + putchar (c); + } + ++#ifdef HAVE_MBRTOWC ++static void ++print_char_multi (char c) ++{ ++ static size_t mbc_pos = 0; ++ static unsigned char mbc[MB_LEN_MAX] = {'\0'}; ++ static mbstate_t state = {'\0'}; ++ mbstate_t state_bak; ++ wchar_t wc; ++ unsigned char uc = (unsigned char) c; ++ size_t mblength; ++ int width; ++ ++ if (tabify_output) ++ { ++ state_bak = state; ++ mbc[mbc_pos++] = uc; ++ mblength = mbrtowc (&wc, mbc, mbc_pos, &state); ++ ++ while (mbc_pos > 0) ++ { ++ switch (mblength) ++ { ++ case (size_t) -2: ++ state = state_bak; ++ return; ++ ++ case (size_t) -1: ++ state = state_bak; ++ ++output_position; ++ putchar (mbc[0]); ++ memmove (mbc, mbc + 1, MB_CUR_MAX - 1); ++ --mbc_pos; ++ break; ++ ++ case 0: ++ mblength = 1; ++ ++ default: ++ if (wc == L' ') ++ { ++ memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength); ++ --mbc_pos; ++ ++spaces_not_printed; ++ return; ++ } ++ else if (spaces_not_printed > 0) ++ print_white_space (); ++ ++ /* Nonprintables are assumed to have width 0, except L'\b'. */ ++ if ((width = wcwidth (wc)) < 1) ++ { ++ if (wc == L'\b') ++ --output_position; ++ } ++ else ++ output_position += width; ++ ++ fwrite (mbc, 1, mblength, stdout); ++ memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength); ++ mbc_pos -= mblength; ++ } ++ } ++ return; ++ } ++ putchar (uc); ++} ++#endif ++ + /* Skip to page PAGE before printing. + PAGE may be larger than total number of pages. */ + +@@ -2517,9 +2720,9 @@ + align_empty_cols = false; + } + +- if (padding_not_printed - col_sep_length > 0) ++ if (padding_not_printed - col_sep_width > 0) + { +- pad_across_to (padding_not_printed - col_sep_length); ++ pad_across_to (padding_not_printed - col_sep_width); + padding_not_printed = ANYWHERE; + } + +@@ -2620,9 +2823,9 @@ + } + } + +- if (padding_not_printed - col_sep_length > 0) ++ if (padding_not_printed - col_sep_width > 0) + { +- pad_across_to (padding_not_printed - col_sep_length); ++ pad_across_to (padding_not_printed - col_sep_width); + padding_not_printed = ANYWHERE; + } + +@@ -2635,8 +2838,8 @@ + if (spaces_not_printed == 0) + { + output_position = p->start_position + end_vector[line]; +- if (p->start_position - col_sep_length == chars_per_margin) +- output_position -= col_sep_length; ++ if (p->start_position - col_sep_width == chars_per_margin) ++ output_position -= col_sep_width; + } + + return true; +@@ -2654,8 +2857,9 @@ + characters in clump_buff. (e.g, the width of '\b' is -1, while the + number of characters is 1.) */ + ++ + static int +-char_to_clump (char c) ++char_to_clump_single (char c) + { + unsigned char uc = c; + char *s = clump_buff; +@@ -2665,10 +2869,10 @@ + int chars; + int chars_per_c = 8; + +- if (c == input_tab_char) ++ if (c == input_tab_char[0]) + chars_per_c = chars_per_input_tab; + +- if (c == input_tab_char || c == '\t') ++ if (c == input_tab_char[0] || c == '\t') + { + width = TAB_WIDTH (chars_per_c, input_position); + +@@ -2739,6 +2943,155 @@ + return chars; + } + ++#ifdef HAVE_MBRTOWC ++static int ++char_to_clump_multi (char c) ++{ ++ static size_t mbc_pos = 0; ++ static unsigned char mbc[MB_LEN_MAX] = {'\0'}; ++ static mbstate_t state = {'\0'}; ++ mbstate_t state_bak; ++ wchar_t wc; ++ unsigned char uc = (unsigned char) c; ++ size_t mblength; ++ int wc_width; ++ register char *s = clump_buff; ++ register int i, j; ++ char esc_buff[4]; ++ int width; ++ int chars; ++ int chars_per_c = 8; ++ ++ state_bak = state; ++ mbc[mbc_pos++] = uc; ++ mblength = mbrtowc (&wc, mbc, mbc_pos, &state); ++ ++ width = 0; ++ chars = 0; ++ while (mbc_pos > 0) ++ { ++ switch (mblength) ++ { ++ case (size_t) -2: ++ state = state_bak; ++ return 0; ++ ++ case (size_t) -1: ++ state = state_bak; ++ mblength = 1; ++ ++ if (use_esc_sequence || use_cntrl_prefix) ++ { ++ width = +4; ++ chars = +4; ++ *s++ = '\\'; ++ sprintf (esc_buff, "%03o", mbc[0]); ++ for (i = 0; i <= 2; ++i) ++ *s++ = (int) esc_buff[i]; ++ } ++ else ++ { ++ width += 1; ++ chars += 1; ++ *s++ = mbc[0]; ++ } ++ break; ++ ++ case 0: ++ mblength = 1; ++ /* Fall through */ ++ ++ default: ++ if (memcmp (mbc, input_tab_char, mblength) == 0) ++ chars_per_c = chars_per_input_tab; ++ ++ if (memcmp (mbc, input_tab_char, mblength) == 0 || c == '\t') ++ { ++ int width_inc; ++ ++ width_inc = TAB_WIDTH (chars_per_c, input_position); ++ width += width_inc; ++ ++ if (untabify_input) ++ { ++ for (i = width_inc; i; --i) ++ *s++ = ' '; ++ chars += width_inc; ++ } ++ else ++ { ++ for (i = 0; i < mblength; i++) ++ *s++ = mbc[i]; ++ chars += mblength; ++ } ++ } ++ else if ((wc_width = wcwidth (wc)) < 1) ++ { ++ if (use_esc_sequence) ++ { ++ for (i = 0; i < mblength; i++) ++ { ++ width += 4; ++ chars += 4; ++ *s++ = '\\'; ++ sprintf (esc_buff, "%03o", uc); ++ for (j = 0; j <= 2; ++j) ++ *s++ = (int) esc_buff[j]; ++ } ++ } ++ else if (use_cntrl_prefix) ++ { ++ if (wc < 0200) ++ { ++ width += 2; ++ chars += 2; ++ *s++ = '^'; ++ *s++ = wc ^ 0100; ++ } ++ else ++ { ++ for (i = 0; i < mblength; i++) ++ { ++ width += 4; ++ chars += 4; ++ *s++ = '\\'; ++ sprintf (esc_buff, "%03o", uc); ++ for (j = 0; j <= 2; ++j) ++ *s++ = (int) esc_buff[j]; ++ } ++ } ++ } ++ else if (wc == L'\b') ++ { ++ width += -1; ++ chars += 1; ++ *s++ = c; ++ } ++ else ++ { ++ width += 0; ++ chars += mblength; ++ for (i = 0; i < mblength; i++) ++ *s++ = mbc[i]; ++ } ++ } ++ else ++ { ++ width += wc_width; ++ chars += mblength; ++ for (i = 0; i < mblength; i++) ++ *s++ = mbc[i]; ++ } ++ } ++ memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength); ++ mbc_pos -= mblength; ++ } ++ ++ input_position += width; ++ return chars; ++} ++#endif ++ + /* We've just printed some files and need to clean up things before + looking for more options and printing the next batch of files. + +--- coreutils-6.5/src/sort.c ++++ coreutils-6.5/src/sort.c +@@ -26,6 +26,19 @@ + #include + #include + #include ++#include ++ ++/* Get mbstate_t, mbrtowc(), wcrtomb(). */ ++#if HAVE_WCHAR_H ++# include ++#endif ++ ++/* Get iswprint(), iswctype() towupper(). */ ++#if HAVE_WCTYPE_H ++# include ++wctype_t blank_type; /* = wctype ("blank"); */ ++#endif ++ + #include "system.h" + #include "error.h" + #include "hard-locale.h" +@@ -50,6 +63,17 @@ + # define getrlimit(Resource, Rlp) (-1) + #endif + ++/* 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 == 1 ++# 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 "sort" + +@@ -98,14 +122,38 @@ + /* Thousands separator; if -1, then there isn't one. */ + static int thousands_sep; + ++static int force_general_numcompare = 0; ++ + /* Nonzero if the corresponding locales are hard. */ + static bool hard_LC_COLLATE; +-#if HAVE_NL_LANGINFO ++#if HAVE_LANGINFO_CODESET + static bool hard_LC_TIME; + #endif + + #define NONZERO(x) ((x) != 0) + ++/* get a multibyte character's byte length. */ ++#define GET_BYTELEN_OF_CHAR(LIM, PTR, MBLENGTH, STATE) \ ++ do \ ++ { \ ++ wchar_t wc; \ ++ mbstate_t state_bak; \ ++ \ ++ state_bak = STATE; \ ++ mblength = mbrtowc (&wc, PTR, LIM - PTR, &STATE); \ ++ \ ++ switch (MBLENGTH) \ ++ { \ ++ case (size_t)-1: \ ++ case (size_t)-2: \ ++ STATE = state_bak; \ ++ /* Fall through. */ \ ++ case 0: \ ++ MBLENGTH = 1; \ ++ } \ ++ } \ ++ while (0) ++ + /* The kind of blanks for '-b' to skip in various options. */ + enum blanktype { bl_start, bl_end, bl_both }; + +@@ -243,13 +291,11 @@ + they were read if all keys compare equal. */ + static bool stable; + +-/* If TAB has this value, blanks separate fields. */ +-enum { TAB_DEFAULT = CHAR_MAX + 1 }; +- +-/* Tab character separating fields. If TAB_DEFAULT, then fields are +- separated by the empty string between a non-blank character and a blank ++/* Tab character separating fields. If NULL, then fields are separated by ++ the empty string between a non-blank character and a blank + character. */ +-static int tab = TAB_DEFAULT; ++static const char *tab; ++static size_t tab_length = 1; + + /* Flag to remove consecutive duplicate lines from the output. + Only the last of a sequence of equal lines will be output. */ +@@ -408,6 +454,43 @@ + static struct tempnode *volatile temphead; + static struct tempnode *volatile *temptail = &temphead; + ++/* Fucntion pointers. */ ++static char * ++(* begfield) (const struct line *line, const struct keyfield *key); ++ ++static char * ++(* limfield) (const struct line *line, const struct keyfield *key); ++ ++static int ++(*getmonth) (const char *s, size_t len); ++ ++static int ++(* keycompare) (const struct line *a, const struct line *b); ++ ++/* Test for white space multibyte character. ++ Set LENGTH the byte length of investigated multibyte character. */ ++#if HAVE_MBRTOWC ++static int ++ismbblank (const char *str, size_t *length) ++{ ++ size_t mblength; ++ wchar_t wc; ++ mbstate_t state; ++ ++ memset (&state, '\0', sizeof(mbstate_t)); ++ mblength = mbrtowc (&wc, str, MB_LEN_MAX, &state); ++ ++ if (mblength == (size_t)-1 || mblength == (size_t)-2) ++ { ++ *length = 1; ++ return 0; ++ } ++ ++ *length = (mblength < 1) ? 1 : mblength; ++ return (iswctype (wc, blank_type)); ++} ++#endif ++ + /* Clean up any remaining temporary files. */ + + static void +@@ -561,7 +644,7 @@ + free (node); + } + +-#if HAVE_NL_LANGINFO ++#if HAVE_LANGINFO_CODESET + + static int + struct_month_cmp (const void *m1, const void *m2) +@@ -588,7 +671,7 @@ + fold_toupper[i] = toupper (i); + } + +-#if HAVE_NL_LANGINFO ++#if HAVE_LANGINFO_CODESET + /* If we're not in the "C" locale, read different names for months. */ + if (hard_LC_TIME) + { +@@ -614,6 +697,71 @@ + #endif + } + ++#if HAVE_MBRTOWC ++static void ++inittables_mb (void) ++{ ++ int i, j, k, l; ++ char *name, *s; ++ size_t s_len, mblength; ++ char mbc[MB_LEN_MAX]; ++ wchar_t wc, pwc; ++ mbstate_t state_mb, state_wc; ++ ++ for (i = 0; i < MONTHS_PER_YEAR; i++) ++ { ++ s = (char *) nl_langinfo (ABMON_1 + i); ++ s_len = strlen (s); ++ monthtab[i].name = name = (char *) xmalloc (s_len + 1); ++ monthtab[i].val = i + 1; ++ ++ memset (&state_mb, '\0', sizeof (mbstate_t)); ++ memset (&state_wc, '\0', sizeof (mbstate_t)); ++ ++ for (j = 0; j < s_len;) ++ { ++ if (!ismbblank (s + j, &mblength)) ++ break; ++ j += mblength; ++ } ++ ++ for (k = 0; j < s_len;) ++ { ++ mblength = mbrtowc (&wc, (s + j), (s_len - j), &state_mb); ++ /* If conversion is failed, fall back into single byte sorting. */ ++ if (mblength == (size_t) -1 || mblength == (size_t) -2) ++ { ++ for (l = 0; l <= i; l++) ++ free ((void *) monthtab[l].name); ++ inittables(); ++ return; ++ } ++ else if (mblength == 0) ++ break; ++ ++ pwc = towupper (wc); ++ if (pwc == wc) ++ { ++ memcpy (mbc, s + j, mblength); ++ j += mblength; ++ } ++ else ++ { ++ j += mblength; ++ mblength = wcrtomb (mbc, wc, &state_wc); ++ assert (mblength != (size_t) 0 && mblength != (size_t) -1); ++ } ++ ++ for (l = 0; l < mblength; l++) ++ name[k++] = mbc[l]; ++ } ++ name[k] = '\0'; ++ } ++ qsort ((void *) monthtab, MONTHS_PER_YEAR, ++ sizeof *monthtab, struct_month_cmp); ++} ++#endif ++ + /* Specify the amount of main memory to use when sorting. */ + static void + specify_sort_size (char const *s) +@@ -824,7 +972,7 @@ + by KEY in LINE. */ + + static char * +-begfield (const struct line *line, const struct keyfield *key) ++begfield_uni (const struct line *line, const struct keyfield *key) + { + char *ptr = line->text, *lim = ptr + line->length - 1; + size_t sword = key->sword; +@@ -834,10 +982,10 @@ + /* The leading field separator itself is included in a field when -t + is absent. */ + +- if (tab != TAB_DEFAULT) ++ if (tab != NULL) + while (ptr < lim && sword--) + { +- while (ptr < lim && *ptr != tab) ++ while (ptr < lim && *ptr != tab[0]) + ++ptr; + if (ptr < lim) + ++ptr; +@@ -865,11 +1013,70 @@ + return ptr; + } + ++#if HAVE_MBRTOWC ++static char * ++begfield_mb (const struct line *line, const struct keyfield *key) ++{ ++ int i; ++ char *ptr = line->text, *lim = ptr + line->length - 1; ++ size_t sword = key->sword; ++ size_t schar = key->schar; ++ size_t mblength; ++ mbstate_t state; ++ ++ memset (&state, '\0', sizeof(mbstate_t)); ++ ++ if (tab != NULL) ++ while (ptr < lim && sword--) ++ { ++ while (ptr < lim && memcmp (ptr, tab, tab_length) != 0) ++ { ++ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); ++ ptr += mblength; ++ } ++ if (ptr < lim) ++ { ++ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); ++ ptr += mblength; ++ } ++ } ++ else ++ while (ptr < lim && sword--) ++ { ++ while (ptr < lim && ismbblank (ptr, &mblength)) ++ ptr += mblength; ++ if (ptr < lim) ++ { ++ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); ++ ptr += mblength; ++ } ++ while (ptr < lim && !ismbblank (ptr, &mblength)) ++ ptr += mblength; ++ } ++ ++ if (key->skipsblanks) ++ while (ptr < lim && ismbblank (ptr, &mblength)) ++ ptr += mblength; ++ ++ for (i = 0; i < schar; i++) ++ { ++ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); ++ ++ if (ptr + mblength > lim) ++ break; ++ else ++ ptr += mblength; ++ } ++ ++ return ptr; ++} ++#endif ++ + /* Return the limit of (a pointer to the first character after) the field + in LINE specified by KEY. */ + + static char * +-limfield (const struct line *line, const struct keyfield *key) ++limfield_uni (const struct line *line, const struct keyfield *key) + { + char *ptr = line->text, *lim = ptr + line->length - 1; + size_t eword = key->eword, echar = key->echar; +@@ -882,10 +1089,10 @@ + `beginning' is the first character following the delimiting TAB. + Otherwise, leave PTR pointing at the first `blank' character after + the preceding field. */ +- if (tab != TAB_DEFAULT) ++ if (tab != NULL) + while (ptr < lim && eword--) + { +- while (ptr < lim && *ptr != tab) ++ while (ptr < lim && *ptr != tab[0]) + ++ptr; + if (ptr < lim && (eword | echar)) + ++ptr; +@@ -931,7 +1138,7 @@ + */ + + /* Make LIM point to the end of (one byte past) the current field. */ +- if (tab != TAB_DEFAULT) ++ if (tab != NULL) + { + char *newlim; + newlim = memchr (ptr, tab, lim - ptr); +@@ -967,6 +1174,107 @@ + return ptr; + } + ++#if HAVE_MBRTOWC ++static char * ++limfield_mb (const struct line *line, const struct keyfield *key) ++{ ++ char *ptr = line->text, *lim = ptr + line->length - 1; ++ size_t eword = key->eword, echar = key->echar; ++ int i; ++ size_t mblength; ++ mbstate_t state; ++ ++ memset (&state, '\0', sizeof(mbstate_t)); ++ ++ if (tab != NULL) ++ while (ptr < lim && eword--) ++ { ++ while (ptr < lim && memcmp (ptr, tab, tab_length) != 0) ++ { ++ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); ++ ptr += mblength; ++ } ++ if (ptr < lim) ++ { ++ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); ++ ptr += mblength; ++ } ++ } ++ else ++ while (ptr < lim && eword--) ++ { ++ while (ptr < lim && ismbblank (ptr, &mblength)) ++ ptr += mblength; ++ if (ptr < lim) ++ { ++ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); ++ ptr += mblength; ++ } ++ while (ptr < lim && !ismbblank (ptr, &mblength)) ++ ptr += mblength; ++ } ++ ++# ifdef POSIX_UNSPECIFIED ++ ++ /* Make LIM point to the end of (one byte past) the current field. */ ++ if (tab != NULL) ++ { ++ char *newlim, *p; ++ ++ newlim = NULL; ++ for (p = ptr; p < lim;) ++ { ++ if (memcmp (p, tab, tab_length) == 0) ++ { ++ newlim = p; ++ break; ++ } ++ ++ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); ++ p += mblength; ++ } ++ } ++ else ++ { ++ char *newlim; ++ newlim = ptr; ++ ++ while (newlim < lim && ismbblank (newlim, &mblength)) ++ newlim += mblength; ++ if (ptr < lim) ++ { ++ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); ++ ptr += mblength; ++ } ++ while (newlim < lim && !ismbblank (newlim, &mblength)) ++ newlim += mblength; ++ lim = newlim; ++ } ++# endif ++ ++ /* If we're skipping leading blanks, don't start counting characters ++ until after skipping past any leading blanks. */ ++ if (key->skipeblanks) ++ while (ptr < lim && ismbblank (ptr, &mblength)) ++ ptr += mblength; ++ ++ memset (&state, '\0', sizeof(mbstate_t)); ++ ++ /* Advance PTR by ECHAR (if possible), but no further than LIM. */ ++ for (i = 0; i < echar; i++) ++ { ++ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); ++ ++ if (ptr + mblength > lim) ++ break; ++ else ++ ptr += mblength; ++ } ++ ++ return ptr; ++} ++#endif ++ + /* 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 +@@ -1049,8 +1357,22 @@ + else + { + if (key->skipsblanks) +- while (blanks[to_uchar (*line_start)]) +- line_start++; ++ { ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ { ++ size_t mblength; ++ ++ while (ismbblank (line_start, &mblength)) ++ line_start += mblength; ++ } ++ else ++#endif ++ { ++ while (blanks[to_uchar (*line_start)]) ++ line_start++; ++ } ++ } + line->keybeg = line_start; + } + } +@@ -1100,15 +1422,59 @@ + /* FIXME: maybe add option to try expensive FP conversion + only if A and B can't be compared more cheaply/accurately. */ + +- char *ea; +- char *eb; +- double a = strtod (sa, &ea); +- double b = strtod (sb, &eb); ++ char *bufa, *ea; ++ char *bufb, *eb; ++ double a; ++ double b; ++ ++ char *p; ++ struct lconv *lconvp = localeconv (); ++ size_t thousands_sep_len = strlen (lconvp->thousands_sep); ++ ++ bufa = (char *) xmalloc (strlen (sa) + 1); ++ bufb = (char *) xmalloc (strlen (sb) + 1); ++ strcpy (bufa, sa); ++ strcpy (bufb, sb); ++ ++ if (force_general_numcompare) ++ { ++ while (1) ++ { ++ a = strtod (bufa, &ea); ++ if (memcmp (ea, lconvp->thousands_sep, thousands_sep_len) == 0) ++ { ++ for (p = ea; *(p + thousands_sep_len) != '\0'; p++) ++ *p = *(p + thousands_sep_len); ++ *p = '\0'; ++ continue; ++ } ++ break; ++ } ++ ++ while (1) ++ { ++ b = strtod (bufb, &eb); ++ if (memcmp (eb, lconvp->thousands_sep, thousands_sep_len) == 0) ++ { ++ for (p = eb; *(p + thousands_sep_len) != '\0'; p++) ++ *p = *(p + thousands_sep_len); ++ *p = '\0'; ++ continue; ++ } ++ break; ++ } ++ } ++ else ++ { ++ a = strtod (bufa, &ea); ++ b = strtod (bufb, &eb); ++ } ++ + + /* Put conversion errors at the start of the collating sequence. */ +- if (sa == ea) +- return sb == eb ? 0 : -1; +- if (sb == eb) ++ if (bufa == ea) ++ return bufb == eb ? 0 : -1; ++ if (bufb == eb) + return 1; + + /* Sort numbers in the usual way, where -0 == +0. Put NaNs after +@@ -1126,7 +1492,7 @@ + Return 0 if the name in S is not recognized. */ + + static int +-getmonth (char const *month, size_t len) ++getmonth_uni (char const *month, size_t len) + { + size_t lo = 0; + size_t hi = MONTHS_PER_YEAR; +@@ -1281,11 +1647,79 @@ + return diff; + } + ++#if HAVE_MBRTOWC ++static int ++getmonth_mb (char const *s, size_t len) ++{ ++ char *month; ++ register size_t i; ++ register int lo = 0, hi = MONTHS_PER_YEAR, result; ++ char *tmp; ++ size_t wclength, mblength; ++ const char **pp; ++ const wchar_t **wpp; ++ wchar_t *month_wcs; ++ mbstate_t state; ++ ++ while (len > 0 && ismbblank (s, &mblength)) ++ { ++ s += mblength; ++ len -= mblength; ++ } ++ ++ if (len == 0) ++ return 0; ++ ++ month = (char *) alloca (len + 1); ++ ++ tmp = (char *) alloca (len + 1); ++ memcpy (tmp, s, len); ++ tmp[len] = '\0'; ++ pp = (const char **) &tmp; ++ month_wcs = (wchar_t *) alloca ((len + 1) * sizeof (wchar_t)); ++ memset (&state, '\0', sizeof (mbstate_t)); ++ ++ wclength = mbsrtowcs (month_wcs, pp, len + 1, &state); ++ assert (wclength != 1 && *pp == NULL); ++ ++ for (i = 0; i < wclength; i++) ++ { ++ month_wcs[i] = towupper (month_wcs[i]); ++ if (iswctype (month_wcs[i], blank_type)) ++ { ++ month_wcs[i] = L'\0'; ++ break; ++ } ++ } ++ ++ wpp = (const wchar_t **) &month_wcs; ++ ++ mblength = wcsrtombs (month, wpp, len + 1, &state); ++ assert (mblength != (-1) && *wpp == NULL); ++ ++ do ++ { ++ int ix = (lo + hi) / 2; ++ ++ if (strncmp (month, monthtab[ix].name, strlen (monthtab[ix].name)) < 0) ++ hi = ix; ++ else ++ lo = ix; ++ } ++ while (hi - lo > 1); ++ ++ result = (!strncmp (month, monthtab[lo].name, strlen (monthtab[lo].name)) ++ ? monthtab[lo].val : 0); ++ ++ return result; ++} ++#endif ++ + /* Compare two lines A and B trying every key in sequence until there + are no more keys or a difference is found. */ + + static int +-keycompare (const struct line *a, const struct line *b) ++keycompare_uni (const struct line *a, const struct line *b) + { + struct keyfield const *key = keylist; + +@@ -1452,12 +1886,189 @@ + + return 0; + +- greater: ++greater: + diff = 1; +- not_equal: ++not_equal: + return key->reverse ? -diff : diff; + } + ++#if HAVE_MBRTOWC ++static int ++keycompare_mb (const struct line *a, const struct line *b) ++{ ++ struct keyfield *key = keylist; ++ ++ /* For the first iteration only, the key positions have been ++ precomputed for us. */ ++ char *texta = a->keybeg; ++ char *textb = b->keybeg; ++ char *lima = a->keylim; ++ char *limb = b->keylim; ++ ++ size_t mblength_a, mblength_b; ++ wchar_t wc_a, wc_b; ++ mbstate_t state_a, state_b; ++ ++ int diff; ++ ++ memset (&state_a, '\0', sizeof (mbstate_t)); ++ memset (&state_b, '\0', sizeof (mbstate_t)); ++ ++ for (;;) ++ { ++ register char const *translate = key->translate; ++ register 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->numeric | key->general_numeric) ++ { ++ char savea = *lima, saveb = *limb; ++ ++ *lima = *limb = '\0'; ++ if (force_general_numcompare) ++ diff = general_numcompare (texta, textb); ++ else ++ diff = ((key->numeric ? numcompare : general_numcompare) ++ (texta, textb)); ++ *lima = savea, *limb = saveb; ++ } ++ else if (key->month) ++ diff = getmonth (texta, lena) - getmonth (textb, lenb); ++ else ++ { ++ if (ignore || translate) ++ { ++ char buf[4000]; ++ size_t size = lena + 1 + lenb + 1; ++ char *copy_a = (size <= sizeof buf ? buf : xmalloc (size)); ++ 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) \ ++ do \ ++ { \ ++ wchar_t uwc; \ ++ char mbc[MB_LEN_MAX]; \ ++ mbstate_t state_wc; \ ++ \ ++ for (NEW_LEN = i = 0; i < LEN;) \ ++ { \ ++ mbstate_t state_bak; \ ++ \ ++ state_bak = STATE; \ ++ MBLENGTH = mbrtowc (&WC, TEXT + i, LEN - i, &STATE); \ ++ \ ++ if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1 \ ++ || MBLENGTH == 0) \ ++ { \ ++ if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1) \ ++ STATE = state_bak; \ ++ if (!ignore) \ ++ COPY[NEW_LEN++] = TEXT[i++]; \ ++ continue; \ ++ } \ ++ \ ++ if (ignore) \ ++ { \ ++ if ((ignore == nonprinting && !iswprint (WC)) \ ++ || (ignore == nondictionary \ ++ && !iswalnum (WC) && !iswctype (WC, blank_type))) \ ++ { \ ++ i += MBLENGTH; \ ++ continue; \ ++ } \ ++ } \ ++ \ ++ if (translate) \ ++ { \ ++ \ ++ uwc = toupper(WC); \ ++ if (WC == uwc) \ ++ { \ ++ memcpy (mbc, TEXT + i, MBLENGTH); \ ++ i += MBLENGTH; \ ++ } \ ++ else \ ++ { \ ++ i += MBLENGTH; \ ++ WC = uwc; \ ++ memset (&state_wc, '\0', sizeof (mbstate_t)); \ ++ \ ++ MBLENGTH = wcrtomb (mbc, WC, &state_wc); \ ++ assert (MBLENGTH != (size_t)-1 && MBLENGTH != 0); \ ++ } \ ++ \ ++ for (j = 0; j < MBLENGTH; j++) \ ++ COPY[NEW_LEN++] = mbc[j]; \ ++ } \ ++ else \ ++ for (j = 0; j < MBLENGTH; j++) \ ++ COPY[NEW_LEN++] = TEXT[i++]; \ ++ } \ ++ 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); ++ ++ if (sizeof buf < size) ++ free (copy_a); ++ } ++ else if (lena == 0) ++ diff = - NONZERO (lenb); ++ else if (lenb == 0) ++ goto greater; ++ else ++ diff = xmemcoll (texta, lena, textb, lenb); ++ } ++ ++ if (diff) ++ goto not_equal; ++ ++ key = key->next; ++ if (! key) ++ break; ++ ++ /* Find the beginning and limit of the next field. */ ++ if (key->eword != SIZE_MAX) ++ lima = limfield (a, key), limb = limfield (b, key); ++ else ++ lima = a->text + a->length - 1, limb = b->text + b->length - 1; ++ ++ if (key->sword != SIZE_MAX) ++ texta = begfield (a, key), textb = begfield (b, key); ++ else ++ { ++ texta = a->text, textb = b->text; ++ if (key->skipsblanks) ++ { ++ while (texta < lima && ismbblank (texta, &mblength_a)) ++ texta += mblength_a; ++ while (textb < limb && ismbblank (textb, &mblength_b)) ++ textb += mblength_b; ++ } ++ } ++ } ++ ++ return 0; ++ ++greater: ++ diff = 1; ++not_equal: ++ return key->reverse ? -diff : diff; ++} ++#endif ++ + /* Compare two lines A and B, returning negative, zero, or positive + depending on whether A compares less than, equal to, or greater than B. */ + +@@ -2253,6 +2864,11 @@ + break; + case 'M': + key->month = true; ++#if HAVE_MBRTOWC ++ if (strcmp (setlocale (LC_CTYPE, NULL), setlocale (LC_TIME, NULL))) ++ error (0, 0, _("As LC_TIME differs from LC_CTYPE, the results may be strange.")); ++ inittables_mb (); ++#endif + break; + case 'n': + key->numeric = true; +@@ -2309,7 +2925,7 @@ + atexit (close_stdout); + + hard_LC_COLLATE = hard_locale (LC_COLLATE); +-#if HAVE_NL_LANGINFO ++#if HAVE_LANGINFO_CODESET + hard_LC_TIME = hard_locale (LC_TIME); + #endif + +@@ -2322,14 +2938,40 @@ + add support for multibyte decimal points. */ + decimal_point = to_uchar (locale->decimal_point[0]); + if (! decimal_point || locale->decimal_point[1]) +- decimal_point = '.'; ++ { ++ decimal_point = '.'; ++ if (locale->decimal_point[0] && locale->decimal_point[1]) ++ force_general_numcompare = 1; ++ } + + /* FIXME: add support for multibyte thousands separators. */ + thousands_sep = to_uchar (*locale->thousands_sep); + if (! thousands_sep || locale->thousands_sep[1]) +- thousands_sep = -1; ++ { ++ thousands_sep = -1; ++ if (locale->thousands_sep[0] && locale->thousands_sep[1]) ++ force_general_numcompare = 1; ++ } + } + ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ { ++ blank_type = wctype ("blank"); ++ begfield = begfield_mb; ++ limfield = limfield_mb; ++ getmonth = getmonth_mb; ++ keycompare = keycompare_mb; ++ } ++ else ++#endif ++ { ++ begfield = begfield_uni; ++ limfield = limfield_uni; ++ keycompare = keycompare_uni; ++ getmonth = getmonth_uni; ++ } ++ + have_read_stdin = false; + inittables (); + +@@ -2544,13 +3186,32 @@ + + case 't': + { +- char newtab = optarg[0]; +- if (! newtab) ++ const char *newtab = optarg; ++ size_t newtab_length; ++ if (! newtab[0]) + error (SORT_FAILURE, 0, _("empty tab")); +- if (optarg[1]) ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ { ++ mbstate_t state; ++ ++ memset (&state, 0, sizeof (mbstate_t)); ++ newtab_length = mbrtowc (NULL, newtab, strlen (newtab), &state); ++ if (newtab_length == (size_t) 0 ++ || newtab_length == (size_t) -1 ++ || newtab_length == (size_t) -2) ++ newtab_length = 1; ++ } ++ else ++#endif ++ newtab_length = 1; ++ if (optarg[newtab_length]) + { + if (STREQ (optarg, "\\0")) +- newtab = '\0'; ++ { ++ newtab = "\0"; ++ newtab_length = 1; ++ } + else + { + /* Provoke with `sort -txx'. Complain about +@@ -2561,9 +3222,12 @@ + quote (optarg)); + } + } +- if (tab != TAB_DEFAULT && tab != newtab) ++ if (tab != NULL ++ && (tab_length != newtab_length ++ || memcmp (tab, newtab, tab_length) != 0)) + error (SORT_FAILURE, 0, _("incompatible tabs")); + tab = newtab; ++ tab_length = newtab_length; + } + break; + +--- coreutils-6.5/src/unexpand.c ++++ coreutils-6.5/src/unexpand.c +@@ -39,11 +39,34 @@ + #include + #include + #include ++ ++/* Get mbstate_t, mbrtowc(), wcwidth() */ ++#if HAVE_WCHAR_H ++# include ++#endif ++/* Get iswblank */ ++#if HAVE_WCTYPE_H ++# include ++#endif ++ ++ ++/* A sentinel value that's placed at the end of the list of tab stops. ++ * This value must be a large number, but not so large that adding the ++ * length of a line to it would cause the column variable to overflow. */ ++#define TAB_STOP_SENTINEL INT_MAX ++ + #include "system.h" + #include "error.h" + #include "quote.h" + #include "xstrndup.h" + ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC ++ installation; work around this configuration error. */ ++#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 ++# undef MB_LEN_MAX ++# define MB_LEN_MAX 16 ++#endif ++ + /* The official name of this program (e.g., no `g' prefix). */ + #define PROGRAM_NAME "unexpand" + +@@ -453,6 +476,237 @@ + } + } + ++#if HAVE_MBRTOWC && HAVE_WCTYPE_H ++static void ++unexpand_multibyte (void) ++{ ++ /* Input stream. */ ++ FILE *fp = next_file (NULL); ++ ++ mbstate_t i_state; /* Current shift state of the input stream. */ ++ char buf[MB_LEN_MAX + BUFSIZ]; /* For spooling a read byte sequence. */ ++ char *bufpos; /* Next read position of BUF. */ ++ size_t buflen = 0; /* The length of the byte sequence in buf. */ ++ ++ /* 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; ++ ++ if (!fp) ++ return; ++ ++ /* 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 = xmalloc (max_column_width); ++ ++ memset (&i_state, '\0', sizeof(mbstate_t)); ++ ++ for (;;) ++ { ++ /* A gotten wide character. */ ++ wint_t wc; ++ ++ /* If true, perform translations. */ ++ bool convert = true; ++ ++ /* The following variables have valid values only when CONVERT ++ is true: */ ++ ++ /* Column of next input character. */ ++ uintmax_t column = 0; ++ ++ /* Column the next input tab stop is on. */ ++ uintmax_t next_tab_column = 0; ++ ++ /* Index in TAB_LIST of next tab stop to examine. */ ++ size_t tab_index = 0; ++ ++ /* If true, the first pending blank came just before a tab stop. */ ++ bool one_blank_before_tab_stop = false; ++ ++ /* If true, the previous input character was a blank. This is ++ initially true, since initial strings of blanks are treated ++ as if the line was preceded by a blank. */ ++ bool prev_blank = true; ++ ++ /* Number of pending columns of blanks. */ ++ size_t pending = 0; ++ ++ /* Convert a line of text. */ ++ do ++ { ++ wchar_t w; ++ size_t mblength; /* The byte size of a multibyte character ++ which shows as same character as WC. */ ++ mbstate_t i_state_bak; /* Back up the I_STATE. */ ++ ++ /* Fill buffer */ ++ if (buflen < MB_LEN_MAX) ++ { ++ if (!feof (fp) && !ferror (fp)) ++ { ++ if (buflen > 0) ++ memmove (buf, bufpos, buflen); ++ buflen += fread (buf + buflen, sizeof (char), BUFSIZ, fp); ++ bufpos = buf; ++ } ++ } ++ ++ if (buflen < 1) ++ { ++ /* Move to the next file */ ++ if (feof (fp) || ferror (fp)) ++ fp = next_file (fp); ++ if (!fp) ++ { ++ if (pending) ++ { ++ if (fwrite (pending_blank, 1, pending, stdout) != pending) ++ error (EXIT_FAILURE, errno, _("write error")); ++ } ++ free (pending_blank); ++ return; ++ } ++ continue; ++ } ++ ++ i_state_bak = i_state; ++ mblength = mbrtowc (&w, bufpos, buflen, &i_state); ++ wc = w; ++ ++ if (mblength == (size_t) -1 || mblength == (size_t) -2) ++ { ++ i_state = i_state_bak; ++ wc = L'\0'; ++ column += convert; ++ mblength = 1; ++ } ++ ++ if (convert) ++ { ++ bool blank = iswblank (wc); ++ ++ if (blank) ++ { ++ if (next_tab_column <= column) ++ { ++ if (tab_size) ++ next_tab_column = ++ column + (tab_size - column % tab_size); ++ else ++ for (;;) ++ if (tab_index == first_free_tab) ++ { ++ convert = false; ++ break; ++ } ++ else ++ { ++ uintmax_t tab = tab_list[tab_index++]; ++ if (column < tab) ++ { ++ next_tab_column = tab; ++ break; ++ } ++ } ++ } ++ ++ if (convert) ++ { ++ if (next_tab_column < column) ++ error (EXIT_FAILURE, 0, _("input line is too long")); ++ ++ if (wc == L'\t') ++ { ++ column = next_tab_column; ++ ++ /* Discard pending blanks, unless it was a single ++ blank just before the previous tab stop. */ ++ if (! (pending == 1 && one_blank_before_tab_stop)) ++ { ++ pending = 0; ++ one_blank_before_tab_stop = false; ++ } ++ } ++ else ++ { ++ column++; ++ ++ if (! (prev_blank && column == next_tab_column)) ++ { ++ /* It is not yet known whether the pending blanks ++ will be replaced by tabs. */ ++ if (column == next_tab_column) ++ one_blank_before_tab_stop = true; ++ pending_blank[pending++] = ' '; ++ prev_blank = true; ++ buflen -= mblength; ++ bufpos += mblength; ++ continue; ++ } ++ ++ /* Replace the pending blanks by a tab or two. */ ++ pending_blank[0] = *bufpos = '\t'; ++ pending = one_blank_before_tab_stop; ++ } ++ } ++ } ++ else if (wc == L'\b') ++ { ++ /* Go back one column, and force recalculation of the ++ next tab stop. */ ++ column -= !!column; ++ next_tab_column = column; ++ tab_index -= !!tab_index; ++ } ++ else ++ { ++ if (!iswcntrl (wc)) ++ { ++ int width = wcwidth (wc); ++ if (width > 0) ++ { ++ if (column > (column + width)) ++ error (EXIT_FAILURE, 0, _("input line is too long")); ++ column += width; ++ } ++ } ++ } ++ ++ if (pending) ++ { ++ if (fwrite (pending_blank, 1, pending, stdout) != pending) ++ error (EXIT_FAILURE, errno, _("write error")); ++ pending = 0; ++ one_blank_before_tab_stop = false; ++ } ++ ++ prev_blank = blank; ++ convert &= convert_entire_line | blank; ++ } ++ ++ if (mblength) ++ { ++ if (fwrite (bufpos, sizeof (char), mblength, stdout) < mblength) ++ error (EXIT_FAILURE, errno, _("write error")); ++ } ++ else ++ { ++ if (putchar ('\0')) ++ error (EXIT_FAILURE, errno, _("write error")); ++ mblength = 1; ++ } ++ ++ buflen -= mblength; ++ bufpos += mblength; ++ } ++ while (wc != L'\n'); ++ } ++} ++#endif ++ + int + main (int argc, char **argv) + { +@@ -531,7 +785,12 @@ + + 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, "-"); +--- coreutils-6.5/src/uniq.c ++++ coreutils-6.5/src/uniq.c +@@ -23,6 +23,16 @@ + #include + #include + ++/* Get mbstate_t, mbrtowc(), wcrtomb() */ ++#if HAVE_WCHAR_H ++# include ++#endif ++ ++/* Get iswctype(), wctype(), towupper)(. */ ++#if HAVE_WCTYPE_H ++# include ++#endif ++ + #include "system.h" + #include "argmatch.h" + #include "linebuffer.h" +@@ -34,6 +44,13 @@ + #include "xstrtol.h" + #include "memcasecmp.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 ++ + /* The official name of this program (e.g., no `g' prefix). */ + #define PROGRAM_NAME "uniq" + +@@ -109,6 +126,12 @@ + /* Select whether/how to delimit groups of duplicate lines. */ + static enum delimit_method delimit_groups; + ++/* Function pointers. */ ++static char * (*find_field) (struct linebuffer *line); ++ ++/* Show the blank character class. */ ++wctype_t blank_type; ++ + static struct option const longopts[] = + { + {"count", no_argument, NULL, 'c'}, +@@ -189,7 +212,7 @@ + return a pointer to the beginning of the line's field to be compared. */ + + static char * +-find_field (const struct linebuffer *line) ++find_field_uni (struct linebuffer *line) + { + size_t count; + char *lp = line->buffer; +@@ -210,6 +233,83 @@ + return lp + 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; ++ ++ pos = 0; ++ statep = &(line->state); ++ ++ /* skip fields. */ ++ for (count = 0; count < skip_fields && pos < size; count++) ++ { ++ while (pos < size) ++ { ++ MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); ++ ++ if (convfail || !iswctype (wc, blank_type)) ++ { ++ pos += mblength; ++ break; ++ } ++ pos += mblength; ++ } ++ ++ while (pos < size) ++ { ++ MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); ++ ++ if (!convfail && iswctype (wc, blank_type)) ++ break; ++ ++ pos += mblength; ++ } ++ } ++ ++ /* skip fields. */ ++ for (count = 0; count < skip_chars && pos < size; count++) ++ { ++ MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); ++ pos += mblength; ++ } ++ ++ 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 +334,73 @@ + return oldlen != newlen || memcmp (old, new, oldlen); + } + ++#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] = alloca (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; ++ } ++ ++ return xmemcoll (copy[0], len[0], copy[1], len[1]); ++} ++#endif ++ + /* Output the line in linebuffer LINE to standard output + provided that the switches say it should be output. + MATCH is true if the line matches the previous line. +@@ -286,15 +453,43 @@ + { + char *prevfield IF_LINT (= NULL); + size_t prevlen IF_LINT (= 0); ++#if HAVE_MBRTOWC ++ mbstate_t prevstate; ++ ++ memset (&prevstate, '\0', sizeof (mbstate_t)); ++#endif + + while (!feof (stdin)) + { + char *thisfield; + size_t thislen; ++#if HAVE_MBRTOWC ++ mbstate_t thisstate; ++#endif + if (readlinebuffer (thisline, stdin) == 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)) ++ { ++ fwrite (thisline->buffer, sizeof (char), ++ thisline->length, stdout); ++ ++ SWAP_LINES (prevline, thisline); ++ prevfield = thisfield; ++ prevlen = thislen; ++ prevstate = thisstate; ++ } ++ } ++ else ++#endif + if (prevline->length == 0 + || different (thisfield, prevfield, thislen, prevlen)) + { +@@ -313,17 +508,26 @@ + size_t prevlen; + uintmax_t match_count = 0; + bool first_delimiter = true; ++#if HAVE_MBRTOWC ++ mbstate_t prevstate; ++#endif + + if (readlinebuffer (prevline, stdin) == 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; ++#endif + if (readlinebuffer (thisline, stdin) == 0) + { + if (ferror (stdin)) +@@ -332,6 +536,15 @@ + } + thisfield = find_field (thisline); + thislen = thisline->length - 1 - (thisfield - thisline->buffer); ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ { ++ thisstate = thisline->state; ++ match = !different_multi (thisfield, prevfield, ++ thislen, prevlen, thisstate, prevstate); ++ } ++ else ++#endif + match = !different (thisfield, prevfield, thislen, prevlen); + match_count += match; + +@@ -364,6 +577,9 @@ + SWAP_LINES (prevline, thisline); + prevfield = thisfield; + prevlen = thislen; ++#if HAVE_MBRTOWC ++ prevstate = thisstate; ++#endif + if (!match) + match_count = 0; + } +@@ -408,6 +624,18 @@ + + atexit (close_stdout); + ++#if HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1) ++ { ++ find_field = find_field_multi; ++ blank_type = wctype ("blank"); ++ } ++ else ++#endif ++ { ++ find_field = find_field_uni; ++ } ++ + skip_chars = 0; + skip_fields = 0; + check_chars = SIZE_MAX; diff --git a/coreutils-5.3.0-pie.diff b/coreutils-5.3.0-pie.diff new file mode 100644 index 0000000..af27733 --- /dev/null +++ b/coreutils-5.3.0-pie.diff @@ -0,0 +1,21 @@ +--- lib/Makefile.am ++++ lib/Makefile.am +@@ -20,6 +20,7 @@ + include gnulib.mk + + AM_CFLAGS = $(WARNING_CFLAGS) $(WERROR_CFLAGS) ++AM_CFLAGS += -fpie + + noinst_PROGRAMS = t-fpending + LDADD = $(noinst_LIBRARIES) +--- src/Makefile.am ++++ src/Makefile.am +@@ -105,6 +105,8 @@ + + su_SOURCES = su.c getdef.c + su_LDADD = $(LDADD) $(LIB_CRYPT) -lpam -lpam_misc -ldl ++su_CFLAGS = -fpie ++su_LDFLAGS = -pie + + dir_LDADD += $(LIB_ACL) + ls_LDADD += $(LIB_ACL) diff --git a/coreutils-5.3.0-sbin4su.diff b/coreutils-5.3.0-sbin4su.diff new file mode 100644 index 0000000..c501f62 --- /dev/null +++ b/coreutils-5.3.0-sbin4su.diff @@ -0,0 +1,143 @@ +--- src/su.c ++++ src/su.c +@@ -344,6 +344,117 @@ + #endif /* !USE_PAM */ + } + ++/* Add or clear /sbin and /usr/sbin for the su command ++ used without `-'. */ ++ ++/* Set if /sbin is found in path. */ ++#define SBIN_MASK 0x01 ++/* Set if /usr/sbin is found in path. */ ++#define USBIN_MASK 0x02 ++ ++static char * ++addsbin (const char *const path) ++{ ++ unsigned char smask = 0; ++ char *ptr, *tmp, *cur, *ret = NULL; ++ size_t len; ++ ++ if (!path || *path == 0) ++ return NULL; ++ ++ tmp = xstrdup (path); ++ cur = tmp; ++ for (ptr = strsep (&cur, ":"); ptr != NULL; ptr = strsep (&cur, ":")) ++ { ++ if (!strcmp (ptr, "/sbin")) ++ smask |= SBIN_MASK; ++ if (!strcmp (ptr, "/usr/sbin")) ++ smask |= USBIN_MASK; ++ } ++ ++ if ((smask & (USBIN_MASK|SBIN_MASK)) == (USBIN_MASK|SBIN_MASK)) ++ { ++ free (tmp); ++ return NULL; ++ } ++ ++ len = strlen (path); ++ if (!(smask & USBIN_MASK)) ++ len += strlen ("/usr/sbin:"); ++ ++ if (!(smask & SBIN_MASK)) ++ len += strlen (":/sbin"); ++ ++ ret = xmalloc (len + 1); ++ strcpy (tmp, path); ++ ++ *ret = 0; ++ cur = tmp; ++ for (ptr = strsep (&cur, ":"); ptr; ptr = strsep (&cur, ":")) ++ { ++ if (!strcmp (ptr, ".")) ++ continue; ++ if (*ret) ++ strcat (ret, ":"); ++ if (!(smask & USBIN_MASK) && !strcmp (ptr, "/bin")) ++ { ++ strcat (ret, "/usr/sbin:"); ++ strcat (ret, ptr); ++ smask |= USBIN_MASK; ++ continue; ++ } ++ if (!(smask & SBIN_MASK) && !strcmp (ptr, "/usr/bin")) ++ { ++ strcat (ret, ptr); ++ strcat (ret, ":/sbin"); ++ smask |= SBIN_MASK; ++ continue; ++ } ++ strcat (ret, ptr); ++ } ++ free (tmp); ++ ++ if (!(smask & USBIN_MASK)) ++ strcat (ret, ":/usr/sbin"); ++ ++ if (!(smask & SBIN_MASK)) ++ strcat (ret, ":/sbin"); ++ ++ return ret; ++} ++ ++static char * ++clearsbin (const char *const path) ++{ ++ char *ptr, *tmp, *cur, *ret = NULL; ++ ++ if (!path || *path == 0) ++ return NULL; ++ ++ tmp = strdup (path); ++ if (!tmp) ++ return NULL; ++ ++ ret = xmalloc (strlen (path) + 1); ++ *ret = 0; ++ cur = tmp; ++ for (ptr = strsep (&cur, ":"); ptr; ptr = strsep (&cur, ":")) ++ { ++ if (!strcmp (ptr, "/sbin")) ++ continue; ++ if (!strcmp (ptr, "/usr/sbin")) ++ continue; ++ if (!strcmp (ptr, "/usr/local/sbin")) ++ continue; ++ if (*ret) ++ strcat (ret, ":"); ++ strcat (ret, ptr); ++ } ++ free (tmp); ++ ++ return ret; ++} ++ + /* Update `environ' for the new shell based on PW, with SHELL being + the value for the SHELL environment variable. */ + +@@ -383,6 +494,22 @@ + DEFAULT_LOGIN_PATH) + : getdef_str ("SUPATH", + DEFAULT_ROOT_LOGIN_PATH))); ++ else ++ { ++ char const *path = getenv ("PATH"); ++ char *new = NULL; ++ ++ if (pw->pw_uid) ++ new = clearsbin (path); ++ else ++ new = addsbin (path); ++ ++ if (new) ++ { ++ xsetenv ("PATH", new); ++ free (new); ++ } ++ } + if (pw->pw_uid) + { + xsetenv ("USER", pw->pw_name); diff --git a/coreutils-6.7.diff b/coreutils-6.7.diff new file mode 100644 index 0000000..f8ac5dd --- /dev/null +++ b/coreutils-6.7.diff @@ -0,0 +1,764 @@ +--- doc/coreutils.texi ++++ doc/coreutils.texi +@@ -64,8 +64,6 @@ + * fold: (coreutils)fold invocation. Wrap long input lines. + * groups: (coreutils)groups invocation. Print group names a user is in. + * head: (coreutils)head invocation. Output the first part of files. +-* hostid: (coreutils)hostid invocation. Print numeric host identifier. +-* hostname: (coreutils)hostname invocation. Print or set system name. + * id: (coreutils)id invocation. Print user identity. + * install: (coreutils)install invocation. Copy and change attributes. + * join: (coreutils)join invocation. Join lines on a common field. +@@ -398,8 +396,6 @@ + + * date invocation:: Print or set system date and time + * uname invocation:: Print system information +-* hostname invocation:: Print or set system name +-* hostid invocation:: Print numeric host identifier. + + @command{date}: Print or set system date and time + +@@ -12190,8 +12186,6 @@ + @menu + * date invocation:: Print or set system date and time. + * uname invocation:: Print system information. +-* hostname invocation:: Print or set system name. +-* hostid invocation:: Print numeric host identifier. + @end menu + + +@@ -12949,55 +12943,6 @@ + @exitstatus + + +-@node hostname invocation +-@section @command{hostname}: Print or set system name +- +-@pindex hostname +-@cindex setting the hostname +-@cindex printing the hostname +-@cindex system name, printing +-@cindex appropriate privileges +- +-With no arguments, @command{hostname} prints the name of the current host +-system. With one argument, it sets the current host name to the +-specified string. You must have appropriate privileges to set the host +-name. Synopsis: +- +-@example +-hostname [@var{name}] +-@end example +- +-The only options are @option{--help} and @option{--version}. @xref{Common +-options}. +- +-@exitstatus +- +- +-@node hostid invocation +-@section @command{hostid}: Print numeric host identifier. +- +-@pindex hostid +-@cindex printing the host identifier +- +-@command{hostid} prints the numeric identifier of the current host +-in hexadecimal. This command accepts no arguments. +-The only options are @option{--help} and @option{--version}. +-@xref{Common options}. +- +-For example, here's what it prints on one system I use: +- +-@example +-$ hostid +-1bac013d +-@end example +- +-On that system, the 32-bit quantity happens to be closely +-related to the system's Internet address, but that isn't always +-the case. +- +-@exitstatus +- +- + @node Modified command invocation + @chapter Modified command invocation + +--- src/Makefile.am ++++ src/Makefile.am +@@ -103,7 +103,8 @@ + # If necessary, add -lm to resolve use of pow in lib/strtod.c. + uptime_LDADD = $(LDADD) $(POW_LIB) $(GETLOADAVG_LIBS) + +-su_LDADD = $(LDADD) $(LIB_CRYPT) ++su_SOURCES = su.c getdef.c ++su_LDADD = $(LDADD) $(LIB_CRYPT) -lpam -lpam_misc -ldl + + dir_LDADD += $(LIB_ACL) + ls_LDADD += $(LIB_ACL) +--- src/getdef.c ++++ src/getdef.c +@@ -0,0 +1,257 @@ ++/* Copyright (C) 2003, 2004, 2005 Thorsten Kukuk ++ Author: Thorsten Kukuk ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License version 2 as ++ published by the Free Software Foundation. ++ ++ 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, write to the Free Software Foundation, ++ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#define _GNU_SOURCE ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "getdef.h" ++ ++struct item { ++ char *name; /* name of the option. */ ++ char *value; /* value of the option. */ ++ struct item *next; /* pointer to next option. */ ++}; ++ ++static struct item *list = NULL; ++ ++void ++free_getdef_data (void) ++{ ++ struct item *ptr; ++ ++ ptr = list; ++ while (ptr != NULL) ++ { ++ struct item *tmp; ++ tmp = ptr->next; ++ free (ptr->name); ++ free (ptr->value); ++ free (ptr); ++ ptr = tmp; ++ } ++ ++ list = NULL; ++} ++ ++/* Add a new entry to the list. */ ++static void ++store (const char *name, const char *value) ++{ ++ struct item *new = malloc (sizeof (struct item)); ++ ++ if (new == NULL) ++ abort (); ++ ++ if (name == NULL) ++ abort (); ++ ++ new->name = strdup (name); ++ new->value = strdup (value?:""); ++ new->next = list; ++ list = new; ++} ++ ++/* search a special entry in the list and return the value. */ ++static const char * ++search (const char *name) ++{ ++ struct item *ptr; ++ ++ ptr = list; ++ while (ptr != NULL) ++ { ++ if (strcasecmp (name, ptr->name) == 0) ++ return ptr->value; ++ ptr = ptr->next; ++ } ++ ++ return NULL; ++} ++ ++/* Load the login.defs file (/etc/login.defs) */ ++static void ++load_defaults_internal (const char *filename) ++{ ++ FILE *fp; ++ char *buf = NULL; ++ size_t buflen = 0; ++ ++ fp = fopen (filename, "r"); ++ if (NULL == fp) ++ return; ++ ++ while (!feof (fp)) ++ { ++ char *tmp, *cp; ++#if defined(HAVE_GETLINE) ++ ssize_t n = getline (&buf, &buflen, fp); ++#elif defined (HAVE_GETDELIM) ++ ssize_t n = getdelim (&buf, &buflen, '\n', fp); ++#else ++ ssize_t n; ++ ++ if (buf == NULL) ++ { ++ buflen = 8096; ++ buf = malloc (buflen); ++ } ++ buf[0] = '\0'; ++ fgets (buf, buflen - 1, fp); ++ if (buf != NULL) ++ n = strlen (buf); ++ else ++ n = 0; ++#endif /* HAVE_GETLINE / HAVE_GETDELIM */ ++ cp = buf; ++ ++ if (n < 1) ++ break; ++ ++ tmp = strchr (cp, '#'); /* remove comments */ ++ if (tmp) ++ *tmp = '\0'; ++ while (isspace ((int)*cp)) /* remove spaces and tabs */ ++ ++cp; ++ if (*cp == '\0') /* ignore empty lines */ ++ continue; ++ ++ if (cp[strlen (cp) - 1] == '\n') ++ cp[strlen (cp) - 1] = '\0'; ++ ++ tmp = strsep (&cp, " \t="); ++ if (cp != NULL) ++ while (isspace ((int)*cp) || *cp == '=') ++ ++cp; ++ ++ store (tmp, cp); ++ } ++ fclose (fp); ++ ++ if (buf) ++ free (buf); ++} ++ ++static void ++load_defaults (void) ++{ ++ load_defaults_internal ("/etc/default/su"); ++ load_defaults_internal ("/etc/login.defs"); ++} ++ ++int ++getdef_bool (const char *name, int dflt) ++{ ++ const char *val; ++ ++ if (list == NULL) ++ load_defaults (); ++ ++ val = search (name); ++ ++ if (val == NULL) ++ return dflt; ++ ++ return (strcasecmp (val, "yes") == 0); ++} ++ ++long ++getdef_num (const char *name, long dflt) ++{ ++ const char *val; ++ char *cp; ++ long retval; ++ ++ if (list == NULL) ++ load_defaults (); ++ ++ val = search (name); ++ ++ if (val == NULL) ++ return dflt; ++ ++ retval = strtol (val, &cp, 0); ++ if (*cp != '\0' || ++ ((retval == LONG_MAX || retval == LONG_MIN) && errno == ERANGE)) ++ { ++ fprintf (stderr, ++ "%s contains invalid numerical value: %s!\n", ++ name, val); ++ retval = dflt; ++ } ++ return retval; ++} ++ ++unsigned long ++getdef_unum (const char *name, unsigned long dflt) ++{ ++ const char *val; ++ char *cp; ++ unsigned long retval; ++ ++ if (list == NULL) ++ load_defaults (); ++ ++ val = search (name); ++ ++ if (val == NULL) ++ return dflt; ++ ++ retval = strtoul (val, &cp, 0); ++ if (*cp != '\0' || (retval == ULONG_MAX && errno == ERANGE)) ++ { ++ fprintf (stderr, ++ "%s contains invalid numerical value: %s!\n", ++ name, val); ++ retval = dflt; ++ } ++ return retval; ++} ++ ++const char * ++getdef_str (const char *name, const char *dflt) ++{ ++ const char *retval; ++ ++ if (list == NULL) ++ load_defaults (); ++ ++ retval = search (name); ++ ++ return retval ?: dflt; ++} ++ ++#if defined(TEST) ++ ++int ++main () ++{ ++ printf ("CYPT=%s\n", getdef_str ("cRypt", "no")); ++ printf ("LOG_UNKFAIL_ENAB=%s\n", getdef_str ("log_unkfail_enab","")); ++ printf ("DOESNOTEXIST=%s\n", getdef_str ("DOESNOTEXIST","yes")); ++ return 0; ++} ++ ++#endif +--- src/getdef.h ++++ src/getdef.h +@@ -0,0 +1,29 @@ ++/* Copyright (C) 2003, 2005 Thorsten Kukuk ++ Author: Thorsten Kukuk ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License version 2 as ++ published by the Free Software Foundation. ++ ++ 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, write to the Free Software Foundation, ++ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ++ ++#ifndef _GETDEF_H_ ++ ++#define _GETDEF_H_ 1 ++ ++extern int getdef_bool (const char *name, int dflt); ++extern long getdef_num (const char *name, long dflt); ++extern unsigned long getdef_unum (const char *name, unsigned long dflt); ++extern const char *getdef_str (const char *name, const char *dflt); ++ ++/* Free all data allocated by getdef_* calls before. */ ++extern void free_getdef_data (void); ++ ++#endif /* _GETDEF_H_ */ +--- src/install.c ++++ src/install.c +@@ -572,7 +572,8 @@ + while (pid != wait (&status)) /* Wait for kid to finish. */ + /* Do nothing. */ ; + if (status) +- error (EXIT_FAILURE, 0, _("strip failed")); ++ /* Don't fail just because `strip' failed. */ ++ error (0, 0, _("strip failed")); + break; + } + } +--- src/su.c ++++ src/su.c +@@ -38,6 +38,12 @@ + restricts who can su to UID 0 accounts. RMS considers that to + be fascist. + ++ Actually, with PAM, su has nothing to do with whether or not a ++ wheel group is enforced by su. RMS tries to restrict your access ++ to a su which implements the wheel group, but PAM considers that ++ to be fascist, and gives the user/sysadmin the opportunity to ++ enforce a wheel group by proper editing of /etc/pam.d/su ++ + Compile-time options: + -DSYSLOG_SUCCESS Log successful su's (by default, to root) with syslog. + -DSYSLOG_FAILURE Log failed su's (by default, to root) with syslog. +@@ -53,6 +59,13 @@ + #include + #include + #include ++#ifdef USE_PAM ++#include ++#include ++#include ++#include ++#include ++#endif + + /* Hide any system prototype for getusershell. + This is necessary because some Cray systems have a conflicting +@@ -66,6 +79,9 @@ + + #if HAVE_SYSLOG_H && HAVE_SYSLOG + # include ++# define SYSLOG_SUCCESS 1 ++# define SYSLOG_FAILURE 1 ++# define SYSLOG_NON_ROOT 1 + #else + # undef SYSLOG_SUCCESS + # undef SYSLOG_FAILURE +@@ -99,19 +115,13 @@ + # include + #endif + ++#include "getdef.h" ++ + /* The default PATH for simulated logins to non-superuser accounts. */ +-#ifdef _PATH_DEFPATH +-# define DEFAULT_LOGIN_PATH _PATH_DEFPATH +-#else +-# define DEFAULT_LOGIN_PATH ":/usr/ucb:/bin:/usr/bin" +-#endif ++#define DEFAULT_LOGIN_PATH "/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin" + + /* The default PATH for simulated logins to superuser accounts. */ +-#ifdef _PATH_DEFPATH_ROOT +-# define DEFAULT_ROOT_LOGIN_PATH _PATH_DEFPATH_ROOT +-#else +-# define DEFAULT_ROOT_LOGIN_PATH "/usr/ucb:/bin:/usr/bin:/etc" +-#endif ++#define DEFAULT_ROOT_LOGIN_PATH "/usr/sbin:/bin:/usr/bin:/sbin:/usr/X11R6/bin" + + /* The shell to run if none is given in the user's passwd entry. */ + #define DEFAULT_SHELL "/bin/sh" +@@ -119,7 +129,9 @@ + /* The user to become if none is specified. */ + #define DEFAULT_USER "root" + ++#ifndef USE_PAM + char *crypt (); ++#endif + char *getusershell (); + void endusershell (); + void setusershell (); +@@ -216,7 +228,26 @@ + } + #endif + ++#ifdef USE_PAM ++ ++static pam_handle_t *pamh = NULL; ++static int retval; ++static struct pam_conv conv = ++{ ++ misc_conv, ++ NULL ++}; ++ ++#define PAM_BAIL_P(a) \ ++ if (retval) \ ++ { \ ++ pam_end (pamh, PAM_SUCCESS); \ ++ a; \ ++ } ++#endif ++ + /* Ask the user for a password. ++ If PAM is in use, let PAM ask for the password if necessary. + Return true if the user gives the correct password for entry PW, + false if not. Return true without asking for a password if run by UID 0 + or if PW has an empty password. */ +@@ -224,10 +255,49 @@ + static bool + correct_password (const struct passwd *pw) + { ++#ifdef USE_PAM ++ const struct passwd *lpw; ++ const char *cp; ++ ++ retval = pam_start ("su", pw->pw_name, &conv, &pamh); ++ PAM_BAIL_P (return false); ++ ++ if (isatty (0) && (cp = ttyname (0)) != NULL) ++ { ++ const char *tty; ++ ++ if (strncmp (cp, "/dev/", 5) == 0) ++ tty = cp + 5; ++ else ++ tty = cp; ++ retval = pam_set_item (pamh, PAM_TTY, tty); ++ PAM_BAIL_P (return false); ++ } ++ cp = getlogin (); ++ if (!(cp && *cp && (lpw = getpwnam (cp)) != NULL && lpw->pw_uid == getuid ())) ++ lpw = getpwuid (getuid ()); ++ if (lpw) ++ { ++ retval = pam_set_item (pamh, PAM_RUSER, (const void *) lpw->pw_name); ++ PAM_BAIL_P (return false); ++ } ++ retval = pam_authenticate (pamh, 0); ++ PAM_BAIL_P (return false); ++ retval = pam_acct_mgmt (pamh, 0); ++ if (retval == PAM_NEW_AUTHTOK_REQD) ++ { ++ /* password has expired. Offer option to change it. */ ++ retval = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK); ++ PAM_BAIL_P (return false); ++ } ++ PAM_BAIL_P (return false); ++ /* must be authenticated if this point was reached */ ++ return true; ++#else /* !USE_PAM */ + char *unencrypted, *encrypted, *correct; + #if HAVE_GETSPNAM && HAVE_STRUCT_SPWD_SP_PWDP + /* Shadow passwd stuff for SVR3 and maybe other systems. */ +- struct spwd *sp = getspnam (pw->pw_name); ++ const struct spwd *sp = getspnam (pw->pw_name); + + endspent (); + if (sp) +@@ -248,6 +318,7 @@ + encrypted = crypt (unencrypted, correct); + memset (unencrypted, 0, strlen (unencrypted)); + return STREQ (encrypted, correct); ++#endif /* !USE_PAM */ + } + + /* Update `environ' for the new shell based on PW, with SHELL being +@@ -272,8 +343,8 @@ + xsetenv ("USER", pw->pw_name); + xsetenv ("LOGNAME", pw->pw_name); + xsetenv ("PATH", (pw->pw_uid +- ? DEFAULT_LOGIN_PATH +- : DEFAULT_ROOT_LOGIN_PATH)); ++ ? getdef_str ("PATH", DEFAULT_LOGIN_PATH) ++ : getdef_str ("SUPATH", DEFAULT_ROOT_LOGIN_PATH))); + } + else + { +@@ -283,6 +354,12 @@ + { + xsetenv ("HOME", pw->pw_dir); + xsetenv ("SHELL", shell); ++ if (getdef_bool ("ALWAYS_SET_PATH", 0)) ++ xsetenv ("PATH", (pw->pw_uid ++ ? getdef_str ("PATH", ++ DEFAULT_LOGIN_PATH) ++ : getdef_str ("SUPATH", ++ DEFAULT_ROOT_LOGIN_PATH))); + if (pw->pw_uid) + { + xsetenv ("USER", pw->pw_name); +@@ -303,12 +380,35 @@ + error (EXIT_FAIL, errno, _("cannot set groups")); + endgrent (); + #endif ++#ifdef USE_PAM ++ retval = pam_setcred (pamh, PAM_ESTABLISH_CRED); ++ if (retval != PAM_SUCCESS) ++ error (EXIT_FAIL, 0, "%s", pam_strerror (pamh, retval)); ++ ++ retval = pam_open_session (pamh,0); ++ if (retval != PAM_SUCCESS) ++ { ++ pam_setcred (pamh, PAM_DELETE_CRED); ++ error (EXIT_FAIL, 0, "could not open session: %s", ++ pam_strerror (pamh, retval)); ++ } ++#endif /* USE_PAM */ + if (setgid (pw->pw_gid)) + error (EXIT_FAIL, errno, _("cannot set group id")); + if (setuid (pw->pw_uid)) + error (EXIT_FAIL, errno, _("cannot set user id")); + } + ++#ifdef USE_PAM ++static bool caught = false; ++/* Signal handler for parent process later */ ++static void ++su_catch_sig (int sig) ++{ ++ caught = true; ++} ++#endif ++ + /* Run SHELL, or DEFAULT_SHELL if SHELL is empty. + If COMMAND is nonzero, pass it to the shell with the -c option. + Pass ADDITIONAL_ARGS to the shell as more arguments; there +@@ -321,6 +421,88 @@ + size_t n_args = 1 + fast_startup + 2 * !!command + n_additional_args + 1; + char const **args = xnmalloc (n_args, sizeof *args); + size_t argno = 1; ++#ifdef USE_PAM ++ pid_t child; ++ sigset_t ourset; ++ int status; ++ ++ child = fork (); ++ if (child == (pid_t) -1) ++ error (EXIT_FAILURE, errno, "cannot fork"); ++ ++ if (child != 0) ++ { ++ /* parent only */ ++ sigfillset (&ourset); ++ if (sigprocmask (SIG_BLOCK, &ourset, NULL)) ++ { ++ error (0, errno, "cannot block signals"); ++ caught = true; ++ } ++ if (!caught) ++ { ++ struct sigaction action; ++ action.sa_handler = su_catch_sig; ++ sigemptyset (&action.sa_mask); ++ action.sa_flags = 0; ++ sigemptyset (&ourset); ++ if (sigaddset (&ourset, SIGTERM) ++ || sigaddset (&ourset, SIGALRM) ++ || sigaction (SIGTERM, &action, NULL) ++ || sigprocmask (SIG_UNBLOCK, &ourset, NULL)) ++ { ++ error (0, errno, "cannot set signal handler"); ++ caught = true; ++ } ++ } ++ if (!caught) ++ { ++ for (;;) ++ { ++ pid_t pid; ++ ++ pid = waitpid (child, &status, WUNTRACED); ++ ++ if (WIFSTOPPED (status)) ++ { ++ kill (getpid (), SIGSTOP); ++ /* once we get here, we must have resumed */ ++ kill (pid, SIGCONT); ++ } ++ else ++ break; ++ } ++ if (WIFSIGNALED (status)) ++ status = WTERMSIG (status) + 128; ++ else ++ status = WEXITSTATUS (status); ++ } ++ else ++ status = 1; ++ ++ if (caught) ++ { ++ fprintf (stderr, "\nSession terminated, killing shell..."); ++ kill (child, SIGTERM); ++ } ++ retval = pam_setcred (pamh, PAM_DELETE_CRED); ++ PAM_BAIL_P (exit (EXIT_FAILURE)); ++ retval = pam_close_session (pamh, 0); ++ PAM_BAIL_P (exit (EXIT_FAILURE)); ++ retval = pam_end (pamh, PAM_SUCCESS); ++ PAM_BAIL_P (exit (EXIT_FAILURE)); ++ if (caught) ++ { ++ sleep (2); ++ kill (child, SIGKILL); ++ fprintf (stderr, " ...killed.\n"); ++ } ++ exit (status); ++ } ++ ++ /* child shell */ ++ pam_end (pamh, 0); ++#endif + + if (simulate_login) + { +@@ -339,6 +521,11 @@ + args[argno++] = "-f"; + if (command) + { ++ if (simulate_login) ++ /* Bash 2.0 have to be invoked as `-su'. See the comments in ++ `shell.c (run_startup_files)'. */ ++ args[0] = "-su"; ++ + args[argno++] = "-c"; + args[argno++] = command; + } +@@ -495,6 +682,9 @@ + #ifdef SYSLOG_FAILURE + log_su (pw, false); + #endif ++#ifdef USE_PAM ++ sleep (getdef_num ("FAIL_DELAY", 1)); ++#endif + error (EXIT_FAIL, 0, _("incorrect password")); + } + #ifdef SYSLOG_SUCCESS +--- src/system.h ++++ src/system.h +@@ -173,7 +173,7 @@ + # define DEV_BSIZE BBSIZE + #endif + #ifndef DEV_BSIZE +-# define DEV_BSIZE 4096 ++# define DEV_BSIZE 512 + #endif + + /* Extract or fake data from a `struct stat'. +--- tests/help-version ++++ tests/help-version +@@ -190,7 +190,7 @@ + + for i in $all_programs; do + # Skip these. +- case $i in chroot|stty|tty|false) continue;; esac ++ case $i in chroot|stty|tty|false|df) continue;; esac + + rm -rf $tmp_in $tmp_in2 $tmp_dir $tmp_out + echo > $tmp_in +--- tests/other-fs-tmpdir ++++ tests/other-fs-tmpdir +@@ -44,6 +44,8 @@ + fi + + done ++# Autobuild hack ++test -f /bin/uname.bin && other_partition_tmpdir= + + if test -z "$other_partition_tmpdir"; then + cat <&2 diff --git a/coreutils-6.7.tar.bz2 b/coreutils-6.7.tar.bz2 new file mode 100644 index 0000000..dba9d75 --- /dev/null +++ b/coreutils-6.7.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d7027cc803682decdadf850095dce7e22cc08eba2b1283e16d0fb7a675ac1f0 +size 5315342 diff --git a/coreutils-8.32.tar.xz b/coreutils-8.32.tar.xz deleted file mode 100644 index ade8076..0000000 --- a/coreutils-8.32.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4458d8de7849df44ccab15e16b1548b285224dbba5f08fac070c1c0e0bcc4cfa -size 5547836 diff --git a/coreutils-8.32.tar.xz.sig b/coreutils-8.32.tar.xz.sig deleted file mode 100644 index 531e238..0000000 --- a/coreutils-8.32.tar.xz.sig +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCAAdFiEEbDfcEhIaUAa8HbgE32/ZcTBgN9kFAl5hC5MACgkQ32/ZcTBg -N9n92Q//Td2GE1f8AZKkxCNI76Q/TqbxAwhjbkR+KdzvsyMePmgHcMgHG6sO2MNF -g6DIBmHpO3vWGzvUxUZRRhuW5QBOnMxHb/WXZ0p/g45d5MQdn4i0dA0wUJgByOqn -/WVfygNg9mrWFx/uTeCdhrwL11m71C7j/eQVu7Wr5DIb20VJ8+nVC2IWW33ZvxRj -Goa0wwDpeeD9qYe/Y+E5ZyhDYHJGRmNAlS03SXLO3+RfsbZFwdQEtzvr+v1VN6/S -9OsoI/GLdRjY1tByppaoZ63ZybB6iF5zZfJiWDF7Nw4MduJpjZQDSywiNleJ9vOi -fwR1180PjMV6aTXvPwqbqQxZjDl7nqvO36ghlTvErJbqdJVIYxmUGNjeJyjqI85l -Lhckh0GWos9K/kl13Ry9KWsxNQgfjNhtgjXGh+W47ojrho2kCiK5BTwDFeVU0jtU -H/1EePSGAIUF/Sfjz3rmGgLaaBwPiRiyzEIuZMyd4NCJWwfOTqgOshOYw15GCWYq -wGesN/4LWzEja7Au5lHP7imXjP0bp4qE/sYrOb4WzVVLCn+z2hu6SEIzjJzSm+D+ -8Wv3Ia1/ypVpR+Z7gUt7VtEvI8zAwlySd/6Jw5U7TL0rzvZsTVWmCvEjPp+o3jCB -Fy/4ybao1gowBFtT1AtPMmxmiJ41KWCxLFrTuGJpFYCGvBH2y8s= -=yHV6 ------END PGP SIGNATURE----- diff --git a/coreutils-build-timeout-as-pie.patch b/coreutils-build-timeout-as-pie.patch deleted file mode 100644 index 0633f3e..0000000 --- a/coreutils-build-timeout-as-pie.patch +++ /dev/null @@ -1,39 +0,0 @@ -From d1a49cccf99373293a88f5bce74857d5bb813e46 Mon Sep 17 00:00:00 2001 -From: Bernhard Voelker -Date: Thu, 10 Jan 2013 09:21:22 +0200 -Subject: build timeout as PIE - -The OBS requires /usr/bin/timeout to be built as an position -independent executable (PIE). This is enforced via RPMLINT. - -* src/local.mk (AM_CFLAGS): Add -fpie option. -(timeout_CFLAGS): Likewise. -(timeout_LDFLAGS): Add -pie option. - ---- - src/local.mk | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -Index: src/local.mk -=================================================================== ---- src/local.mk.orig -+++ src/local.mk -@@ -17,7 +17,7 @@ - ## along with this program. If not, see . - - # FIXME: once lib/ and gnulib-tests/ are also converted, hoist to Makefile.am --AM_CFLAGS = $(WERROR_CFLAGS) -+AM_CFLAGS = $(WERROR_CFLAGS) -fpie - - # The list of all programs (separated in different variables to express - # the how and when they should be installed) is defined in this makefile -@@ -280,6 +280,9 @@ src_factor_LDADD += $(LIB_GMP) - # for getloadavg - src_uptime_LDADD += $(GETLOADAVG_LIBS) - -+src_timeout_CFLAGS = -fpie -+src_timeout_LDFLAGS = -pie -+ - # for various ACL functions - copy_ldadd += $(LIB_ACL) - src_ls_LDADD += $(LIB_HAS_ACL) diff --git a/coreutils-changelog.diff b/coreutils-changelog.diff new file mode 100644 index 0000000..2cafff1 --- /dev/null +++ b/coreutils-changelog.diff @@ -0,0 +1,44 @@ +2005-10-20 Andreas Gruenbacher + + * Add support for access control lists and extended attributes + (see below). + + * lib/acl.h: Remove HAVE_ACL symbol; is needed for POSIX + ACLs even if there is no acl system call. + + * lib/acl.c (file_has_acl, copy_acl, set_acl): Add Linux/POSIX ACL + implementation. + + * src/copy.c (get_dest_mode): Remove, no longer correct with acls. + + * src/copy.c (copy_internal): Check effective permissions after + mkdir(). Add S_IRWXU only after saving the default permissions, + so that the default permissions can be restored. This is needed + with POSIX 1003.1e draft 17 acls. Add dst_mode and dst_mode_valid, + which are set when the destination file mode is changed + temporarily. Remove obsolete ran_chown. + + * src/copy.c (copy_internal): Use copy_acl and set_acl instead of + chmod. + + * src/copy.c: Add --attributes option for controlling which extended + attributes to copy. + + * src/cp.c (make_path_private): Remove the mode parameter. Pass in + cp_options, instead of cp_options->xstat only. Stat the source dir, + and create the destination dir with the source dir's mode as create + mode (see analog change to src/copy.c (copy_internal)). Check if the + effective permissions include S_IRWXU. Remember the original mode + only if needed later. + + * src/cp.c, src/install.c, src/mv.c, src/copy.h: Remove umask_kill, + and never change the startup umask. The functions creating files + need the original umask to create the correct permissions inside + directories with default ACLs. + + * src/cp.c (struct dir_attr, re_protect, make_path_private): Replace + is_new_dir by mode and mode_valid variables. + + * src/ls.c: change `HAVE_ACL' to `USE_ACL' for POSIX ACLs: POSIX ACLs + have no acl syscall. + diff --git a/coreutils-disable_tests.patch b/coreutils-disable_tests.patch deleted file mode 100644 index efb32e8..0000000 --- a/coreutils-disable_tests.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- - gnulib-tests/gnulib.mk | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -Index: gnulib-tests/gnulib.mk -=================================================================== ---- gnulib-tests/gnulib.mk.orig -+++ gnulib-tests/gnulib.mk -@@ -951,10 +951,10 @@ EXTRA_DIST += test-getloadavg.c signatur - - ## begin gnulib module getlogin-tests - --TESTS += test-getlogin --check_PROGRAMS += test-getlogin --test_getlogin_LDADD = $(LDADD) $(LIB_GETLOGIN) --EXTRA_DIST += test-getlogin.c test-getlogin.h signature.h macros.h -+#TESTS += test-getlogin -+#check_PROGRAMS += test-getlogin -+#test_getlogin_LDADD = $(LDADD) $(LIB_GETLOGIN) -+#EXTRA_DIST += test-getlogin.c test-getlogin.h signature.h macros.h - - ## end gnulib module getlogin-tests - diff --git a/coreutils-getaddrinfo.patch b/coreutils-getaddrinfo.patch deleted file mode 100644 index 410d377..0000000 --- a/coreutils-getaddrinfo.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- - gnulib-tests/test-getaddrinfo.c | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) - -Index: gnulib-tests/test-getaddrinfo.c -=================================================================== ---- gnulib-tests/test-getaddrinfo.c.orig -+++ gnulib-tests/test-getaddrinfo.c -@@ -93,11 +93,7 @@ simple (char const *host, char const *se - the test merely because someone is down the country on their - in-law's farm. */ - if (res == EAI_AGAIN) -- { -- skip++; -- fprintf (stderr, "skipping getaddrinfo test: no network?\n"); -- return 77; -- } -+ return 0; - /* IRIX reports EAI_NONAME for "https". Don't fail the test - merely because of this. */ - if (res == EAI_NONAME) diff --git a/coreutils-gnulib-disable-test-float.patch b/coreutils-gnulib-disable-test-float.patch deleted file mode 100644 index c49e107..0000000 --- a/coreutils-gnulib-disable-test-float.patch +++ /dev/null @@ -1,25 +0,0 @@ -Disable gnulib test 'test-float' temporarily as it fails on ppc and ppc64le. - -* gnulib-tests/gnulib.mk: Comment lines related to 'test-float'. ---- - gnulib-tests/gnulib.mk | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -Index: gnulib-tests/gnulib.mk -=================================================================== ---- gnulib-tests/gnulib.mk.orig -+++ gnulib-tests/gnulib.mk -@@ -635,9 +635,10 @@ EXTRA_DIST += test-filevercmp.c macros.h - - ## begin gnulib module float-tests - --TESTS += test-float --check_PROGRAMS += test-float --EXTRA_DIST += test-float.c macros.h -+# Test fails with GCC-10 on ppc and ppc64le. -+#TESTS += test-float -+#check_PROGRAMS += test-float -+#EXTRA_DIST += test-float.c macros.h - - ## end gnulib module float-tests - diff --git a/coreutils-i18n.patch b/coreutils-i18n.patch deleted file mode 100644 index 965d65b..0000000 --- a/coreutils-i18n.patch +++ /dev/null @@ -1,5332 +0,0 @@ - bootstrap.conf | 1 - configure.ac | 2 - lib/linebuffer.h | 8 - lib/mbfile.c | 3 - lib/mbfile.h | 255 ++++++++++++++ - m4/mbfile.m4 | 14 - src/cut.c | 441 ++++++++++++++++++++++++- - src/expand-common.c | 114 ++++++ - src/expand-common.h | 12 - src/expand.c | 90 ++++- - src/fold.c | 308 ++++++++++++++++- - src/join.c | 359 +++++++++++++++++--- - src/pr.c | 443 ++++++++++++++++++++++--- - src/sort.c | 772 +++++++++++++++++++++++++++++++++++++++++--- - src/unexpand.c | 101 ++++- - src/uniq.c | 119 ++++++ - tests/expand/mb.sh | 183 ++++++++++ - tests/i18n/sort.sh | 29 + - tests/local.mk | 4 - tests/misc/expand.pl | 42 ++ - tests/misc/fold.pl | 50 ++ - tests/misc/join.pl | 50 ++ - tests/misc/sort-mb-tests.sh | 45 ++ - tests/misc/sort-merge.pl | 42 ++ - tests/misc/sort.pl | 40 ++ - tests/misc/unexpand.pl | 39 ++ - tests/misc/uniq.pl | 55 +++ - tests/pr/pr-tests.pl | 49 ++ - tests/unexpand/mb.sh | 172 +++++++++ - 29 files changed, 3632 insertions(+), 210 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 - -Index: bootstrap.conf -=================================================================== ---- bootstrap.conf.orig -+++ bootstrap.conf -@@ -154,6 +154,7 @@ gnulib_modules=" - maintainer-makefile - malloc-gnu - manywarnings -+ mbfile - mbrlen - mbrtowc - mbsalign -Index: configure.ac -=================================================================== ---- configure.ac.orig -+++ configure.ac -@@ -446,6 +446,8 @@ fi - # I'm leaving it here for now. This whole thing needs to be modernized... - gl_WINSIZE_IN_PTEM - -+gl_MBFILE -+ - gl_HEADER_TIOCGWINSZ_IN_TERMIOS_H - - if test $gl_cv_sys_tiocgwinsz_needs_termios_h = no && \ -Index: lib/linebuffer.h -=================================================================== ---- lib/linebuffer.h.orig -+++ lib/linebuffer.h -@@ -21,6 +21,11 @@ - - # include - -+/* Get mbstate_t. */ -+# if HAVE_WCHAR_H -+# include -+# endif -+ - /* A 'struct linebuffer' holds a line of text. */ - - struct linebuffer -@@ -28,6 +33,9 @@ struct linebuffer - size_t size; /* Allocated. */ - size_t length; /* Used. */ - char *buffer; -+# if HAVE_WCHAR_H -+ mbstate_t state; -+# endif - }; - - /* Initialize linebuffer LINEBUFFER for use. */ -Index: lib/mbfile.c -=================================================================== ---- /dev/null -+++ lib/mbfile.c -@@ -0,0 +1,3 @@ -+#include -+#define MBFILE_INLINE _GL_EXTERN_INLINE -+#include "mbfile.h" -Index: lib/mbfile.h -=================================================================== ---- /dev/null -+++ lib/mbfile.h -@@ -0,0 +1,255 @@ -+/* Multibyte character I/O: macros for multi-byte encodings. -+ Copyright (C) 2001, 2005, 2009-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 . */ -+ -+/* 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 -+ -+#include -+#include -+#include -+#include -+ -+/* Tru64 with Desktop Toolkit C has a bug: must be included before -+ . -+ BSD/OS 4.1 has a bug: and must be included before -+ . */ -+#include -+#include -+#include -+ -+#include "mbchar.h" -+ -+#ifndef _GL_INLINE_HEADER_BEGIN -+ #error "Please include config.h first." -+#endif -+_GL_INLINE_HEADER_BEGIN -+#ifndef MBFILE_INLINE -+# define MBFILE_INLINE _GL_INLINE -+#endif -+ -+struct mbfile_multi { -+ FILE *fp; -+ bool eof_seen; -+ bool have_pushback; -+ mbstate_t state; -+ unsigned int bufcount; -+ char buf[MBCHAR_BUF_SIZE]; -+ struct mbchar pushback; -+}; -+ -+MBFILE_INLINE void -+mbfile_multi_getc (struct mbchar *mbc, struct mbfile_multi *mbf) -+{ -+ size_t bytes; -+ -+ /* 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; -+ -+ /* Return character pushed back, if there is one. */ -+ if (mbf->have_pushback) -+ { -+ mb_copy (mbc, &mbf->pushback); -+ mbf->have_pushback = false; -+ return; -+ } -+ -+ /* Before using mbrtowc, we need at least one byte. */ -+ if (mbf->bufcount == 0) -+ { -+ int c = getc (mbf->fp); -+ if (c == EOF) -+ { -+ mbf->eof_seen = true; -+ goto eof; -+ } -+ mbf->buf[0] = (unsigned char) c; -+ mbf->bufcount++; -+ } -+ -+ /* Handle most ASCII characters quickly, without calling mbrtowc(). */ -+ if (mbf->bufcount == 1 && mbsinit (&mbf->state) && is_basic (mbf->buf[0])) -+ { -+ /* These characters are part of the basic character set. ISO C 99 -+ guarantees that their wide character code is identical to their -+ char code. */ -+ 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 mbrtowc 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 (;;) -+ { -+ /* We don't know whether the 'mbrtowc' function updates the state when -+ it returns -2, - this is the ISO C 99 and glibc-2.2 behaviour - or -+ not - amended ANSI C, glibc-2.1 and Solaris 2.7 behaviour. We -+ don't have an autoconf test for this, yet. -+ The new behaviour would allow us to feed the bytes one by one into -+ mbrtowc. But the old behaviour forces us to feed all bytes since -+ the end of the last character into mbrtowc. Since we want to retry -+ with more bytes when mbrtowc returns -2, we must backup the state -+ before calling mbrtowc, because implementations with the new -+ behaviour will clobber it. */ -+ mbstate_t backup_state = mbf->state; -+ -+ bytes = mbrtowc (&mbc->wc, &mbf->buf[0], mbf->bufcount, &mbf->state); -+ -+ if (bytes == (size_t) -1) -+ { -+ /* An invalid multibyte sequence was encountered. */ -+ /* Return a single byte. */ -+ bytes = 1; -+ mbc->wc_valid = false; -+ break; -+ } -+ else if (bytes == (size_t) -2) -+ { -+ /* An incomplete multibyte character. */ -+ mbf->state = backup_state; -+ 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 mbrtowc. */ -+ int c = getc (mbf->fp); -+ if (c == EOF) -+ { -+ /* An incomplete multibyte character at the end. */ -+ mbf->eof_seen = true; -+ bytes = mbf->bufcount; -+ mbc->wc_valid = false; -+ break; -+ } -+ mbf->buf[mbf->bufcount] = (unsigned char) c; -+ mbf->bufcount++; -+ } -+ } -+ else -+ { -+ if (bytes == 0) -+ { -+ /* A null 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) -+{ -+ mb_copy (&mbf->pushback, mbc); -+ mbf->have_pushback = true; -+} -+ -+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).have_pushback = false, \ -+ memset (&(mbf).state, '\0', sizeof (mbstate_t)), \ -+ (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) -+ -+#ifndef _GL_INLINE_HEADER_BEGIN -+ #error "Please include config.h first." -+#endif -+_GL_INLINE_HEADER_BEGIN -+ -+#endif /* _MBFILE_H */ -Index: m4/mbfile.m4 -=================================================================== ---- /dev/null -+++ m4/mbfile.m4 -@@ -0,0 +1,14 @@ -+# mbfile.m4 serial 7 -+dnl Copyright (C) 2005, 2008-2015 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 autoconf tests required for use of mbfile.h -+dnl From Bruno Haible. -+ -+AC_DEFUN([gl_MBFILE], -+[ -+ AC_REQUIRE([AC_TYPE_MBSTATE_T]) -+ : -+]) -Index: src/cut.c -=================================================================== ---- src/cut.c.orig -+++ src/cut.c -@@ -28,6 +28,11 @@ - #include - #include - #include -+ -+/* Get mbstate_t, mbrtowc(). */ -+#if HAVE_WCHAR_H -+# include -+#endif - #include "system.h" - - #include "error.h" -@@ -38,6 +43,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. */ -+#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 -+ - /* The official name of this program (e.g., no 'g' prefix). */ - #define PROGRAM_NAME "cut" - -@@ -54,6 +71,52 @@ - } \ - while (0) - -+/* Refill the buffer BUF to get a multibyte character. */ -+#define REFILL_BUFFER(BUF, BUFPOS, BUFLEN, STREAM) \ -+ do \ -+ { \ -+ if (BUFLEN < MB_LEN_MAX && !feof (STREAM) && !ferror (STREAM)) \ -+ { \ -+ memmove (BUF, BUFPOS, BUFLEN); \ -+ BUFLEN += fread (BUF + BUFLEN, sizeof(char), BUFSIZ, STREAM); \ -+ BUFPOS = BUF; \ -+ } \ -+ } \ -+ while (0) -+ -+/* Get wide character on BUFPOS. BUFPOS is not included after that. -+ If byte sequence is not valid as a character, CONVFAIL is true. Otherwise false. */ -+#define GET_NEXT_WC_FROM_BUFFER(WC, BUFPOS, BUFLEN, MBLENGTH, STATE, CONVFAIL) \ -+ do \ -+ { \ -+ mbstate_t state_bak; \ -+ \ -+ if (BUFLEN < 1) \ -+ { \ -+ WC = WEOF; \ -+ break; \ -+ } \ -+ \ -+ /* Get a wide character. */ \ -+ CONVFAIL = false; \ -+ state_bak = STATE; \ -+ MBLENGTH = mbrtowc ((wchar_t *)&WC, BUFPOS, BUFLEN, &STATE); \ -+ \ -+ switch (MBLENGTH) \ -+ { \ -+ case (size_t)-1: \ -+ case (size_t)-2: \ -+ CONVFAIL = true; \ -+ STATE = state_bak; \ -+ /* Fall througn. */ \ -+ \ -+ case 0: \ -+ MBLENGTH = 1; \ -+ break; \ -+ } \ -+ } \ -+ while (0) -+ - - /* Pointer inside RP. When checking if a byte or field is selected - by a finite range, we check if it is between CURRENT_RP.LO -@@ -61,6 +124,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 -@@ -77,15 +143,25 @@ enum operating_mode - { - undefined_mode, - -- /* Output characters that are in the given bytes. */ -+ /* Output bytes that are at the given positions. */ - byte_mode, - -+ /* Output characters that are at the given positions. */ -+ character_mode, -+ - /* Output the given delimiter-separated fields. */ - field_mode - }; - - static enum operating_mode operating_mode; - -+/* If nonzero, when in byte mode, don't split multibyte characters. */ -+static int byte_mode_character_aware; -+ -+/* If nonzero, the function for single byte locale is work -+ if this program runs on multibyte locale. */ -+static int force_singlebyte_mode; -+ - /* If true do not output lines containing no delimiter characters. - Otherwise, all such lines are printed. This option is valid only - with field mode. */ -@@ -97,6 +173,9 @@ static bool complement; - - /* The delimiter character for field mode. */ - static unsigned char delim; -+#if HAVE_WCHAR_H -+static wchar_t wcdelim; -+#endif - - /* The delimiter for each line/record. */ - static unsigned char line_delim = '\n'; -@@ -164,7 +243,7 @@ Print selected parts of lines from each - -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\ -- -n (ignored)\n\ -+ -n with -b: don't split multibyte characters\n\ - "), stdout); - fputs (_("\ - --complement complement the set of selected bytes, characters\n\ -@@ -280,6 +359,82 @@ cut_bytes (FILE *stream) - } - } - -+#if HAVE_MBRTOWC -+/* This function is in use for the following case. -+ -+ 1. Read from the stream STREAM, printing to standard output any selected -+ characters. -+ -+ 2. Read from stream STREAM, printing to standard output any selected bytes, -+ without splitting multibyte characters. */ -+ -+static void -+cut_characters_or_cut_bytes_no_split (FILE *stream) -+{ -+ 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. */ -+ 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 of the stream. */ -+ 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; -+ -+ idx = 0; -+ buflen = 0; -+ bufpos = buf; -+ memset (&state, '\0', sizeof(mbstate_t)); -+ -+ current_rp = frp; -+ -+ while (1) -+ { -+ REFILL_BUFFER (buf, bufpos, buflen, stream); -+ -+ GET_NEXT_WC_FROM_BUFFER (wc, bufpos, buflen, mblength, state, convfail); -+ (void) convfail; /* ignore unused */ -+ -+ if (wc == WEOF) -+ { -+ if (idx > 0) -+ putchar (line_delim); -+ break; -+ } -+ else if (wc == line_delim) -+ { -+ putchar (line_delim); -+ idx = 0; -+ print_delimiter = false; -+ current_rp = frp; -+ } -+ else -+ { -+ next_item (&idx); -+ if (print_kth (idx)) -+ { -+ if (output_delimiter_specified) -+ { -+ 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); -+ } -+ } -+ -+ buflen -= mblength; -+ bufpos += mblength; -+ } -+} -+#endif -+ - /* Read from stream STREAM, printing to standard output any selected fields. */ - - static void -@@ -425,13 +580,211 @@ cut_fields (FILE *stream) - } - } - -+#if HAVE_MBRTOWC -+static void -+cut_fields_mb (FILE *stream) -+{ -+ int c; -+ uintmax_t field_idx; -+ int found_any_selected_field; -+ int buffer_first_field; -+ int empty_input; -+ 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. */ -+ wint_t wc = 0; /* 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 of the stream. */ -+ bool convfail = false; /* true, when conversion failed. Otherwise false. */ -+ -+ current_rp = frp; -+ -+ found_any_selected_field = 0; -+ field_idx = 1; -+ bufpos = buf; -+ buflen = 0; -+ memset (&state, '\0', sizeof(mbstate_t)); -+ -+ c = getc (stream); -+ empty_input = (c == EOF); -+ if (c != EOF) -+ { -+ ungetc (c, stream); -+ wc = 0; -+ } -+ else -+ wc = WEOF; -+ -+ /* To support the semantics of the -s flag, we may have to buffer -+ all of the first field to determine whether it is `delimited.' -+ But that is unnecessary if all non-delimited lines must be printed -+ 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)); -+ -+ while (1) -+ { -+ if (field_idx == 1 && buffer_first_field) -+ { -+ int len = 0; -+ -+ while (1) -+ { -+ REFILL_BUFFER (buf, bufpos, buflen, stream); -+ -+ GET_NEXT_WC_FROM_BUFFER -+ (wc, bufpos, buflen, mblength, state, convfail); -+ -+ if (wc == WEOF) -+ break; -+ -+ field_1_buffer = xrealloc (field_1_buffer, len + mblength); -+ memcpy (field_1_buffer + len, bufpos, mblength); -+ len += mblength; -+ buflen -= mblength; -+ bufpos += mblength; -+ -+ if (!convfail && (wc == line_delim || wc == wcdelim)) -+ break; -+ } -+ -+ if (len <= 0 && wc == WEOF) -+ break; -+ -+ /* If the first field extends to the end of line (it is not -+ delimited) and we are printing all non-delimited lines, -+ print this one. */ -+ if (convfail || (!convfail && wc != wcdelim)) -+ { -+ if (suppress_non_delimited) -+ { -+ /* Empty. */ -+ } -+ else -+ { -+ fwrite (field_1_buffer, sizeof (char), len, stdout); -+ /* Make sure the output line is newline terminated. */ -+ if (convfail || (!convfail && wc != line_delim)) -+ putchar (line_delim); -+ } -+ continue; -+ } -+ -+ 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; -+ } -+ next_item (&field_idx); -+ } -+ -+ if (wc != WEOF) -+ { -+ if (print_kth (field_idx)) -+ { -+ if (found_any_selected_field) -+ { -+ fwrite (output_delimiter_string, sizeof (char), -+ output_delimiter_length, stdout); -+ } -+ found_any_selected_field = 1; -+ } -+ -+ while (1) -+ { -+ REFILL_BUFFER (buf, bufpos, buflen, stream); -+ -+ GET_NEXT_WC_FROM_BUFFER -+ (wc, bufpos, buflen, mblength, state, convfail); -+ -+ if (wc == WEOF) -+ break; -+ else if (!convfail && (wc == wcdelim || wc == line_delim)) -+ { -+ buflen -= mblength; -+ bufpos += mblength; -+ break; -+ } -+ -+ if (print_kth (field_idx)) -+ fwrite (bufpos, mblength, sizeof(char), stdout); -+ -+ buflen -= mblength; -+ bufpos += mblength; -+ } -+ } -+ -+ if ((!convfail || wc == line_delim) && buflen < 1) -+ wc = WEOF; -+ -+ if (!convfail && wc == wcdelim) -+ 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 (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); -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1 && !force_singlebyte_mode) -+ { -+ switch (operating_mode) -+ { -+ case byte_mode: -+ if (byte_mode_character_aware) -+ cut_characters_or_cut_bytes_no_split (stream); -+ else -+ cut_bytes (stream); -+ break; -+ -+ case character_mode: -+ cut_characters_or_cut_bytes_no_split (stream); -+ 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; -+ -+ default: -+ abort (); -+ } -+ } - else -- cut_fields (stream); -+#endif -+ { -+ if (operating_mode == field_mode) -+ cut_fields (stream); -+ else -+ cut_bytes (stream); -+ } - } - - /* Process file FILE to standard output. -@@ -483,6 +836,7 @@ main (int argc, char **argv) - bool ok; - bool delim_specified = false; - char *spec_list_string IF_LINT ( = NULL); -+ char mbdelim[MB_LEN_MAX + 1]; - - initialize_main (&argc, &argv); - set_program_name (argv[0]); -@@ -505,7 +859,6 @@ 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")); -@@ -513,6 +866,14 @@ main (int argc, char **argv) - spec_list_string = optarg; - break; - -+ case 'c': -+ /* Build the character list. */ -+ if (operating_mode != undefined_mode) -+ FATAL_ERROR (_("only one type of list may be specified")); -+ operating_mode = character_mode; -+ spec_list_string = optarg; -+ break; -+ - case 'f': - /* Build the field list. */ - if (operating_mode != undefined_mode) -@@ -524,10 +885,38 @@ main (int argc, char **argv) - case 'd': - /* New delimiter. */ - /* Interpret -d '' to mean 'use the NUL byte as the delimiter.' */ -- if (optarg[0] != '\0' && optarg[1] != '\0') -- FATAL_ERROR (_("the delimiter must be a single character")); -- delim = optarg[0]; -- delim_specified = true; -+ { -+#if HAVE_MBRTOWC -+ if(MB_CUR_MAX > 1) -+ { -+ mbstate_t state; -+ -+ memset (&state, '\0', sizeof(mbstate_t)); -+ delimlen = mbrtowc (&wcdelim, optarg, strnlen(optarg, MB_LEN_MAX), &state); -+ -+ if (delimlen == (size_t)-1 || delimlen == (size_t)-2) -+ ++force_singlebyte_mode; -+ else -+ { -+ delimlen = (delimlen < 1) ? 1 : delimlen; -+ 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; -+ } -+ } -+ -+ if (MB_CUR_MAX <= 1 || force_singlebyte_mode) -+#endif -+ { -+ if (optarg[0] != '\0' && optarg[1] != '\0') -+ FATAL_ERROR (_("the delimiter must be a single character")); -+ delim = (unsigned char) optarg[0]; -+ } -+ delim_specified = true; -+ } - break; - - case OUTPUT_DELIMITER_OPTION: -@@ -540,6 +929,7 @@ main (int argc, char **argv) - break; - - case 'n': -+ byte_mode_character_aware = 1; - break; - - case 's': -@@ -579,15 +969,34 @@ main (int argc, char **argv) - | (complement ? SETFLD_COMPLEMENT : 0) ); - - if (!delim_specified) -- delim = '\t'; -+ { -+ delim = '\t'; -+#ifdef HAVE_MBRTOWC -+ wcdelim = L'\t'; -+ mbdelim[0] = '\t'; -+ mbdelim[1] = '\0'; -+ delimlen = 1; -+#endif -+ } - - if (output_delimiter_string == NULL) - { -- static char dummy[2]; -- dummy[0] = delim; -- dummy[1] = '\0'; -- output_delimiter_string = dummy; -- output_delimiter_length = 1; -+#ifdef HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1 && !force_singlebyte_mode) -+ { -+ output_delimiter_string = xstrdup(mbdelim); -+ output_delimiter_length = delimlen; -+ } -+ -+ if (MB_CUR_MAX <= 1 || force_singlebyte_mode) -+#endif -+ { -+ static char dummy[2]; -+ dummy[0] = delim; -+ dummy[1] = '\0'; -+ output_delimiter_string = dummy; -+ output_delimiter_length = 1; -+ } - } - - if (optind == argc) -Index: src/expand-common.c -=================================================================== ---- src/expand-common.c.orig -+++ src/expand-common.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include "system.h" - #include "die.h" - #include "error.h" -@@ -126,6 +127,119 @@ set_increment_size (uintmax_t 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 -Index: src/expand-common.h -=================================================================== ---- src/expand-common.h.orig -+++ src/expand-common.h -@@ -34,6 +34,18 @@ extern size_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 (uintmax_t tabval); -Index: src/expand.c -=================================================================== ---- src/expand.c.orig -+++ src/expand.c -@@ -37,6 +37,9 @@ - #include - #include - #include -+ -+#include -+ - #include "system.h" - #include "die.h" - #include "xstrndup.h" -@@ -98,19 +101,41 @@ expand (void) - { - /* Input stream. */ - FILE *fp = next_file (NULL); -+ 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(); - - if (!fp) - return; -+ mbf_init (mbf, fp); -+ found_bom=check_bom(fp,&mbf); - -- while (true) -+ if (using_utf_locale == false && found_bom == true) -+ { -+ /*try using some predefined locale */ -+ -+ if (set_utf_locale () != 0) - { -- /* Input character, or EOF. */ -- int c; -+ error (EXIT_FAILURE, errno, _("cannot set UTF-8 locale")); -+ } -+ } -+ - -+ if (found_bom == true) -+ { -+ print_bom(); -+ } -+ -+ while (true) -+ { - /* If true, perform translations. */ - bool convert = true; - -- - /* The following variables have valid values only when CONVERT - is true: */ - -@@ -120,17 +145,48 @@ expand (void) - /* Index in TAB_LIST of next tab stop to examine. */ - size_t tab_index = 0; - -- - /* Convert a line of text. */ - - do - { -- while ((c = getc (fp)) < 0 && (fp = next_file (fp))) -- continue; -+ while (true) { -+ mbf_getc (c, mbf); -+ if ((mb_iseof (c)) && (fp = next_file (fp))) -+ { -+ mbf_init (mbf, fp); -+ if (fp!=NULL) -+ { -+ if (check_bom(fp,&mbf)==true) -+ { -+ /*Not the first file - check BOM header*/ -+ if (using_utf_locale==false && found_bom==false) -+ { -+ /*BOM header in subsequent file but not in the first one. */ -+ error (EXIT_FAILURE, errno, _("combination of files with and without BOM header")); -+ } -+ } -+ else -+ { -+ if(using_utf_locale==false && found_bom==true) -+ { -+ /*First file conatined BOM header - locale was switched to UTF -+ *all subsequent files should contain BOM. */ -+ error (EXIT_FAILURE, errno, _("combination of files with and without BOM header")); -+ } -+ } -+ } -+ continue; -+ } -+ else -+ { -+ break; -+ } -+ } -+ - - if (convert) - { -- if (c == '\t') -+ if (mb_iseq (c, '\t')) - { - /* Column the next input tab stop is on. */ - uintmax_t next_tab_column; -@@ -149,32 +205,34 @@ expand (void) - if (putchar (' ') < 0) - die (EXIT_FAILURE, errno, _("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)) - { -- column++; -+ column += mb_width (c); - if (!column) - die (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)) - die (EXIT_FAILURE, errno, _("write error")); - } -- while (c != '\n'); -+ while (!mb_iseq (c, '\n')); - } - } - -Index: src/fold.c -=================================================================== ---- src/fold.c.orig -+++ src/fold.c -@@ -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 "die.h" - #include "error.h" - #include "fadvise.h" - #include "xdectoint.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}, -@@ -76,6 +119,7 @@ Wrap input lines in each FILE, writing t - - 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); -@@ -93,7 +137,7 @@ Wrap input lines in each FILE, writing t - static size_t - adjust_column (size_t column, char c) - { -- if (!count_bytes) -+ if (operating_mode != byte_mode) - { - if (c == '\b') - { -@@ -116,30 +160,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", quotef (filename)); -- return false; -- } - - fadvise (istream, FADVISE_SEQUENTIAL); - -@@ -169,6 +197,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) - { -@@ -215,11 +252,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 const *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", quotef (filename)); -@@ -252,7 +499,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) - { -@@ -261,7 +509,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. */ -Index: src/join.c -=================================================================== ---- src/join.c.orig -+++ src/join.c -@@ -22,19 +22,33 @@ - #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 "die.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" - -@@ -136,10 +150,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 -@@ -276,13 +292,14 @@ xfields (struct line *line) - if (ptr == lim) - return; - -- if (0 <= tab && tab != '\n') -+ if (tab != NULL) - { -+ unsigned char t = tab[0]; - char *sep; -- for (; (sep = memchr (ptr, tab, lim - ptr)) != NULL; ptr = sep + 1) -+ for (; (sep = memchr (ptr, t, lim - ptr)) != NULL; ptr = sep + 1) - extract_field (line, ptr, sep - ptr); - } -- else if (tab < 0) -+ else - { - /* Skip leading blanks before the first field. */ - while (field_sep (*ptr)) -@@ -306,6 +323,147 @@ xfields (struct line *line) - extract_field (line, ptr, lim - ptr); - } - -+#if HAVE_MBRTOWC -+static void -+xfields_multibyte (struct line *line) -+{ -+ char *ptr = line->buf.buffer; -+ char const *lim = ptr + line->buf.length - 1; -+ wchar_t wc = 0; -+ size_t mblength = 1; -+ mbstate_t state, state_bak; -+ -+ memset (&state, 0, sizeof (mbstate_t)); -+ -+ if (ptr >= lim) -+ return; -+ -+ if (tab != NULL) -+ { -+ 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) && wc != '\n') -+ 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) || wc == '\n') -+ 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) && wc != '\n') -+ break; -+ -+ ptr += mblength; -+ } -+ } -+ while (ptr < lim); -+ } -+ -+ extract_field (line, ptr, lim - ptr); -+} -+#endif -+ - static void - freeline (struct line *line) - { -@@ -327,56 +485,133 @@ keycmp (struct line const *line1, struct - size_t jf_1, size_t jf_2) - { - /* Start of field to compare in each file. */ -- char *beg1; -- char *beg2; -- -- size_t len1; -- size_t len2; /* Length of fields to compare. */ -+ char *beg[2]; -+ char *copy[2]; -+ size_t len[2]; /* Length of fields to compare. */ - int diff; -+ int i, j; -+ int mallocd = 0; - - if (jf_1 < line1->nfields) - { -- beg1 = line1->fields[jf_1].beg; -- len1 = line1->fields[jf_1].len; -+ beg[0] = line1->fields[jf_1].beg; -+ len[0] = line1->fields[jf_1].len; - } - else - { -- beg1 = NULL; -- len1 = 0; -+ beg[0] = NULL; -+ len[0] = 0; - } - - if (jf_2 < line2->nfields) - { -- beg2 = line2->fields[jf_2].beg; -- len2 = line2->fields[jf_2].len; -+ beg[1] = line2->fields[jf_2].beg; -+ len[1] = line2->fields[jf_2].len; - } - else - { -- beg2 = NULL; -- len2 = 0; -+ beg[1] = NULL; -+ len[1] = 0; - } - -- if (len1 == 0) -- return len2 == 0 ? 0 : -1; -- if (len2 == 0) -+ if (len[0] == 0) -+ return len[1] == 0 ? 0 : -1; -+ if (len[1] == 0) - return 1; - - if (ignore_case) - { -- /* FIXME: ignore_case does not work with NLS (in particular, -- with multibyte chars). */ -- diff = memcasecmp (beg1, beg2, MIN (len1, len2)); -+#ifdef HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ { -+ size_t mblength; -+ wchar_t wc, uwc; -+ mbstate_t state, state_bak; -+ -+ memset (&state, '\0', sizeof (mbstate_t)); -+ -+ for (i = 0; i < 2; i++) -+ { -+ mallocd = 1; -+ copy[i] = xmalloc (len[i] + 1); -+ memset (copy[i], '\0',len[i] + 1); -+ -+ for (j = 0; j < MIN (len[0], len[1]);) -+ { -+ state_bak = state; -+ mblength = mbrtowc (&wc, beg[i] + j, len[i] - j, &state); -+ -+ switch (mblength) -+ { -+ case (size_t) -1: -+ case (size_t) -2: -+ state = state_bak; -+ /* Fall through */ -+ case 0: -+ mblength = 1; -+ break; -+ -+ default: -+ uwc = towupper (wc); -+ -+ if (uwc != wc) -+ { -+ mbstate_t state_wc; -+ size_t mblen; -+ -+ memset (&state_wc, '\0', sizeof (mbstate_t)); -+ mblen = wcrtomb (copy[i] + j, uwc, &state_wc); -+ assert (mblen != (size_t)-1); -+ } -+ else -+ memcpy (copy[i] + j, beg[i] + j, mblength); -+ } -+ 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] = beg[0]; -+ copy[1] = 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 -@@ -468,6 +703,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]) -@@ -563,21 +803,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); - } - } -@@ -588,7 +835,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; - -@@ -622,7 +868,7 @@ prjoin (struct line const *line1, struct - o = o->next; - if (o == NULL) - break; -- putchar (output_separator); -+ PUT_TAB_CHAR; - } - putchar (eolchar); - } -@@ -1098,20 +1344,43 @@ main (int argc, char **argv) - - case 't': - { -- unsigned char newtab = optarg[0]; -+ char *newtab = NULL; -+ size_t newtablen; -+ newtab = xstrdup (optarg); -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ { -+ mbstate_t state; -+ -+ memset (&state, 0, sizeof (mbstate_t)); -+ newtablen = mbrtowc (NULL, newtab, -+ strnlen (newtab, MB_LEN_MAX), -+ &state); -+ if (newtablen == (size_t) 0 -+ || newtablen == (size_t) -1 -+ || newtablen == (size_t) -2) -+ newtablen = 1; -+ } -+ else -+#endif -+ newtablen = 1; - if (! newtab) -- newtab = '\n'; /* '' => process the whole line. */ -+ newtab = (char*)"\n"; /* '' => process the whole line. */ - else if (optarg[1]) - { -- if (STREQ (optarg, "\\0")) -- newtab = '\0'; -- else -- die (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); -+ die (EXIT_FAILURE, 0, _("incompatible tabs")); - } -- if (0 <= tab && tab != newtab) -- die (EXIT_FAILURE, 0, _("incompatible tabs")); - tab = newtab; -+ tablen = newtablen; - } - break; - -Index: src/pr.c -=================================================================== ---- src/pr.c.orig -+++ src/pr.c -@@ -311,6 +311,24 @@ - - #include - #include -+ -+/* Get MB_LEN_MAX. */ -+#include -+/* 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 == 1 -+# define MB_LEN_MAX 16 -+#endif -+ -+/* Get MB_CUR_MAX. */ -+#include -+ -+/* Solaris 2.5 has a bug: must be included before . */ -+/* Get mbstate_t, mbrtowc(), wcwidth(). */ -+#if HAVE_WCHAR_H -+# include -+#endif -+ - #include "system.h" - #include "die.h" - #include "error.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 -+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) -+#endif -+ -+#ifndef HAVE_DECL_WCWIDTH -+"this configure-time declaration test was not run" -+#endif -+#if !HAVE_DECL_WCWIDTH -+extern int wcwidth (); -+#endif -+ - /* The official name of this program (e.g., no 'g' prefix). */ - #define PROGRAM_NAME "pr" - -@@ -417,7 +447,20 @@ struct COLUMN - - typedef struct COLUMN COLUMN; - --static int char_to_clump (char c); -+/* Funtion pointers to switch functions for single byte locale or for -+ multibyte locale. If multibyte functions do not exist in your sysytem, -+ these pointers always point the function for single byte locale. */ -+static void (*print_char) (char c); -+static int (*char_to_clump) (char c); -+ -+/* Functions for single byte locale. */ -+static void print_char_single (char c); -+static int char_to_clump_single (char c); -+ -+/* Functions for multibyte locale. */ -+static void print_char_multi (char c); -+static int char_to_clump_multi (char c); -+ - static bool read_line (COLUMN *p); - static bool print_page (void); - static bool print_stored (COLUMN *p); -@@ -429,6 +472,7 @@ static void add_line_number (COLUMN *p); - static void getoptnum (const char *n_str, int min, int *num, - const char *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); -@@ -442,7 +486,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); -@@ -454,7 +497,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]. */ --static char *buff; -+static unsigned char *buff; - - /* Index of the position in buff where the next character - will be stored. */ -@@ -558,7 +601,7 @@ static int chars_per_column; - static bool untabify_input = false; - - /* (-e) The input tab character. */ --static char input_tab_char = '\t'; -+static char input_tab_char[MB_LEN_MAX] = "\t"; - - /* (-e) Tabstops are at chars_per_tab, 2*chars_per_tab, 3*chars_per_tab, ... - where the leftmost column is 1. */ -@@ -568,7 +611,10 @@ static int chars_per_input_tab = 8; - static bool tabify_output = false; - - /* (-i) The output tab character. */ --static char output_tab_char = '\t'; -+static char output_tab_char[MB_LEN_MAX] = "\t"; -+ -+/* (-i) The byte length of output tab character. */ -+static int output_tab_char_length = 1; - - /* (-i) The width of the output tab. */ - static int chars_per_output_tab = 8; -@@ -638,7 +684,13 @@ static int line_number; - static bool numbered_lines = false; - - /* (-n) Character which follows each line number. */ --static char number_separator = '\t'; -+static char number_separator[MB_LEN_MAX] = "\t"; -+ -+/* (-n) The byte length of the character which follows each line number. */ -+static int number_separator_length = 1; -+ -+/* (-n) The character width of the character which follows each line number. */ -+static int number_separator_width = 0; - - /* (-n) line counting starts with 1st line of input file (not with 1st - line of 1st page printed). */ -@@ -691,6 +743,7 @@ static bool use_col_separator = false; - -a|COLUMN|-m is a 'space' and with the -J option a 'tab'. */ - static char const *col_sep_string = ""; - static int col_sep_length = 0; -+static int col_sep_width = 0; - static char *column_separator = (char *) " "; - static char *line_separator = (char *) "\t"; - -@@ -852,6 +905,13 @@ separator_string (const char *optarg_S) - integer_overflow (); - col_sep_length = len; - col_sep_string = optarg_S; -+ -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ col_sep_width = mbswidth (col_sep_string, 0); -+ else -+#endif -+ col_sep_width = col_sep_length; - } - - int -@@ -876,6 +936,21 @@ main (int argc, char **argv) - - atexit (close_stdout); - -+/* Define which functions are used, the ones for single byte locale or the ones -+ for multibyte locale. */ -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ { -+ print_char = print_char_multi; -+ char_to_clump = char_to_clump_multi; -+ } -+ else -+#endif -+ { -+ print_char = print_char_single; -+ char_to_clump = char_to_clump_single; -+ } -+ - n_files = 0; - file_names = (argc > 1 - ? xnmalloc (argc - 1, sizeof (char *)) -@@ -952,8 +1027,12 @@ main (int argc, char **argv) - break; - case 'e': - if (optarg) -- getoptarg (optarg, 'e', &input_tab_char, -- &chars_per_input_tab); -+ { -+ int dummy_length, dummy_width; -+ -+ getoptarg (optarg, 'e', input_tab_char, &dummy_length, -+ &dummy_width, &chars_per_input_tab); -+ } - /* Could check tab width > 0. */ - untabify_input = true; - break; -@@ -966,8 +1045,12 @@ main (int argc, char **argv) - break; - case 'i': - if (optarg) -- getoptarg (optarg, 'i', &output_tab_char, -- &chars_per_output_tab); -+ { -+ int dummy_width; -+ -+ getoptarg (optarg, 'i', output_tab_char, &output_tab_char_length, -+ &dummy_width, &chars_per_output_tab); -+ } - /* Could check tab width > 0. */ - tabify_output = true; - break; -@@ -985,8 +1068,8 @@ main (int argc, char **argv) - case 'n': - numbered_lines = true; - if (optarg) -- getoptarg (optarg, 'n', &number_separator, -- &chars_per_number); -+ getoptarg (optarg, 'n', number_separator, &number_separator_length, -+ &number_separator_width, &chars_per_number); - break; - case 'N': - skip_count = false; -@@ -1011,6 +1094,7 @@ main (int argc, char **argv) - /* Reset an additional input of -s, -S dominates -s */ - col_sep_string = ""; - col_sep_length = 0; -+ col_sep_width = 0; - use_col_separator = true; - if (optarg) - separator_string (optarg); -@@ -1166,10 +1250,45 @@ getoptnum (const char *n_str, int min, i - a number. */ - - static void --getoptarg (char *arg, char switch_char, char *character, int *number) -+getoptarg (char *arg, char switch_char, char *character, int *character_length, -+ int *character_width, int *number) - { - if (!ISDIGIT (*arg)) -- *character = *arg++; -+ { -+#ifdef HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) /* for multibyte locale. */ -+ { -+ wchar_t wc; -+ size_t mblength; -+ int width; -+ mbstate_t state = {'\0'}; -+ -+ mblength = mbrtowc (&wc, arg, strnlen(arg, MB_LEN_MAX), &state); -+ -+ if (mblength == (size_t)-1 || mblength == (size_t)-2) -+ { -+ *character_length = 1; -+ *character_width = 1; -+ } -+ else -+ { -+ *character_length = (mblength < 1) ? 1 : mblength; -+ width = wcwidth (wc); -+ *character_width = (width < 0) ? 0 : width; -+ } -+ -+ strncpy (character, arg, *character_length); -+ arg += *character_length; -+ } -+ else /* for single byte locale. */ -+#endif -+ { -+ *character = *arg++; -+ *character_length = 1; -+ *character_width = 1; -+ } -+ } -+ - if (*arg) - { - long int tmp_long; -@@ -1191,6 +1310,11 @@ static void - init_parameters (int number_of_files) - { - int chars_used_by_number = 0; -+ int mb_len = 1; -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ mb_len = MB_LEN_MAX; -+#endif - - lines_per_body = lines_per_page - lines_per_header - lines_per_footer; - if (lines_per_body <= 0) -@@ -1228,7 +1352,7 @@ init_parameters (int number_of_files) - else - col_sep_string = column_separator; - -- col_sep_length = 1; -+ col_sep_length = col_sep_width = 1; - use_col_separator = true; - } - /* It's rather pointless to define a TAB separator with column -@@ -1258,11 +1382,11 @@ init_parameters (int number_of_files) - + TAB_WIDTH (chars_per_input_tab, chars_per_number); */ - - /* Estimate chars_per_text without any margin and keep it constant. */ -- if (number_separator == '\t') -+ if (number_separator[0] == '\t') - number_width = (chars_per_number - + TAB_WIDTH (chars_per_default_tab, chars_per_number)); - else -- number_width = chars_per_number + 1; -+ number_width = chars_per_number + number_separator_width; - - /* The number is part of the column width unless we are - printing files in parallel. */ -@@ -1271,7 +1395,7 @@ init_parameters (int number_of_files) - } - - int sep_chars, useful_chars; -- if (INT_MULTIPLY_WRAPV (columns - 1, col_sep_length, &sep_chars)) -+ if (INT_MULTIPLY_WRAPV (columns - 1, col_sep_width, &sep_chars)) - sep_chars = INT_MAX; - if (INT_SUBTRACT_WRAPV (chars_per_line - chars_used_by_number, sep_chars, - &useful_chars)) -@@ -1294,7 +1418,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, -@@ -1400,7 +1524,7 @@ init_funcs (void) - - /* Enlarge p->start_position of first column to use the same form of - padding_not_printed with all columns. */ -- h = h + col_sep_length; -+ h = h + col_sep_width; - - /* This loop takes care of all but the rightmost column. */ - -@@ -1434,7 +1558,7 @@ init_funcs (void) - } - else - { -- h = h_next + col_sep_length; -+ h = h_next + col_sep_width; - h_next = h + chars_per_column; - } - } -@@ -1725,9 +1849,9 @@ static void - align_column (COLUMN *p) - { - padding_not_printed = p->start_position; -- if (col_sep_length < padding_not_printed) -+ if (col_sep_width < padding_not_printed) - { -- pad_across_to (padding_not_printed - col_sep_length); -+ pad_across_to (padding_not_printed - col_sep_width); - padding_not_printed = ANYWHERE; - } - -@@ -2002,13 +2126,13 @@ store_char (char c) - /* May be too generous. */ - buff = X2REALLOC (buff, &buff_allocated); - } -- buff[buff_current++] = c; -+ buff[buff_current++] = (unsigned char) c; - } - - static void - add_line_number (COLUMN *p) - { -- int i; -+ int i, j; - char *s; - int num_width; - -@@ -2025,22 +2149,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. */ -- if (number_separator == '\t') -+ if (number_separator[0] == '\t') - { - i = number_width - chars_per_number; - while (i-- > 0) - (p->char_func) (' '); - } - else -- (p->char_func) (number_separator); -+ for (j = 0; j < number_separator_length; j++) -+ (p->char_func) (number_separator[j]); - } - else - /* To comply with POSIX, we avoid any expansion of default TAB - separator with a single column output. No column_width requirement - has to be considered. */ - { -- (p->char_func) (number_separator); -- if (number_separator == '\t') -+ for (j = 0; j < number_separator_length; j++) -+ (p->char_func) (number_separator[j]); -+ if (number_separator[0] == '\t') - output_position = POS_AFTER_TAB (chars_per_output_tab, - output_position); - } -@@ -2199,7 +2325,7 @@ print_white_space (void) - while (goal - h_old > 1 - && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal) - { -- putchar (output_tab_char); -+ fwrite (output_tab_char, sizeof(char), output_tab_char_length, stdout); - h_old = h_new; - } - while (++h_old <= goal) -@@ -2219,6 +2345,7 @@ print_sep_string (void) - { - char const *s = col_sep_string; - int l = col_sep_length; -+ int not_space_flag; - - if (separators_not_printed <= 0) - { -@@ -2230,6 +2357,7 @@ print_sep_string (void) - { - for (; separators_not_printed > 0; --separators_not_printed) - { -+ not_space_flag = 0; - while (l-- > 0) - { - /* 3 types of sep_strings: spaces only, spaces and chars, -@@ -2243,12 +2371,15 @@ print_sep_string (void) - } - else - { -+ not_space_flag = 1; - if (spaces_not_printed > 0) - print_white_space (); - putchar (*s++); -- ++output_position; - } - } -+ if (not_space_flag) -+ output_position += col_sep_width; -+ - /* sep_string ends with some spaces */ - if (spaces_not_printed > 0) - print_white_space (); -@@ -2276,7 +2407,7 @@ print_clump (COLUMN *p, int n, char *clu - required number of tabs and spaces. */ - - static void --print_char (char c) -+print_char_single (char c) - { - if (tabify_output) - { -@@ -2300,6 +2431,74 @@ print_char (char c) - putchar (c); - } - -+#ifdef HAVE_MBRTOWC -+static void -+print_char_multi (char c) -+{ -+ static size_t mbc_pos = 0; -+ static char mbc[MB_LEN_MAX] = {'\0'}; -+ static mbstate_t state = {'\0'}; -+ mbstate_t state_bak; -+ wchar_t wc; -+ size_t mblength; -+ int width; -+ -+ if (tabify_output) -+ { -+ state_bak = state; -+ mbc[mbc_pos++] = c; -+ mblength = mbrtowc (&wc, mbc, mbc_pos, &state); -+ -+ while (mbc_pos > 0) -+ { -+ switch (mblength) -+ { -+ case (size_t)-2: -+ state = state_bak; -+ return; -+ -+ case (size_t)-1: -+ state = state_bak; -+ ++output_position; -+ putchar (mbc[0]); -+ memmove (mbc, mbc + 1, MB_CUR_MAX - 1); -+ --mbc_pos; -+ break; -+ -+ case 0: -+ mblength = 1; -+ -+ default: -+ if (wc == L' ') -+ { -+ memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength); -+ --mbc_pos; -+ ++spaces_not_printed; -+ return; -+ } -+ else if (spaces_not_printed > 0) -+ print_white_space (); -+ -+ /* Nonprintables are assumed to have width 0, except L'\b'. */ -+ if ((width = wcwidth (wc)) < 1) -+ { -+ if (wc == L'\b') -+ --output_position; -+ } -+ else -+ output_position += width; -+ -+ fwrite (mbc, sizeof(char), mblength, stdout); -+ memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength); -+ mbc_pos -= mblength; -+ } -+ } -+ return; -+ } -+ putchar (c); -+} -+#endif -+ - /* Skip to page PAGE before printing. - PAGE may be larger than total number of pages. */ - -@@ -2477,9 +2676,9 @@ read_line (COLUMN *p) - align_empty_cols = false; - } - -- 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; - } - -@@ -2548,7 +2747,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: -@@ -2560,7 +2759,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; - -@@ -2580,9 +2779,9 @@ print_stored (COLUMN *p) - } - } - -- 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; - } - -@@ -2595,8 +2794,8 @@ print_stored (COLUMN *p) - if (spaces_not_printed == 0) - { - output_position = p->start_position + end_vector[line]; -- if (p->start_position - col_sep_length == chars_per_margin) -- output_position -= col_sep_length; -+ if (p->start_position - col_sep_width == chars_per_margin) -+ output_position -= col_sep_width; - } - - return true; -@@ -2615,7 +2814,7 @@ print_stored (COLUMN *p) - number of characters is 1.) */ - - static int --char_to_clump (char c) -+char_to_clump_single (char c) - { - unsigned char uc = c; - char *s = clump_buff; -@@ -2625,10 +2824,10 @@ char_to_clump (char c) - int chars; - int chars_per_c = 8; - -- if (c == input_tab_char) -+ if (c == input_tab_char[0]) - chars_per_c = chars_per_input_tab; - -- if (c == input_tab_char || c == '\t') -+ if (c == input_tab_char[0] || c == '\t') - { - width = TAB_WIDTH (chars_per_c, input_position); - -@@ -2709,6 +2908,164 @@ char_to_clump (char c) - return chars; - } - -+#ifdef HAVE_MBRTOWC -+static int -+char_to_clump_multi (char c) -+{ -+ static size_t mbc_pos = 0; -+ static char mbc[MB_LEN_MAX] = {'\0'}; -+ static mbstate_t state = {'\0'}; -+ mbstate_t state_bak; -+ wchar_t wc; -+ size_t mblength; -+ int wc_width; -+ register char *s = clump_buff; -+ register int i, j; -+ char esc_buff[4]; -+ int width; -+ int chars; -+ int chars_per_c = 8; -+ -+ state_bak = state; -+ mbc[mbc_pos++] = c; -+ mblength = mbrtowc (&wc, mbc, mbc_pos, &state); -+ -+ width = 0; -+ chars = 0; -+ while (mbc_pos > 0) -+ { -+ switch (mblength) -+ { -+ case (size_t)-2: -+ state = state_bak; -+ return 0; -+ -+ case (size_t)-1: -+ state = state_bak; -+ mblength = 1; -+ -+ if (use_esc_sequence || use_cntrl_prefix) -+ { -+ width = +4; -+ chars = +4; -+ *s++ = '\\'; -+ sprintf (esc_buff, "%03o", (unsigned char) mbc[0]); -+ for (i = 0; i <= 2; ++i) -+ *s++ = (int) esc_buff[i]; -+ } -+ else -+ { -+ width += 1; -+ chars += 1; -+ *s++ = mbc[0]; -+ } -+ break; -+ -+ case 0: -+ mblength = 1; -+ /* Fall through */ -+ -+ default: -+ if (memcmp (mbc, input_tab_char, mblength) == 0) -+ chars_per_c = chars_per_input_tab; -+ -+ if (memcmp (mbc, input_tab_char, mblength) == 0 || c == '\t') -+ { -+ int width_inc; -+ -+ width_inc = TAB_WIDTH (chars_per_c, input_position); -+ width += width_inc; -+ -+ if (untabify_input) -+ { -+ for (i = width_inc; i; --i) -+ *s++ = ' '; -+ chars += width_inc; -+ } -+ else -+ { -+ for (i = 0; i < mblength; i++) -+ *s++ = mbc[i]; -+ chars += mblength; -+ } -+ } -+ else if ((wc_width = wcwidth (wc)) < 1) -+ { -+ if (use_esc_sequence) -+ { -+ for (i = 0; i < mblength; i++) -+ { -+ width += 4; -+ chars += 4; -+ *s++ = '\\'; -+ sprintf (esc_buff, "%03o", (unsigned char) mbc[i]); -+ for (j = 0; j <= 2; ++j) -+ *s++ = (int) esc_buff[j]; -+ } -+ } -+ else if (use_cntrl_prefix) -+ { -+ if (wc < 0200) -+ { -+ width += 2; -+ chars += 2; -+ *s++ = '^'; -+ *s++ = wc ^ 0100; -+ } -+ else -+ { -+ for (i = 0; i < mblength; i++) -+ { -+ width += 4; -+ chars += 4; -+ *s++ = '\\'; -+ sprintf (esc_buff, "%03o", (unsigned char) mbc[i]); -+ for (j = 0; j <= 2; ++j) -+ *s++ = (int) esc_buff[j]; -+ } -+ } -+ } -+ else if (wc == L'\b') -+ { -+ width += -1; -+ chars += 1; -+ *s++ = c; -+ } -+ else -+ { -+ width += 0; -+ chars += mblength; -+ for (i = 0; i < mblength; i++) -+ *s++ = mbc[i]; -+ } -+ } -+ else -+ { -+ width += wc_width; -+ chars += mblength; -+ for (i = 0; i < mblength; i++) -+ *s++ = mbc[i]; -+ } -+ } -+ memmove (mbc, mbc + mblength, MB_CUR_MAX - mblength); -+ mbc_pos -= mblength; -+ } -+ -+ /* Too many backspaces must put us in position 0 -- never negative. */ -+ if (width < 0 && input_position == 0) -+ { -+ chars = 0; -+ input_position = 0; -+ } -+ else if (width < 0 && input_position <= -width) -+ input_position = 0; -+ else -+ input_position += width; -+ -+ return chars; -+} -+#endif -+ - /* We've just printed some files and need to clean up things before - looking for more options and printing the next batch of files. - -Index: src/sort.c -=================================================================== ---- src/sort.c.orig -+++ src/sort.c -@@ -29,6 +29,14 @@ - #include - #include - #include -+#if HAVE_WCHAR_H -+# include -+#endif -+/* Get isw* functions. */ -+#if HAVE_WCTYPE_H -+# include -+#endif -+ - #include "system.h" - #include "argmatch.h" - #include "die.h" -@@ -157,14 +165,39 @@ static int decimal_point; - /* Thousands separator; if -1, then there isn't one. */ - static int thousands_sep; - -+/* True if -f is specified. */ -+static bool folding; -+ - /* Nonzero if the corresponding locales are hard. */ - static bool hard_LC_COLLATE; --#if HAVE_NL_LANGINFO -+#if HAVE_LANGINFO_CODESET - static bool hard_LC_TIME; - #endif - - #define NONZERO(x) ((x) != 0) - -+/* get a multibyte character's byte length. */ -+#define GET_BYTELEN_OF_CHAR(LIM, PTR, MBLENGTH, STATE) \ -+ do \ -+ { \ -+ wchar_t wc; \ -+ mbstate_t state_bak; \ -+ \ -+ state_bak = STATE; \ -+ mblength = mbrtowc (&wc, PTR, LIM - PTR, &STATE); \ -+ \ -+ switch (MBLENGTH) \ -+ { \ -+ case (size_t)-1: \ -+ case (size_t)-2: \ -+ STATE = state_bak; \ -+ /* Fall through. */ \ -+ case 0: \ -+ MBLENGTH = 1; \ -+ } \ -+ } \ -+ while (0) -+ - /* The kind of blanks for '-b' to skip in various options. */ - enum blanktype { bl_start, bl_end, bl_both }; - -@@ -338,13 +371,11 @@ static bool reverse; - they were read if all keys compare equal. */ - static bool stable; - --/* If TAB has this value, blanks separate fields. */ --enum { TAB_DEFAULT = CHAR_MAX + 1 }; -- --/* Tab character separating fields. If TAB_DEFAULT, then fields are -+/* Tab character separating fields. If tab_length is 0, then fields are - separated by the empty string between a non-blank character and a blank - character. */ --static int tab = TAB_DEFAULT; -+static char tab[MB_LEN_MAX + 1]; -+static size_t tab_length = 0; - - /* Flag to remove consecutive duplicate lines from the output. - Only the last of a sequence of equal lines will be output. */ -@@ -802,6 +833,46 @@ reap_all (void) - reap (-1); - } - -+/* Function pointers. */ -+static void -+(*inittables) (void); -+static char * -+(*begfield) (const struct line*, const struct keyfield *); -+static char * -+(*limfield) (const struct line*, const struct keyfield *); -+static void -+(*skipblanks) (char **ptr, char *lim); -+static int -+(*getmonth) (char const *, size_t, char **); -+static int -+(*keycompare) (const struct line *, const struct line *); -+static int -+(*numcompare) (const char *, const char *); -+ -+/* Test for white space multibyte character. -+ Set LENGTH the byte length of investigated multibyte character. */ -+#if HAVE_MBRTOWC -+static int -+ismbblank (const char *str, size_t len, size_t *length) -+{ -+ size_t mblength; -+ wchar_t wc; -+ mbstate_t state; -+ -+ memset (&state, '\0', sizeof(mbstate_t)); -+ mblength = mbrtowc (&wc, str, len, &state); -+ -+ if (mblength == (size_t)-1 || mblength == (size_t)-2) -+ { -+ *length = 1; -+ return 0; -+ } -+ -+ *length = (mblength < 1) ? 1 : mblength; -+ return iswblank (wc) || wc == '\n'; -+} -+#endif -+ - /* Clean up any remaining temporary files. */ - - static void -@@ -1270,7 +1341,7 @@ zaptemp (char const *name) - free (node); - } - --#if HAVE_NL_LANGINFO -+#if HAVE_LANGINFO_CODESET - - static int - struct_month_cmp (void const *m1, void const *m2) -@@ -1285,7 +1356,7 @@ struct_month_cmp (void const *m1, void c - /* Initialize the character class tables. */ - - static void --inittables (void) -+inittables_uni (void) - { - size_t i; - -@@ -1297,7 +1368,7 @@ inittables (void) - fold_toupper[i] = toupper (i); - } - --#if HAVE_NL_LANGINFO -+#if HAVE_LANGINFO_CODESET - /* If we're not in the "C" locale, read different names for months. */ - if (hard_LC_TIME) - { -@@ -1379,6 +1450,84 @@ specify_nmerge (int oi, char c, char con - xstrtol_fatal (e, oi, c, long_options, s); - } - -+#if HAVE_MBRTOWC -+static void -+inittables_mb (void) -+{ -+ int i, j, k, l; -+ char *name, *s, *lc_time, *lc_ctype; -+ size_t s_len, mblength; -+ char mbc[MB_LEN_MAX]; -+ wchar_t wc, pwc; -+ mbstate_t state_mb, state_wc; -+ -+ lc_time = setlocale (LC_TIME, ""); -+ if (lc_time) -+ lc_time = xstrdup (lc_time); -+ -+ lc_ctype = setlocale (LC_CTYPE, ""); -+ if (lc_ctype) -+ lc_ctype = xstrdup (lc_ctype); -+ -+ if (lc_time && lc_ctype) -+ /* temporarily set LC_CTYPE to match LC_TIME, so that we can convert -+ * the names of months to upper case */ -+ setlocale (LC_CTYPE, lc_time); -+ -+ for (i = 0; i < MONTHS_PER_YEAR; i++) -+ { -+ s = (char *) nl_langinfo (ABMON_1 + i); -+ s_len = strlen (s); -+ monthtab[i].name = name = (char *) xmalloc (s_len + 1); -+ monthtab[i].val = i + 1; -+ -+ memset (&state_mb, '\0', sizeof (mbstate_t)); -+ memset (&state_wc, '\0', sizeof (mbstate_t)); -+ -+ for (j = 0; j < s_len;) -+ { -+ if (!ismbblank (s + j, s_len - j, &mblength)) -+ break; -+ j += mblength; -+ } -+ -+ for (k = 0; j < s_len;) -+ { -+ mblength = mbrtowc (&wc, (s + j), (s_len - j), &state_mb); -+ assert (mblength != (size_t)-1 && mblength != (size_t)-2); -+ if (mblength == 0) -+ break; -+ -+ pwc = towupper (wc); -+ if (pwc == wc) -+ { -+ memcpy (mbc, s + j, mblength); -+ j += mblength; -+ } -+ else -+ { -+ j += mblength; -+ mblength = wcrtomb (mbc, pwc, &state_wc); -+ assert (mblength != (size_t)0 && mblength != (size_t)-1); -+ } -+ -+ for (l = 0; l < mblength; l++) -+ name[k++] = mbc[l]; -+ } -+ name[k] = '\0'; -+ } -+ qsort ((void *) monthtab, MONTHS_PER_YEAR, -+ sizeof (struct month), struct_month_cmp); -+ -+ if (lc_time && lc_ctype) -+ /* restore the original locales */ -+ setlocale (LC_CTYPE, lc_ctype); -+ -+ free (lc_ctype); -+ free (lc_time); -+} -+#endif -+ - /* Specify the amount of main memory to use when sorting. */ - static void - specify_sort_size (int oi, char c, char const *s) -@@ -1610,7 +1759,7 @@ buffer_linelim (struct buffer const *buf - by KEY in LINE. */ - - static char * --begfield (struct line const *line, struct keyfield const *key) -+begfield_uni (const struct line *line, const struct keyfield *key) - { - char *ptr = line->text, *lim = ptr + line->length - 1; - size_t sword = key->sword; -@@ -1619,10 +1768,10 @@ begfield (struct line const *line, struc - /* The leading field separator itself is included in a field when -t - is absent. */ - -- if (tab != TAB_DEFAULT) -+ if (tab_length) - while (ptr < lim && sword--) - { -- while (ptr < lim && *ptr != tab) -+ while (ptr < lim && *ptr != tab[0]) - ++ptr; - if (ptr < lim) - ++ptr; -@@ -1648,11 +1797,70 @@ begfield (struct line const *line, struc - return ptr; - } - -+#if HAVE_MBRTOWC -+static char * -+begfield_mb (const struct line *line, const struct keyfield *key) -+{ -+ int i; -+ char *ptr = line->text, *lim = ptr + line->length - 1; -+ size_t sword = key->sword; -+ size_t schar = key->schar; -+ size_t mblength; -+ mbstate_t state; -+ -+ memset (&state, '\0', sizeof(mbstate_t)); -+ -+ if (tab_length) -+ while (ptr < lim && sword--) -+ { -+ while (ptr < lim && memcmp (ptr, tab, tab_length) != 0) -+ { -+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); -+ ptr += mblength; -+ } -+ if (ptr < lim) -+ { -+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); -+ ptr += mblength; -+ } -+ } -+ else -+ while (ptr < lim && sword--) -+ { -+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength)) -+ ptr += mblength; -+ if (ptr < lim) -+ { -+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); -+ ptr += mblength; -+ } -+ while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength)) -+ ptr += mblength; -+ } -+ -+ if (key->skipsblanks) -+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength)) -+ ptr += mblength; -+ -+ for (i = 0; i < schar; i++) -+ { -+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); -+ -+ if (ptr + mblength > lim) -+ break; -+ else -+ ptr += mblength; -+ } -+ -+ return ptr; -+} -+#endif -+ - /* Return the limit of (a pointer to the first character after) the field - in LINE specified by KEY. */ - - static char * --limfield (struct line const *line, struct keyfield const *key) -+limfield_uni (const struct line *line, const struct keyfield *key) - { - char *ptr = line->text, *lim = ptr + line->length - 1; - size_t eword = key->eword, echar = key->echar; -@@ -1667,10 +1875,10 @@ limfield (struct line const *line, struc - 'beginning' is the first character following the delimiting TAB. - Otherwise, leave PTR pointing at the first 'blank' character after - the preceding field. */ -- if (tab != TAB_DEFAULT) -+ if (tab_length) - while (ptr < lim && eword--) - { -- while (ptr < lim && *ptr != tab) -+ while (ptr < lim && *ptr != tab[0]) - ++ptr; - if (ptr < lim && (eword || echar)) - ++ptr; -@@ -1716,10 +1924,10 @@ limfield (struct line const *line, struc - */ - - /* Make LIM point to the end of (one byte past) the current field. */ -- if (tab != TAB_DEFAULT) -+ if (tab_length) - { - char *newlim; -- newlim = memchr (ptr, tab, lim - ptr); -+ newlim = memchr (ptr, tab[0], lim - ptr); - if (newlim) - lim = newlim; - } -@@ -1750,6 +1958,130 @@ limfield (struct line const *line, struc - return ptr; - } - -+#if HAVE_MBRTOWC -+static char * -+limfield_mb (const struct line *line, const struct keyfield *key) -+{ -+ char *ptr = line->text, *lim = ptr + line->length - 1; -+ size_t eword = key->eword, echar = key->echar; -+ int i; -+ size_t mblength; -+ mbstate_t state; -+ -+ if (echar == 0) -+ eword++; /* skip all of end field. */ -+ -+ memset (&state, '\0', sizeof(mbstate_t)); -+ -+ if (tab_length) -+ while (ptr < lim && eword--) -+ { -+ while (ptr < lim && memcmp (ptr, tab, tab_length) != 0) -+ { -+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); -+ ptr += mblength; -+ } -+ if (ptr < lim && (eword | echar)) -+ { -+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); -+ ptr += mblength; -+ } -+ } -+ else -+ while (ptr < lim && eword--) -+ { -+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength)) -+ ptr += mblength; -+ if (ptr < lim) -+ { -+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); -+ ptr += mblength; -+ } -+ while (ptr < lim && !ismbblank (ptr, lim - ptr, &mblength)) -+ ptr += mblength; -+ } -+ -+ -+# ifdef POSIX_UNSPECIFIED -+ /* Make LIM point to the end of (one byte past) the current field. */ -+ if (tab_length) -+ { -+ char *newlim, *p; -+ -+ newlim = NULL; -+ for (p = ptr; p < lim;) -+ { -+ if (memcmp (p, tab, tab_length) == 0) -+ { -+ newlim = p; -+ break; -+ } -+ -+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); -+ p += mblength; -+ } -+ } -+ else -+ { -+ char *newlim; -+ newlim = ptr; -+ -+ while (newlim < lim && ismbblank (newlim, lim - newlim, &mblength)) -+ newlim += mblength; -+ if (ptr < lim) -+ { -+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); -+ ptr += mblength; -+ } -+ while (newlim < lim && !ismbblank (newlim, lim - newlim, &mblength)) -+ newlim += mblength; -+ lim = newlim; -+ } -+# endif -+ -+ if (echar != 0) -+ { -+ /* If we're skipping leading blanks, don't start counting characters -+ * until after skipping past any leading blanks. */ -+ if (key->skipeblanks) -+ while (ptr < lim && ismbblank (ptr, lim - ptr, &mblength)) -+ ptr += mblength; -+ -+ memset (&state, '\0', sizeof(mbstate_t)); -+ -+ /* Advance PTR by ECHAR (if possible), but no further than LIM. */ -+ for (i = 0; i < echar; i++) -+ { -+ GET_BYTELEN_OF_CHAR (lim, ptr, mblength, state); -+ -+ if (ptr + mblength > lim) -+ break; -+ else -+ ptr += mblength; -+ } -+ } -+ -+ return ptr; -+} -+#endif -+ -+static void -+skipblanks_uni (char **ptr, char *lim) -+{ -+ while (*ptr < lim && blanks[to_uchar (**ptr)]) -+ ++(*ptr); -+} -+ -+#if HAVE_MBRTOWC -+static void -+skipblanks_mb (char **ptr, char *lim) -+{ -+ size_t mblength; -+ while (*ptr < lim && ismbblank (*ptr, lim - *ptr, &mblength)) -+ (*ptr) += mblength; -+} -+#endif -+ - /* 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 -@@ -1836,8 +2168,22 @@ fillbuf (struct buffer *buf, FILE *fp, c - else - { - if (key->skipsblanks) -- while (blanks[to_uchar (*line_start)]) -- line_start++; -+ { -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ { -+ size_t mblength; -+ while (line_start < line->keylim && -+ ismbblank (line_start, -+ line->keylim - line_start, -+ &mblength)) -+ line_start += mblength; -+ } -+ else -+#endif -+ while (blanks[to_uchar (*line_start)]) -+ line_start++; -+ } - line->keybeg = line_start; - } - } -@@ -1971,12 +2317,10 @@ find_unit_order (char const *number) - < K/k < M < G < T < P < E < Z < Y */ - - 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)); -@@ -1987,7 +2331,7 @@ human_numcompare (char const *a, char co - hideously fast. */ - - static int --numcompare (char const *a, char const *b) -+numcompare_uni (const char *a, const char *b) - { - while (blanks[to_uchar (*a)]) - a++; -@@ -1997,6 +2341,25 @@ numcompare (char const *a, char const *b - return strnumcmp (a, b, decimal_point, thousands_sep); - } - -+#if HAVE_MBRTOWC -+static int -+numcompare_mb (const char *a, const char *b) -+{ -+ size_t mblength, len; -+ len = strlen (a); /* okay for UTF-8 */ -+ while (*a && ismbblank (a, len > MB_CUR_MAX ? MB_CUR_MAX : len, &mblength)) -+ { -+ a += mblength; -+ len -= mblength; -+ } -+ len = strlen (b); /* okay for UTF-8 */ -+ while (*b && ismbblank (b, len > MB_CUR_MAX ? MB_CUR_MAX : len, &mblength)) -+ b += mblength; -+ -+ return strnumcmp (a, b, decimal_point, thousands_sep); -+} -+#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 if -@@ -2047,7 +2410,7 @@ general_numcompare (char const *sa, char - Return 0 if the name in S is not recognized. */ - - static int --getmonth (char const *month, char **ea) -+getmonth_uni (char const *month, size_t len, char **ea) - { - size_t lo = 0; - size_t hi = MONTHS_PER_YEAR; -@@ -2323,15 +2686,14 @@ debug_key (struct line const *line, stru - char saved = *lim; - *lim = '\0'; - -- while (blanks[to_uchar (*beg)]) -- beg++; -+ skipblanks (&beg, lim); - - char *tighter_lim = beg; - - if (lim < beg) - tighter_lim = lim; - else if (key->month) -- getmonth (beg, &tighter_lim); -+ getmonth (beg, lim-beg, &tighter_lim); - else if (key->general_numeric) - ignore_value (strtold (beg, &tighter_lim)); - else if (key->numeric || key->human_numeric) -@@ -2465,7 +2827,7 @@ key_warnings (struct keyfield const *gke - /* 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 (!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))) -@@ -2523,11 +2885,87 @@ key_warnings (struct keyfield const *gke - error (0, 0, _("option '-r' only applies to last-resort comparison")); - } - -+#if HAVE_MBRTOWC -+static int -+getmonth_mb (const char *s, size_t len, char **ea) -+{ -+ char *month; -+ register size_t i; -+ register int lo = 0, hi = MONTHS_PER_YEAR, result; -+ char *tmp; -+ size_t wclength, mblength; -+ const char *pp; -+ const wchar_t *wpp; -+ wchar_t *month_wcs; -+ mbstate_t state; -+ -+ while (len > 0 && ismbblank (s, len, &mblength)) -+ { -+ s += mblength; -+ len -= mblength; -+ } -+ -+ if (len == 0) -+ return 0; -+ -+ if (SIZE_MAX - len < 1) -+ xalloc_die (); -+ -+ month = (char *) xnmalloc (len + 1, MB_CUR_MAX); -+ -+ pp = tmp = (char *) xnmalloc (len + 1, MB_CUR_MAX); -+ memcpy (tmp, s, len); -+ tmp[len] = '\0'; -+ 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) -+ error (SORT_FAILURE, 0, _("Invalid multibyte input %s."), quote(s)); -+ -+ for (i = 0; i < wclength; i++) -+ { -+ month_wcs[i] = towupper(month_wcs[i]); -+ if (iswblank (month_wcs[i])) -+ { -+ month_wcs[i] = L'\0'; -+ break; -+ } -+ } -+ -+ mblength = wcsrtombs (month, &wpp, (len + 1) * MB_CUR_MAX, &state); -+ assert (mblength != (-1) && wpp == NULL); -+ -+ do -+ { -+ int ix = (lo + hi) / 2; -+ -+ if (strncmp (month, monthtab[ix].name, strlen (monthtab[ix].name)) < 0) -+ hi = ix; -+ else -+ lo = ix; -+ } -+ while (hi - lo > 1); -+ -+ result = (!strncmp (month, monthtab[lo].name, strlen (monthtab[lo].name)) -+ ? monthtab[lo].val : 0); -+ -+ if (ea && result) -+ *ea = (char*) s + strlen (monthtab[lo].name); -+ -+ free (month); -+ free (tmp); -+ free (month_wcs); -+ -+ return result; -+} -+#endif -+ - /* Compare two lines A and B trying every key in sequence until there - are no more keys or a difference is found. */ - - static int --keycompare (struct line const *a, struct line const *b) -+keycompare_uni (const struct line *a, const struct line *b) - { - struct keyfield *key = keylist; - -@@ -2612,7 +3050,7 @@ keycompare (struct line const *a, struct - 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); - else if (key->random) - diff = compare_random (ta, tlena, tb, tlenb); - else if (key->version) -@@ -2728,6 +3166,211 @@ keycompare (struct line const *a, struct - return key->reverse ? -diff : diff; - } - -+#if HAVE_MBRTOWC -+static int -+keycompare_mb (const struct line *a, const struct line *b) -+{ -+ struct keyfield *key = keylist; -+ -+ /* For the first iteration only, the key positions have been -+ precomputed for us. */ -+ char *texta = a->keybeg; -+ char *textb = b->keybeg; -+ char *lima = a->keylim; -+ char *limb = b->keylim; -+ -+ size_t mblength_a, mblength_b; -+ wchar_t wc_a, wc_b; -+ mbstate_t state_a, state_b; -+ -+ 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; -+ -+ -+ /* Ignore and/or translate chars before comparing. */ -+# define IGNORE_CHARS(NEW_LEN, LEN, TEXT, COPY, WC, MBLENGTH, STATE) \ -+ do \ -+ { \ -+ wchar_t uwc; \ -+ char mbc[MB_LEN_MAX]; \ -+ mbstate_t state_wc; \ -+ \ -+ for (NEW_LEN = i = 0; i < LEN;) \ -+ { \ -+ mbstate_t state_bak; \ -+ \ -+ state_bak = STATE; \ -+ MBLENGTH = mbrtowc (&WC, TEXT + i, LEN - i, &STATE); \ -+ \ -+ if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1 \ -+ || MBLENGTH == 0) \ -+ { \ -+ if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1) \ -+ STATE = state_bak; \ -+ if (!ignore) \ -+ COPY[NEW_LEN++] = TEXT[i]; \ -+ i++; \ -+ continue; \ -+ } \ -+ \ -+ if (ignore) \ -+ { \ -+ if ((ignore == nonprinting && !iswprint (WC)) \ -+ || (ignore == nondictionary \ -+ && !iswalnum (WC) && !iswblank (WC))) \ -+ { \ -+ i += MBLENGTH; \ -+ continue; \ -+ } \ -+ } \ -+ \ -+ if (translate) \ -+ { \ -+ \ -+ uwc = towupper(WC); \ -+ if (WC == uwc) \ -+ { \ -+ memcpy (mbc, TEXT + i, MBLENGTH); \ -+ i += MBLENGTH; \ -+ } \ -+ else \ -+ { \ -+ i += MBLENGTH; \ -+ WC = uwc; \ -+ memset (&state_wc, '\0', sizeof (mbstate_t)); \ -+ \ -+ MBLENGTH = wcrtomb (mbc, WC, &state_wc); \ -+ assert (MBLENGTH != (size_t)-1 && MBLENGTH != 0); \ -+ } \ -+ \ -+ for (j = 0; j < MBLENGTH; j++) \ -+ COPY[NEW_LEN++] = mbc[j]; \ -+ } \ -+ else \ -+ for (j = 0; j < MBLENGTH; j++) \ -+ COPY[NEW_LEN++] = TEXT[i++]; \ -+ } \ -+ COPY[NEW_LEN] = '\0'; \ -+ } \ -+ while (0) -+ -+ /* Actually compare the fields. */ -+ -+ for (;;) -+ { -+ /* Find the lengths. */ -+ size_t lena = lima <= texta ? 0 : lima - texta; -+ size_t lenb = limb <= textb ? 0 : limb - textb; -+ -+ char enda IF_LINT (= 0); -+ char endb IF_LINT (= 0); -+ -+ char const *translate = key->translate; -+ bool const *ignore = key->ignore; -+ -+ if (ignore || translate) -+ { -+ if (SIZE_MAX - lenb - 2 < lena) -+ xalloc_die (); -+ char *copy_a = (char *) xnmalloc (lena + lenb + 2, MB_CUR_MAX); -+ char *copy_b = copy_a + lena * MB_CUR_MAX + 1; -+ size_t new_len_a, new_len_b; -+ size_t i, j; -+ -+ IGNORE_CHARS (new_len_a, lena, texta, copy_a, -+ wc_a, mblength_a, state_a); -+ IGNORE_CHARS (new_len_b, lenb, textb, copy_b, -+ wc_b, mblength_b, state_b); -+ texta = copy_a; textb = copy_b; -+ lena = new_len_a; lenb = new_len_b; -+ } -+ else -+ { -+ /* Use the keys in-place, temporarily null-terminated. */ -+ enda = texta[lena]; texta[lena] = '\0'; -+ endb = textb[lenb]; textb[lenb] = '\0'; -+ } -+ -+ if (key->random) -+ diff = compare_random (texta, lena, textb, lenb); -+ else if (key->numeric | key->general_numeric | key->human_numeric) -+ { -+ char savea = *lima, saveb = *limb; -+ -+ *lima = *limb = '\0'; -+ diff = (key->numeric ? numcompare (texta, textb) -+ : key->general_numeric ? general_numcompare (texta, textb) -+ : human_numcompare (texta, textb)); -+ *lima = savea, *limb = saveb; -+ } -+ else if (key->version) -+ diff = filevercmp (texta, textb); -+ else if (key->month) -+ diff = getmonth (texta, lena, NULL) - getmonth (textb, lenb, NULL); -+ else if (lena == 0) -+ diff = - NONZERO (lenb); -+ else if (lenb == 0) -+ diff = 1; -+ else if (hard_LC_COLLATE && !folding) -+ { -+ diff = xmemcoll0 (texta, lena + 1, textb, lenb + 1); -+ } -+ else -+ { -+ diff = memcmp (texta, textb, MIN (lena, lenb)); -+ if (diff == 0) -+ diff = lena < lenb ? -1 : lena != lenb; -+ } -+ -+ if (ignore || translate) -+ free (texta); -+ else -+ { -+ texta[lena] = enda; -+ textb[lenb] = endb; -+ } -+ -+ if (diff) -+ goto not_equal; -+ -+ key = key->next; -+ if (! key) -+ break; -+ -+ /* Find the beginning and limit of the next field. */ -+ if (key->eword != -1) -+ lima = limfield (a, key), limb = limfield (b, key); -+ else -+ lima = a->text + a->length - 1, limb = b->text + b->length - 1; -+ -+ if (key->sword != -1) -+ texta = begfield (a, key), textb = begfield (b, key); -+ else -+ { -+ texta = a->text, textb = b->text; -+ if (key->skipsblanks) -+ { -+ while (texta < lima && ismbblank (texta, lima - texta, &mblength_a)) -+ texta += mblength_a; -+ while (textb < limb && ismbblank (textb, limb - textb, &mblength_b)) -+ textb += mblength_b; -+ } -+ } -+ } -+ -+not_equal: -+ 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. */ - -@@ -2755,7 +3398,7 @@ compare (struct line const *a, struct li - 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 -@@ -4145,6 +4788,7 @@ set_ordering (char const *s, struct keyf - break; - case 'f': - key->translate = fold_toupper; -+ folding = true; - break; - case 'g': - key->general_numeric = true; -@@ -4224,7 +4868,7 @@ main (int argc, char **argv) - initialize_exit_failure (SORT_FAILURE); - - hard_LC_COLLATE = hard_locale (LC_COLLATE); --#if HAVE_NL_LANGINFO -+#if HAVE_LANGINFO_CODESET - hard_LC_TIME = hard_locale (LC_TIME); - #endif - -@@ -4245,6 +4889,29 @@ main (int argc, char **argv) - thousands_sep = -1; - } - -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ { -+ inittables = inittables_mb; -+ begfield = begfield_mb; -+ limfield = limfield_mb; -+ skipblanks = skipblanks_mb; -+ getmonth = getmonth_mb; -+ keycompare = keycompare_mb; -+ numcompare = numcompare_mb; -+ } -+ else -+#endif -+ { -+ inittables = inittables_uni; -+ begfield = begfield_uni; -+ limfield = limfield_uni; -+ skipblanks = skipblanks_uni; -+ getmonth = getmonth_uni; -+ keycompare = keycompare_uni; -+ numcompare = numcompare_uni; -+ } -+ - have_read_stdin = false; - inittables (); - -@@ -4519,13 +5186,34 @@ main (int argc, char **argv) - - case 't': - { -- char newtab = optarg[0]; -- if (! newtab) -+ char newtab[MB_LEN_MAX + 1]; -+ size_t newtab_length = 1; -+ strncpy (newtab, optarg, MB_LEN_MAX); -+ if (! newtab[0]) - die (SORT_FAILURE, 0, _("empty tab")); -- if (optarg[1]) -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ { -+ wchar_t wc; -+ mbstate_t state; -+ -+ memset (&state, '\0', sizeof (mbstate_t)); -+ newtab_length = mbrtowc (&wc, newtab, strnlen (newtab, -+ MB_LEN_MAX), -+ &state); -+ switch (newtab_length) -+ { -+ case (size_t) -1: -+ case (size_t) -2: -+ case 0: -+ newtab_length = 1; -+ } -+ } -+#endif -+ if (newtab_length == 1 && optarg[1]) - { - if (STREQ (optarg, "\\0")) -- newtab = '\0'; -+ newtab[0] = '\0'; - else - { - /* Provoke with 'sort -txx'. Complain about -@@ -4536,9 +5224,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)) - die (SORT_FAILURE, 0, _("incompatible tabs")); -- tab = newtab; -+ memcpy (tab, newtab, newtab_length); -+ tab_length = newtab_length; - } - break; - -@@ -4767,12 +5457,10 @@ main (int argc, char **argv) - sort (files, nfiles, outfile, nthreads); - } - --#ifdef lint - if (files_from) - readtokens0_free (&tok); - else - free (files); --#endif - - if (have_read_stdin && fclose (stdin) == EOF) - sort_die (_("close failed"), "-"); -Index: src/unexpand.c -=================================================================== ---- src/unexpand.c.orig -+++ src/unexpand.c -@@ -38,6 +38,9 @@ - #include - #include - #include -+ -+#include -+ - #include "system.h" - #include "die.h" - #include "xstrndup.h" -@@ -107,24 +110,47 @@ unexpand (void) - { - /* Input stream. */ - FILE *fp = next_file (NULL); -+ mb_file_t mbf; - - /* The array of pending blanks. In non-POSIX locales, blanks can - include characters other than spaces, so the blanks must be - stored, not merely counted. */ -- char *pending_blank; -+ mbf_char_t *pending_blank; -+ /* True if the starting locale is utf8. */ -+ bool using_utf_locale; -+ -+ /* True if the first file contains BOM header. */ -+ bool found_bom; -+ using_utf_locale=check_utf_locale(); - - if (!fp) - return; -+ mbf_init (mbf, fp); -+ found_bom=check_bom(fp,&mbf); - -+ if (using_utf_locale == false && found_bom == true) -+ { -+ /*try using some predefined locale */ -+ -+ if (set_utf_locale () != 0) -+ { -+ error (EXIT_FAILURE, errno, _("cannot set UTF-8 locale")); -+ } -+ } - /* 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 = xmalloc (max_column_width); -+ pending_blank = xmalloc (max_column_width * sizeof (mbf_char_t)); -+ -+ if (found_bom == true) -+ { -+ print_bom(); -+ } - - while (true) - { - /* Input character, or EOF. */ -- int c; -+ mbf_char_t c; - - /* If true, perform translations. */ - bool convert = true; -@@ -158,12 +184,44 @@ unexpand (void) - - do - { -- while ((c = getc (fp)) < 0 && (fp = next_file (fp))) -- continue; -+ while (true) { -+ mbf_getc (c, mbf); -+ if ((mb_iseof (c)) && (fp = next_file (fp))) -+ { -+ mbf_init (mbf, fp); -+ if (fp!=NULL) -+ { -+ if (check_bom(fp,&mbf)==true) -+ { -+ /*Not the first file - check BOM header*/ -+ if (using_utf_locale==false && found_bom==false) -+ { -+ /*BOM header in subsequent file but not in the first one. */ -+ error (EXIT_FAILURE, errno, _("combination of files with and without BOM header")); -+ } -+ } -+ else -+ { -+ if(using_utf_locale==false && found_bom==true) -+ { -+ /*First file conatined BOM header - locale was switched to UTF -+ *all subsequent files should contain BOM. */ -+ error (EXIT_FAILURE, errno, _("combination of files with and without BOM header")); -+ } -+ } -+ } -+ continue; -+ } -+ else -+ { -+ break; -+ } -+ } -+ - - if (convert) - { -- bool blank = !! isblank (c); -+ bool blank = mb_isblank (c); - - if (blank) - { -@@ -180,16 +238,16 @@ unexpand (void) - if (next_tab_column < column) - die (EXIT_FAILURE, 0, _("input line is too long")); - -- 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)) - { -@@ -197,13 +255,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 -@@ -211,7 +270,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. */ -@@ -219,9 +278,9 @@ unexpand (void) - next_tab_column = column; - tab_index -= !!tab_index; - } -- else -+ else if (!mb_iseq (c, '\n')) - { -- column++; -+ column += mb_width (c); - if (!column) - die (EXIT_FAILURE, 0, _("input line is too long")); - } -@@ -229,8 +288,11 @@ unexpand (void) - 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)) - die (EXIT_FAILURE, errno, _("write error")); - pending = 0; - one_blank_before_tab_stop = false; -@@ -240,16 +302,17 @@ unexpand (void) - convert &= convert_entire_line || blank; - } - -- if (c < 0) -+ if (mb_iseof (c)) - { - free (pending_blank); - return; - } - -- if (putchar (c) < 0) -+ mb_putc (c, stdout); -+ if (ferror (stdout)) - die (EXIT_FAILURE, errno, _("write error")); - } -- while (c != '\n'); -+ while (!mb_iseq (c, '\n')); - } - } - -Index: src/uniq.c -=================================================================== ---- src/uniq.c.orig -+++ src/uniq.c -@@ -21,6 +21,17 @@ - #include - #include - -+/* Get mbstate_t, mbrtowc(). */ -+#if HAVE_WCHAR_H -+# include -+#endif -+ -+/* Get isw* functions. */ -+#if HAVE_WCTYPE_H -+# include -+#endif -+#include -+ - #include "system.h" - #include "argmatch.h" - #include "linebuffer.h" -@@ -33,6 +44,18 @@ - #include "memcasecmp.h" - #include "quote.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" - -@@ -139,6 +162,10 @@ enum - GROUP_OPTION = CHAR_MAX + 1 - }; - -+/* Function pointers. */ -+static char * -+(*find_field) (struct linebuffer *line); -+ - static struct option const longopts[] = - { - {"count", no_argument, NULL, 'c'}, -@@ -253,7 +280,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; -@@ -273,6 +300,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) -+ { -+ MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); -+ -+ if (convfail || !(iswblank (wc) || wc == '\n')) -+ { -+ pos += mblength; -+ break; -+ } -+ pos += mblength; -+ } -+ -+ while (pos < size) -+ { -+ MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); -+ -+ if (!convfail && (iswblank (wc) || wc == '\n')) -+ break; -+ -+ pos += mblength; -+ } -+ } -+ -+ /* skip fields. */ -+ for (count = 0; count < skip_chars && pos < size; count++) -+ { -+ MBCHAR_TO_WCHAR (wc, mblength, lp, pos, size, statep, convfail); -+ pos += mblength; -+ } -+ -+ 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. -@@ -493,6 +597,19 @@ main (int argc, char **argv) - - atexit (close_stdout); - -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ { -+ find_field = find_field_multi; -+ } -+ else -+#endif -+ { -+ find_field = find_field_uni; -+ } -+ -+ -+ - skip_chars = 0; - skip_fields = 0; - check_chars = SIZE_MAX; -Index: tests/expand/mb.sh -=================================================================== ---- /dev/null -+++ 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 -+ -+ -+ -+#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 -Index: tests/i18n/sort.sh -=================================================================== ---- /dev/null -+++ 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 -Index: tests/local.mk -=================================================================== ---- tests/local.mk.orig -+++ tests/local.mk -@@ -369,6 +369,8 @@ all_tests = \ - tests/misc/sort-discrim.sh \ - tests/misc/sort-files0-from.pl \ - tests/misc/sort-float.sh \ -+ tests/misc/sort-mb-tests.sh \ -+ tests/i18n/sort.sh \ - tests/misc/sort-h-thousands-sep.sh \ - tests/misc/sort-merge.pl \ - tests/misc/sort-merge-fdlimit.sh \ -@@ -567,6 +569,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 \ -@@ -714,6 +717,7 @@ all_tests = \ - tests/touch/read-only.sh \ - tests/touch/relative.sh \ - tests/touch/trailing-slash.sh \ -+ tests/unexpand/mb.sh \ - $(all_root_tests) - - # See tests/factor/create-test.sh. -Index: tests/misc/expand.pl -=================================================================== ---- tests/misc/expand.pl.orig -+++ 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}; - -Index: tests/misc/fold.pl -=================================================================== ---- tests/misc/fold.pl.orig -+++ tests/misc/fold.pl -@@ -20,9 +20,18 @@ use strict; - - (my $program_name = $0) =~ s|.*/||; - -+my $prog = 'fold'; -+my $try = "Try \`$prog --help' for more information.\n"; -+my $inval = "$prog: invalid byte, character or field list\n$try"; -+ - # Turn off localization of executable's output. - @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; - -+# uncommented to enable multibyte paths -+my $mb_locale = $ENV{LOCALE_FR_UTF8}; -+! defined $mb_locale || $mb_locale eq 'none' -+ and $mb_locale = 'C'; -+ - my @Tests = - ( - ['s1', '-w2 -s', {IN=>"a\t"}, {OUT=>"a\n\t"}], -@@ -31,9 +40,48 @@ my @Tests = - ['s4', '-w4 -s', {IN=>"abc ef\n"}, {OUT=>"abc \nef\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 fold 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 => "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}; - --my $prog = 'fold'; - my $fail = run_tests ($program_name, $prog, \@Tests, $save_temps, $verbose); - exit $fail; -Index: tests/misc/join.pl -=================================================================== ---- tests/misc/join.pl.orig -+++ tests/misc/join.pl -@@ -25,6 +25,15 @@ my $limits = getlimits (); - - my $prog = 'join'; - -+my $try = "Try \`$prog --help' for more information.\n"; -+my $inval = "$prog: invalid byte, character or field list\n$try"; -+ -+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 $delim = chr 0247; - sub t_subst ($) - { -@@ -333,8 +342,49 @@ foreach my $t (@tv) - push @Tests, $new_ent; - } - -+# 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 join 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; -+ } -+ #Adjust the output some error messages including test_name for mb -+ if (grep {ref $_ eq 'HASH' && exists $_->{ERR}} -+ (@new_t)) -+ { -+ my $sub2 = {ERR_SUBST => "s/$test_name-mb/$test_name/"}; -+ push @new_t, $sub2; -+ push @$t, $sub2; -+ } -+ push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}]; -+ } -+ push @Tests, @new; -+ } -+ - @Tests = triple_test \@Tests; - -+#skip invalid-j-mb test, it is failing because of the format -+@Tests = grep {$_->[0] ne 'invalid-j-mb'} @Tests; -+ - my $save_temps = $ENV{DEBUG}; - my $verbose = $ENV{VERBOSE}; - -Index: tests/misc/sort-mb-tests.sh -=================================================================== ---- /dev/null -+++ 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 -Index: tests/misc/sort-merge.pl -=================================================================== ---- tests/misc/sort-merge.pl.orig -+++ tests/misc/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}; - -Index: tests/misc/sort.pl -=================================================================== ---- tests/misc/sort.pl.orig -+++ tests/misc/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}; -+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 $try = "Try \`$prog --help' for more information.\n"; -+my $inval = "$prog: invalid byte, character or field list\n$try"; -+ - # Since each test is run with a file name and with redirected stdin, - # the name in the diagnostic is either the file name or "-". - # Normalize each diagnostic to use '-'. -@@ -423,6 +428,38 @@ foreach my $t (@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; - - # Remember that triple_test creates from each test with exactly one "IN" -@@ -432,6 +469,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}; -Index: tests/misc/unexpand.pl -=================================================================== ---- tests/misc/unexpand.pl.orig -+++ 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"}], -@@ -128,6 +136,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}; - -Index: tests/misc/uniq.pl -=================================================================== ---- tests/misc/uniq.pl.orig -+++ tests/misc/uniq.pl -@@ -23,9 +23,17 @@ my $limits = getlimits (); - my $prog = 'uniq'; - my $try = "Try '$prog --help' for more information.\n"; - -+my $inval = "$prog: invalid byte, character or field list\n$try"; -+ - # Turn off localization of executable's output. - @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; - -+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'; -+ - # When possible, create a "-z"-testing variant of each test. - sub add_z_variants($) - { -@@ -262,6 +270,53 @@ foreach my $t (@Tests) - and push @$t, {ENV=>'_POSIX2_VERSION=199209'}; - } - -+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 uniq 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; -+ } -+ # In test #145, replace the each ‘...’ by '...'. -+ if ($test_name =~ "145") -+ { -+ my $sub = { ERR_SUBST => "s/‘([^’]+)’/'\$1'/g"}; -+ push @new_t, $sub; -+ push @$t, $sub; -+ } -+ next if ( $test_name =~ "schar" -+ or $test_name =~ "^obs-plus" -+ or $test_name =~ "119"); -+ push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}]; -+ } -+ push @Tests, @new; -+ } -+ -+# 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; -+ - @Tests = add_z_variants \@Tests; - @Tests = triple_test \@Tests; - -Index: tests/pr/pr-tests.pl -=================================================================== ---- tests/pr/pr-tests.pl.orig -+++ 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 -@@ -474,8 +483,48 @@ push @Tests, - {IN=>{2=>"a\n"}}, - {OUT=>"a\t\t\t\t \t\t\ta\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}; - -Index: tests/unexpand/mb.sh -=================================================================== ---- /dev/null -+++ 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 -+ -+#input containing multibyte characters -+cat > in <<\EOF -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+ -+cat > exp <<\EOF -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+ -+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 diff --git a/coreutils-invalid-ids.patch b/coreutils-invalid-ids.patch deleted file mode 100644 index 731565d..0000000 --- a/coreutils-invalid-ids.patch +++ /dev/null @@ -1,30 +0,0 @@ -While uid_t and gid_t are both unsigned, the values (uid_t) -1 and -(gid_t) -1 are reserved. A uid or gid argument of -1 to the chown(2) -system call means to leave the uid/gid unchanged. Catch this case -so that trying to set a uid or gid to -1 will result in an error. - -Test cases: - - chown 4294967295 file - chown :4294967295 file - chgrp 4294967295 file - -Andreas Gruenbacher - ---- - src/chgrp.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: src/chgrp.c -=================================================================== ---- src/chgrp.c.orig -+++ src/chgrp.c -@@ -89,7 +89,7 @@ parse_group (const char *name) - { - uintmax_t tmp; - if (! (xstrtoumax (name, NULL, 10, &tmp, "") == LONGINT_OK -- && tmp <= GID_T_MAX)) -+ && tmp <= GID_T_MAX && (gid_t) tmp != (gid_t) -1)) - die (EXIT_FAILURE, 0, _("invalid group: %s"), - quote (name)); - gid = tmp; diff --git a/coreutils-ls-restore-8.31-behavior-on-removed-dirs.patch b/coreutils-ls-restore-8.31-behavior-on-removed-dirs.patch deleted file mode 100644 index ac4f6b7..0000000 --- a/coreutils-ls-restore-8.31-behavior-on-removed-dirs.patch +++ /dev/null @@ -1,156 +0,0 @@ -Upstream commits (squashed) after the release of coreutils-8.32: - [PATCH 1/2] ls: restore 8.31 behavior on removed directories - [PATCH 2/2] ls: improve removed-directory test -Remove this patch with the next coreutils release. - -Discussed at: - https://lists.gnu.org/archive/html/bug-coreutils/2020-03/msg00008.html - -Upstream commits: - https://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=10fcb97 - https://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=672819c - -commit 672819c73f2e94e61386dc0584bddf9da860cc26 (HEAD -> master, origin/master, origin/HEAD) -Author: Paul Eggert -Date: Sat Mar 7 10:29:51 2020 -0800 - - ls: improve removed-directory test - - * tests/ls/removed-directory.sh: Remove host_triplet test. - Skip this test if one cannot remove the working directory. - From a suggestion by Bernhard Voelker (Bug#39929). - -commit 10fcb97bd728f09d4a027eddf8ad2900f0819b0a -Author: Paul Eggert -Date: Thu Mar 5 17:25:29 2020 -0800 - - ls: restore 8.31 behavior on removed directories - - * NEWS: Mention this. - * src/ls.c: Do not include - (print_dir): Don't worry about whether the directory is removed. - * tests/ls/removed-directory.sh: Adjust to match new (i.e., old) - behavior. ---- - NEWS | 9 +++++++++ - src/ls.c | 22 ---------------------- - tests/ls/removed-directory.sh | 23 ++++++----------------- - 3 files changed, 15 insertions(+), 39 deletions(-) - -Index: NEWS -=================================================================== ---- NEWS.orig -+++ NEWS -@@ -1,5 +1,14 @@ - GNU coreutils NEWS -*- outline -*- - -+* Noteworthy downstream changes (on top of upstream coreutils-8.32) -+ -+** Changes in behavior -+ -+ On GNU/Linux systems, ls no longer issues an error message on -+ directory merely because it was removed. This reverts a change -+ that was made in release 8.32. -+ -+ - * Noteworthy changes in release 8.32 (2020-03-05) [stable] - - ** Bug fixes -Index: src/ls.c -=================================================================== ---- src/ls.c.orig -+++ src/ls.c -@@ -49,10 +49,6 @@ - # include - #endif - --#ifdef __linux__ --# include --#endif -- - #include - #include - #include -@@ -2896,7 +2892,6 @@ print_dir (char const *name, char const - struct dirent *next; - uintmax_t total_blocks = 0; - static bool first = true; -- bool found_any_entries = false; - - errno = 0; - dirp = opendir (name); -@@ -2972,7 +2967,6 @@ print_dir (char const *name, char const - next = readdir (dirp); - if (next) - { -- found_any_entries = true; - if (! file_ignored (next->d_name)) - { - enum filetype type = unknown; -@@ -3018,22 +3012,6 @@ print_dir (char const *name, char const - if (errno != EOVERFLOW) - break; - } --#ifdef __linux__ -- else if (! found_any_entries) -- { -- /* If readdir finds no directory entries at all, not even "." or -- "..", then double check that the directory exists. */ -- if (syscall (SYS_getdents, dirfd (dirp), NULL, 0) == -1 -- && errno != EINVAL) -- { -- /* We exclude EINVAL as that pertains to buffer handling, -- and we've passed NULL as the buffer for simplicity. -- ENOENT is returned if appropriate before buffer handling. */ -- file_failure (command_line_arg, _("reading directory %s"), name); -- } -- break; -- } --#endif - else - break; - -Index: tests/ls/removed-directory.sh -=================================================================== ---- tests/ls/removed-directory.sh.orig -+++ tests/ls/removed-directory.sh -@@ -1,7 +1,7 @@ - #!/bin/sh --# If ls is asked to list a removed directory (e.g. the parent process's --# current working directory that has been removed by another process), it --# emits an error message. -+# If ls is asked to list a removed directory (e.g., the parent process's -+# current working directory has been removed by another process), it -+# should not emit an error message merely because the directory is removed. - - # Copyright (C) 2020 Free Software Foundation, Inc. - -@@ -21,25 +21,14 @@ - . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src - print_ver_ ls - --case $host_triplet in -- *linux*) ;; -- *) skip_ 'non linux kernel' ;; --esac -- --LS_FAILURE=2 -- --cat <<\EOF >exp-err || framework_failure_ --ls: reading directory '.': No such file or directory --EOF -- - cwd=$(pwd) - mkdir d || framework_failure_ - cd d || framework_failure_ --rmdir ../d || framework_failure_ -+rmdir ../d || skip_ "can't remove working directory on this platform" - --returns_ $LS_FAILURE ls >../out 2>../err || fail=1 -+ls >../out 2>../err || fail=1 - cd "$cwd" || framework_failure_ - compare /dev/null out || fail=1 --compare exp-err err || fail=1 -+compare /dev/null err || fail=1 - - Exit $fail diff --git a/coreutils-misc.patch b/coreutils-misc.patch deleted file mode 100644 index 63c6008..0000000 --- a/coreutils-misc.patch +++ /dev/null @@ -1,61 +0,0 @@ ---- - gnulib-tests/test-isnanl.h | 5 +++-- - tests/misc/help-version.sh | 1 + - tests/other-fs-tmpdir | 3 +++ - 3 files changed, 7 insertions(+), 2 deletions(-) - -Index: gnulib-tests/test-isnanl.h -=================================================================== ---- gnulib-tests/test-isnanl.h.orig -+++ gnulib-tests/test-isnanl.h -@@ -47,7 +47,7 @@ main () - /* Quiet NaN. */ - ASSERT (isnanl (NaNl ())); - --#if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT -+#if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT && 0 - /* A bit pattern that is different from a Quiet NaN. With a bit of luck, - it's a Signalling NaN. */ - { -@@ -98,6 +98,7 @@ main () - { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) }; - ASSERT (isnanl (x.value)); - } -+#if 0 - /* isnanl should return something for noncanonical values. */ - { /* Pseudo-NaN. */ - static memory_long_double x = -@@ -125,6 +126,6 @@ main () - ASSERT (isnanl (x.value) || !isnanl (x.value)); - } - #endif -- -+#endif - return 0; - } -Index: tests/misc/help-version.sh -=================================================================== ---- tests/misc/help-version.sh.orig -+++ tests/misc/help-version.sh -@@ -239,6 +239,7 @@ parted_setup () { args="-s $tmp_in mklab - for i in $built_programs; do - # Skip these. - case $i in chroot|stty|tty|false|chcon|runcon|coreutils) continue;; esac -+ case $i in df) continue;; esac - - rm -rf $tmp_in $tmp_in2 $tmp_dir $tmp_out $bigZ_in $zin $zin2 - echo z |gzip > $zin -Index: tests/other-fs-tmpdir -=================================================================== ---- tests/other-fs-tmpdir.orig -+++ tests/other-fs-tmpdir -@@ -43,6 +43,9 @@ for d in $CANDIDATE_TMP_DIRS; do - - done - -+# Autobuild hack -+test -f /bin/uname.bin && other_partition_tmpdir= -+ - if test -z "$other_partition_tmpdir"; then - skip_ \ - "requires a writable directory on a different disk partition, diff --git a/coreutils-remove_hostname_documentation.patch b/coreutils-remove_hostname_documentation.patch deleted file mode 100644 index 39211ae..0000000 --- a/coreutils-remove_hostname_documentation.patch +++ /dev/null @@ -1,92 +0,0 @@ ---- - doc/coreutils.texi | 42 +----------------------------------------- - 1 file changed, 1 insertion(+), 41 deletions(-) - -Index: doc/coreutils.texi -=================================================================== ---- doc/coreutils.texi.orig -+++ doc/coreutils.texi -@@ -71,7 +71,6 @@ - * groups: (coreutils)groups invocation. Print group names a user is in. - * head: (coreutils)head invocation. Output the first part of files. - * hostid: (coreutils)hostid invocation. Print numeric host identifier. --* hostname: (coreutils)hostname invocation. Print or set system name. - * id: (coreutils)id invocation. Print user identity. - * install: (coreutils)install invocation. Copy files and set attributes. - * join: (coreutils)join invocation. Join lines on a common field. -@@ -203,7 +202,7 @@ Free Documentation License''. - * File name manipulation:: dirname basename pathchk mktemp realpath - * Working context:: pwd stty printenv tty - * User information:: id logname whoami groups users who --* System context:: date arch nproc uname hostname hostid uptime -+* System context:: date arch nproc uname hostid uptime - * SELinux context:: chcon runcon - * Modified command invocation:: chroot env nice nohup stdbuf timeout - * Process control:: kill -@@ -426,7 +425,6 @@ System context - * date invocation:: Print or set system date and time - * nproc invocation:: Print the number of processors - * uname invocation:: Print system information --* hostname invocation:: Print or set system name - * hostid invocation:: Print numeric host identifier - * uptime invocation:: Print system uptime and load - -@@ -15761,7 +15759,6 @@ information. - * arch invocation:: Print machine hardware name. - * nproc invocation:: Print the number of processors. - * uname invocation:: Print system information. --* hostname invocation:: Print or set system name. - * hostid invocation:: Print numeric host identifier. - * uptime invocation:: Print system uptime and load. - @end menu -@@ -16623,15 +16620,6 @@ Note this is non-portable (even across G - Print the machine hardware name (sometimes called the hardware class - or hardware type). - --@item -n --@itemx --nodename --@opindex -n --@opindex --nodename --@cindex hostname --@cindex node name --@cindex network node name --Print the network node hostname. -- - @item -p - @itemx --processor - @opindex -p -@@ -16685,34 +16673,6 @@ Print the kernel version. - - @exitstatus - -- --@node hostname invocation --@section @command{hostname}: Print or set system name -- --@pindex hostname --@cindex setting the hostname --@cindex printing the hostname --@cindex system name, printing --@cindex appropriate privileges -- --With no arguments, @command{hostname} prints the name of the current host --system. With one argument, it sets the current host name to the --specified string. You must have appropriate privileges to set the host --name. Synopsis: -- --@example --hostname [@var{name}] --@end example -- --The only options are @option{--help} and @option{--version}. @xref{Common --options}. -- --@command{hostname} is not installed by default, and other packages --also supply a @command{hostname} command, so portable scripts should --not rely on its existence or on the exact behavior documented above. -- --@exitstatus -- - - @node hostid invocation - @section @command{hostid}: Print numeric host identifier diff --git a/coreutils-remove_kill_documentation.patch b/coreutils-remove_kill_documentation.patch deleted file mode 100644 index ee1089b..0000000 --- a/coreutils-remove_kill_documentation.patch +++ /dev/null @@ -1,126 +0,0 @@ ---- - doc/coreutils.texi | 90 ----------------------------------------------------- - 1 file changed, 90 deletions(-) - -Index: doc/coreutils.texi -=================================================================== ---- doc/coreutils.texi.orig -+++ doc/coreutils.texi -@@ -74,7 +74,6 @@ - * id: (coreutils)id invocation. Print user identity. - * install: (coreutils)install invocation. Copy files and set attributes. - * join: (coreutils)join invocation. Join lines on a common field. --* kill: (coreutils)kill invocation. Send a signal to processes. - * link: (coreutils)link invocation. Make hard links between files. - * ln: (coreutils)ln invocation. Make links between files. - * logname: (coreutils)logname invocation. Print current login name. -@@ -205,7 +204,6 @@ Free Documentation License''. - * System context:: date arch nproc uname hostid uptime - * SELinux context:: chcon runcon - * Modified command invocation:: chroot env nice nohup stdbuf timeout --* Process control:: kill - * Delaying:: sleep - * Numeric operations:: factor numfmt seq - * File permissions:: Access modes -@@ -453,10 +451,6 @@ Modified command invocation - * stdbuf invocation:: Run a command with modified I/O buffering - * timeout invocation:: Run a command with a time limit - --Process control -- --* kill invocation:: Sending a signal to processes. -- - Delaying - - * sleep invocation:: Delay for a specified time -@@ -18089,90 +18083,6 @@ the exit status of @var{command} otherwi - @end display - - --@node Process control --@chapter Process control -- --@cindex processes, commands for controlling --@cindex commands for controlling processes -- --@menu --* kill invocation:: Sending a signal to processes. --@end menu -- -- --@node kill invocation --@section @command{kill}: Send a signal to processes -- --@pindex kill --@cindex send a signal to processes -- --The @command{kill} command sends a signal to processes, causing them --to terminate or otherwise act upon receiving the signal in some way. --Alternatively, it lists information about signals. Synopses: -- --@example --kill [-s @var{signal} | --signal @var{signal} | -@var{signal}] @var{pid}@dots{} --kill [-l | --list | -t | --table] [@var{signal}]@dots{} --@end example -- --@mayConflictWithShellBuiltIn{kill} -- --The first form of the @command{kill} command sends a signal to all --@var{pid} arguments. The default signal to send if none is specified --is @samp{TERM}@. The special signal number @samp{0} does not denote a --valid signal, but can be used to test whether the @var{pid} arguments --specify processes to which a signal could be sent. -- --If @var{pid} is positive, the signal is sent to the process with the --process ID @var{pid}. If @var{pid} is zero, the signal is sent to all --processes in the process group of the current process. If @var{pid} --is @minus{}1, the signal is sent to all processes for which the user has --permission to send a signal. If @var{pid} is less than @minus{}1, the signal --is sent to all processes in the process group that equals the absolute --value of @var{pid}. -- --If @var{pid} is not positive, a system-dependent set of system --processes is excluded from the list of processes to which the signal --is sent. -- --If a negative @var{pid} argument is desired as the first one, it --should be preceded by @option{--}. However, as a common extension to --POSIX, @option{--} is not required with @samp{kill ---@var{signal} -@var{pid}}. The following commands are equivalent: -- --@example --kill -15 -1 --kill -TERM -1 --kill -s TERM -- -1 --kill -- -1 --@end example -- --The first form of the @command{kill} command succeeds if every @var{pid} --argument specifies at least one process that the signal was sent to. -- --The second form of the @command{kill} command lists signal information. --Either the @option{-l} or @option{--list} option, or the @option{-t} --or @option{--table} option must be specified. Without any --@var{signal} argument, all supported signals are listed. The output --of @option{-l} or @option{--list} is a list of the signal names, one --per line; if @var{signal} is already a name, the signal number is --printed instead. The output of @option{-t} or @option{--table} is a --table of signal numbers, names, and descriptions. This form of the --@command{kill} command succeeds if all @var{signal} arguments are valid --and if there is no output error. -- --The @command{kill} command also supports the @option{--help} and --@option{--version} options. @xref{Common options}. -- --A @var{signal} may be a signal name like @samp{HUP}, or a signal --number like @samp{1}, or an exit status of a process terminated by the --signal. A signal name can be given in canonical form or prefixed by --@samp{SIG}@. The case of the letters is ignored, except for the --@option{-@var{signal}} option which must use upper case to avoid --ambiguity with lower case option letters. --@xref{Signal specifications}, for a list of supported --signal names and numbers. -- - @node Delaying - @chapter Delaying - diff --git a/coreutils-skip-gnulib-test-tls.patch b/coreutils-skip-gnulib-test-tls.patch deleted file mode 100644 index f951565..0000000 --- a/coreutils-skip-gnulib-test-tls.patch +++ /dev/null @@ -1,37 +0,0 @@ -Subject: Skip the gnulib test 'test-tls' on some platforms - -On i586, x86_64, ppc and ppc64, this test is known to sometimes fail -with a diagnostic like: - - Starting test_tls ...*** Error in `./test-tls': free(): invalid pointer: 0x00007f21500008c0 *** - ======= Backtrace: ========= - /lib64/libc.so.6(+0x7406f)[0x7f215845006f] - /lib64/libc.so.6(+0x7989e)[0x7f215845589e] - /lib64/libpthread.so.0(+0x7ee2)[0x7f215878fee2] - /lib64/libpthread.so.0(+0x813e)[0x7f215879013e] - /lib64/libc.so.6(clone+0x6d)[0x7f21584c3d6d] - -* gnulib-tests/gnulib.mk (test-tls): Comment to skip for now. - ---- - gnulib-tests/gnulib.mk | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -Index: gnulib-tests/gnulib.mk -=================================================================== ---- gnulib-tests/gnulib.mk.orig -+++ gnulib-tests/gnulib.mk -@@ -2485,9 +2485,10 @@ EXTRA_DIST += test-timespec.c macros.h - - ## begin gnulib module tls-tests - --TESTS += test-tls --check_PROGRAMS += test-tls --test_tls_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@ -+# Fails on i586 and x86_64. -+#TESTS += test-tls -+#check_PROGRAMS += test-tls -+#test_tls_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@ - - EXTRA_DIST += test-tls.c - diff --git a/coreutils-skip-some-sort-tests-on-ppc.patch b/coreutils-skip-some-sort-tests-on-ppc.patch deleted file mode 100644 index 5a304e0..0000000 --- a/coreutils-skip-some-sort-tests-on-ppc.patch +++ /dev/null @@ -1,52 +0,0 @@ -Subject: tests: skip some valgrind-ed tests of sort on ppc/ppc64 - -Valgrind diagnoses problems in 'mkstemp64' deep down in glibc on PowerPC: - - Conditional jump or move depends on uninitialised value(s) - at 0xFDB37DC: __udivmoddi4 (in /lib/libc-2.18.90.so) - by 0xFDB3DD7: __umoddi3@GLIBC_2.0 (in /lib/libc-2.18.90.so) - by 0xFDFDF9F: __gen_tempname (in /lib/libc-2.18.90.so) - by 0xFE77563: mkstemp64 (in /lib/libc-2.18.90.so) - by 0x100135D3: mkstemp_safer (mkstemp-safer.c:33) - by 0x10006ECF: create_temp_file (sort.c:942) - by 0x1000A427: maybe_create_temp (sort.c:1176) - by 0x100031BF: main (sort.c:1223) - -* tests/misc/sort-stale-thread-mem.sh: Skip on ppc/ppc64. -* tests/misc/sort-u-FMR.sh: Likewise. - ---- - tests/misc/sort-stale-thread-mem.sh | 4 ++++ - tests/misc/sort-u-FMR.sh | 4 ++++ - 2 files changed, 8 insertions(+) - -Index: tests/misc/sort-stale-thread-mem.sh -=================================================================== ---- tests/misc/sort-stale-thread-mem.sh.orig -+++ tests/misc/sort-stale-thread-mem.sh -@@ -27,6 +27,10 @@ require_valgrind_ - grep '^#define HAVE_PTHREAD_T 1' "$CONFIG_HEADER" > /dev/null || - skip_ 'requires pthreads' - -+case "$( uname -m )" in -+ ppc | ppc64) skip_ "SUSE: disabled for now on ppc/ppc64";; -+esac -+ - # gensort output seems to trigger the failure more often, - # so prefer gensort if it is available. - (gensort -a 10000 in) 2>/dev/null || -Index: tests/misc/sort-u-FMR.sh -=================================================================== ---- tests/misc/sort-u-FMR.sh.orig -+++ tests/misc/sort-u-FMR.sh -@@ -20,6 +20,10 @@ - print_ver_ sort - require_valgrind_ - -+case "$( uname -m )" in -+ ppc | ppc64) skip_ "SUSE: disabled for now on ppc/ppc64";; -+esac -+ - { echo 0; printf '%0900d\n' 1; } > in || framework_failure_ - - valgrind --error-exitcode=1 sort --p=1 -S32b -u in > out || fail=1 diff --git a/coreutils-sysinfo.patch b/coreutils-sysinfo.diff similarity index 74% rename from coreutils-sysinfo.patch rename to coreutils-sysinfo.diff index c3fbb74..d922ee6 100644 --- a/coreutils-sysinfo.patch +++ b/coreutils-sysinfo.diff @@ -1,14 +1,8 @@ ---- - src/uname.c | 42 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 42 insertions(+) - -Index: src/uname.c -=================================================================== ---- src/uname.c.orig -+++ src/uname.c -@@ -338,6 +338,36 @@ main (int argc, char **argv) +--- coreutils-5.90/src/uname.c ++++ coreutils-5.90/src/uname.c +@@ -287,6 +287,36 @@ # endif - } + } #endif + if (element == unknown) + { @@ -41,11 +35,11 @@ Index: src/uname.c +#endif + } if (! (toprint == UINT_MAX && element == unknown)) - print_element (element); + print_element (element); } -@@ -363,6 +393,18 @@ main (int argc, char **argv) - element = hardware_platform; - } +@@ -312,6 +342,18 @@ + element = hardware_platform; + } #endif + if (element == unknown) + { @@ -60,5 +54,5 @@ Index: src/uname.c + element = hardware_platform; + } if (! (toprint == UINT_MAX && element == unknown)) - print_element (element); + print_element (element); } diff --git a/coreutils-test_without_valgrind.patch b/coreutils-test_without_valgrind.patch deleted file mode 100644 index ce39d8a..0000000 --- a/coreutils-test_without_valgrind.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- - tests/misc/shuf-reservoir.sh | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -Index: tests/misc/shuf-reservoir.sh -=================================================================== ---- tests/misc/shuf-reservoir.sh.orig -+++ tests/misc/shuf-reservoir.sh -@@ -37,8 +37,7 @@ run_shuf_n() - - # Critical memory-related bugs will cause a segfault here - # (with varying numbers of input/output lines) -- seq "$INPUT_LINES" | valgrind --leak-check=$leaklevel --error-exitcode=1 \ -- shuf -n "$OUTPUT_LINES" -o "out_${INPUT_LINES}_${OUTPUT_LINES}" || return 1 -+ seq "$INPUT_LINES" | shuf -n "$OUTPUT_LINES" -o "out_${INPUT_LINES}_${OUTPUT_LINES}" || return 1 - - EXPECTED_LINES="$OUTPUT_LINES" - test "$INPUT_LINES" -lt "$OUTPUT_LINES" && EXPECTED_LINES="$INPUT_LINES" diff --git a/coreutils-tests-fix-FP-in-ls-stat-free-color.patch b/coreutils-tests-fix-FP-in-ls-stat-free-color.patch deleted file mode 100644 index 0f4aec4..0000000 --- a/coreutils-tests-fix-FP-in-ls-stat-free-color.patch +++ /dev/null @@ -1,46 +0,0 @@ -Upstream patch to avoid FP in testsuite. -Remove with coreutils version > 8.32. - -Discussed at: - https://lists.gnu.org/r/coreutils/2021-04/msg00050.html -Upstream patch: - https://git.sv.gnu.org/cgit/coreutils.git/commit/?id=b7091093bb - -From b7091093bb6505c33279f9bc940b2e94763a6e5d Mon Sep 17 00:00:00 2001 -From: Bernhard Voelker -Date: Wed, 21 Apr 2021 00:12:00 +0200 -Subject: [PATCH] tests: fix FP in ls/stat-free-color.sh - -On newer systems like Fedora 34 and openSUSE Tumbleweed, ls(1) calls -newfstatat(STDOUT_FILENO, ...), but only when there is something to -output. - -* tests/ls/stat-free-color.sh: Add -a option to the reference invocation -of ls, thus enforcing something gets output. ---- - tests/ls/stat-free-color.sh | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -Index: tests/ls/stat-free-color.sh -=================================================================== ---- tests/ls/stat-free-color.sh.orig -+++ tests/ls/stat-free-color.sh -@@ -56,12 +56,14 @@ eval $(dircolors -b color-without-stat) - # The system may perform additional stat-like calls before main. - # Furthermore, underlying library functions may also implicitly - # add an extra stat call, e.g. opendir since glibc-2.21-360-g46f894d. --# To avoid counting those, first get a baseline count for running --# ls with one empty directory argument. Then, compare that with the --# invocation under test. -+# Finally, ls(1) makes a stat call for stdout, but only in the case -+# when there is something to output. -+# To get the comparison right, first get a baseline count for running -+# 'ls -a' with one empty directory argument. Then, compare that with -+# the invocation under test. - mkdir d || framework_failure_ - --strace -q -o log1 -e $stats ls --color=always d || fail=1 -+strace -q -o log1 -e $stats ls -a --color=always d || fail=1 - n_stat1=$(grep -vF '+++' log1 | wc -l) || framework_failure_ - - test $n_stat1 = 0 \ diff --git a/coreutils-tests-shorten-extreme-factor-tests.patch b/coreutils-tests-shorten-extreme-factor-tests.patch deleted file mode 100644 index c21c21b..0000000 --- a/coreutils-tests-shorten-extreme-factor-tests.patch +++ /dev/null @@ -1,36 +0,0 @@ -From d3b433bd41c8978c31fee085cc7e6b0554a4c03e Mon Sep 17 00:00:00 2001 -From: Bernhard Voelker -Date: Wed, 8 Jan 2014 01:15:58 +0100 -Subject: [PATCH] tests: shorten extreme-expensive factor tests - -The extended factor tests alone can take several hours on e.g. i586 -or arm6l. Strip the tests down from 37 to 3. - -* tests/local.mk (factor_tests): From the sequence of the tests -00..36, remove all but t00, t05 and t36. ---- - tests/local.mk | 11 +++-------- - 1 file changed, 3 insertions(+), 8 deletions(-) - -Index: tests/local.mk -=================================================================== ---- tests/local.mk.orig -+++ tests/local.mk -@@ -723,14 +723,9 @@ all_tests = \ - # See tests/factor/create-test.sh. - tf = tests/factor - factor_tests = \ -- $(tf)/t00.sh $(tf)/t01.sh $(tf)/t02.sh $(tf)/t03.sh $(tf)/t04.sh \ -- $(tf)/t05.sh $(tf)/t06.sh $(tf)/t07.sh $(tf)/t08.sh $(tf)/t09.sh \ -- $(tf)/t10.sh $(tf)/t11.sh $(tf)/t12.sh $(tf)/t13.sh $(tf)/t14.sh \ -- $(tf)/t15.sh $(tf)/t16.sh $(tf)/t17.sh $(tf)/t18.sh $(tf)/t19.sh \ -- $(tf)/t20.sh $(tf)/t21.sh $(tf)/t22.sh $(tf)/t23.sh $(tf)/t24.sh \ -- $(tf)/t25.sh $(tf)/t26.sh $(tf)/t27.sh $(tf)/t28.sh $(tf)/t29.sh \ -- $(tf)/t30.sh $(tf)/t31.sh $(tf)/t32.sh $(tf)/t33.sh $(tf)/t34.sh \ -- $(tf)/t35.sh $(tf)/t36.sh -+ $(tf)/t00.sh \ -+ $(tf)/t05.sh \ -+ $(tf)/t36.sh - - $(factor_tests): $(tf)/run.sh $(tf)/create-test.sh - $(AM_V_GEN)$(MKDIR_P) $(tf) diff --git a/coreutils-use-python3.patch b/coreutils-use-python3.patch deleted file mode 100644 index 1cbb22a..0000000 --- a/coreutils-use-python3.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- tests/du/move-dir-while-traversing.sh -+++ tests/du/move-dir-while-traversing.sh -@@ -20,9 +20,9 @@ - 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' -+# We use a python3-inotify script, so... -+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 @@ - # 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 - diff --git a/coreutils-xattr.diff b/coreutils-xattr.diff new file mode 100644 index 0000000..8b6e328 --- /dev/null +++ b/coreutils-xattr.diff @@ -0,0 +1,321 @@ +Index: coreutils-6.2/configure.ac +=================================================================== +--- coreutils-6.2.orig/configure.ac ++++ coreutils-6.2/configure.ac +@@ -246,6 +246,9 @@ AC_CHECK_DECLS([strtoimax, strtoumax]) + + cu_LIB_CHECK + ++# Extended attribute copying. ++AC_FUNC_XATTR ++ + AM_GNU_GETTEXT([external], [need-formatstring-macros]) + AM_GNU_GETTEXT_VERSION([0.15]) + +Index: coreutils-6.2/m4/xattr.m4 +=================================================================== +--- /dev/null ++++ coreutils-6.2/m4/xattr.m4 +@@ -0,0 +1,38 @@ ++# xattr.m4 - check for Extended Attributes (Linux) ++ ++# Copyright (C) 2003 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 2, 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, write to the Free Software Foundation, ++# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ ++ ++# Written by Andreas Gruenbacher. ++ ++AC_DEFUN([AC_FUNC_XATTR], ++[ ++ AC_CHECK_HEADERS(attr/error_context.h attr/libattr.h) ++ if test "$ac_cv_header_attr_libattr_h" = yes \ ++ && test "$ac_cv_header_attr_error_context_h" = yes; then ++ use_xattr=1 ++ else ++ use_xattr=0 ++ fi ++ AC_DEFINE_UNQUOTED(USE_XATTR, $use_xattr, ++ [Define if you want extended attribute support.]) ++ xattr_saved_LIBS=$LIBS ++ AC_SEARCH_LIBS(attr_copy_file, attr, ++ [test "$ac_cv_search_attr_copy_file" = "none required" || LIB_XATTR=$ac_cv_search_attr_copy_file]) ++ AC_SUBST(LIB_XATTR) ++ AC_CHECK_FUNCS(attr_copy_file) ++ LIBS=$xattr_saved_LIBS ++]) +Index: coreutils-6.2/src/Makefile.am +=================================================================== +--- coreutils-6.2.orig/src/Makefile.am ++++ coreutils-6.2/src/Makefile.am +@@ -112,6 +112,10 @@ cp_LDADD += $(LIB_ACL) + mv_LDADD += $(LIB_ACL) + ginstall_LDADD += $(LIB_ACL) + ++cp_LDADD += $(LIB_XATTR) ++mv_LDADD += $(LIB_XATTR) ++ginstall_LDADD += $(LIB_XATTR) ++ + $(PROGRAMS): ../lib/libcoreutils.a + + SUFFIXES = .sh +Index: coreutils-6.2/src/copy.c +=================================================================== +--- coreutils-6.2.orig/src/copy.c ++++ coreutils-6.2/src/copy.c +@@ -53,6 +53,12 @@ + #include "xreadlink.h" + #include "yesno.h" + ++#if USE_XATTR ++# include ++# include ++# include ++#endif ++ + #ifndef HAVE_FCHOWN + # define HAVE_FCHOWN false + # define fchown(fd, uid, gid) (-1) +@@ -118,6 +124,98 @@ is_ancestor (const struct stat *sb, cons + return false; + } + ++#if USE_XATTR ++static void ++copy_xattr_error (struct error_context *ctx, const char *fmt, ...) ++{ ++ int err = errno; ++ va_list ap; ++ int len; ++ char *buffer; ++ ++ /* There is no error function that takes a va_list argument, ++ so we print the message in a buffer first. */ ++ ++ va_start (ap, fmt); ++ len = vsnprintf (NULL, 0, fmt, ap); ++ va_end (ap); ++ if (len > 0) ++ { ++ buffer = xmalloc (len + 1); ++ va_start (ap, fmt); ++ vsnprintf (buffer, len + 1, fmt, ap); ++ va_end (ap); ++ error (0, err, "%s", buffer); ++ free (buffer); ++ } ++} ++ ++static const char * ++copy_xattr_quote (struct error_context *ctx, const char *str) ++{ ++ return xstrdup (quote (str)); ++} ++ ++static void ++copy_xattr_free (struct error_context *ctx, const char *str) ++{ ++ free ((void *) str); ++} ++ ++struct copy_xattr_context { ++ struct error_context ctx; ++ struct cp_options *x; ++}; ++ ++static int ++copy_xattr_filter (const char *name, struct error_context *ctx) ++{ ++ struct copy_xattr_context *copy_ctx = (struct copy_xattr_context *) ctx; ++ int action; ++ ++ /* We handle POSIX ACLs separately. */ ++ if (!strcmp(name, "system.posix_acl_access") ++ || !strcmp(name, "system.posix_acl_default")) ++ return 0; ++ ++ action = attr_copy_action(name, ctx); ++ return (action != ATTR_ACTION_SKIP && ++ (!copy_ctx->x->preserve_mode ++ || action != ATTR_ACTION_PERMISSIONS)); ++} ++#endif /* USE_XATTR */ ++ ++static bool ++copy_xattrs (const char *src_path, int source_desc, const char *dst_path, ++ int dest_desc, const struct cp_options *x) ++{ ++ struct copy_xattr_context copy_xattr_ctx = { ++ { copy_xattr_error, ++ copy_xattr_quote, ++ copy_xattr_free }, ++ x ++ }; ++ ++#if USE_XATTR ++ if (x->preserve_xattrs) ++ { ++ int ret; ++ ++ if (source_desc != -1 && dest_desc != -1) ++ ret = attr_copy_fd(src_path, source_desc, dst_path, dest_desc, ++ copy_xattr_filter, ©_xattr_ctx.ctx); ++ else ++ ret = attr_copy_file (src_path, dst_path, ++ copy_xattr_filter, ©_xattr_ctx.ctx); ++ return ret == 0 || !x->require_preserve; ++ } ++ else ++ return true; ++#else /* USE_XATTR */ ++ return true; ++#endif /* USE_XATTR */ ++} ++ + /* Read the contents of the directory SRC_NAME_IN, and recursively + copy the contents to DST_NAME_IN. NEW_DST is true if + DST_NAME_IN is a directory that was created previously in the +@@ -509,6 +607,9 @@ copy_reg (char const *src_name, char con + } + } + ++ if (!copy_xattrs (src_name, source_desc, dst_name, dest_desc, x)) ++ return_val = false; ++ + set_author (dst_name, dest_desc, src_sb); + + if (x->preserve_mode || x->move_mode) +@@ -1755,6 +1856,9 @@ copy_internal (char const *src_name, cha + return false; + } + ++ if (!copy_xattrs (src_name, -1, dst_name, -1, x)) ++ delayed_ok = false; ++ + set_author (dst_name, -1, &src_sb); + + if (x->preserve_mode || x->move_mode) +Index: coreutils-6.2/src/copy.h +=================================================================== +--- coreutils-6.2.orig/src/copy.h ++++ coreutils-6.2/src/copy.h +@@ -128,6 +128,9 @@ struct cp_options + bool preserve_mode; + bool preserve_timestamps; + ++ /* If true, attempt to copy extended attributes. */ ++ bool preserve_xattrs; ++ + /* 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 +Index: coreutils-6.2/src/cp.c +=================================================================== +--- coreutils-6.2.orig/src/cp.c ++++ coreutils-6.2/src/cp.c +@@ -191,7 +191,7 @@ Mandatory arguments to long options are + -p same as --preserve=mode,ownership,timestamps\n\ + --preserve[=ATTR_LIST] preserve the specified attributes (default:\n\ + mode,ownership,timestamps), if possible\n\ +- additional attributes: links, all\n\ ++ additional attributes: links, xattrs, all\n\ + "), stdout); + fputs (_("\ + --no-preserve=ATTR_LIST don't preserve the specified attributes\n\ +@@ -724,6 +724,7 @@ cp_option_init (struct cp_options *x) + x->preserve_links = false; + x->preserve_mode = false; + x->preserve_timestamps = false; ++ x->preserve_xattrs = false; + + x->require_preserve = false; + x->recursive = false; +@@ -752,18 +753,21 @@ decode_preserve_arg (char const *arg, st + PRESERVE_TIMESTAMPS, + PRESERVE_OWNERSHIP, + PRESERVE_LINK, ++ PRESERVE_XATTRS, + PRESERVE_ALL + }; + static enum File_attribute const preserve_vals[] = + { + PRESERVE_MODE, PRESERVE_TIMESTAMPS, +- PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_ALL ++ PRESERVE_OWNERSHIP, PRESERVE_LINK, ++ PRESERVE_XATTRS, PRESERVE_ALL + }; + /* Valid arguments to the `--preserve' option. */ + static char const* const preserve_args[] = + { + "mode", "timestamps", +- "ownership", "links", "all", NULL ++ "ownership", "links", ++ "xattrs", "all", NULL + }; + ARGMATCH_VERIFY (preserve_args, preserve_vals); + +@@ -799,11 +803,16 @@ decode_preserve_arg (char const *arg, st + x->preserve_links = on_off; + break; + ++ case PRESERVE_XATTRS: ++ x->preserve_xattrs = on_off; ++ break; ++ + case PRESERVE_ALL: + x->preserve_mode = on_off; + x->preserve_timestamps = on_off; + x->preserve_ownership = on_off; + x->preserve_links = on_off; ++ x->preserve_xattrs = on_off; + break; + + default: +Index: coreutils-6.2/src/install.c +=================================================================== +--- coreutils-6.2.orig/src/install.c ++++ coreutils-6.2/src/install.c +@@ -154,6 +154,7 @@ cp_option_init (struct cp_options *x) + x->preserve_links = false; + x->preserve_mode = false; + x->preserve_timestamps = false; ++ x->preserve_xattrs = false; + x->require_preserve = false; + x->recursive = false; + x->sparse_mode = SPARSE_AUTO; +Index: coreutils-6.2/src/mv.c +=================================================================== +--- coreutils-6.2.orig/src/mv.c ++++ coreutils-6.2/src/mv.c +@@ -125,6 +125,7 @@ cp_option_init (struct cp_options *x) + x->preserve_links = true; + x->preserve_mode = true; + x->preserve_timestamps = true; ++ x->preserve_xattrs = true; + x->require_preserve = false; /* FIXME: maybe make this an option */ + x->recursive = true; + x->sparse_mode = SPARSE_AUTO; /* FIXME: maybe make this an option */ +Index: coreutils-6.2/doc/coreutils.texi +=================================================================== +--- coreutils-6.2.orig/doc/coreutils.texi ++++ coreutils-6.2/doc/coreutils.texi +@@ -6948,6 +6948,8 @@ Preserve in the destination files + any links between corresponding source files. + @c Give examples illustrating how hard links are preserved. + @c Also, show how soft links map to hard links with -L and -H. ++@itemx xattrs ++Preserve extended attributes. (See /etc/xattr.conf.) + @itemx all + Preserve all file attributes. + Equivalent to specifying all of the above. diff --git a/coreutils.changes b/coreutils.changes index 27514df..9e232c6 100644 --- a/coreutils.changes +++ b/coreutils.changes @@ -1,3327 +1,3 @@ -------------------------------------------------------------------- -Thu Apr 29 16:21:49 UTC 2021 - Callum Farmer - -- Use new packageand format - -------------------------------------------------------------------- -Fri Apr 23 14:08:32 UTC 2021 - Bernhard Voelker - -- coreutils-tests-fix-FP-in-ls-stat-free-color.patch: Add upstream patch - to avoid FP in testsuite. -- coreutils.spec: - - Reference the above patch. - - Change keyring URL to new GNU coreutils Group Release Keyring. -- coreutils.keyring: Update with the Group Release Keyring. - -------------------------------------------------------------------- -Fri Oct 16 07:26:20 UTC 2020 - Ludwig Nussel - -- prepare usrmerge (boo#1029961) - -------------------------------------------------------------------- -Mon Aug 31 07:14:12 UTC 2020 - Bernhard Voelker - -- gnulib-test-avoid-FP-perror-strerror.patch: Add patch to -avoid false-positive error in gnulib tests 'test-perror2' and -'test-strerror_r', visible on armv7l. -- coreutils.spec: Reference the patch. - -------------------------------------------------------------------- -Thu Jul 16 11:23:47 UTC 2020 - Dominique Leuenberger - -- Drop suse-module-tools BuildRequires: this was used for the macro - regenerate_initrd_post/posttrans, which have been moved to - rpm-config-SUSE in Jan 2019. - -------------------------------------------------------------------- -Sat Jun 13 08:48:03 UTC 2020 - Bernhard Voelker - -- coreutils-gnulib-disable-test-float.patch: Add patch to temporarily - disable the gnulib test 'test-float' failing on ppc and ppc64le. -- coreutils.spec: Reference the patch. While at it, avoid conditional - Patch and Source entries as that break cross-platform builds from - source RPMs. - -------------------------------------------------------------------- -Mon May 4 08:05:15 UTC 2020 - Dirk Mueller - -- add coreutils-use-python3.patch to minimally port away from - python 2.x use of pyinotify in the testsuite - -------------------------------------------------------------------- -Mon Mar 9 07:17:46 UTC 2020 - Bernhard Voelker - -- Update to 8.32: - * Noteworthy changes in release 8.32 (2020-03-05) [stable] - - ** Bug fixes - - cp now copies /dev/fd/N correctly on platforms like Solaris where - it is a character-special file whose minor device number is N. - [bug introduced in fileutils-4.1.6] - - dd conv=fdatasync no longer reports a "Bad file descriptor" error - when fdatasync is interrupted, and dd now retries interrupted calls - to close, fdatasync, fstat and fsync instead of incorrectly - reporting an "Interrupted system call" error. - [bugs introduced in coreutils-6.0] - - df now correctly parses the /proc/self/mountinfo file for unusual entries - like ones with '\r' in a field value ("mount -t tmpfs tmpfs /foo$'\r'bar"), - when the source field is empty ('mount -t tmpfs "" /mnt'), and when the - filesystem type contains characters like a blank which need escaping. - [bugs introduced in coreutils-8.24 with the introduction of reading - the /proc/self/mountinfo file] - - factor again outputs immediately when stdout is a tty but stdin is not. - [bug introduced in coreutils-8.24] - - ln works again on old systems without O_DIRECTORY support (like Solaris 10), - and on systems where symlink ("x", ".") fails with errno == EINVAL - (like Solaris 10 and Solaris 11). - [bug introduced in coreutils-8.31] - - rmdir --ignore-fail-on-non-empty now works correctly for directories - that fail to be removed due to permission issues. Previously the exit status - was reversed, failing for non empty and succeeding for empty directories. - [bug introduced in coreutils-6.11] - - 'shuf -r -n 0 file' no longer mistakenly reads from standard input. - [bug introduced with the --repeat feature in coreutils-8.22] - - split no longer reports a "output file suffixes exhausted" error - when the specified number of files is evenly divisible by 10, 16, 26, - for --numeric, --hex, or default alphabetic suffixes respectively. - [bug introduced in coreutils-8.24] - - seq no longer prints an extra line under certain circumstances (such as - 'seq -f "%g " 1000000 1000000'). - [bug introduced in coreutils-6.10] - - ** Changes in behavior - - Several programs now check that numbers end properly. For example, - 'du -d 1x' now reports an error instead of silently ignoring the 'x'. - Affected programs and options include du -d, expr's numeric operands - on non-GMP builds, install -g and -o, ls's TABSIZE environment - variable, mknod b and c, ptx -g and -w, shuf -n, and sort --batch-size - and --parallel. - - date now parses military time zones in accordance with common usage: - "A" to "M" are equivalent to UTC+1 to UTC+12 - "N" to "Y" are equivalent to UTC-1 to UTC-12 - "Z" is "zulu" time (UTC). - For example, 'date -d "09:00B" is now equivalent to 9am in UTC+2 time zone. - Previously, military time zones were parsed according to the obsolete - rfc822, with their value negated (e.g., "B" was equivalent to UTC-2). - [The old behavior was introduced in sh-utils 2.0.15 ca. 1999, predating - coreutils package.] - - ls issues an error message on a removed directory, on GNU/Linux systems. - Previously no error and no entries were output, and so indistinguishable - from an empty directory, with default ls options. - - uniq no longer uses strcoll() to determine string equivalence, - and so will operate more efficiently and consistently. - - ** New Features - - ls now supports the --time=birth option to display and sort by - file creation time, where available. - - od --skip-bytes now can use lseek even if the input is not a regular - file, greatly improving performance in some cases. - - stat(1) supports a new --cached= option, used on systems with statx(2) - to control cache coherency of file system attributes, - useful on network file systems. - - ** Improvements - - stat and ls now use the statx() system call where available, which can - operate more efficiently by only retrieving requested attributes. - - stat and tail now know about the "binderfs", "dma-buf-fs", "erofs", - "ppc-cmm-fs", and "z3fold" file systems. - stat -f -c%T now reports the file system type, and tail -f uses inotify. - - ** Build-related - - gzip-compressed tarballs are distributed once again - -- Refresh patches: - * coreutils-disable_tests.patch - * coreutils-getaddrinfo.patch - * coreutils-i18n.patch - * coreutils-invalid-ids.patch - * coreutils-remove_hostname_documentation.patch - * coreutils-remove_kill_documentation.patch - * coreutils-skip-gnulib-test-tls.patch - * coreutils-tests-shorten-extreme-factor-tests.patch - -- coreutils-i18n.patch: - * uniq: remove collation handling as required by newer POSIX; see - - https://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=8e81d44b5 - - https://www.austingroupbugs.net/view.php?id=963 - -- coreutils-ls-restore-8.31-behavior-on-removed-dirs.patch: - * Add patch for 'ls' to restore 8.31 behavior on removed directories. - -- coreutils.spec: - * Version: bump version. - * %check: re-enable regular 'make check' for non-multibuild package. - * reference the above new patch. - -- coreutils.keyring: - * Update from upstream (Savannah). - -------------------------------------------------------------------- -Tue Jan 28 08:13:51 UTC 2020 - Ludwig Nussel - -- disable single and testsuite builds in rings/staging -- remove duplicate "coreutils" in flavor to make it look nicer in OBS - -------------------------------------------------------------------- -Mon Jan 20 15:00:06 UTC 2020 - Bernhard Voelker - -- minor: remove obsolete comment in spec file. - -------------------------------------------------------------------- -Thu Jan 9 16:23:59 UTC 2020 - Ludwig Nussel - -- switch to multibuild -- add coreutils-single subpackage that contains a single binary coreutils tool - similar to busybox -- package LC_CTIME directories also in lang package -- split off doc package -- remove info macros, handled by file trigger nowadays - -------------------------------------------------------------------- -Thu Sep 19 11:53:13 UTC 2019 - Ludwig Nussel - -- Do not recommend lang package. The lang package already has a - supplements. - -------------------------------------------------------------------- -Mon Mar 11 07:13:38 UTC 2019 - Bernhard Voelker - -- Update to 8.31: - * Noteworthy changes in release 8.31 (2019-03-10) [stable] - - ** Bug fixes - - 'base64 a b' now correctly diagnoses 'b' as the extra operand, not 'a'. - [bug introduced in coreutils-5.3.0] - - When B already exists, 'cp -il A B' no longer immediately fails - after asking the user whether to proceed. - [This bug was present in "the beginning".] - - df no longer corrupts displayed multibyte characters on macOS. - [bug introduced with coreutils-8.18] - - seq no longer outputs inconsistent decimal point characters - for the last number, when locales are misconfigured. - [bug introduced in coreutils-7.0] - - shred, sort, and split no longer falsely report ftruncate errors - when outputting to less-common file types. For example, the shell - command 'sort /dev/null -o /dev/stdout | cat' no longer fails with - an "error truncating" diagnostic. - [bug was introduced with coreutils-8.18 for sort and split, and - (for shared memory objects only) with fileutils-4.1 for shred] - - sync no longer fails for write-only file arguments. - [bug introduced with argument support to sync in coreutils-8.24] - - 'tail -f file | filter' no longer exits immediately on AIX. - [bug introduced in coreutils-8.28] - - 'tail -f file | filter' no longer goes into an infinite loop - if filter exits and SIGPIPE is ignored. - [bug introduced in coreutils-8.28] - - ** Changes in behavior - - cksum, dd, hostid, hostname, link, logname, sleep, tsort, unlink, - uptime, users, whoami, yes: now always process --help and --version options, - regardless of any other arguments present before any optional '--' - end-of-options marker. - - nohup now processes --help and --version as first options even if other - parameters follow. - - 'yes a -- b' now outputs 'a b' instead of including the end-of-options - marker as before: 'a -- b'. - - echo now always processes backslash escapes when the POSIXLY_CORRECT - environment variable is set. - - When possible 'ln A B' now merely links A to B and reports an error - if this fails, instead of statting A and B before linking. This - uses fewer system calls and avoids some races. The old statting - approach is still used in situations where hard links to directories - are allowed (e.g., NetBSD when superuser). - - ls --group-directories-first will also group symlinks to directories. - - 'test -a FILE' is not supported anymore. Long ago, there were concerns about - the high probability of humans confusing the -a primary with the -a binary - operator, so POSIX changed this to 'test -e FILE'. Scripts using it were - already broken and non-portable; the -a unary operator was never documented. - - wc now treats non breaking space characters as word delimiters - unless the POSIXLY_CORRECT environment variable is set. - - ** New features - - id now supports specifying multiple users. - - 'date' now supports the '+' conversion specification flag, - introduced in POSIX.1-2017. - - printf, seq, sleep, tail, and timeout now accept floating point - numbers in either the current or the C locale. For example, if the - current locale's decimal point is ',', 'sleep 0,1' and 'sleep 0.1' - now mean the same thing. Previously, these commands accepted only - C-locale syntax with '.' as the decimal point. The new behavior is - more compatible with other implementations in non-C locales. - - test now supports the '-N FILE' unary operator (like e.g. bash) to check - whether FILE exists and has been modified since it was last read. - - env now supports '--default-signal[=SIG]', '--ignore-signal[=SIG]', and - '--block-signal[=SIG], to setup signal handling before executing a program. - - env now supports '--list-signal-handling' to indicate non-default - signal handling before executing a program. - - ** New commands - - basenc is added to complement existing base64,base32 commands, - and encodes and decodes printable text using various common encodings: - base64,base64url,base32,base32hex,base16,base2,z85. - - ** Improvements - - ls -l now better aligns abbreviated months containing digits, - which is common in Asian locales. - - stat and tail now know about the "sdcardfs" file system on Android. - stat -f -c%T now reports the file system type, and tail -f uses inotify. - - stat now prints file creation time when supported by the file system, - on GNU Linux systems with glibc >= 2.28 and kernel >= 4.11. - -- Refresh patches (line number changes only): - * coreutils-disable_tests.patch - * coreutils-i18n.patch - * coreutils-misc.patch - * coreutils-remove_hostname_documentation.patch - * coreutils-remove_kill_documentation.patch - * coreutils-skip-gnulib-test-tls.patch - * coreutils-tests-shorten-extreme-factor-tests.patch - - -- coreutils.spec: - * Version: bump version. - * URL: Use https scheme. - * %description: Add 'basenc' tool. - * Change gitweb to cgit URL with https in a comment. - -- coreutils.keyring: - * Update for added section headers ('GPG keys of '). - -------------------------------------------------------------------- -Tue Jul 3 23:20:18 UTC 2018 - mail@bernhard-voelker.de - -- Update to 8.30: - * Noteworthy changes in release 8.30 (2018-07-01) [stable] - - ** Bug fixes - - 'cp --symlink SRC DST' will again correctly validate DST. - If DST is a regular file and SRC is a symlink to DST, - then cp will no longer allow that operation to clobber DST. - Also with -d, if DST is a symlink, then it can always be replaced, - even if it points to SRC on a separate device. - [bugs introduced with coreutils-8.27] - - 'cp -n -u' and 'mv -n -u' now consistently ignore the -u option. - Previously, this option combination suffered from race conditions - that caused -u to sometimes override -n. - [bug introduced with coreutils-7.1] - - 'cp -a --no-preserve=mode' now sets appropriate default permissions - for non regular files like fifos and character device nodes etc., - and leaves mode bits of existing files unchanged. - Previously it would have set executable bits on created special files, - and set mode bits for existing files as if they had been created. - [bug introduced with coreutils-8.20] - - 'cp --remove-destination file symlink' now removes the symlink - even if it can't be traversed. - [bug introduced with --remove-destination in fileutils-4.1.1] - - ls no longer truncates the abbreviated month names that have a - display width between 6 and 12 inclusive. Previously this would have - output ambiguous months for Arabic or Catalan locales. - - 'ls -aA' is now equivalent to 'ls -A', since -A now overrides -a. - [bug introduced in coreutils-5.3.0] - - 'mv -n A B' no longer suffers from a race condition that can - overwrite a simultaneously-created B. This bug fix requires - platform support for the renameat2 or renameatx_np syscalls, found - in recent Linux and macOS kernels. As a side effect, ‘mv -n A A’ - now silently does nothing if A exists. - [bug introduced with coreutils-7.1] - - ** Changes in behavior - - 'cp --force file symlink' now removes the symlink even if - it is self referential. - - ls --color now matches file extensions case insensitively. - - ** New features - - cp --reflink now supports --reflink=never to enforce a standard copy. - - env supports a new -v/--debug option to show verbose information about - each processing step. - - env supports a new -S/--split-string=S option to split a single argument - string into multiple arguments. Used to pass multiple arguments in scripts - (shebang lines). - - md5sum accepts a new option: --zero (-z) to delimit the output lines with a - NUL instead of a newline character. This also disables file name escaping. - This also applies to sha*sum and b2sum. - - rm --preserve-root now supports the --preserve-root=all option to - reject any command line argument that is mounted to a separate file system. - - ** Improvements - - cut supports line lengths up to the max file size on 32 bit systems. - Previously only offsets up to SIZE_MAX-1 were supported. - - stat and tail now know about the "exfs" file system, which is a - version of XFS. stat -f --format=%T now reports the file system type, - and tail -f uses inotify. - - wc avoids redundant processing of ASCII text in multibyte locales, - which is especially significant on macOS. - - ** Build-related - - Adjust to glibc >= 2.28 (bsc#1182550, jsc#SLE-13520, jsc#SLE-13756) - -- Refresh patches (line number changes only): - * coreutils-build-timeout-as-pie.patch - * coreutils-disable_tests.patch - * coreutils-remove_hostname_documentation.patch - * coreutils-remove_kill_documentation.patch - * coreutils-skip-gnulib-test-tls.patch - * coreutils-tests-shorten-extreme-factor-tests.patch - -- coreutils.spec: - * (License): osc changed the value from "GPL-3.0+" to "GPL-3.0-or-later". - * (build): Make sure that parse-datetime.{c,y} ends up in debuginfo (rh#1555079). - -- coreutils-i18n.patch: - * src/exand.c,src/unexpand.c: Avoid -Wcomment warning. - * src/cut.c (cut_characters_or_cut_bytes_no_split): Change idx from size_t - to uintmax_t type to avoid a regression on i586, armv7l and ppc. - Compare upstream, non-MB commit: - https://git.sv.gnu.org/cgit/coreutils.git/commit/?id=d1a754c8272 - (cut_fields_mb): Likewise for field_idx. - * tests/misc/cut.pl: Remove downstream tweaks as upstream MB tests are - working since a while. - -- coreutils.keyring: Update Assaf Gordon's GPG public key. - -------------------------------------------------------------------- -Thu Feb 22 15:12:57 UTC 2018 - fvogt@suse.com - -- Use %license (boo#1082318) - -------------------------------------------------------------------- -Thu Dec 28 18:18:20 UTC 2017 - mail@bernhard-voelker.de - -- Update to 8.29: - * Noteworthy changes in release 8.29 (2017-12-27) [stable] - - ** Bug fixes - - b2sum no longer crashes when processing certain truncated check files. - [bug introduced with b2sum coreutils-8.26] - - dd now ensures the correct cache ranges are specified for the "nocache" - and "direct" flags. Previously some pages in the page cache were not - invalidated. [bug introduced for "direct" in coreutils-7.5, - and with the "nocache" implementation in coreutils-8.11] - - df no longer hangs when given a fifo argument. - [bug introduced in coreutils-7.3] - - ptx -S no longer infloops for a pattern which returns zero-length matches. - [the bug dates back to the initial implementation] - - shred --remove will again repeatedly rename files with shortening names - to attempt to hide the original length of the file name. - [bug introduced in coreutils-8.28] - - stty no longer crashes when processing settings with -F also specified. - [bug introduced in fileutils-4.0] - - tail --bytes again supports non seekable inputs on all systems. - On systems like android it always tried to process as seekable inputs. - [bug introduced in coreutils-8.24] - - timeout will again notice its managed command exiting, even when - invoked with blocked CHLD signal, or in a narrow window where - this CHLD signal from the exiting child was missed. In each case - timeout would have then waited for the time limit to expire. - [bug introduced in coreutils-8.27] - - ** New features - - timeout now supports the --verbose option to diagnose forced termination. - - ** Improvements - - dd now supports iflag=direct with arbitrary sized files on all file systems. - - tail --bytes=NUM will efficiently seek to the end of block devices, - rather than reading from the start. - - Utilities which do not support long options (other than the default --help - and --version), e.g. cksum and sleep, now use more consistent error diagnostic - for unknown long options. - - ** Build-related - - Default man pages are now distributed which are used if perl is - not available on the build system, or when cross compiling. - -- Refresh patches (line number changes only): - * coreutils-i18n.patch - * coreutils-remove_hostname_documentation.patch - * coreutils-remove_kill_documentation.patch - * coreutils-tests-shorten-extreme-factor-tests.patch - -------------------------------------------------------------------- -Mon Sep 4 18:00:24 UTC 2017 - mail@bernhard-voelker.de - -- Update to 8.28 - (for details see included NEWS file) -- Refresh patches: - * coreutils-disable_tests.patch - * coreutils-i18n.patch - * coreutils-remove_hostname_documentation.patch - * coreutils-remove_kill_documentation.patch - * coreutils-skip-gnulib-test-tls.patch - * coreutils-tests-shorten-extreme-factor-tests.patch -- coreutils.keyring: Update from upstream (Savannah). -- Remove now-upstream patches: - * coreutils-cve-2017-7476-out-of-bounds-with-large-tz.patch - * coreutils-tests-port-to-timezone-2017a.patch -- coreutils.spec: Add "BuildRequires: user(bin)" for the tests. - -------------------------------------------------------------------- -Wed Aug 16 14:26:30 UTC 2017 - ghe@suse.com - -- Drop coreutils-ocfs2_reflinks.patch - OCFS2 file system has supported file clone ioctls like btrfs, - then, coreutils doesn't need this patch from the kernel v4.10-rc1 - -------------------------------------------------------------------- -Tue May 2 21:29:32 UTC 2017 - mail@bernhard-voelker.de - -- coreutils-cve-2017-7476-out-of-bounds-with-large-tz.patch: - Add upstream patch to fix an heap overflow security issue - in date(1) and touch(1) with a large TZ variable - (CVE-2017-7476, rh#1444774, boo#1037124). - -------------------------------------------------------------------- -Fri Mar 10 09:42:51 UTC 2017 - mail@bernhard-voelker.de - -- Update to 8.27 - (for details see included NEWS file) -- Refresh patches: - * coreutils-build-timeout-as-pie.patch - * coreutils-disable_tests.patch - * coreutils-getaddrinfo.patch - * coreutils-i18n.patch - * coreutils-ocfs2_reflinks.patch - * coreutils-remove_hostname_documentation.patch - * coreutils-remove_kill_documentation.patch - * coreutils-skip-gnulib-test-tls.patch - * coreutils-tests-shorten-extreme-factor-tests.patch - * coreutils-testsuite.spec -- coreutils.keyring: Update (now ascii-armored) by - 'osc service localrun download_files'. -- coreutils-tests-port-to-timezone-2017a.patch: Add patch to - workaround a FP test failure with newer timezone-2017a. - -------------------------------------------------------------------- -Fri Dec 2 17:17:40 UTC 2016 - mail@bernhard-voelker.de - -- Update to 8.26 - (for details see included NEWS file) -- coreutils.spec (%description): Add b2sum, a new utility. -(BuildRequires): Add timezone to enable new 'date-debug.sh' test. -- coreutils-i18n.patch: Sync I18N patch from Fedora, as the diff - for the old i18n implementation of expand/unexpand has become - unmaintainable: - git://pkgs.fedoraproject.org/coreutils.git -- Remove now-upstream patches: - * coreutils-df-hash-in-filter.patch - * coreutils-diagnose-fts-readdir-failure.patch - * coreutils-m5sum-sha-sum-fix-ignore-missing-with-00-checksums.patch - * coreutils-maint-fix-dependency-of-man-arch.1.patch -- Refresh/merge all other patches: - * coreutils-invalid-ids.patch - * coreutils-ocfs2_reflinks.patch - * coreutils-remove_hostname_documentation.patch - * coreutils-remove_kill_documentation.patch - * coreutils-skip-gnulib-test-tls.patch - * coreutils-sysinfo.patch - * coreutils-tests-shorten-extreme-factor-tests.patch - -------------------------------------------------------------------- -Tue Nov 1 09:41:12 UTC 2016 - mail@bernhard-voelker.de - -- coreutils-m5sum-sha-sum-fix-ignore-missing-with-00-checksums.patch: - Add upstream patch to fix "md5sum --check --ignore-missing" which - treated files with checksums starting with "00" as missing. - -------------------------------------------------------------------- -Thu Jul 28 17:02:53 UTC 2016 - mail@bernhard-voelker.de - -- coreutils-maint-fix-dependency-of-man-arch.1.patch: Add Upstream - patch to fix the build dependency between src/arch -> man/arch.1 - which lead to spurious build failures. -- coreutils-df-hash-in-filter.patch: Refresh with -p0. - -------------------------------------------------------------------- -Fri Jul 22 10:48:50 CEST 2016 - pth@suse.de - -- Add coreutils-df-hash-in-filter.patch that speeds up df. - -------------------------------------------------------------------- -Wed Jul 6 06:54:54 UTC 2016 - mail@bernhard-voelker.de - -- coreutils-diagnose-fts-readdir-failure.patch: Add upstream patch - to diagnose readdir() failures in fts-based utilities: rm, chmod, - du, etc. (boo#984910) - -------------------------------------------------------------------- -Fri Jan 29 22:08:45 UTC 2016 - mail@bernhard-voelker.de - -- Update to 8.25 - (for details see included NEWS file) -- coreutils.spec (%description): Add base32, a new utility. -- Remove now-upstream patch: - * coreutils-tests-avoid-FP-of-ls-stat-free-color.patch -- Refresh/merge all other patches: - * coreutils-build-timeout-as-pie.patch - * coreutils-disable_tests.patch - * coreutils-i18n.patch - * coreutils-invalid-ids.patch - * coreutils-misc.patch - * coreutils-ocfs2_reflinks.patch - * coreutils-remove_hostname_documentation.patch - * coreutils-remove_kill_documentation.patch - * coreutils-skip-gnulib-test-tls.patch - * coreutils-test_without_valgrind.patch - * coreutils-tests-shorten-extreme-factor-tests.patch - -------------------------------------------------------------------- -Sun Sep 20 15:22:45 UTC 2015 - mail@bernhard-voelker.de - -- coreutils-i18n.patch: Sync I18N patch from semi-official repository - (shared among distributions, maintained by Padraig Brady): - https://github.com/pixelb/coreutils/tree/i18n - This fixes the following issues in multi-byte locales: - * sort: fix large mem leak with --month-sort (boo#945361, rh#1259942): - https://github.com/pixelb/coreutils/commit/b429f5d8c7 - * sort: fix assertion with some inputs to --month-sort - https://github.com/pixelb/coreutils/commit/31e8211aca - -------------------------------------------------------------------- -Sun Aug 30 21:52:13 UTC 2015 - mail@bernhard-voelker.de - -- coreutils-tests-avoid-FP-of-ls-stat-free-color.patch: Add upstream -patch on top of v8.24 to avoid a FP test failure with glibc>=2.22. - -------------------------------------------------------------------- -Thu Jul 16 01:28:36 UTC 2015 - mail@bernhard-voelker.de - -- Sync I18N patch from semi-official repository (shared among - distributions, maintained by Padraig Brady): - https://github.com/pixelb/coreutils/tree/i18n - * coreutils-i18n.patch: Improve cut(1) performance in field-mode - in UTF8 locales. Squash in sort-keycompare-mb.patch. - * sort-keycompare-mb.patch: Remove. - -- coreutils-build-timeout-as-pie.patch: Refresh. - -------------------------------------------------------------------- -Thu Jul 9 15:12:10 CEST 2015 - pth@suse.de - -- Update to 8.24: - ** Bug fixes - - * dd supports more robust SIGINFO/SIGUSR1 handling for outputting statistics. - Previously those signals may have inadvertently terminated the process. - - * df --local no longer hangs with inaccessible remote mounts. - [bug introduced in coreutils-8.21] - - * du now silently ignores all directory cycles due to bind mounts. - Previously it would issue a warning and exit with a failure status. - [bug introduced in coreutils-8.1 and partially fixed in coreutils-8.23] - - * chroot again calls chroot(DIR) and chdir("/"), even if DIR is "/". - This handles separate bind mounted "/" trees, and environments - depending on the implicit chdir("/"). - [bugs introduced in coreutils-8.23] - - * cp no longer issues an incorrect warning about directory hardlinks when a - source directory is specified multiple times. Now, consistent with other - file types, a warning is issued for source directories with duplicate names, - or with -H the directory is copied again using the symlink name. - - * factor avoids writing partial lines, thus supporting parallel operation. - [the bug dates back to the initial implementation] - - * head, od, split, tac, tail, and wc no longer mishandle input from files in - /proc and /sys file systems that report somewhat-incorrect file sizes. - - * mkdir --parents -Z now correctly sets the context for the last component, - even if the parent directory exists and has a different default context. - [bug introduced with the -Z restorecon functionality in coreutils-8.22] - - * numfmt no longer outputs incorrect overflowed values seen with certain - large numbers, or with numbers with increased precision. - [bug introduced when numfmt was added in coreutils-8.21] - - * numfmt now handles leading zeros correctly, not counting them when - settings processing limits, and making them optional with floating point. - [bug introduced when numfmt was added in coreutils-8.21] - - * paste no longer truncates output for large input files. This would happen - for example with files larger than 4GiB on 32 bit systems with a '\n' - character at the 4GiB position. - [the bug dates back to the initial implementation] - - * rm indicates the correct number of arguments in its confirmation prompt, - on all platforms. [bug introduced in coreutils-8.22] - - * shuf -i with a single redundant operand, would crash instead of issuing - a diagnostic. [bug introduced in coreutils-8.22] - - * tail releases inotify resources when unused. Previously it could exhaust - resources with many files, or with -F if files were replaced many times. - [bug introduced in coreutils-7.5] - - * tail -f again follows changes to a file after it's renamed. - [bug introduced in coreutils-7.5] - - * tail --follow no longer misses changes to files if those files were - replaced before inotify watches were created. - [bug introduced in coreutils-7.5] - - * tail --follow consistently outputs all data for a truncated file. - [bug introduced in the beginning] - - * tail --follow=name correctly outputs headers for multiple files - when those files are being created or renamed. - [bug introduced in coreutils-7.5] - - ** New features - - * chroot accepts the new --skip-chdir option to not change the working directory - to "/" after changing into the chroot(2) jail, thus retaining the current wor- - king directory. The new option is only permitted if the new root directory is - the old "/", and therefore is useful with the --group and --userspec options. - - * dd accepts a new status=progress level to print data transfer statistics - on stderr approximately every second. - - * numfmt can now process multiple fields with field range specifications similar - to cut, and supports setting the output precision with the --format option. - - * split accepts a new --separator option to select a record separator character - other than the default newline character. - - * stty allows setting the "extproc" option where supported, which is - a useful setting with high latency links. - - * sync no longer ignores arguments, and syncs each specified file, or with the - --file-system option, the file systems associated with each specified file. - - * tee accepts a new --output-error option to control operation with pipes - and output errors in general. - - ** Changes in behavior - - * df no longer suppresses separate exports of the same remote device, as - these are generally explicitly mounted. The --total option does still - suppress duplicate remote file systems. - [suppression was introduced in coreutils-8.21] - - * mv no longer supports moving a file to a hardlink, instead issuing an error. - The implementation was susceptible to races in the presence of multiple mv - instances, which could result in both hardlinks being deleted. Also on case - insensitive file systems like HFS, mv would just remove a hardlinked 'file' - if called like `mv file File`. The feature was added in coreutils-5.0.1. - - * numfmt --from-unit and --to-unit options now interpret suffixes as SI units, - and IEC (power of 2) units are now specified by appending 'i'. - - * tee will exit early if there are no more writable outputs. - - * tee does not treat the file operand '-' as meaning standard output any longer, - for better conformance to POSIX. This feature was added in coreutils-5.3.0. - - * timeout --foreground no longer sends SIGCONT to the monitored process, - which was seen to cause intermittent issues with GDB for example. - - ** Improvements - - * cp,install,mv will convert smaller runs of NULs in the input to holes, - and cp --sparse=always avoids speculative preallocation on XFS for example. - - * cp will read sparse files more efficiently when the destination is a - non regular file. For example when copying a disk image to a device node. - - * mv will try a reflink before falling back to a standard copy, which is - more efficient when moving files across BTRFS subvolume boundaries. - - * stat and tail now know about IBRIX. stat -f --format=%T now reports the file - system type, and tail -f uses polling for files on IBRIX file systems. - - * wc -l processes short lines much more efficiently. - - * References from --help and the man pages of utilities have been corrected - in various cases, and more direct links to the corresponding online - documentation are provided. - -- Patches adapted because of changed sources: - coreutils-disable_tests.patch - coreutils-i18n.patch - coreutils-misc.patch - coreutils-ocfs2_reflinks.patch - coreutils-remove_hostname_documentation.patch - coreutils-remove_kill_documentation.patch - coreutils-skip-gnulib-test-tls.patch - coreutils-tests-shorten-extreme-factor-tests.patch - sort-keycompare-mb.patch - -- Patches removed because they're included in 8.24: - coreutils-chroot-perform-chdir-unless-skip-chdir.patch - coreutils-df-doc-df-a-includes-duplicate-file-systems.patch - coreutils-df-improve-mount-point-selection.patch - coreutils-df-show-all-remote-file-systems.patch - coreutils-df-total-suppress-separate-remotes.patch - coreutils-doc-adjust-reference-to-info-nodes-in-man-pages.patch - coreutils-fix_false_du_failure_on_newer_xfs.patch - coreutils-fix-man-deps.patch - coreutils-tests-aarch64-env.patch - coreutils-tests-make-inotify-rotate-more-robust-and-efficient.patch - coreutils-tests-rm-ext3-perf-increase-timeout.patch - -------------------------------------------------------------------- -Wed Jun 3 10:56:39 UTC 2015 - mail@bernhard-voelker.de - -- coreutils-doc-adjust-reference-to-info-nodes-in-man-pages.patch: - add upstream patch: - doc: adjust reference to info nodes in man pages (boo#933396) -- coreutils-i18n.patch: Use a later version of the previous patch - to fix the sort I18N issue (boo#928749, CVE-2015-4041) to also - avoid CVE-2015-4042. - https://github.com/pixelb/coreutils/commit/bea5e36cc876 - -------------------------------------------------------------------- -Tue May 12 09:32:53 UTC 2015 - mail@bernhard-voelker.de - -- Download keyring file from Savannah; prefer HTTPS over FTP - for remote sources. - -------------------------------------------------------------------- -Tue May 12 08:56:13 UTC 2015 - mail@bernhard-voelker.de - -- Fix memory handling error with case insensitive sort using UTF-8 - (boo#928749): coreutils-i18n.patch - src/sort.c (keycompare_mb): Ensure the buffer is big enough - to handle anything output from wctomb(). Theoretically any - input char could be converted to multiple output chars, - and so we need to multiply the storage by MB_CUR_MAX. - -------------------------------------------------------------------- -Tue Apr 7 18:18:31 UTC 2015 - crrodriguez@opensuse.org - -- If coreutils changes, for consistency, we must regenerate - the initrd. - -------------------------------------------------------------------- -Thu Apr 2 15:26:50 UTC 2015 - mpluskal@suse.com - -- Add gpg signature - -------------------------------------------------------------------- -Thu Mar 26 13:06:58 UTC 2015 - rguenther@suse.com - -- For openSUSE > 13.2 drop coreutils-build-timeout-as-pie.patch and - instead add a BuildRequire for gcc-PIE. - -------------------------------------------------------------------- -Thu Feb 5 06:58:52 UTC 2015 - mail@bernhard-voelker.de - -- coreutils-tests-aarch64-env.patch: Add patch to avoid false - positive failures of the coreutils-testsuite on OBS/aarch64: - work around execve() reversing the order of "env" output. - -------------------------------------------------------------------- -Mon Jan 19 23:06:22 UTC 2015 - mail@bernhard-voelker.de - -- Add upstream patches for df(1) from upstream, thus aligning with SLES12: - * df: improve mount point selection with inaccurate mount list: - - coreutils-df-improve-mount-point-selection.patch - * doc: mention that df -a includes duplicate file systems (deb#737399) - - coreutils-df-doc-df-a-includes-duplicate-file-systems.patch - * df: ensure -a shows all remote file system entries (deb#737399) - - coreutils-df-show-all-remote-file-systems.patch - * df: only suppress remote mounts of separate exports with --total - (deb#737399, rh#920806, boo#866010, boo#901905) - - coreutils-df-total-suppress-separate-remotes.patch -- Refresh patches: - * coreutils-chroot-perform-chdir-unless-skip-chdir.patch - * coreutils-tests-make-inotify-rotate-more-robust-and-efficient.patch - -------------------------------------------------------------------- -Sat Nov 1 00:20:55 UTC 2014 - mail@bernhard-voelker.de - -Avoid spurious false positive failures of the testsuite on OBS due -to high load. - -- coreutils-tests-rm-ext3-perf-increase-timeout.patch: - Add patch to increase timeout. - -- coreutils-tests-make-inotify-rotate-more-robust-and-efficient.patch: - Add upstream patch. - -------------------------------------------------------------------- -Sat Sep 27 17:46:01 UTC 2014 - schwab@linux-m68k.org - -- sort-keycompare-mb.patch: make sure to NUL-terminate the sort keys. - Fixes http://bugs.gnu.org/18540 - -------------------------------------------------------------------- -Thu Sep 18 18:04:37 CEST 2014 - pth@suse.de - -- Add coreutils-fix_false_du_failure_on_newer_xfs.patch that fixes a false - negative in the testsuite. -- Add coreutils-disable_tests.patch to not run a tests that fail inside the OBS. -- Add coreutils-test_without_valgrind.patch to not use valgrind in shuf-reservoir. - -------------------------------------------------------------------- -Fri Aug 1 15:54:41 UTC 2014 - mail@bernhard-voelker.de - -- Add patches for upstream glitches: - - coreutils-fix-man-deps.patch - - coreutils-chroot-perform-chdir-unless-skip-chdir.patch - -- Refresh patches: - - coreutils-build-timeout-as-pie.patch - - coreutils-getaddrinfo.patch - - coreutils-i18n.patch - - coreutils-misc.patch - - coreutils-ocfs2_reflinks.patch - - coreutils-remove_hostname_documentation.patch - - coreutils-remove_kill_documentation.patch - - coreutils-skip-gnulib-test-tls.patch - - coreutils-tests-shorten-extreme-factor-tests.patch - -- Remove now-upstream patches: - - coreutils-copy-fix-selinux-existing-dirs.patch - - coreutils-gnulib-tests-ppc64le.patch - - coreutils-tests-avoid-FP-cp-cpuinfo.patch - - coreutils-test-avoid-FP-when-no-ACL-support.patch - - coreutils-ln-avoid-segfault-for-empty-target.patch - - coreutils-date-avoid-crash-in-TZ-parsing.patch - - coreutils-shuf-repeat-avoid-crash-when-input-empty.patch - - coreutils-improve_df_--human_and_--si,_help_and_man_page.patch - - coreutils-avoid_sizeof_charPP__static_analysis_warning.patch - - coreutils-also_deduplicate_virtual_file_systems.patch - - coreutils-fix_handling_of_symlinks_in_mount_list.patch - - coreutils-ignore_non_file_system_entries_in_proc_mounts.patch - - coreutils-avoid_clang_-Wtautological-constant-out-of-range-compare_warning.patch - - coreutils-use_the_last_device_name_provided_by_the_system.patch - - coreutils-avoid_compiler_warnings_with_some_assert_implementations.patch - - coreutils-use_all_of_the_last_device_details_provided.patch - - coreutils-output_placeholder_values_for_inaccessible_mount_points.patch - - coreutils-look_for_accessible_mount_points_for_specified_devices.patch - - coreutils-report_correct_device_in_presence_of_eclipsed_mounts.patch - - coreutils-avoid_an_inconsequential_mem_leak.patch - -- Update to 8.23 (2014-07-18) [stable] - - ** Bug fixes - - chmod -Rc no longer issues erroneous warnings for files with special bits set. - [bug introduced in coreutils-6.0] - - cp -a, mv, and install --preserve-context, once again set the correct SELinux - context for existing directories in the destination. Previously they set - the context of an existing directory to that of its last copied descendent. - [bug introduced in coreutils-8.22] - - cp -a, mv, and install --preserve-context, no longer seg fault when running - with SELinux enabled, when copying from file systems that return an error - when reading the SELinux context for a file. - [bug introduced in coreutils-8.22] - - cp -a and mv now preserve xattrs of symlinks copied across file systems. - [bug introduced with extended attribute preservation feature in coreutils-7.1] - - date could crash or go into an infinite loop when parsing a malformed TZ="". - [bug introduced with the --date='TZ="" ..' parsing feature in coreutils-5.3.0] - - dd's ASCII and EBCDIC conversions were incompatible with common practice and - with POSIX, and have been corrected as follows. First, conv=ascii now - implies conv=unblock, and conv=ebcdic and conv=ibm now imply conv=block. - Second, the translation tables for dd conv=ascii and conv=ebcdic have been - corrected as shown in the following table, where A is the ASCII value, W is - the old, wrong EBCDIC value, and E is the new, corrected EBCDIC value; all - values are in octal. - - A W E - 041 117 132 - 133 112 255 - 135 132 275 - 136 137 232 - 174 152 117 - 176 241 137 - 313 232 152 - 325 255 112 - 345 275 241 - - [These dd bugs were present in "the beginning".] - - df has more fixes related to the newer dynamic representation of file systems: - Duplicates are elided for virtual file systems like tmpfs. - Details for the correct device are output for points mounted multiple times. - Placeholder values are output for inaccessible file systems, rather than - than error messages or values for the wrong file system. - [These bugs were present in "the beginning".] - - df now outputs all appropriate entries in the presence of bind mounts. - On some systems, entries would have been incorrectly elided due to - them being considered "dummy" mounts. - [bug introduced in coreutils-8.22] - - du now silently ignores directory cycles introduced with bind mounts. - Previously it would issue a warning and exit with a failure status. - [bug introduced in coreutils-8.1] - - head --bytes=-N and --lines=-N now handles devices more - consistently, not ignoring data from virtual devices like /dev/zero, - or on BSD systems data from tty devices. - [bug introduced in coreutils-5.0.1] - - head --bytes=-N - no longer fails with a bogus diagnostic when stdin's - seek pointer is not at the beginning. - [bug introduced with the --bytes=-N feature in coreutils-5.0.1] - - head --lines=-0, when the input does not contain a trailing '\n', - now copies all input to stdout. Previously nothing was output in this case. - [bug introduced with the --lines=-N feature in coreutils-5.0.1] - - id, when invoked with no user name argument, now prints the correct group ID. - Previously, in the default output format, it would print the default group ID - in the password database, which may be neither real nor effective. For e.g., - when run set-GID, or when the database changes outside the current session. - [bug introduced in coreutils-8.1] - - ln -sf now replaces symbolic links whose targets can't exist. Previously - it would display an error, requiring --no-dereference to avoid the issue. - [bug introduced in coreutils-5.3.0] - - ln -sr '' F no longer segfaults. Now works as expected. - [bug introduced with the --relative feature in coreutils-8.16] - - numfmt now handles blanks correctly in all unibyte locales. Previously - in locales where character 0xA0 is a blank, numfmt would mishandle it. - [bug introduced when numfmt was added in coreutils-8.21] - - ptx --format long option parsing no longer falls through into the --help case. - [bug introduced in TEXTUTILS-1_22i] - - ptx now consistently trims whitespace when processing multiple files. - [This bug was present in "the beginning".] - - seq again generates correct output with start or end values = -0. - [bug introduced in coreutils-8.20.] - - shuf --repeat no longer dumps core if the input is empty. - [bug introduced with the --repeat feature in coreutils-8.22] - - sort when using multiple threads now avoids undefined behavior with mutex - destruction, which could cause deadlocks on some implementations. - [bug introduced in coreutils-8.6] - - tail -f now uses polling mode for VXFS to cater for its clustered mode. - [bug introduced with inotify support added in coreutils-7.5] - - ** New features - - od accepts a new option: --endian=TYPE to handle inputs with different byte - orders, or to provide consistent output on systems with disparate endianness. - - configure accepts the new option --enable-single-binary to build all the - selected programs in a single binary called "coreutils". The selected - programs can still be called directly using symlinks to "coreutils" or - shebangs with the option --coreutils-prog= passed to this program. The - install behavior is determined by the option --enable-single-binary=symlinks - or --enable-single-binary=shebangs (the default). With the symlinks option, - you can't make a second symlink to any program because that will change the - name of the called program, which is used by coreutils to determine the - desired program. The shebangs option doesn't suffer from this problem, but - the /proc/$pid/cmdline file might not be updated on all the platforms. The - functionality of each program is not affected but this single binary will - depend on all the required dynamic libraries even to run simple programs. - If you desire to build some tools outside the single binary file, you can - pass the option --enable-single-binary-exceptions=PROG_LIST with the comma - separated list of programs you want to build separately. This flag - considerably reduces the overall size of the installed binaries which makes - it suitable for embedded system. - - ** Changes in behavior - - chroot with an argument of "/" no longer implicitly changes the current - directory to "/", allowing changing only user credentials for a command. - - chroot --userspec will now unset supplemental groups associated with root, - and instead use the supplemental groups of the specified user. - - cut -d$'\n' again outputs lines identified in the --fields list, having - not done so in v8.21 and v8.22. Note using this non portable functionality - will result in the delayed output of lines. - - ls with none of LS_COLORS or COLORTERM environment variables set, - will now honor an empty or unknown TERM environment variable, - and not output colors even with --colors=always. - - ** Improvements - - chroot has better --userspec and --group look-ups, with numeric IDs never - causing name look-up errors. Also look-ups are first done outside the chroot, - in case the look-up within the chroot fails due to library conflicts etc. - - install now allows the combination of the -D and -t options. - - numfmt supports zero padding of numbers using the standard printf - syntax of a leading zero, for example --format="%010f". - Also throughput was improved by up to 800% by avoiding redundant processing. - - shred now supports multiple passes on GNU/Linux tape devices by rewinding - the tape before each pass, avoids redundant writes to empty files, - uses direct I/O for all passes where possible, and attempts to clear - inode storage used for small files on some file systems. - - split avoids unnecessary input buffering, immediately writing input to output - which is significant with --filter or when writing to fifos or stdout etc. - - stat and tail work better with HFS+, HFSX, LogFS and ConfigFS. stat -f - --format=%T now reports the file system type, and tail -f now uses inotify, - rather than the default of issuing a warning and reverting to polling. - -------------------------------------------------------------------- -Fri Jul 25 23:48:47 CEST 2014 - pth@suse.de - -- Incorporate 9 bugfixes, one documentation update and two maintenance - patches that won't harm (bnc#888215), See NEWS for specifics: - - coreutils-improve_df_--human_and_--si,_help_and_man_page.patch - coreutils-avoid_sizeof_charPP__static_analysis_warning.patch - coreutils-also_deduplicate_virtual_file_systems.patch - coreutils-fix_handling_of_symlinks_in_mount_list.patch - coreutils-ignore_non_file_system_entries_in_proc_mounts.patch - coreutils-avoid_clang_-Wtautological-constant-out-of-range-compare_warning.patch - coreutils-use_the_last_device_name_provided_by_the_system.patch - coreutils-avoid_compiler_warnings_with_some_assert_implementations.patch - coreutils-use_all_of_the_last_device_details_provided.patch - coreutils-output_placeholder_values_for_inaccessible_mount_points.patch - coreutils-look_for_accessible_mount_points_for_specified_devices.patch - coreutils-report_correct_device_in_presence_of_eclipsed_mounts.patch - coreutils-avoid_an_inconsequential_mem_leak.patch - -------------------------------------------------------------------- -Sun Mar 16 20:38:48 UTC 2014 - mail@bernhard-voelker.de - -- Add upstream patch (gnu#16855): - * coreutils-shuf-repeat-avoid-crash-when-input-empty.patch: Add - patch for shuf: with -r, don't dump core if the input is empty. - -------------------------------------------------------------------- -Sun Mar 16 19:28:34 UTC 2014 - mail@bernhard-voelker.de - -- Add upstream patch (gnu#16872): - * coreutils-date-avoid-crash-in-TZ-parsing.patch: Add patch for - date: fix crash or infinite loop when parsing a malformed TZ="". - -------------------------------------------------------------------- -Sun Mar 16 16:00:15 UTC 2014 - mail@bernhard-voelker.de - -- Add upstream patch (gnu#17010): - * coreutils-ln-avoid-segfault-for-empty-target.patch: Add patch - to avoid that ln(1) segfaults for an empty, relative target. - -------------------------------------------------------------------- -Mon Feb 24 14:59:35 CET 2014 - pth@suse.de - -- Add three patches from SLE12 that aren't upstream: - coreutils-misc.patch (fixes for tests) - coreutils-getaddrinfo.patch (fake success as there's no network - in the build system) - coreutils-ocfs2_reflinks.patch (support ocfs2 reflinks in cp) - -------------------------------------------------------------------- -Fri Jan 24 13:36:37 UTC 2014 - mail@bernhard-voelker.de - -- Testsuite: avoid a failure of tests/mkdir/p-acl.sh on armv7l. - * coreutils-test-avoid-FP-when-no-ACL-support.patch: Add upstream - patch to improve the check for a working ACL support. - -- Refresh patches with QUILT_REFRESH_ARGS="-p0 --no-timestamps" - for easier patch handling. - -------------------------------------------------------------------- -Thu Jan 9 01:55:08 UTC 2014 - mail@bernhard-voelker.de - -- Add upstream patch (coreutils-copy-fix-selinux-existing-dirs.patch): - cp -a: set the correct SELinux context on already existing - destination directories (rh#1045122). - -- Merge I18n fixes from Fedora (coreutils-i18n.patch): - * sort: fix sorting by non-first field (rh#1003544) - * cut: avoid using slower multi-byte code in non-UTF-8 locales - (rh#1021403, rh#499220). - -- Testsuite: skip some tests: - * coreutils-skip-some-sort-tests-on-ppc.patch: Add patch to - skip 2 valgrind'ed sort tests on ppc/ppc64. - * coreutils-skip-gnulib-test-tls.patch: Add patch to skip - the gnulib test 'test-tls' on i586, x86_64, ppc and ppc64. - * coreutils-tests-avoid-FP-cp-cpuinfo.patch: Add patch to skip a - test when cp fails for /proc/cpuinfo which happens on aarch64. - * coreutils-tests-shorten-extreme-factor-tests.patch: Add patch - to skip most of the extreme-expensive factor tests. - -------------------------------------------------------------------- -Sat Jan 4 23:05:46 UTC 2014 - mail@bernhard-voelker.de - -- Refresh patches to match the new version. - - * coreutils-build-timeout-as-pie.patch: Update line number. - * coreutils-gnulib-tests-ppc64le.patch: Likewise. - * coreutils-invalid-ids.patch: Likewise. - * coreutils-remove_hostname_documentation.patch: Likewise. - * coreutils-remove_kill_documentation.patch: Likewise. - * coreutils-sysinfo.patch: Likewise. - * coreutils-i18n.patch: Likewise. - -- Additional changes in coreutils-i18n.patch: - * Accommodate to upstream changes in cut.c and uniq.c. - * Fix some compiler warnings. - * Fix 145-mb test in tests/misc/uniq.pl. - * Skip sort's "2[01]a" test cases for now - to avoid a test failure on i586/x86_64. - -- Remove now-upstream and therefore obsolete patches. - - * coreutils-8.21.de.po.xz: Remove, upstream is latest. - * coreutils-gnulib-tests-fix-nap-race-obs.patch: - Remove, now upstream. - * coreutils-gnulib-tests-fix-nap-race.patch: Likewise. - * longlong-aarch64.patch: Likewise. - -- Update to 8.22 (2013-12-13) [stable] - - ** Bug fixes - - df now processes the mount list correctly in the presence of unstatable - mount points. Previously it may have failed to output some mount points. - [bug introduced in coreutils-8.21] - - df now processes symbolic links and relative paths to special files containing - a mounted file system correctly. Previously df displayed the statistics about - the file system the file is stored on rather than the one inside. - [This bug was present in "the beginning".] - - df now processes disk device nodes correctly in the presence of bind mounts. - Now df shows the base mounted file system rather than the last one mounted. - [This bug was present in "the beginning".] - - install now removes the target file if the strip program failed for any - reason. Before, that file was left behind, sometimes even with wrong - permissions. - [This bug was present in "the beginning".] - - ln --relative now updates existing symlinks correctly. Previously it based - the relative link on the dereferenced path of an existing link. - [This bug was introduced when --relative was added in coreutils-8.16.] - - ls --recursive will no longer exit with "serious" exit code (2), if there - is an error reading a directory not specified on the command line. - [Bug introduced in coreutils-5.3.0] - - mkdir, mkfifo, and mknod now work better when creating a file in a directory - with a default ACL whose umask disagrees with the process's umask, on a - system such as GNU/Linux where directory ACL umasks override process umasks. - [bug introduced in coreutils-6.0] - - mv will now replace empty directories in the destination with directories - from the source, when copying across file systems. - [This bug was present in "the beginning".] - - od -wN with N larger than 64K on a system with 32-bit size_t would - print approximately 2*N bytes of extraneous padding. - [Bug introduced in coreutils-7.0] - - rm -I now prompts for confirmation before removing a write protected file. - [Bug introduced in coreutils-6.8] - - shred once again uses direct I/O on systems requiring aligned buffers. - Also direct I/O failures for odd sized writes at end of file are now handled. - [The "last write" bug was introduced in coreutils-5.3.0 but masked - by the alignment bug introduced in coreutils-6.0] - - tail --retry -f now waits for the files specified to appear. Before, tail - would immediately exit when such a file is initially inaccessible. - [This bug was introduced when inotify support was added in coreutils-7.5] - - tail -F has improved handling of symlinks. Previously tail didn't respond - to the symlink target (re)appearing after being (re)created. - [This bug was introduced when inotify support was added in coreutils-7.5] - - ** New features - - cp, install, mkdir, mknod, mkfifo and mv now support "restorecon" - functionality through the -Z option, to set the SELinux context - appropriate for the new item location in the file system. - - csplit accepts a new option: --suppressed-matched, to elide the lines - used to identify the split points. - - df --output now accepts a 'file' field, to propagate a specified - command line argument through to the output. - - du accepts a new option: --inodes to show the number of inodes instead - of the blocks used. - - id accepts a new option: --zero (-z) to delimit the output entries by - a NUL instead of a white space character. - - id and ls with -Z report the SMACK security context where available. - mkdir, mkfifo and mknod with -Z set the SMACK context where available. - - id can now lookup by user ID, in addition to the existing name lookup. - - join accepts a new option: --zero-terminated (-z). As with the sort,uniq - option of the same name, this makes join consume and produce NUL-terminated - lines rather than newline-terminated lines. - - uniq accepts a new option: --group to print all items, while separating - unique groups with empty lines. - - shred accepts new parameters to the --remove option to give greater - control over that operation, which can greatly reduce sync overhead. - - shuf accepts a new option: --repeat (-r), which can repeat items in - the output. - - ** Changes in behavior - - cp --link now dereferences a symbolic link as source before creating the - hard link in the destination unless the -P,--no-deref option is specified. - Previously, it would create a hard link of the symbolic link, even when - the dereferencing options -L or -H were specified. - - cp, install, mkdir, mknod and mkfifo no longer accept an argument to the - short -Z option. The --context equivalent still takes an optional argument. - - dd status=none now suppresses all non fatal diagnostic messages, - not just the transfer counts. - - df no longer accepts the long-obsolescent --megabytes option. - - stdbuf now requires at least one buffering mode option to be specified, - as per the documented interface. - - ** Improvements - - base64 encoding throughput for bulk data is increased by about 60%. - - md5sum can use libcrypto hash routines where allowed to potentially - get better performance through using more system specific logic. - sha1sum for example has improved throughput by 40% on an i3-2310M. - This also affects sha1sum, sha224sum, sha256sum, sha384sum and sha512sum. - - stat and tail work better with EFIVARFS, EXOFS, F2FS, HOSTFS, SMACKFS, SNFS - and UBIFS. stat -f --format=%T now reports the file system type, and tail -f - now uses inotify for files on all those except SNFS, rather than the default - (for unknown file system types) of issuing a warning and reverting to polling. - - shuf outputs subsets of large inputs much more efficiently. - Reservoir sampling is used to limit memory usage based on the number of - outputs, rather than the number of inputs. - - shred increases the default write block size from 12KiB to 64KiB - to align with other utilities and reduce the system call overhead. - - split --line-bytes=SIZE, now only allocates memory as needed rather - than allocating SIZE bytes at program start. - - stty now supports configuring "stick" (mark/space) parity where available. - - ** Build-related - - factor now builds on aarch64 based systems [bug introduced in coreutils-8.20] - -------------------------------------------------------------------- -Thu Dec 19 23:37:39 UTC 2013 - uweigand@de.ibm.com - -- coreutils-gnulib-tests-ppc64le.patch: Fix imported gnulib long double - math tests for little-endian PowerPC. - -------------------------------------------------------------------- -Thu Dec 19 22:54:26 UTC 2013 - mail@bernhard-voelker.de - -- Fix issue with binary input in non-C locale (rh#1036289) - (coreutils-i18n.patch): Initialize memory for some edge cases - in the i18n patch for uniq and join. - -------------------------------------------------------------------- -Wed Dec 11 20:22:47 UTC 2013 - mail@bernhard-voelker.de - -- Avoid false sort test failure (coreutils-i18n.patch): - As for the C locale, skip the multi-byte test case - 'output-is-input-mb.p'. - -------------------------------------------------------------------- -Sat Dec 7 19:15:40 UTC 2013 - schwab@linux-m68k.org - -- Require valgrind only when it exists - -------------------------------------------------------------------- -Sun Dec 1 22:48:48 UTC 2013 - mail@bernhard-voelker.de - -- Update I18N patch from Fedora: - (coreutils-i18n.patch) - * sort: fix multibyte incompabilities (rh#821264) - * pr -e, with a mix of backspaces and TABs, could corrupt the - heap in multibyte locales (analyzed by J.Koncicky) - * path in the testsuite to cover i18n regressions - * Enable cut and sort-merge perl tests for multibyte as well -- Refresh longlong-aarch64.patch. - -------------------------------------------------------------------- -Wed Aug 7 08:10:22 UTC 2013 - mail@bernhard-voelker.de - -- Remove "BuildRequires: help2man" as it is included. - -------------------------------------------------------------------- -Tue Aug 6 14:02:42 CEST 2013 - pth@suse.de - -- Remove the the unnecessary povision of itself as rpmbuild takes - care of that. -- Remove all traces of coreutils-8.9-singlethreaded-sort.patch in - the spec file. - -------------------------------------------------------------------- -Tue Jul 23 13:22:21 UTC 2013 - mail@bernhard-voelker.de - -- Undo the previous change. - Remove configure options gl_cv_func_printf_directive_n and - gl_cv_func_printf_infinite_long_double again because of constant - factory build failures on x86_64 and i586. The argument for - adding them was that the fortify checks would be bypassed - by the gnulib "reimplementation of printf", but that is not - the case: instead, gnulib just adds some wrapping code to ensure - a consistent behaviour on all supported platforms. - -------------------------------------------------------------------- -Mon Jul 8 15:09:22 UTC 2013 - schwab@suse.de - -- Override broken configure checks -- coreutils-gl_printf_safe.patch: remove unused patch - -------------------------------------------------------------------- -Sun Jun 16 23:59:28 UTC 2013 - jengelh@inai.de - -- Explicitly list libattr-devel as BuildRequires -- More robust make install call - -------------------------------------------------------------------- -Fri Jun 7 14:36:26 UTC 2013 - schwab@suse.de - -- longlong-aarch64.patch: fix build on aarch64 - -------------------------------------------------------------------- -Fri Jun 7 01:50:04 UTC 2013 - mail@bernhard-voelker.de - -- Remove su(1) and kill(1) - both are provided by util-linux now. - * su.pamd, su.default, coreutils-su.patch: Remove patch and PAM - config files related to su(1). - * coreutils-remove_kill_documentation.patch: Add patch to remove - kill from the texinfo manual. - * coreutils.spec: Remove above, su-related patch and sources. - Remove Requires:pam and BuildRequires:pam-devel. - Remove Provides:/bin/{su,kill}. - Remove paragraph mentioning su(1) and kill(1) in %description. - Remove `moving su trickery` and other left-overs from %install, - %post and %files. - Remove %posttrans and %verifyscript sections (as these contained - su-related stuff). - Add code to %install to remove kill's program and man page. - -------------------------------------------------------------------- -Mon May 20 15:38:30 UTC 2013 - mail@bernhard-voelker.de - -- Try to fix nap() races in gnulib-tests. - (coreutils-gnulib-tests-fix-nap-race.patch: add upstream patch) - (coreutils-gnulib-tests-fix-nap-race-obs.patch: add openSUSE patch for OBS) - -------------------------------------------------------------------- -Wed May 15 11:26:29 UTC 2013 - mhrusecky@suse.com - -- Provides: /bin/{kill,su} - * for compatibility with programs requiring these (like lsb) until these will - be provided by util-linux - -------------------------------------------------------------------- -Thu Apr 4 23:25:17 UTC 2013 - mail@bernhard-voelker.de - -- Fix source url for coreutils-testsuite. - -------------------------------------------------------------------- -Thu Mar 21 11:55:13 UTC 2013 - mmeister@suse.com - -- Added url as source. - Please see http://en.opensuse.org/SourceUrls - -------------------------------------------------------------------- -Thu Mar 21 11:54:05 UTC 2013 - mail@bernhard-voelker.de - -- Fix multibyte issue in unexpand (rh#821262) - (coreutils-i18n.patch: patch by Roman Kollár ) - -- Fix cut to terminate mbdelim string - - Otherwise, cut might do an unbounded strdup of the delimiter string - in i18n mode (https://bugzilla.redhat.com/show_bug.cgi?id=911929) - (coreutils-i18n.patch, from Mark Wielaard ) - -- Add su(1) again - - Now, su(1) will be provided via a symlink trick - to the file installed with a ".core" suffix. - By this, we can upgrade to 8.21 without having to wait - for a util-linux version providing it. - - * coreutils-su.patch: Add cumulative su patch from previous Base:System - version 8.17, ported to 8.21 build structure. This supersedes the - following partial patches: - coreutils-8.6-compile-su-with-fpie.diff, - coreutils-8.6-honor-settings-in-etc-default-su-resp-etc-login.defs.diff, - coreutils-8.6-log-all-su-attempts.diff, - coreutils-8.6-make-sure-sbin-resp-usr-sbin-are-in-PATH.diff, - coreutils-8.6-pam-support-for-su.diff, - coreutils-8.6-set-sane-default-path.diff, - coreutils-8.6-update-man-page-for-pam.diff, - coreutils-bnc#697897-setsid.patch. - - * pam, pam-devel: Add as requirements, also during build. - * coreutils.spec (%description): Clarify that su is included although removed - upstreams. - (%install): Install su+kill files with suffix ".core". - (%post): Move setting permissions on su from %posttrans to %install. - (%posttrans): Create symlinks to files with ".core" suffix unless already - existing. - -- Install kill(1) with the same symlink trick. - -- Remove now-obsolete patches and files: - - * coreutils-8.17.de.po.xz: - * coreutils-8.17.tar.xz: - Remove sources + translation of previous version - - * coreutils-acl-nofollow.patch: - * coreutils-basename_documentation.patch: - * coreutils-cp-corrupt-fragmented-sparse.patch: - * coreutils-df-always-hide-rootfs.patch: - * coreutils-skip-du-slink-test.patch: - Fixed upstream. - - * coreutils-getaddrinfo.patch: - * coreutils-misc.patch: - * coreutils-no_silent-rule.patch: - Remove test and build related patches. - - * coreutils-ptr_int_casts.patch: - Remove because merged into coreutils-i18n.patch. - -- Add files: - - * coreutils-8.21.tar.xz: - Add tarball of the new upstream version - * coreutils-8.21.de.po.xz: - Add language file. - -- Update patches: - - * coreutils-i18n.patch - Merge some Fedora changes to keep the i18n patch like theirs. - Fix and cleanup sort's multibyte test with incorporated test data. - - * coreutils-remove_hostname_documentation.patch - -- Add patch to build 'timeout' as PIE (OBS requires it). - This patch actually was included in one of the old su patches. - - * new patch name: coreutils-build-timeout-as-pie.patch - -- Temporary disable some questionable patches (by commenting in the spec file): - - * coreutils-gl_printf_safe.patch - * coreutils-8.9-singlethreaded-sort.patch - -- Change build / spec file: - - * Bump version from 8.17 to 8.21. - * Fix macro invocation in "Provides" for stat. - * Remove ancient "Obsoletes" entries. - * Remove/add the above removed/added sources and patches. - * Temporarily comment the code for statically linking LIB_GMP - (as it does not work). - * Remove -Wall from CFLAGS as it is already included in OBS' default options. - * Remove the --without-included-regex option to use - coreutils' regex implementation. - * Remove custom gl_cv_func_printf_directive_n and gl_cv_func_isnanl_works. - * Touch "man/*.x" to force the rebuild of the man pages. - * Make sort's multi-byte test script executable in %check section. - * Hardcode package name for "%find_lang" and "%files lang -f" lines. - * In the %files section, add the COPYING and THANKS files. - Furthermore, fix the path to the LC_TIME files. - * Change package description to accomodate to added programs - (hostid, nproc, realpath, stdbuf, truncate) - and mention the hacky installation of programs to move (kill, su). - - -- Update to 8.21 (2013-02-14) [stable] - - ** New programs - - numfmt: reformat numbers - - ** New features - - df now accepts the --output[=FIELD_LIST] option to define the list of columns - to include in the output, or all available columns if the FIELD_LIST is - omitted. Note this enables df to output both block and inode fields together. - - du now accepts the --threshold=SIZE option to restrict the output to entries - with such a minimum SIZE (or a maximum SIZE if it is negative). - du recognizes -t SIZE as equivalent, for compatibility with FreeBSD. - - ** Bug fixes - - cp --no-preserve=mode now no longer exits non-zero. - [bug introduced in coreutils-8.20] - - cut with a range like "N-" no longer allocates N/8 bytes. That buffer - would never be used, and allocation failure could cause cut to fail. - [bug introduced in coreutils-8.10] - - cut no longer accepts the invalid range 0-, which made it print empty lines. - Instead, cut now fails and emits an appropriate diagnostic. - [This bug was present in "the beginning".] - - cut now handles overlapping to-EOL ranges properly. Before, it would - interpret "-b2-,3-" like "-b3-". Now it's treated like "-b2-". - [This bug was present in "the beginning".] - - cut no longer prints extraneous delimiters when a to-EOL range subsumes - another range. Before, "echo 123|cut --output-delim=: -b2-,3" would print - "2:3". Now it prints "23". [bug introduced in 5.3.0] - - cut -f no longer inspects input line N+1 before fully outputting line N, - which avoids delayed output for intermittent input. - [bug introduced in TEXTUTILS-1_8b] - - factor no longer loops infinitely on 32 bit powerpc or sparc systems. - [bug introduced in coreutils-8.20] - - install -m M SOURCE DEST no longer has a race condition where DEST's - permissions are temporarily derived from SOURCE instead of from M. - - pr -n no longer crashes when passed values >= 32. Also, line numbers are - consistently padded with spaces, rather than with zeros for certain widths. - [bug introduced in TEXTUTILS-1_22i] - - seq -w ensures that for numbers input in scientific notation, - the output numbers are properly aligned and of the correct width. - [This bug was present in "the beginning".] - - seq -w ensures correct alignment when the step value includes a precision - while the start value does not, and the number sequence narrows. - [This bug was present in "the beginning".] - - seq -s no longer prints an erroneous newline after the first number, and - outputs a newline after the last number rather than a trailing separator. - Also seq no longer ignores a specified step value when the end value is 1. - [bugs introduced in coreutils-8.20] - - timeout now ensures that blocking of ALRM signals is not inherited from - its parent, which would cause timeouts to be ignored. - [the bug dates back to the initial implementation] - - ** Changes in behavior - - df --total now prints '-' into the target column (mount point) of the - summary line, accommodating the --output option where the target field - can be in any column. If there is no source column, then df prints - 'total' in the target column. - - df now properly outputs file system information with bind mounts present on - the system by skipping duplicate entries (identified by the device number). - Consequently, df also elides the early-boot pseudo file system type "rootfs". - - nl no longer supports the --page-increment option, which has been - deprecated since coreutils-7.5. Use --line-increment instead. - - ** Improvements - - readlink now supports multiple arguments, and a complementary - -z, --zero option to delimit output items with the NUL character. - - stat and tail now know about CEPH. stat -f --format=%T now reports the file - system type, and tail -f uses polling for files on CEPH file systems. - - stty now supports configuring DTR/DSR hardware flow control where available. - - ** Build-related - - Perl is now more of a prerequisite. It has long been required in order - to run (not skip) a significant percentage of the tests. Now, it is - also required in order to generate proper man pages, via help2man. The - generated man/*.1 man pages are no longer distributed. Building without - perl, you would create stub man pages. Thus, while perl is not an - official prerequisite (build and "make check" will still succeed), any - resulting man pages would be inferior. In addition, this fixes a bug - in distributed (not from clone) Makefile.in that could cause parallel - build failure when building from modified sources, as is common practice - for a patched distribution package. - - factor now builds on x86_64 with x32 ABI, 32 bit MIPS, and all HPPA systems, - by avoiding incompatible asm. [bug introduced in coreutils-8.20] - - A root-only test predicate would always fail. Its job was to determine - whether our dummy user, $NON_ROOT_USERNAME, was able to run binaries from - the build directory. As a result, all dependent tests were always skipped. - Now, those tests may be run once again. [bug introduced in coreutils-8.20] - - -- Update to 8.20 (2012-10-23) [stable] - - ** New features - - dd now accepts 'status=none' to suppress all informational output. - - md5sum now accepts the --tag option to print BSD-style output with GNU - file name escaping. This also affects sha1sum, sha224sum, sha256sum, - sha384sum and sha512sum. - - ** Bug fixes - - cp could read from freed memory and could even make corrupt copies. - This could happen with a very fragmented and sparse input file, - on GNU/Linux file systems supporting fiemap extent scanning. - This bug also affects mv when it resorts to copying, and install. - [bug introduced in coreutils-8.11] - - cp --no-preserve=mode now no longer preserves the original file's - permissions but correctly sets mode specified by 0666 & ~umask - - du no longer emits a "disk-corrupted"-style diagnostic when it detects - a directory cycle that is due to a bind-mounted directory. Instead, - it detects this precise type of cycle, diagnoses it as such and - eventually exits nonzero. - - factor (when using gmp) would mistakenly declare some composite numbers - to be prime, e.g., 465658903, 2242724851, 6635692801 and many more. - The fix makes factor somewhat slower (~25%) for ranges of consecutive - numbers, and up to 8 times slower for some worst-case individual numbers. - [bug introduced in coreutils-7.0, with GNU MP support] - - ls now correctly colors dangling symlinks when listing their containing - directories, with orphaned symlink coloring disabled in LS_COLORS. - [bug introduced in coreutils-8.14] - - rm -i -d now prompts the user then removes an empty directory, rather - than ignoring the -d option and failing with an 'Is a directory' error. - [bug introduced in coreutils-8.19, with the addition of --dir (-d)] - - rm -r S/ (where S is a symlink-to-directory) no longer gives the invalid - "Too many levels of symbolic links" diagnostic. - [bug introduced in coreutils-8.6] - - seq now handles arbitrarily long non-negative whole numbers when the - increment is 1 and when no format-changing option is specified. - Before, this would infloop: - b=100000000000000000000; seq $b $b - [the bug dates back to the initial implementation] - - ** Changes in behavior - - nproc now diagnoses with an error, non option command line parameters. - - ** Improvements - - factor's core has been rewritten for speed and increased range. - It can now factor numbers up to 2^128, even without GMP support. - Its speed is from a few times better (for small numbers) to over - 10,000 times better (just below 2^64). The new code also runs a - deterministic primality test for each prime factor, not just a - probabilistic test. - - seq is now up to 70 times faster than it was in coreutils-8.19 and prior, - but only with non-negative whole numbers, an increment of 1, and no - format-changing options. - - stat and tail know about ZFS, VZFS and VMHGFS. stat -f --format=%T now - reports the file system type, and tail -f now uses inotify for files on - ZFS and VZFS file systems, rather than the default (for unknown file - system types) of issuing a warning and reverting to polling. tail -f - still uses polling for files on VMHGFS file systems. - - ** Build-related - - root-only tests now check for permissions of our dummy user, - $NON_ROOT_USERNAME, before trying to run binaries from the build directory. - Before, we would get hard-to-diagnose reports of failing root-only tests. - Now, those tests are skipped with a useful diagnostic when the root tests - are run without following the instructions in README. - - We now build most directories using non-recursive make rules. I.e., - rather than running make in man/, lib/, src/, tests/, instead, the top - level Makefile.am includes a $dir/local.mk that describes how to build - the targets in the corresponding directory. Two directories remain - unconverted: po/, gnulib-tests/. One nice side-effect is that the more - accurate dependencies have eliminated a nagging occasional failure that - was seen when running parallel "make syntax-check". - - -- Update to 8.19 (2012-08-20) [stable] - - ** Bug fixes - - df now fails when the list of mounted file systems (/etc/mtab) cannot - be read, yet the file system type information is needed to process - certain options like -a, -l, -t and -x. - [This bug was present in "the beginning".] - - sort -u could fail to output one or more result lines. - For example, this command would fail to print "1": - (yes 7 | head -11; echo 1) | sort --p=1 -S32b -u - [bug introduced in coreutils-8.6] - - sort -u could read freed memory. - For example, this evokes a read from freed memory: - perl -le 'print "a\n"."0"x900'|valgrind sort --p=1 -S32b -u>/dev/null - [bug introduced in coreutils-8.6] - - ** New features - - rm now accepts the --dir (-d) option which makes it remove empty directories. - Since removing empty directories is relatively safe, this option can be - used as a part of the alias rm='rm --dir'. This improves compatibility - with Mac OS X and BSD systems which also honor the -d option. - - -- Update to 8.18 (2012-08-12) [stable] - - ** Bug fixes - - cksum now prints checksums atomically so that concurrent - processes will not intersperse their output. - [the bug dates back to the initial implementation] - - date -d "$(printf '\xb0')" would print 00:00:00 with today's date - rather than diagnosing the invalid input. Now it reports this: - date: invalid date '\260' - [This bug was present in "the beginning".] - - df no longer outputs control characters present in the mount point name. - Such characters are replaced with '?', so for example, scripts consuming - lines output by df, can work reliably. - [This bug was present in "the beginning".] - - df --total now exits with an appropriate diagnostic and error code, when - file system --type options do not lead to a processed file system. - [This bug dates back to when --total was added in coreutils-7.0] - - head --lines=-N (-n-N) now resets the read pointer of a seekable input file. - This means that "head -n-3" no longer consumes all of its input, and lines - not output by head may be processed by other programs. For example, this - command now prints the final line, 2, while before it would print nothing: - seq 2 > k; (head -n-1 > /dev/null; cat) < k - [This bug was present in "the beginning".] - - ls --color would mis-color relative-named symlinks in / - [bug introduced in coreutils-8.17] - - split now ensures it doesn't overwrite the input file with generated output. - [the bug dates back to the initial implementation] - - stat and df now report the correct file system usage, - in all situations on GNU/Linux, by correctly determining the block size. - [df bug since coreutils-5.0.91, stat bug since the initial implementation] - - tail -f no longer tries to use inotify on AUFS or PanFS file systems - [you might say this was introduced in coreutils-7.5, along with inotify - support, but even now, its magic number isn't in the usual place.] - - ** New features - - stat -f recognizes the new remote file system types: aufs, panfs. - - ** Changes in behavior - - su: this program has been removed. We stopped installing "su" by - default with the release of coreutils-6.9.90 on 2007-12-01. Now, - that the util-linux package has the union of the Suse and Fedora - patches as well as enough support to build on the Hurd, we no longer - have any reason to include it here. - - ** Improvements - - sort avoids redundant processing in the presence of inaccessible inputs, - or unwritable output. Sort now diagnoses certain errors at start-up, - rather than after potentially expensive processing. - - sort now allocates no more than 75% of physical memory by default, - to better share system resources, and thus operate more efficiently. - [The default max memory usage changed from 50% to 100% in coreutils-8.16] - -------------------------------------------------------------------- -Sun Jan 27 08:16:16 UTC 2013 - coolo@suse.com - -- do not require texinfo for building, texlive is a bit too heavy - -------------------------------------------------------------------- -Sun Jan 20 13:18:28 UTC 2013 - mail@bernhard-voelker.de - -- Avoid segmentation fault in "join -i" with long line input - (bnc#798541, VUL-1, CVE-2013-0223) - - * src/join.c: Instead of usig unreliable alloca() stack allocation, - use heap allocation via xmalloc()+free(). - (coreutils-i18n.patch, from Philipp Thomas ) - -- Avoid segmentation fault in "sort -d" and "sort -M" with long line input - (bnc#798538, VUL-1, CVE-2013-0221) - - * src/sort.c: Instead of usig unreliable alloca() stack allocation, - use heap allocation via xmalloc()+free(). - (coreutils-i18n.patch, from Philipp Thomas ) - -- Avoid segmentation fault in "uniq" with long line input - (bnc#796243, VUL-1, CVE-2013-0222) - - * src/cut.c: Instead of usig unreliable alloca() stack allocation, - use heap allocation via xmalloc()+free(). - (coreutils-i18n.patch) - -- Fix test-suite errors (bnc#798261). - - * tests/cp/fiemap-FMR: Fix path to src directory and declare - require_valgrind_ function. - (coreutils-cp-corrupt-fragmented-sparse.patch) - * tests/misc/cut: - Fix src/cut.c to properly pass output-delimiter tests. - Synchronize cut.c related part of the i18n patch with Fedora's. - Merge coreutils-i18n-infloop.patch into coreutils-i18n.patch. - Merge coreutils-i18n-uninit.patch into coreutils-i18n.patch. - In tests/misc/cut, do not replace the non-i18n error messages. - (coreutils-i18n.patch) - * tests/rm/ext3-perf: - This test failed due to heavy parallel CPU and/or disk load because it - is based on timeouts. Do not run the test-suite with 'make -jN. - (coreutils.spec, coreutils-testsuite.spec) - * tests/du/slink: - This test fails on OBS infrastructure and will be removed upstreams - in coreutils-8.21 anyway. Skip the test until we upgrade. - Upstream discussion: - http://lists.gnu.org/archive/html/coreutils/2013-01/msg00053.html - (coreutils-skip-du-slink-test.patch) - * Further spec changes: - Run more tests: also run "very expensive" tests; add acl, python-pyinotify, - strace and valgrind to the build requirements. - Remove patch5 and patch6 as they are now merged into coreutils-i18n.patch - (see above). - (coreutils.spec, coreutils-testsuite.spec) - -- Maintenance changes: - (coreutils.spec, coreutils-testsuite.spec) - - * Add perl and texinfo to the build requirements as they are needed to - re-generate the man pages and the texinfo documentation. - * Remove already-active "-Wall" compiler option from CFLAGS variable. - * Install the compressed test-suite.log into the documentation directory - of the coreutils-testsuite package (section %check and %files). - * Properly guard the spec sections for the coreutils and the - coreutils-testsuite package. - * Update patches to reflect new line numbers. - -------------------------------------------------------------------- -Thu Jan 10 21:18:52 CET 2013 - phisama@suse.de - -- Hardcode the name passed to find_lang so that it works for - coreutils-testsuite too. - -------------------------------------------------------------------- -Thu Jan 10 11:58:17 CET 2013 - pth@suse.de - -- Don't call autoreconf on distributions older then 12.0 - because their autoconf is too old, so also patch Makefile.in - in addition to Makefile.am where needed. - -------------------------------------------------------------------- -Tue Dec 4 08:16:35 UTC 2012 - mail@bernhard-voelker.de - -- Update default posix version to 200112 (bnc#783352). -- Add coreutils-df-always-hide-rootfs.patch: - Hide rootfs in df (df not using yet /proc/self/mountinfo). - -------------------------------------------------------------------- -Mon Nov 19 13:04:44 UTC 2012 - idonmez@suse.com - -- Statically link to gmp otherwise expr depends on gmp and gmp - configure script depends on expr which creates a build cycle. - -------------------------------------------------------------------- -Thu Nov 8 13:12:25 CET 2012 - pth@suse.de - -- Add the missing parts in coreutil.spec so that the testsuite is - only run when coreutils-testsuite is built. Also add additional - BuildRequires for the testsuite. - -------------------------------------------------------------------- -Tue Nov 6 13:23:45 CET 2012 - pth@suse.de - -- Add script pre_checkin.sh that creates spec and changes for - coreutils-testsuite from their coreutils counterparts. - -------------------------------------------------------------------- -Sun Oct 28 20:31:28 UTC 2012 - mail@bernhard-voelker.de - -- Add upstream patch: - - * cp could read from freed memory and could even make corrupt copies. - This could happen with a very fragmented and sparse input file, - on GNU/Linux file systems supporting fiemap extent scanning. - This bug also affects mv when it resorts to copying, and install. - [bug introduced in coreutils-8.11] (bnc#788459 gnu#12656) - -------------------------------------------------------------------- -Fri Sep 21 11:55:12 UTC 2012 - froh@suse.com - -- fix coreutils-8.9-singlethreaded-sort.patch to - respect OMP_NUM_THREADS again. - -------------------------------------------------------------------- -Tue Jun 19 12:37:47 CEST 2012 - pth@suse.de - -- Update to 8.17: - ** Bug fixes - - * stat no longer reports a negative file size as a huge positive - number. [bug present since 'stat' was introduced in - fileutils-4.1.9] - - ** New features - - * split and truncate now allow any seekable files in situations - where the file size is needed, instead of insisting on regular - files. - - * fmt now accepts the --goal=WIDTH (-g) option. - - * stat -f recognizes new file system types: bdevfs, inodefs, qnx6 - - ** Changes in behavior - - * cp,mv,install,cat,split: now read and write a minimum of 64KiB at - a time. This was previously 32KiB and increasing to 64KiB was - seen to increase throughput by about 10% when reading cached - files on 64 bit GNU/Linux. - - * cp --attributes-only no longer truncates any existing destination - file, allowing for more general copying of attributes from one - file to another. -- Bring german message catalog up-to-date - -------------------------------------------------------------------- -Tue May 15 22:34:03 UTC 2012 - schwab@linux-m68k.org - -- Build factor with gmp support - -------------------------------------------------------------------- -Mon May 7 14:22:29 CEST 2012 - pth@suse.de - -- Two new upstream patches: - - * id and groups, when invoked with no user name argument, would - print the default group ID listed in the password database, and - sometimes that ID would be neither real nor effective. For - example, when run set-GID, or in a session for which the default - group has just been changed, the new group ID would be listed, - even though it is not yet effective. - - * 'cp S D' is no longer subject to a race: if an existing D were - removed between the initial stat and subsequent - open-without-O_CREAT, cp would fail with a confusing diagnostic - saying that the destination, D, was not found. Now, in this - unusual case, it retries the open (but with O_CREAT), and hence - usually succeeds. With NFS attribute caching, the condition was - particularly easy to trigger, since there, the removal of D could - precede the initial stat. [This bug was present in "the - beginning".] (bnc#760926). - -------------------------------------------------------------------- -Fri Apr 27 12:38:23 CEST 2012 - pth@suse.de - -- Make stdbuf binary find libstdbuf.so by looking in the right - path (bnc#741241). - -------------------------------------------------------------------- -Mon Apr 16 13:23:56 CEST 2012 - pth@suse.de - -- Update to 8.16: - - - Improvements: - * As a GNU extension, 'chmod', 'mkdir', and 'install' now accept - operators '-', '+', '=' followed by octal modes; - * Also, ordinary numeric modes with five or more digits no longer - preserve setuid and setgid bits, so that 'chmod 00755 FOO' now - clears FOO's setuid and setgid bits. - * dd now accepts the count_bytes, skip_bytes iflags and the - seek_bytes oflag, to more easily allow processing portions of a - file. - * dd now accepts the conv=sparse flag to attempt to create sparse - output, by seeking rather than writing to the output file. - * ln now accepts the --relative option, to generate a relative - symbolic link to a target, irrespective of how the target is - specified. - * split now accepts an optional "from" argument to - --numeric-suffixes, which changes the start number from the - default of 0. - * split now accepts the --additional-suffix option, to append an - additional static suffix to output file names. - * basename now supports the -a and -s options, which allow - processing of more than one argument at a time. Also the - complementary -z option was added to delimit output items with - the NUL character. - * dirname now supports more than one argument. Also the complementary - z option was added to delimit output items with the NUL character. - - - Bug fixes - * du --one-file-system (-x) would ignore any non-directory - specified on the command line. For example, "touch f; du -x f" - would print nothing. [bug introduced in coreutils-8.15] - * mv now lets you move a symlink onto a same-inode destination - file that has two or more hard links. - * "mv A B" could succeed, yet A would remain. - * realpath no longer mishandles a root directory. - - - Improvements - * ls can be much more efficient, especially with large directories - on file systems for which getfilecon-, ACL-check- and XATTR- - check-induced syscalls fail with ENOTSUP or similar. - * 'realpath --relative-base=dir' in isolation now implies - '--relative-to=dir' instead of causing a usage failure. - * split now supports an unlimited number of split files as default - behavior. - - For a detaild list se NEWS in the documentation. - -- Add up-to-date german translation. - -------------------------------------------------------------------- -Mon Apr 16 12:00:34 CEST 2012 - pth@suse.de - -- Add two upstream patches that speed up ls (bnc#752943): - * Cache (l)getfilecon calls to avoid the vast majority of the failing - underlying getxattr syscalls. - * Avoids always-failing queries for whether a file has a nontrivial - ACL and for whether a file has certain "capabilities". - -------------------------------------------------------------------- -Fri Mar 9 17:30:19 CET 2012 - pth@suse.de - -- Update to 8.15: - ** New programs - - realpath: print resolved file names. - - ** Bug fixes - - du --one-file-system (-x) would ignore any non-directory specified on - the command line. For example, "touch f; du -x f" would print nothing. - [bug introduced in coreutils-8.14] - - du -x no longer counts root directories of other file systems. - [bug introduced in coreutils-5.1.0] - - ls --color many-entry-directory was uninterruptible for too long - [bug introduced in coreutils-5.2.1] - - ls's -k option no longer affects how ls -l outputs file sizes. - It now affects only the per-directory block counts written by -l, - and the sizes written by -s. This is for compatibility with BSD - and with POSIX 2008. Because -k is no longer equivalent to - --block-size=1KiB, a new long option --kibibyte stands for -k. - [bug introduced in coreutils-4.5.4] - - ls -l would leak a little memory (security context string) for each - nonempty directory listed on the command line, when using SELinux. - [bug probably introduced in coreutils-6.10 with SELinux support] - - split -n 1/2 FILE no longer fails when operating on a growing file, or - (on some systems) when operating on a non-regular file like /dev/zero. - It would report "/dev/zero: No such file or directory" even though - the file obviously exists. Same for -n l/2. - [bug introduced in coreutils-8.8, with the addition of the -n option] - - stat -f now recognizes the FhGFS and PipeFS file system types. - - tac no longer fails to handle two or more non-seekable inputs - [bug introduced in coreutils-5.3.0] - - tail -f no longer tries to use inotify on GPFS or FhGFS file systems - [you might say this was introduced in coreutils-7.5, along with inotify - support, but the new magic numbers weren't in the usual places then.] - - ** Changes in behavior - - df avoids long UUID-including file system names in the default listing. - With recent enough kernel/tools, these long names would be used, pushing - second and subsequent columns far to the right. Now, when a long name - refers to a symlink, and no file systems are specified, df prints the - usually-short referent instead. - - tail -f now uses polling (not inotify) when any of its file arguments - resides on a file system of unknown type. In addition, for each such - argument, tail -f prints a warning with the FS type magic number and a - request to report it to the bug-reporting address. - -- Bring german message catalog up to date. -- Include upstream fix for du. -- Include upstream patch fixing basename documentation. - -------------------------------------------------------------------- -Mon Feb 6 17:18:37 UTC 2012 - rschweikert@suse.com - -- keep binaries in /usr (UserMerge project) - -------------------------------------------------------------------- -Mon Dec 19 15:09:12 UTC 2011 - lnussel@suse.de - -- Adjust license for coreutils-8.6-honor-settings-in-etc-default-su-resp-etc-login.defs.diff - [bnc#735081]. - -------------------------------------------------------------------- -Fri Dec 2 08:09:09 UTC 2011 - cfarrell@suse.com - -- license update: GPL-3.0+ - Consolidate to GPL-3.0+ and use SPDX format - (http://www.spdx.org/licenses). More or less compatible to Fedora package - (who don^t use full SPDX implementation) - -------------------------------------------------------------------- -Wed Nov 30 09:45:46 UTC 2011 - coolo@suse.com - -- add automake as buildrequire to avoid implicit dependency - -------------------------------------------------------------------- -Mon Oct 17 15:25:21 CEST 2011 - pth@suse.de - -- Add upstream patch that fixes three bugs in tac: - - remove sole use of sprintf in favor of stpcpy - - don't misbehave with multiple non-seekable inputs - - don't leak a file descriptor for each non-seekable input - -------------------------------------------------------------------- -Fri Oct 14 16:51:48 CEST 2011 - pth@suse.de - -- Uniformly use german quotes not french ones in german messages. - -------------------------------------------------------------------- -Thu Oct 13 16:07:16 CEST 2011 - pth@suse.de - -- Update to 8.14. Changes since 8.12: - Bug fixes: - - - ls --dereference no longer outputs erroneous "argetm" strings for - dangling symlinks when an 'ln=target' entry is in $LS_COLORS. - [bug introduced in fileutils-4.0] - - - ls -lL symlink once again properly prints "+" when the referent has - an ACL. [bug introduced in coreutils-8.13] - - - sort -g no longer infloops for certain inputs containing NaNs [bug - introduced in coreutils-8.5] - - - chown and chgrp with the -v --from= options, now output the correct - owner. I.E. for skipped files, the original ownership is output, - not the new one. [bug introduced in sh-utils-2.0g] - - - cp -r could mistakenly change the permissions of an existing - destination directory. [bug introduced in coreutils-6.8] - - - cp -u -p would fail to preserve one hard link for each up-to-date - copy of a src-hard-linked name in the destination tree. I.e., if - s/a and s/b are hard-linked and dst/s/a is up to date, "cp -up s - dst" would copy s/b to dst/s/b rather than simply linking dst/s/b - to dst/s/a. [This bug appears to have been present in "the - beginning".] - - - fts-using tools (rm, du, chmod, chgrp, chown, chcon) no longer use - memory proportional to the number of entries in each directory they - process. Before, rm -rf 4-million-entry-directory would consume - about 1GiB of memory. Now, it uses less than 30MB, no matter how - many entries there are. [this bug was inherent in the use of fts: - thus, for rm the bug was introduced in coreutils-8.0. The prior - implementation of rm did not use as much memory. du, chmod, chgrp - and chown started using fts in 6.0. chcon was added in - coreutils-6.9.91 with fts support. ] - - - pr -T no longer ignores a specified LAST_PAGE to stop at. [bug - introduced in textutils-1.19q] - - - printf '%d' '"' no longer accesses out-of-bounds memory in the - diagnostic. [bug introduced in sh-utils-1.16] - - - split --number l/... no longer creates extraneous files in certain - cases. [bug introduced in coreutils-8.8] - - - timeout now sends signals to commands that create their own process - group. timeout is no longer confused when starting off with a - child process. [bugs introduced in coreutils-7.0] - - - unexpand -a now aligns correctly when there are spaces spanning a - tabstop, followed by a tab. In that case a space was dropped, - causing misalignment. We also now ensure that a space never - precedes a tab. [bug introduced in coreutils-5.3.0] - - New features: - - - date now accepts ISO 8601 date-time strings with "T" as the - separator. It has long parsed dates like "2004-02-29 16:21:42" - with a space between the date and time strings. Now it also parses - "2004-02-29T16:21:42" and fractional-second and time-zone-annotated - variants like "2004-02-29T16:21:42.333-07:00" - - md5sum accepts the new --strict option. With --check, it makes the - tool exit non-zero for any invalid input line, rather than just warning. - This also affects sha1sum, sha224sum, sha384sum and sha512sum. - - - split accepts a new --filter=CMD option. With it, split filters - output through CMD. CMD may use the $FILE environment variable, - which is set to the nominal output file name for each invocation of - CMD. For example, to split a file into 3 approximately equal - parts, which are then compressed: - - split -n3 --filter='xz > $FILE.xz' big - - Note the use of single quotes, not double quotes. That creates - files named xaa.xz, xab.xz and xac.xz. - - - timeout accepts a new --foreground option, to support commands not - started directly from a shell prompt, where the command is - interactive or needs to receive signals initiated from the - terminal. - - Improvements: - - - md5sum --check now supports the -r format from the corresponding - BSD tool. This also affects sha1sum, sha224sum, sha384sum and - sha512sum. - - - pwd now works also on systems without openat. On such systems, pwd - would fail when run from a directory whose absolute name contained - more than PATH_MAX / 3 components. The df, stat and readlink - programs are also affected due to their use of the canonicalize_* - functions. - - - join --check-order now prints "join: FILE:LINE_NUMBER: bad_line" - for an unsorted input, rather than e.g., "join: file 1 is not in - sorted order". - - - shuf outputs small subsets of large permutations much more - efficiently. For example `shuf -i1-$((2**32-1)) -n2` no longer - exhausts memory. - - - stat -f now recognizes the GPFS, MQUEUE and PSTOREFS file system - types. - - - timeout now supports sub-second timeouts. - - Changes in behavior: - - - chmod, chown and chgrp now output the original attributes in - messages, when -v or -c specified. - - - cp -au (where --preserve=links is implicit) may now replace newer - files in the destination, to mirror hard links from the source. - -------------------------------------------------------------------- -Sat Sep 17 23:29:33 UTC 2011 - jengelh@medozas.de - -- Remove redundant tags/sections from specfile - -------------------------------------------------------------------- -Tue Aug 2 00:26:05 UTC 2011 - lchiquitto@suse.com - -- file-has-acl: use acl_extended_file_nofollow if available to - avoid triggering unwanted AutoFS mounts (bnc#701659). - -------------------------------------------------------------------- -Tue May 3 16:42:41 CEST 2011 - pth@suse.de - -- Remove services. - -------------------------------------------------------------------- -Tue May 3 14:28:01 CEST 2011 - ro@suse.de - -- delete coreutils-testsuite.spec - -------------------------------------------------------------------- -Thu Apr 28 15:35:59 CEST 2011 - pth@suse.de - -- Update to 8.12: - * Bug fixes - - tail's --follow=name option no longer implies --retry on systems - with inotify support. [bug introduced in coreutils-7.5] - - * Changes in behavior - - cp's extent-based (FIEMAP) copying code is more reliable in the face - of varying and undocumented file system semantics: - - it no longer treats unwritten extents specially - - a FIEMAP-based extent copy always uses the FIEMAP_FLAG_SYNC flag. - Before, it would incur the performance penalty of that sync only - for 2.6.38 and older kernels. We thought all problems would be - resolved for 2.6.39. - - it now attempts a FIEMAP copy only on a file that appears sparse. - Sparse files are relatively unusual, and the copying code incurs - the performance penalty of the now-mandatory sync only for them. -- Add complete german meesage catalogue. - -------------------------------------------------------------------- -Thu Apr 14 14:46:41 CEST 2011 - pth@suse.de - -- Update to 8.11: - - * Bug fixes - - cp -a --link would not create a hardlink to a symlink, instead - copying the symlink and then not preserving its timestamp. - [bug introduced in coreutils-8.0] - - cp now avoids FIEMAP issues with BTRFS before Linux 2.6.38, - which could result in corrupt copies of sparse files. - [bug introduced in coreutils-8.10] - - cut could segfault when invoked with a user-specified output - delimiter and an unbounded range like "-f1234567890-". - [bug introduced in coreutils-5.3.0] - - du would infloop when given --files0-from=DIR - [bug introduced in coreutils-7.1] - - sort no longer spawns 7 worker threads to sort 16 lines - [bug introduced in coreutils-8.6] - - touch built on Solaris 9 would segfault when run on Solaris 10 - [bug introduced in coreutils-8.8] - - wc would dereference a NULL pointer upon an early out-of-memory error - [bug introduced in coreutils-7.1] - - ** New features - - dd now accepts the 'nocache' flag to the iflag and oflag options, - which will discard any cache associated with the files, or - processed portion thereof. - - dd now warns that 'iflag=fullblock' should be used, - in various cases where partial reads can cause issues. - - ** Changes in behavior - - cp now avoids syncing files when possible, when doing a FIEMAP copy. - The sync is only needed on Linux kernels before 2.6.39. - [The sync was introduced in coreutils-8.10] - - cp now copies empty extents efficiently, when doing a FIEMAP copy. - It no longer reads the zero bytes from the input, and also can - efficiently create a hole in the output file when --sparse=always - is specified. - - df now aligns columns consistently, and no longer wraps entries - with longer device identifiers, over two lines. - - install now rejects its long-deprecated --preserve_context option. - Use --preserve-context instead. - - test now accepts "==" as a synonym for "=" - -------------------------------------------------------------------- -Tue Apr 5 15:13:42 CEST 2011 - pth@suse.de - -- Adapt coreutils-testsuite.spec to changes in patches. - -------------------------------------------------------------------- -Tue Apr 5 11:40:19 CEST 2011 - pth@suse.de - -- Remove unneeded split_suffix patch. - -------------------------------------------------------------------- -Mon Apr 4 16:13:04 CEST 2011 - pth@suse.de - -- Remove the last patch as it isn't needed. It was an old patch - that removed the documentation for both hostname and hostid. - I've modified that to only remove the hostname documentation. - -------------------------------------------------------------------- -Fri Apr 1 15:34:49 CEST 2011 - pth@suse.de - -- Readd documentation of hostname and hostid to texinfo - documentation. -- Remove obsolete and unused german translation. - -------------------------------------------------------------------- -Thu Feb 10 14:35:49 CET 2011 - pth@suse.de - -- Update to 8.10: - * Bug fixes - - - du would abort with a failed assertion when two conditions are - met: part of the hierarchy being traversed is moved to a higher - level in the directory tree, and there is at least one more - command line directory argument following the one containing - the moved sub-tree. [bug introduced in coreutils-5.1.0] - - - join --header now skips the ordering check for the first line - even if the other file is empty. [bug introduced in - coreutils-8.5] - - - rm -f no longer fails for EINVAL or EILSEQ on file systems that - reject file names invalid for that file system. - - - uniq -f NUM no longer tries to process fields after end of - line. [bug introduced in coreutils-7.0] - - * New features - - - cp now copies sparse files efficiently on file systems with - FIEMAP support (ext4, btrfs, xfs, ocfs2). Before, it had to - read 2^20 bytes when copying a 1MiB sparse file. Now, it - copies bytes only for the non-sparse sections of a file. - Similarly, to induce a hole in the output file, it had to - detect a long sequence of zero bytes. Now, it knows precisely - where each hole in an input file is, and can reproduce them - efficiently in the output file. mv also benefits when it - resorts to copying, e.g., between file systems. - - - join now supports -o 'auto' which will automatically infer the - output format from the first line in each file, to ensure the - same number of fields are output for each line. - - * Changes in behavior - - - join no longer reports disorder when one of the files is empty. - This allows one to use join as a field extractor like: - join -a1 -o 1.3,1.1 - /dev/null - -- Add upstream patch that fixes a segfault in cut. -- Add upstream patch to fix sparse fiemap tests. -- Fix i18n patch for join. - -------------------------------------------------------------------- -Fri Jan 14 14:13:28 CET 2011 - uli@suse.de - -- sort threading still broken, it deadlocks occasionally; set - default number of threads to 1 as a workaround - -------------------------------------------------------------------- -Wed Jan 5 14:25:16 CET 2011 - pth@suse.de - -- Update to 8.9: - Bug fixes - - split no longer creates files with a suffix length that - is dependent on the number of bytes or lines per file. - [bug introduced in coreutils-8.8] - -------------------------------------------------------------------- -Mon Jan 3 19:32:57 CET 2011 - pth@suse.de - -- Update to 8.8. Changes since 8.6: - - Bug fixes: - - cp -u no longer does unnecessary copying merely because the source - has finer-grained time stamps than the destination. - - od now prints floating-point numbers without losing information, and - it no longer omits spaces between floating-point columns in some cases. - - sort -u with at least two threads could attempt to read through a - corrupted pointer. [bug introduced in coreutils-8.6] - - sort with at least two threads and with blocked output would busy-loop - (spinlock) all threads, often using 100% of available CPU cycles to - do no work. I.e., "sort < big-file | less" could waste a lot of power. - [bug introduced in coreutils-8.6] - - sort with at least two threads no longer segfaults due to use of pointers - into the stack of an expired thread. [bug introduced in coreutils-8.6] - - sort --compress no longer mishandles subprocesses' exit statuses, - no longer hangs indefinitely due to a bug in waiting for subprocesses, - and no longer generates many more than NMERGE subprocesses. - - sort -m -o f f ... f no longer dumps core when file descriptors are limited. - - csplit no longer corrupts heap when writing more than 999 files, - nor does it leak memory for every chunk of input processed - [the bugs were present in the initial implementation] - - tail -F once again notices changes in a currently unavailable - remote directory [bug introduced in coreutils-7.5] - - Changes in behavior: - - sort will not create more than 8 threads by default due to diminishing - performance gains. Also the --parallel option is no longer restricted - to the number of available processors. - - cp --attributes-only now completely overrides --reflink. - Previously a reflink was needlessly attempted. - - stat's %X, %Y, and %Z directives once again print only the integer - part of seconds since the epoch. This reverts a change from - coreutils-8.6, that was deemed unnecessarily disruptive. - To obtain a nanosecond-precision time stamp for %X use %.X; - if you want (say) just 3 fractional digits, use %.3X. - Likewise for %Y and %Z. - - stat's new %W format directive would print floating point seconds. - However, with the above change to %X, %Y and %Z, we've made %W work - the same way as the others. - - New features: - - split accepts the --number option to generate a specific number of files. - -- Add a complete german translation. -- Add upstreams patch for suffix calculation in split. - -------------------------------------------------------------------- -Wed Dec 22 15:53:13 UTC 2010 - pth@novell.com - -- Use software services. -- Remove coreutils tarball. -- Don't use version specific patches as it breaks automatic - updates. - -------------------------------------------------------------------- -Wed Nov 17 08:33:10 UTC 2010 - coolo@novell.com - -- remove the prerequire on permissions - this will create a bad - cycle, coreutils is just too core - -------------------------------------------------------------------- -Tue Nov 16 10:50:04 UTC 2010 - lnussel@suse.de - -- split pam patch into separate independent files so the main - feature can be shared with other distros -- don't hard require coreutils-lang - -------------------------------------------------------------------- -Thu Nov 11 16:33:50 CET 2010 - pth@suse.de - -- Update to 8.6: - o bugfixes - * du no longer multiply counts a file that is a directory or whose - link count is 1. - * du -H and -L now consistently count pointed-to files instead of - symbolic links, and correctly diagnose dangling symlinks. - * du --ignore=D now ignores directory D even when that directory is - found to be part of a directory cycle. - * split now diagnoses read errors rather than silently exiting. - * tac would perform a double-free when given an input line longer - than 16KiB. - * tail -F once again notices changes in a currently unavailable - directory, and works around a Linux kernel bug where inotify runs - out of resources. - * tr now consistently handles case conversion character classes. - - o New features - * cp now accepts the --attributes-only option to not copy file data. - * du recognizes -d N as equivalent to --max-depth=N - * sort now accepts the --debug option, to highlight the part of the - line significant in the sort, and warns about questionable options. - * sort now supports -d, -f, -i, -R, and -V in any combination. - * stat now accepts the %m format directive to output the mount point - for a file. It also accepts the %w and %W format directives for - outputting the birth time of a file, if one is available. - - o Changes in behavior - * df now consistently prints the device name for a bind mounted file, - rather than its aliased target. - * du now uses less than half as much memory when operating on trees - with many hard-linked files. - * ls -l now uses the traditional three field time style rather than - the wider two field numeric ISO style in locales where a style has - not been specified. - * rm's -d now evokes an error; before, it was silently ignored. - * sort -g now uses long doubles for greater range and precision. - * sort -h no longer rejects numbers with leading or trailing ".", and - no longer accepts numbers with multiple ".". It now considers all - zeros to be equal. - * sort now uses the number of available processors to parallelize - the sorting operation. - * stat now provides translated output when no format is specified. - * stat no longer accepts the --context (-Z) option. - * stat no longer accepts the %C directive when the --file-system - option is in effect. - * stat now outputs the full sub-second resolution for the atime, - mtime, and ctime values since the Epoch, when using the %X, %Y, and - %Z directives of the --format option. - * touch's --file option is no longer recognized. Use --reference=F - (-r) instead. - * truncate now supports setting file sizes relative to a reference - file. Also errors are no longer suppressed for unsupported file - types, and relative sizes are restricted to supported file types. - - See NEWS in the package documentation for more verbose description. -- Add a man page for [ (a link to test1). -- Fix assignment of a char to a char * in join.c -- Add permissions verifying for su. -- Use RELRO for su. - -------------------------------------------------------------------- -Tue Aug 31 09:36:00 UTC 2010 - aj@suse.de - -- Recommend instead of require lang package since it's not mandatory. - -------------------------------------------------------------------- -Thu Jul 1 21:23:40 UTC 2010 - jengelh@medozas.de - -- Use %_smp_mflags - -------------------------------------------------------------------- -Tue Jun 29 20:18:04 CEST 2010 - pth@suse.de - -- Fix 'sort -V' not working because the i18n (mb handling) patch - wasn't updated to handle the new option (bnc#615073). - -------------------------------------------------------------------- -Mon Jun 28 12:52:15 CEST 2010 - pth@suse.de - -- Fix typo in spec file (% missing from version). - -------------------------------------------------------------------- -Fri Jun 18 11:57:47 CEST 2010 - kukuk@suse.de - -- Last part of fix for [bnc#533249]: Don't run account part of - PAM stack for su as root. Requires pam > 1.1.1. - -------------------------------------------------------------------- -Fri May 7 15:44:53 UTC 2010 - pth@novell.com - -- Update to 8.5: - Bug fixes - * cp and mv once again support preserving extended attributes. - * cp now preserves "capabilities" when also preserving file ownership.7 - * ls --color once again honors the 'NORMAL' dircolors directive. - [bug introduced in coreutils-6.11] - * sort -M now handles abbreviated months that are aligned using - blanks in the locale database. Also locales with 8 bit characters - are handled correctly, including multi byte locales with the caveat - that multi byte characters are matched case sensitively. - * sort again handles obsolescent key formats (+POS -POS) correctly. - Previously if -POS was specified, 1 field too many was used in the - sort. [bug introduced in coreutils-7.2] - - New features - - * join now accepts the --header option, to treat the first line of - each file as a header line to be joined and printed - unconditionally. - - * timeout now accepts the --kill-after option which sends a kill - signal to the monitored command if it's still running the specified - duration after the initial signal was sent. - - * who: the "+/-" --mesg (-T) indicator of whether a user/tty is - accepting messages could be incorrectly listed as "+", when in - fact, the user was not accepting messages (mesg no). Before, who - would examine only the permission bits, and not consider the group - of the TTY device file. Thus, if a login tty's group would change - somehow e.g., to "root", that would make it unwritable (via - write(1)) by normal users, in spite of whatever the permission bits - might imply. Now, when configured using the - --with-tty-group[=NAME] option, who also compares the group of the - TTY device with NAME (or "tty" if no group name is specified). - - Changes in behavior - - * ls --color no longer emits the final 3-byte color-resetting escape - sequence when it would be a no-op. - - * join -t '' no longer emits an error and instead operates on each - line as a whole (even if they contain NUL characters). - - For other changes since 7.1 see NEWS. -- Split-up coreutils-%%{version}.diff as far as possible. -- Prefix all patches with coreutils-. -- All patches have the .patch suffix. -- Use the i18n patch from Archlinux as it fixes at least one test - suite failure. - -------------------------------------------------------------------- -Tue May 4 17:13:37 UTC 2010 - pth@novell.com - -- Fix security bug in distcheck (bnc#564373). -- refresh patches to apply cleanly. - -------------------------------------------------------------------- -Tue Mar 2 09:54:10 UTC 2010 - lnussel@suse.de - -- enable hostid (bnc#584562) - -------------------------------------------------------------------- -Sat Dec 12 18:46:28 CET 2009 - jengelh@medozas.de - -- add baselibs.conf as a source - -------------------------------------------------------------------- -Mon Mar 23 15:34:29 CET 2009 - pth@suse.de - -- Add .ogv to dircolors (bnc#487561). - -------------------------------------------------------------------- -Sun Feb 22 10:49:52 CET 2009 - schwab@suse.de - -- Update to coreutils 7.1. - ** New features - Add extended attribute support available on certain filesystems like ext2 - and XFS. - cp: Tries to copy xattrs when --preserve=xattr or --preserve=all specified - mv: Always tries to copy xattrs - install: Never copies xattrs - cp and mv accept a new option, --no-clobber (-n): silently refrain - from overwriting any existing destination file - dd accepts iflag=cio and oflag=cio to open the file in CIO (concurrent I/O) - mode where this feature is available. - install accepts a new option, --compare (-C): compare each pair of source - and destination files, and if the destination has identical content and - any specified owner, group, permissions, and possibly SELinux context, then - do not modify the destination at all. - ls --color now highlights hard linked files, too - stat -f recognizes the Lustre file system type - ** Bug fixes - chgrp, chmod, chown --silent (--quiet, -f) no longer print some diagnostics - [bug introduced in coreutils-5.1] - cp uses much less memory in some situations - cp -a now correctly tries to preserve SELinux context (announced in 6.9.90), - doesn't inform about failure, unlike with --preserve=all - du --files0-from=FILE no longer reads all of FILE into RAM before - processing the first file name - seq 9223372036854775807 9223372036854775808 now prints only two numbers - on systems with extended long double support and good library support. - Even with this patch, on some systems, it still produces invalid output, - from 3 to at least 1026 lines long. [bug introduced in coreutils-6.11] - seq -w now accounts for a decimal point added to the last number - to correctly print all numbers to the same width. - wc --files0-from=FILE no longer reads all of FILE into RAM, before - processing the first file name, unless the list of names is known - to be small enough. - ** Changes in behavior - cp and mv: the --reply={yes,no,query} option has been removed. - Using it has elicited a warning for the last three years. - dd: user specified offsets that are too big are handled better. - Previously, erroneous parameters to skip and seek could result - in redundant reading of the file with no warnings or errors. - du: -H (initially equivalent to --si) is now equivalent to - --dereference-args, and thus works as POSIX requires - shred: now does 3 overwrite passes by default rather than 25. - ls -l now marks SELinux-only files with the less obtrusive '.', - rather than '+'. A file with any other combination of MAC and ACL - is still marked with a '+'. - -------------------------------------------------------------------- -Wed Nov 19 12:42:10 CET 2008 - werner@suse.de - -- Enable stat(1) to detect (k)AFS and CIFS network file systems - -------------------------------------------------------------------- -Tue Nov 18 16:48:05 CET 2008 - schwab@suse.de - -- Move stat to /bin. - -------------------------------------------------------------------- -Tue Oct 21 11:31:35 CEST 2008 - schwab@suse.de - -- Fix pam cleanup. - -------------------------------------------------------------------- -Thu Sep 18 16:38:01 CEST 2008 - schwab@suse.de - -- Move readlink and md5sum to /bin. - -------------------------------------------------------------------- -Wed Aug 20 15:40:47 CEST 2008 - schwab@suse.de - -- Add libselinux-devel to BuildRequires. - -------------------------------------------------------------------- -Tue Jun 24 15:57:01 CEST 2008 - schwab@suse.de - -- Fix sort field limit in multibyte case. - -------------------------------------------------------------------- -Wed Jun 4 14:10:05 CEST 2008 - schwab@suse.de - -- Update to coreutils 6.12. - ** Bug fixes - chcon, runcon: --help output now includes the bug-reporting address - cp -p copies permissions more portably. For example, on MacOS X 10.5, - "cp -p some-fifo some-file" no longer fails while trying to copy the - permissions from the some-fifo argument. - id with no options now prints the SELinux context only when invoked - with no USERNAME argument. - id and groups once again print the AFS-specific nameless group-ID (PAG). - Printing of such large-numbered, kernel-only (not in /etc/group) group-IDs - was suppressed in 6.11 due to ignorance that they are useful. - uniq: avoid subtle field-skipping malfunction due to isblank misuse. - In some locales on some systems, isblank(240) (aka  ) is nonzero. - On such systems, uniq --skip-fields=N would fail to skip the proper - number of fields for some inputs. - tac: avoid segfault with --regex (-r) and multiple files, e.g., - "echo > x; tac -r x x". [bug present at least in textutils-1.8b, from 1992] - ** Changes in behavior - install once again sets SELinux context, when possible - [it was deliberately disabled in 6.9.90] - -------------------------------------------------------------------- -Sun Apr 20 00:19:07 CEST 2008 - schwab@suse.de - -- Update to coreutils 6.11. - ** Bug fixes - configure --enable-no-install-program=groups now works. - "cp -fR fifo E" now succeeds with an existing E. Before this fix, using - -fR to copy a fifo or "special" file onto an existing file would fail - with EEXIST. Now, it once again unlinks the destination before trying - to create the destination file. [bug introduced in coreutils-5.90] - dd once again works with unnecessary options like if=/dev/stdin and - of=/dev/stdout. [bug introduced in fileutils-4.0h] - id now uses getgrouplist, when possible. This results in - much better performance when there are many users and/or groups. - ls no longer segfaults on files in /proc when linked with an older version - of libselinux. E.g., ls -l /proc/sys would dereference a NULL pointer. - md5sum would segfault for invalid BSD-style input, e.g., - echo 'MD5 (' | md5sum -c - Now, md5sum ignores that line. - sha1sum, sha224sum, sha384sum, and sha512sum are affected, too. - [bug introduced in coreutils-5.1.0] - md5sum -c would accept a NUL-containing checksum string like "abcd\0..." - and would unnecessarily read and compute the checksum of the named file, - and then compare that checksum to the invalid one: guaranteed to fail. - Now, it recognizes that the line is not valid and skips it. - sha1sum, sha224sum, sha384sum, and sha512sum are affected, too. - [bug present in the original version, in coreutils-4.5.1, 1995] - "mkdir -Z x dir" no longer segfaults when diagnosing invalid context "x" - mkfifo and mknod would fail similarly. Now they're fixed. - mv would mistakenly unlink a destination file before calling rename, - when the destination had two or more hard links. It no longer does that. - [bug introduced in coreutils-5.3.0] - "paste -d'\' file" no longer overruns memory (heap since coreutils-5.1.2, - stack before then) [bug present in the original version, in 1992] - "pr -e" with a mix of backspaces and TABs no longer corrupts the heap - [bug present in the original version, in 1992] - "ptx -F'\' long-file-name" would overrun a malloc'd buffer and corrupt - the heap. That was triggered by a lone backslash (or odd number of them) - at the end of the option argument to --flag-truncation=STRING (-F), - --word-regexp=REGEXP (-W), or --sentence-regexp=REGEXP (-S). - "rm -r DIR" would mistakenly declare to be "write protected" -- and - prompt about -- full DIR-relative names longer than MIN (PATH_MAX, 8192). - "rmdir --ignore-fail-on-non-empty" detects and ignores the failure - in more cases when a directory is empty. - "seq -f % 1" would issue the erroneous diagnostic "seq: memory exhausted" - rather than reporting the invalid string format. - [bug introduced in coreutils-6.0] - ** New features - join now verifies that the inputs are in sorted order. This check can - be turned off with the --nocheck-order option. - sort accepts the new option --sort=WORD, where WORD can be one of - general-numeric, month, numeric or random. These are equivalent to the - options --general-numeric-sort/-g, --month-sort/-M, --numeric-sort/-n - and --random-sort/-R, resp. - ** Improvements - id and groups work around an AFS-related bug whereby those programs - would print an invalid group number, when given no user-name argument. - ls --color no longer outputs unnecessary escape sequences - seq gives better diagnostics for invalid formats. - ** Portability - rm now works properly even on systems like BeOS and Haiku, - which have negative errno values. - ** Consistency - install, mkdir, rmdir and split now write --verbose output to stdout, - not to stderr. - - -------------------------------------------------------------------- -Fri Apr 11 11:42:57 CEST 2008 - schwab@suse.de - -- Work around a recent glibc/getopt.c diagnostic change. -- Fix frexpl test. - -------------------------------------------------------------------- -Thu Apr 10 12:54:45 CEST 2008 - ro@suse.de - -- added baselibs.conf file to build xxbit packages - for multilib support - -------------------------------------------------------------------- -Mon Feb 18 18:19:19 CET 2008 - dmueller@suse.de - -- split off -lang subpackage to reduce one CD media size - -------------------------------------------------------------------- -Mon Feb 4 12:33:30 CET 2008 - kukuk@suse.de - -- sux is deprecated since 3 years, let's finaly remove symlink. - -------------------------------------------------------------------- -Tue Jan 22 23:03:33 CET 2008 - schwab@suse.de - -- Update to coreutils 6.10. - ** Bug fixes - Fix a non-portable use of sed in configure.ac. - [bug introduced in coreutils-6.9.92] - -------------------------------------------------------------------- -Sun Jan 13 12:59:37 CET 2008 - rguenther@suse.de - -- Reapply dropped patch: - adjust test-getaddrinfo to not fail w/o network connection - -------------------------------------------------------------------- -Sat Jan 12 19:08:54 CET 2008 - schwab@suse.de - -- Update to coreutils 6.9.92. - ** Bug fixes - cp --parents no longer uses uninitialized memory when restoring the - permissions of a just-created destination directory. - [bug introduced in coreutils-6.9.90] - tr's case conversion would fail in a locale with differing numbers - of lower case and upper case characters. E.g., this would fail: - env LC_CTYPE=en_US.ISO-8859-1 tr '[:upper:]' '[:lower:]' - [bug introduced in coreutils-6.9.90] - ** Improvements - "touch -d now writable-but-owned-by-someone-else" now succeeds - whenever that same command would succeed without "-d now". - Before, it would work fine with no -d option, yet it would - fail with the ostensibly-equivalent "-d now". - -------------------------------------------------------------------- -Mon Jan 7 16:14:51 CET 2008 - schwab@suse.de - -- Update to coreutils 6.9.91. - ** Bug fixes - "ls -l" would not output "+" on SELinux hosts unless -Z was also given. - "rm" would fail to unlink a non-directory when run in an environment - in which the user running rm is capable of unlinking a directory. - [bug introduced in coreutils-6.9] - -------------------------------------------------------------------- -Mon Jan 7 11:12:01 CET 2008 - jblunck@suse.de - -- fix a cp bug with -p --parents - -------------------------------------------------------------------- -Wed Dec 12 11:27:08 CET 2007 - rguenther@suse.de - -- adjust test-getaddrinfo to not fail w/o network connection - -------------------------------------------------------------------- -Mon Dec 10 17:50:07 CET 2007 - ro@suse.de - -- change source archive compression back to .bz2 to avoid another - dependency in the lowest basesystem - -------------------------------------------------------------------- -Mon Dec 3 10:44:24 CET 2007 - schwab@suse.de - -- Update to coreutils-6.9.90. - ** New programs - arch: equivalent to uname -m, not installed by default - But don't install this program on Solaris systems. - chcon: change the SELinux security context of a file - mktemp: create a temporary file or directory (or names) - runcon: run a program in a different SELinux security context - ** Programs no longer installed by default - hostname, su - ** Changes in behavior - cp, by default, refuses to copy through a dangling destination symlink - Set POSIXLY_CORRECT if you require the old, risk-prone behavior. - pr -F no longer suppresses the footer or the first two blank lines in - the header. This is for compatibility with BSD and POSIX. - tr now warns about an unescaped backslash at end of string. - The tr from coreutils-5.2.1 and earlier would fail for such usage, - and Solaris' tr ignores that final byte. - ** New features - Add SELinux support, based on the patch from Fedora: - * cp accepts new --preserve=context option. - * "cp -a" works with SELinux: - Now, cp -a attempts to preserve context, but failure to do so does - not change cp's exit status. However "cp --preserve=context" is - similar, but failure *does* cause cp to exit with nonzero status. - * install accepts new "-Z, --context=C" option. - * id accepts new "-Z" option. - * stat honors the new %C format directive: SELinux security context string - * ls accepts a slightly modified -Z option. - * ls: contrary to Fedora version, does not accept --lcontext and --scontext - cp -p tries to preserve the GID of a file even if preserving the UID - is not possible. - uniq accepts a new option: --zero-terminated (-z). As with the sort - option of the same name, this makes uniq consume and produce - NUL-terminated lines rather than newline-terminated lines. - wc no longer warns about character decoding errors in multibyte locales. - This means for example that "wc /bin/sh" now produces normal output - (though the word count will have no real meaning) rather than many - error messages. - ** New build options - By default, "make install" no longer attempts to install (or even build) su. - To change that, use ./configure --enable-install-program=su. - If you also want to install the new "arch" program, do this: - ./configure --enable-install-program=arch,su. - You can inhibit the compilation and installation of selected programs - at configure time. For example, to avoid installing "hostname" and - "uptime", use ./configure --enable-no-install-program=hostname,uptime - Note: currently, "make check" passes, even when arch and su are not - built (that's the new default). However, if you inhibit the building - and installation of other programs, don't be surprised if some parts - of "make check" fail. - ** Remove deprecated options - df no longer accepts the --kilobytes option. - du no longer accepts the --kilobytes or --megabytes options. - ls no longer accepts the --kilobytes option. - ptx longer accepts the --copyright option. - who no longer accepts -i or --idle. - ** Improved robustness - ln -f can no longer silently clobber a just-created hard link. - In some cases, ln could be seen as being responsible for data loss. - For example, given directories a, b, c, and files a/f and b/f, we - should be able to do this safely: ln -f a/f b/f c && rm -f a/f b/f - However, before this change, ln would succeed, and thus cause the - loss of the contents of a/f. - stty no longer silently accepts certain invalid hex values - in its 35-colon commmand-line argument - ** Bug fixes - chmod no longer ignores a dangling symlink. Now, chmod fails - with a diagnostic saying that it cannot operate on such a file. - [bug introduced in coreutils-5.1.0] - cp attempts to read a regular file, even if stat says it is empty. - Before, "cp /proc/cpuinfo c" would create an empty file when the kernel - reports stat.st_size == 0, while "cat /proc/cpuinfo > c" would "work", - and create a nonempty one. [bug introduced in coreutils-6.0] - cp --parents no longer mishandles symlinks to directories in file - name components in the source, e.g., "cp --parents symlink/a/b d" - no longer fails. Also, 'cp' no longer considers a destination - symlink to be the same as the referenced file when copying links - or making backups. For example, if SYM is a symlink to FILE, - "cp -l FILE SYM" now reports an error instead of silently doing - nothing. The behavior of 'cp' is now better documented when the - destination is a symlink. - "cp -i --update older newer" no longer prompts; same for mv - "cp -i" now detects read errors on standard input, and no longer consumes - too much seekable input; same for ln, install, mv, and rm. - cut now diagnoses a range starting with zero (e.g., -f 0-2) as invalid; - before, it would treat it as if it started with 1 (-f 1-2). - "cut -f 2-0" now fails; before, it was equivalent to "cut -f 2-" - cut now diagnoses the '-' in "cut -f -" as an invalid range, rather - than interpreting it as the unlimited range, "1-". - date -d now accepts strings of the form e.g., 'YYYYMMDD +N days', - in addition to the usual 'YYYYMMDD N days'. - du -s now includes the size of any stat'able-but-inaccessible directory - in the total size. - du (without -s) prints whatever it knows of the size of an inaccessible - directory. Before, du would print nothing for such a directory. - ls -x DIR would sometimes output the wrong string in place of the - first entry. [introduced in coreutils-6.8] - ls --color would mistakenly color a dangling symlink as if it were - a regular symlink. This would happen only when the dangling symlink - was not a command-line argument and in a directory with d_type support. - [introduced in coreutils-6.0] - ls --color, (with a custom LS_COLORS envvar value including the - ln=target attribute) would mistakenly output the string "target" - before the name of each symlink. [introduced in coreutils-6.0] - od's --skip (-j) option now works even when the kernel says that a - nonempty regular file has stat.st_size = 0. This happens at least - with files in /proc and linux-2.6.22. - "od -j L FILE" had a bug: when the number of bytes to skip, L, is exactly - the same as the length of FILE, od would skip *no* bytes. When the number - of bytes to skip is exactly the sum of the lengths of the first N files, - od would skip only the first N-1 files. [introduced in textutils-2.0.9] - ./printf %.10000000f 1 could get an internal ENOMEM error and generate - no output, yet erroneously exit with status 0. Now it diagnoses the error - and exits with nonzero status. [present in initial implementation] - seq no longer mishandles obvious cases like "seq 0 0.000001 0.000003", - so workarounds like "seq 0 0.000001 0.0000031" are no longer needed. - seq would mistakenly reject some valid format strings containing %%, - and would mistakenly accept some invalid ones. e.g., %g%% and %%g, resp. - "seq .1 .1" would mistakenly generate no output on some systems - Obsolete sort usage with an invalid ordering-option character, e.g., - "env _POSIX2_VERSION=199209 sort +1x" no longer makes sort free an - invalid pointer [introduced in coreutils-6.5] - sorting very long lines (relative to the amount of available memory) - no longer provokes unaligned memory access - split --line-bytes=N (-C N) no longer creates an empty file - [this bug is present at least as far back as textutils-1.22 (Jan, 1997)] - tr -c no longer aborts when translating with Set2 larger than the - complement of Set1. [present in the original version, in 1992] - tr no longer rejects an unmatched [:lower:] or [:upper:] in SET1. - [present in the original version] - -------------------------------------------------------------------- -Thu Nov 29 14:28:26 CET 2007 - schwab@suse.de - -- Update to coreutils-6.9.89.48 snapshot. - -------------------------------------------------------------------- -Mon Jul 23 15:15:11 CEST 2007 - schwab@suse.de - -- Fix random sort. -- Fix invalid free. -- Fix misalignment. - -------------------------------------------------------------------- -Sun May 20 19:17:21 CEST 2007 - schwab@suse.de - -- Fix compiling with glibc 2.6. - -------------------------------------------------------------------- -Sun May 20 10:53:16 CEST 2007 - schwab@suse.de - -- Fix fchownat test. - -------------------------------------------------------------------- -Mon Apr 2 11:17:36 CEST 2007 - schwab@suse.de - -- Fix ls -x. - -------------------------------------------------------------------- -Fri Mar 23 17:03:38 CET 2007 - schwab@suse.de - -- Update to coreutils 6.9. - ** Bug fixes - cp -x (--one-file-system) would fail to set mount point permissions - The default block size and output format for df -P are now unaffected by - the DF_BLOCK_SIZE, BLOCK_SIZE, and BLOCKSIZE environment variables. It - is still affected by POSIXLY_CORRECT, though. - Using pr -m -s (i.e. merging files, with TAB as the output separator) - no longer inserts extraneous spaces between output columns. - -------------------------------------------------------------------- -Wed Mar 14 15:50:36 CET 2007 - lnussel@suse.de - -- su: actually use /etc/pam.d/su-l when running su - (#254428) - -------------------------------------------------------------------- -Mon Mar 5 17:23:45 CET 2007 - lnussel@suse.de - -- su: don't chdir("/") before fork() (#251287) - -------------------------------------------------------------------- -Fri Mar 2 13:47:35 CET 2007 - lnussel@suse.de - -- split off and rework PAM patch for su: - * run pam_open_session as root (#245706) - * use separate pam configs for "su" and "su -" (RedHat #198639) - * detect pam libs in configure script, add option to disable it - * don't set argv[0] to "-su", use upstream behavior instead - * don't use getlogin() for setting PAM_RUSER - -------------------------------------------------------------------- -Sun Feb 25 10:58:58 CET 2007 - schwab@suse.de - -- Update to coreutils 6.8. - ** Bug fixes - chgrp, chmod, and chown now honor the --preserve-root option. - Before, they would warn, yet continuing traversing and operating on /. - chmod no longer fails in an environment (e.g., a chroot) with openat - support but with insufficient /proc support. - "cp --parents F/G D" no longer creates a directory D/F when F is not - a directory (and F/G is therefore invalid). - "cp --preserve=mode" would create directories that briefly had - too-generous permissions in some cases. For example, when copying a - directory with permissions 777 the destination directory might - temporarily be setgid on some file systems, which would allow other - users to create subfiles with the same group as the directory. Fix - similar problems with 'install' and 'mv'. - cut no longer dumps core for usage like "cut -f2- f1 f2" with two or - more file arguments. This was due to a double-free bug, introduced - in coreutils-5.3.0. - dd bs= operands now silently override any later ibs= and obs= - operands, as POSIX and tradition require. - "ls -FRL" always follows symbolic links on Linux. Introduced in - coreutils-6.0. - A cross-partition "mv /etc/passwd ~" (by non-root) now prints - a reasonable diagnostic. Before, it would print this: - "mv: cannot remove `/etc/passwd': Not a directory". - pwd and "readlink -e ." no longer fail unnecessarily when a parent - directory is unreadable. - "rm -rf /etc/passwd" (run by non-root) now prints a diagnostic. - Before it would print nothing. - "rm --interactive=never F" no longer prompts for an unwritable F - ** New features - sort's new --compress-program=PROG option specifies a compression - program to use when writing and reading temporary files. - This can help save both time and disk space when sorting large inputs. - ** New features - sort accepts the new option -C, which acts like -c except no diagnostic - is printed. Its --check option now accepts an optional argument, and - --check=quiet and --check=silent are now aliases for -C, while - --check=diagnose-first is an alias for -c or plain --check. - -------------------------------------------------------------------- -Tue Jan 9 13:08:01 CET 2007 - schwab@suse.de - -- Fix localized month sorting [#231790]. - ------------------------------------------------------------------- Wed Dec 13 13:27:36 CET 2006 - schwab@suse.de diff --git a/coreutils.keyring b/coreutils.keyring deleted file mode 100644 index befb97a..0000000 --- a/coreutils.keyring +++ /dev/null @@ -1,312 +0,0 @@ -Release GPG keyring of coreutils group. - ------BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBE58fE4BEADGS6VzDkx2OOQMPQedsmBtRs3S5sz9tzO51EwkS779js3Sjt96 -KlQM0SbwtbUxOFor42LRXJKUU9T/Jl3v3+onASvoHAUcuAL15WAhnY9cuQeFOvZP -/iy0I1+bV0CILrz364T6vL614obnBBdTg8ZqSZM+csRlpGwXJiuY6mkrsPLXakxA -35n/nAgQOcQPj36CuuvpCH4JKPkzklwUMqueDzXkYMNSdWmVnI+ZSfDmeiwzAbFY -tE5uGW+c3DzD98RGCLt3FLr86n24IDlaTZSsaWbTJVsur9s4sbp6rST3pspDSQYF -ShhJ5aqqEYIvPp5kXj2CZJjOFBnIkn+0aDSps+XrnZjJn/f8f9lIAg0/0JjmytHY -yopo6HFZMdtOvklmnsIuJ/fdyk7761+necYHf5dopVuv29PSu62+A/gnKGfGaqtY -AjXFfsiLp/+iTQ+LNV4hWFbFKHHZOn4G194pWl6nY1gArwQKPZ5p6uy5EXgiNPRs -C1CcuVZNJp1RiayhTI68uuI+cldBU6N7+yZKGhjDUQKjIZ3eDB8X7vsCC9S1GgvX -Hcv8mjcMcHtnoC0w0FiW35JYtAu9mY4+uQhoRPTyPHh+ufX+OdKf7q5BKCppY1r7 -HF1VRFKjSybhEwMeGBdj1EEY413/A8ynpgpHLosPT36n8HtAWUGu+TadZQARAQAB -tCFQw6FkcmFpZyBCcmFkeSA8UEBkcmFpZ0JyYWR5LmNvbT6JAjsEEwECACUCGwMG -CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheABQJOfIDXAhkBAAoJEN9v2XEwYDfZ4AEP -/jr6zmXUVhNiVCtqiHqc4jOs1OPC51iEcMUwpeaEEWHq17uMMIqz+nd8B7CAyjzw -FJIW4gtwPS3uTsXR2+KOl1VnMS5O/M9suyG5eM+fpCWkzyTC1He/1M9iaRMGY8u2 -wOjZoeY40QFN5fvL/BuC8GLBefI0rTzMaYO0WFlVWTpaemj4pL1Z4JoQdmR49H6O -qI155jfsXuv2VWjN1NoYT8w3FEugc7rdNWe4dmscU5H54JEQMuFd34X7Ja2S9YnQ -OdqO/nVQGm3te2X6ElOBoA68HyuXcEozf0KgKkcPrBEV/tjQrzn5Mc7jOgeCDDV3 -7MFwBZUi+z69jjOc85tNYf/FHRfUFnBLPC1HrOIlrraaqydPfvHBRTybTJVhXlQW -b9kqfrT1HU8UGfwP+5cwTy2WjZecxvozZakYBO4cdcmsSNE5jM8Tp7EU7ktxPXg1 -IQwZ8sEFJN6HRhRVmhK1FyR1hrwdcvfYrFmoYbyWUCW1RNuGw3RXdjXjGSl6VxzC -vrWXjeiMyLQQ7l7IneFaIPV22quPi/NVJbNeT5DqKa58kYgEVASfZVZkL7S3PJvj -fEqhw5jTi3l84AHtYNNo95UXWQQCWhpYjZ3q61satme++Eth552VAGP+JK4634mj -vVViYmWAnjs0efSN9yCOWKDKBONviW5WGZwi7MVtgF6uiQIcBBMBCAAGBQJOhIiA -AAoJEH/Z/MsAC+7uW3YP/RJlgRTkRa8t0t4oK06zg+jSMMQ3ZFsiipQEBMzJfCXy -C9pG+gU/mgcOoqnpxY6iA9ufY0dLOJYhMPsSLtrkjwMAIU54UY+WRpaTcXB+5Zma -1OoA/Oh6wcZHy61PEUkSfoiQ8vtXhzqQn7PAUbi7ds5ecn0hy8E6KKEEysFt+Say -zrINiCeO3wr6LUqUtpxdo8JGaHhdXGZsk5OMARnYlC/rzZxFKsie3+FKO7KNFoNr -edIElFKdx6b7r4CXqfK9XpZr8SaM+f3wh8mBCK4W2Re50/6inHAnTYwW0octwr0b -AtlHOY2myauBdj+19IWntZnhoKxuhVPLaEoG8j26k+LIP6h8fB8GoRh5oUarLiCk -fahDRNY/bPFtBnsE6Co5OTTy41CFkGX0JbguTpL0uPQxygIKz7x29P509fMpq5t8 -z0hcVYJ5/cXiNjFLid2JsWugKAWe5k53E7qQKR+jLSvPtZ2oOHAMUzu6hOnwDY4Q -5r+j6t81tFAlS6P4fcpVU+alUwvVNdXc6MSkfmK9ahumjYnLKy0uo242U1wuBZgN -adr6pFxKrMiC/0PVJz+ZQOZU4OUt/t4E9KpyUEasfOl1z4r+q+6dZffRbrP5CCIQ -M6A01GRbEufrcXjgYnmaDncV8JnmLbHOoZ8WF+xczywFg45ULSt0N5ZiS/BbatuO -iEYEExECAAYFAlE+Z4wACgkQFg9ft4s9SAbl2ACgqTFvvpXJzTpZrKrisKY2i9RR -dNsAoJt0xI/urG+JIn5kUJobcPsZtY62iQIcBBMBAgAGBQJRY/sdAAoJEGiHnitP -7eG+NrgP/iKO5+3ytwRYwwbtQNROUQSbLwpUN2N3S3XH9lRV2NGEx5nx9Yn0l22w -gRMbULeFk4S1Ak3mR16D/mlnfPMyVqrJotp/E4rkK5OzjIsy58vL6B4PLgut2Xlw -Clg+XklxkQDfT4m/QtLGJYOnx/AjBn6ABu2zD4FWsn7hIMdXDq9bpr9IT96iqd1P -MYogglYK5OBFIGefjf+Sut7i3vuwJcjuNdL79tIbn5yple96EOL6eoHSRv5ndcoS -mxHtmin0lVeQ1ajoBETNh/E6/yItZNtc7BKbttYF/tN0GYpQB+dcCeiXLAOJ9n/2 -ET0gAWMP+kHzdcl3mdfw+KiZOK0gak0cu6LW+3GGAXXZkFYh7I70Y7K0wYNNgy3W -rzlISbAeC0zKOzpJJ2eQWJAs13FyinUPEyKRorRSubajbhJzHa4t3SwevR9DExnG -DL23UWreDO4ElDbvT3MzMA7ifaVSLFR/Rxu/6xsK1lPs2NygmGpdDnPjJung9CTa -1yyadMi3Cfgggu5IuUaKtzW61lbD8sMXqLRoFIIkZjcQagS/ybGeKIAedCE6pqMh -MViSIVi2G/F1wVaahfhjvaj87yYPxUuHq4hHwx2RE1EjP66a1IoR4key/eZDWfHi -th2VeeaVnma12NTl1GzfaEig3mzgtB7lM50/qJ7ml+MeE5agga7oiQIcBBABCgAG -BQJVfds0AAoJECFMgsI2H9co0u0QAK+EhLBUwJJ1XfuheL8pXSJ7FxaicSPk9dKL -Fbhc2oIAItqGSAsBRncYH8jYAPSwtCq1whATbyPgoEDm5G8KQEdAZ4bA6mhXw7Nj -UgHtkbnm1bIbavM/lhZLdNi+H0ZV4w5G4e47/zMLbwK84ZhiArRdklq58200CmPB -qNnfaxRxxkJBA6Bn6Cnv0FUSRvHUlSXgOw+pZXGNFZpzi50d38L1na7iCxrfyxH1 -sS3Nhn3zTf8BCKDcCVyP8UeBP9Fb2+fYJ/f3/KN0C12Hnbqc9WsYvFSYWq6u+I8/ -GP0oQohe3Fv5S1VEHWB1feCNmvVtV50J7hukTBojERhC07Z+2T5G2aw1Cc4zxkOA -uwOBTzuij53sErn5o+hca/pJTlXz8jJ8OxSFY8FT1QGVlLAN10yl9mDsdnZb2VSn -bQdqYG/qfbdC2cm2rCrhcKFpierXURLr14UC1O7tbDmLFYXDxvQfjtj9GSo4NHrK -wlTvfHi+3x6fGyx+Auulcjt65A5kQ3mycOc5paZhTdIKhS5mFdQoKw1Sg6RPiRIy -OH5fx8ob6I7gN+bcuX3r8KCH1FcIiyZd3WsVQlI1EfnpujkFo1O2xDVpm/D9IjAO -MRqKTtnHbCjaPUrsRRysAharr47YuzQUYGaMmIJfSN3kP4U2OukYmVFSUpxrlNep -M7LGQsmdiQIzBBMBCAAdFiEEP0srMOiHNvRbOiwMIhOnPE4lafEFAlimlJcACgkQ -IhOnPE4lafEZRA//bTNw4mi9B04yacqaFlJ5f3i9v0fWnsSXNEkW5wslhbjoD8Ab -PpVNrrw7Jm0YTFNa5TtnNc7fcnHNNfsL0LbtCfdrZOTm7vZstFJrASHam7La5655 -RgvTbozSWuuYrfLyKAituRmhJyv3ntpP9K6yUAAuJjxR3ny1sn8KNIFX7g49emlC -k5eIEujcmaVJp1l8wbnf/jioKr6QeXz0cxWUUFXolR0AUt8Vy11V+qRQb9Iw902y -2gmbMun4HjYEtCtm+eY9TRD5jY7hCHTYTFEfWITnGIRDyHyLIS9a0xql3W3EyWO0 -JkHNIm1ajqbuUp4IIxoZmIxNmEmW3aS8rsuIY1P0zXjj6j+GcRX8lZJOIhieBfWk -ku6dZwwtv9wF3K1UQzFwRsERqiwj4CAwlUy4um1eLOcjx6ge7Ub67FQCihx0VEpO -jnngjQN4clth8YM5nst/+lOFsZb/k2SHqTnpdE9pFl39aij5Y7nAI6xZL8xyM+CG -9tcFMXBrmyZAmD83v0N2PyjWuLAyY2b2SSYhOXIVfonHYSfuGw27yvn6mQ0jICZu -vdeZQASYgBAohMDXOgDgKdL6g143d96tQST72RflXAxoKTbblKK0kqxZnfdRIja6 -MTLstYJUNwWQsSD7bwcY8wnTXPK5TpPtBH4q0sjkjd1ZNNAQvbbowTlZ/smJAjME -EwEKAB0WIQQSG9otSstjYWs2eg5Y4Rux5BTZrQUCWKj25AAKCRBY4Rux5BTZrY/1 -EACrnMsYUnN9sc9qhy67pAMPy5QaGsYY5IMOnQlTcjXYrBRBx0kEWhiMrX4USqRK -Yj51J5U/6MIyeFbmDMaGrUQ/Ba9GxxjOnYAUri5S7lvtuYZGYsQqQc4ORgNCSRAQ -GMiB5Q+3oWbkaoads3ezhcE+R7/0HrqgxgCRg5mzTx6up5vrkBN8kbI6BIpgoPBy -AzTOul/EIkJuBYHg4IPt9dWOmbFbJyxMJg7kNwTS65GypIEiMeQXK4VzcdB6jr2L -Ju77Ia+pWyzKpq323swdRZtM/hHrGJrwJDbdKMfWxoWf9e8cqvO5hIM2mzchHCQ8 -7OQSnb3JIsHQIPHCxeaxzMOS1smRNbYu4/yY/MRcWaNiScuoMJqI0gVWd+XIScwE -PSGyKlncV8moki4pFNkseaLw3MEQDoxqf9TtxXnEB7ZduvR/UcELUB85lVjNnoiy -GjrcagTZ4jDISxADvqBP+a02GsY28dLOk6smqPPwezbVWqV+ABPeQ+bgPd313MGl -a22s72O4/nXzzt0rNgmgEIqMy0OkgmxAUBCSfcQp88HEnk/roHsUV4iYwAks2cOp -CDriBnwjIywK+hVq0r8nuBNRQt0P/Yp75ZITffPRrOLVXvA8D7tV+kIm1GrjDbIZ -OFCNpAUCHXv/cXPeUvHsSd9hmyjGbNN3UzpxhykiDF9GWYkBHAQTAQgABgUCWKaB -cAAKCRCZRTN/KIg+y2JSCADAOSj2N7T8PriPsuGbRWehb2zvfjQ1C/IiDIWf6s7F -QuEjfg4NuWUJ2rPl2bYFey2yzSx7Ld0yNNdzSRxng6QADHUHYAneQi2WuGlyA06P -DDfFERlWRv6JZgnL9R7rWHB+RAa6DnPPgpxifABv9RR4caU+8uAP24KHRxCQXPx7 -LfB8hi+G8G3UYbuLnO5FTTuCObjjSh50h8qEt0f5y65R4kDDA40/L26POJNsHc5u -EE9rZlh0c4AqmakRSmH83+Q6XRWOtn/zPggj85ir0gsxLAezZG/OtuAyXW+rOC0L -RJDJ3JaiScUC3xewY5L/7jgg9aTcvuwxKoLBIaHOYtJQiQIzBBMBCgAdFiEE+ymK -u+HQChyPpNwfqLUfXoAyzOQFAlimepMACgkQqLUfXoAyzOQokg/8CqbMll42B+nG -VDdSNFCNjhjhKYctR/aZa2th7iDRwsTFuqSVHbywRL0XrkI0YOOJU57V56fBY7Uh -kfOKc6oeL7EXxpox8ehMToWMOcLSvi37EGMmlGLXokM9bN1gxfdFIrZr1Ji1kBYX -hvSj2Fxxi2NGRp0uy+IIOa0vB29u2xHi6GWk8U8MBMn0UcP6H053Kk6tMsMDEhF2 -rSYGpvKFSWywuFuELosSS6jG73+6pg9fMWBTDYQyWFH8YRA9AlpxWxT29gcKaftM -SBIz86Svh3PZ7qOEDVxh+yWAQTVUTVuGzUSleDDuJt75QLSt+ZERS9iezodB6EOb -AZr6canAJGmDwmjPTLwS0E3U197QW6encv3qUSA0Sb/QyAzr5007d2PzkIk6wJq3 -SxBdBRqCjAyR0VxZr2kE1Yr3t5rI3MOFsVWIKIpmkLzmCSPuUGFTvOZHlYVaTOKI -x5ge8d9smXdHjpSF0iGl45e0u1UMDsiU9dpo++ygdZWAnMI12Md5MO+K2uB4gLk8 -Njln1duZ0MQP9M6swkiIwH6jig3BkRCIAIWCNhbScBWJ79+HKD4Swk92+vTKDFRV -lrD8TQlQSbS69Lbon4/v+NwgcpHRTigY5TZZ6s4DXBUl8OIkXDs2LHeboTvm2Zu8 -gX+uWujFHr0nJmvwI1P/ih3kYoEFqLuJAjMEEwEKAB0WIQS7Pk4P+lsqogxkAaHa -lBBIg4QoJgUCWKeHnwAKCRDalBBIg4QoJv+gD/9AygNKRsaxJ19u0wyLifpGOsi2 -a6mlmwZkLLYhomeC82iV4+7EeI++QFhLc+KlRNZtkQld9rmihbcJo9UOfqTwwG/W -bzSF/Ed0GSFzPtS6HDjVPTn7qiKQoeat/e6g+VmYoK765wLknj75Tq0jPltX0/Yl -78s0ZwMI+HhirTBreOS6AVPlS8wFD4ywe64PN/YjgePAEfiIEiYICXmwGUHjPBgK -a50z9VuVs3TRLo+b00N73YDEW8tlpouhETQuL8hAYhjGgivHss0DRnuB5fNe6FgN -vwretguK3uknup1vrvVvDXOUOIdI1UksplrJvDbjYrFJB+L4VSbyGk7Kl6oSGKiz -YRF7gM4I+hpXlVWSKVxEdUlA9F6KPm3iqM5ld6K3Q6rDuppO/2BaqlBhinR+Z3bJ -TLtM1uKh0IgyGUstEkML/kjF9wJcCC+z7ZmW0k2CdA9JyMiHDQdVblxZpUI//Yge -gA4P32X1OofAFX2oXua88qehbEY2uYk3OFsR3bJwbTn40bJkxE8072IpBozYzskg -14Q/xnUxXkIL1wqLU1GPi9l+kbuh2+8yAdlz799x7De/uZhk8IwOOC5H+2oLp+vd -iRXDLKU1sDBiVFRJb9kosvUj7S/a15My1eqOSVP5Fa0GbXNw7ndvcpybMoFqbVSC -lzjlN2OgZuXYEl2PU4kCMwQQAQgAHRYhBH/Z1lK/X9LsXxORsHmPHjXLTTipBQJY -qndrAAoJEHmPHjXLTTip6uUP/j3RieBfyGnau1a4KClaXlPGHxlu9M1fFw+aRqV7 -r8ALWuQzsKlh8QlPEWhtqkty0BFXAhzRMYJd3G/5j9kaoS9NAeNpJpbZd9Gz25ZN -k+3PCkww4XthvKNY/ONwnwGuelLpIbwa25+f7Oct55tthkyM2TWXlwkRVNpeMNhk -uUkP4+gFnpvtzUTFqwYtaEtNY3UFw1CjmcA5xTGL6pIg2FKf6m1YyJJkDLpU2/pB -Ca8Mk/A9wQZ/9+M/l8goNq05vsQsp8nlh9zo1XpwWYBq3OwPQKDt4d6rAwU+zMHC -XI5MP5B2g2Pj+M5bQMNOxa4sLw71ALaCYETeHHi24Kp/ZhOWsUomwc+v7t5gApAk -6gjxbGklMWhdJuk2I+lv796J4cFI4VZpTXAygMSnnlo+GoMiqTz0C9eElZlp8z/Z -yy9g88Z8fBoAY1SmrroaxLOvlFKRG92xhd+JUh0kj72loB+Fozg5HV1OqkF6c2us -w3XCoIcht87TxmZWPTXqXdPXrStS74g59vrVyGvsNN2hG/l4dPGZSEV63Kn2eiti -Of3JPYJcy0iQpBBnhhKQwPVNgWso7NxsNsVYOUZCDeSoCFEvrdUFSr6q26IBBLcw -itnF/KEX3MyJLGr1BjDF9KqdP3+YL5Eqrq1Zn7LtyAbC2Odo4KY6vOT3SRrSkBRH -RRq4iQIcBBMBAgAGBQJYrLQ2AAoJEPaR/VwUa1eD1d8P/1qcubzbb/p4jpnrZsXW -i6+CAeJuA2f2qyBJtdVPhiz2swSHMNIlhVWh20w4892yv7Mgafj6i3Zoben088Bd -BTvCUOXRtkepCSTLTg1fTa/l3a2vNxLyK3LT6Xf8KuY5lXTH+XWn7vG/N4T6jyd2 -MQLP9VUltRkk7aNarIZvoYMd6/JVqKVhvxg42UZmcjke3PFKiHMIHBVSGBu3W1Mx -TDNgVZqTJlsqvfShwoBjPPYLBpSVZKHKgjirsDkZTS+ufpVmt2rzlujeVyC6y5f4 -subOde/pxGnTT+sMJENe/3uJxjUIy07xyXKBRnhpPxXbpTafZCcVc688er0CLRW2 -JsL9aEmEM0FV6HlnvW4ivoW1v9mSevAxe+KvgCO2cU2+HFqN/tCtxnr8rZ2HIpf8 -00cTpdvIn7wibGP9jfwMisD2Mugx28eLrZ+1sNaRLwVmroedjo9NJr2BiyPozOEN -lGX8V/RxQLaQfiHwyuKVpxA8rlx5evvtDE2d31ekVtdLXtN+GmCymnPhu1KbD5Mq -+Xk+yj1t8tdMD+SiFclz1uVeAOGpX5u7GMIsy4W8yoB5JlrwrsFot6UBaVZjAVHB -XTdMvBGsfxmimO7d0p2tBFJ1QV2lAafVhVIklCT8zXk4McqqtWxXIKWEB9dfIpbD -/A5MPtu7X91BTISC7SmRdBjViQGcBBMBCAAGBQJYrnXHAAoJEBzIdvEMrJ+JDgAM -AJyHN3j+g47bSERRxLevoRybp8/BoRfK/OjcLRxhOru4prOAiJEfNo77IbG9Quz3 -aBn7vRDh44BxXIR/NjI6kM3hsN40BBDVwfeFEFGKciV3cjCBqlqnhwt4MV6iDoGQ -1CkTm4LZQvtjQN26PAXUxxl/GO39vze3a8z3QP9BatZ+KrLOp2u7pOkwHNkY3Anb -/H0AUq0fH2Dq5omDJB8R54jlHc3/ZrLvujCVAmEuTPxK6LGl5xg4TaBtYeUgIki8 -A9iwrcFgh9OjgAuG1PFs+6RroE+nVPm/ZPDJ5l45ZHR4qQB52qp2lxf745PlSHj7 -23d6ASx/I8mDZ7bPqk2aCKXGQqkZ31b+I+Ut2ru2nEW6JAna26kgBMhNrINqLNxO -qPXjZHqZHG1amvlTAwGpAgeW5WBPvNjFn1WNPB1+9vCPTSwkWLR8dnzy46Rsfohk -RAGFtQjdccBxaikRHuUlIUI32M0WjKCP/sy5nVLQKrX9xqkOj+mSblmbS+u8cmIH -0rQiUMOhZHJhaWcgQnJhZHkgPHBicmFkeUByZWRoYXQuY29tPokCHwQwAQIACQUC -Vp+cpgIdIAAKCRDfb9lxMGA32UftD/9jYqsCfNAzb0vhDOaU1AchzaQa1pIKEjoL -6d4AMeXFSBpMi4nYJpN+rmM8DAzcbenBcSoIqecdfENp3mY+hI8mYdnMiVpldsro -EAl/SDxY6//pPd0Dnmoe6sNodBB2uwHxhQi9ubz72iWX5WiKP8+OUAj91cLMl9nK -IYfcHy3iinSRqT02JP33DGDwsHCoAMmp59g6AHnf0sjCtZEtK79MtKiKTkUdMazP -VGs81x1jCO2kvvmy0fDZxkGuyso0inae2hsaMSqqoga5lC0jQanFIXSEkLZgJglj -LmiWPO0IGHPFth/e//51atGUmpdd2ufQ/QVoxSnQKRFQ98eO/SQ75bO5vbE8dGv8 -oX9S3M9NjKOY9VnXC/JDyMXt2aMDs9tqSo22lJuT2Wq20wM5hlszxKI7c9QphnuH -yPNtszzXo1+5/UEuCNIQoe59MoscGmx7GN5WvlENaixGg7tzpZ+wdftN7BUcpJfC -gsEQurHzPEIomlszp3xraX0G84plClas13Ie8CIVM7UPbF0Cwx6XwhryjaDTkq3f -+mjQXtNJQk487q8cc9dxplslXiDqBYVngV+oDKOjrqc5PXSQm2M8EYRn9SXuFnT8 -iF5SkuFYtgOEj3KNZ04ZB1I7AQebylS2LGwWan8yWJSAs22eR9urWBVpmre6GUGZ -fo7YBdOvbLQiUMOhZHJhaWcgQnJhZHkgPHBpeGVsYmVhdEBnbnUub3JnPokCOAQT -AQIAIgUCTnyAtAIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ32/ZcTBg -N9moHg/+Mjq/O1RnNg7kdUjRK1wOflym7itgE8kq4G55EJvLSxo6wIgd7ZKUj+cv -X+iXQpGRc3bicpNTsKcW6EjDtyg+VCSWD7qJ3EtwxVf9mN3bIqWSVwP0k8kc1N+t -p+L+/9jve+h7Hf7rXZoNo+l9h0/AIIr9YyM2r1VtiAsMNCfD/Ssvc5Yx4fZHR+2V -kOLeVb2lqdYVe7ZrXDt8qkdBHMCtxm+9jaY3pZVDFKk19NeI74Vzr9+mYn0I0OZS -0capUuG7+a+FGI1Dx2jn8uL+x4eLDdI3vvr/vGWparikBExGq1pAKWm5gBF10CDP -4nx9+5hzjPipvCuQerRnjL3FQyXa6E/GpCp4Mk7SdB4zML1CmnYUzz4n0TcV5aFi -yaMQPk5TByxzYXWUqjFJzFwmU0z8Oy/d64ZMGLyAxCly6gBc/AmXzsUhg2hJB3nG -3JRw2WmpOIeOdYn6S3onfAFT1tGo7kWNIWYxX5fT7qAHVlnAmgjz+zvfB8Hwq/B0 -FDZPzgwYX4LeRMCj9VDspoCVnaMd4rWqbH2lKUU/k0SFRt3iAqjvT6WPbJIDtEF0 -ifU2R79laaZZU5rbYWZC52AfO7NdLP+7uwxtPYyOdP/4s0HS0e8WDuykdZbTaC9K -HbIiKMW9YXQJRo6YupWJWOpFpPkvx9ttcQQ7C5s8YFjVR/96dYKJAhwEEwEIAAYF -Ak6EiIAACgkQf9n8ywAL7u5OexAAjb2+LR8Pa80t3ooladI3Q1icII1hvfb6C+KB -lzm0d8nMNqcjpPdkbppcVmjqbF3xw70uMnT9m1Y5NGMzJEZiNv6VWT3/m+VJ/aih -ci/lccUA46pL6Edxw2F/l6ftEOcPRAefNvszCQPNSVHPoQ1m+HuweVgYs9by6s6E -FFCG8BbqxpAxGxaByoq7ZtlxfMAjKHSPCJSJQTntj5dz79+K+eI8i6bMP8isPBvu -HAT8ZJ8mn2kQTEpuMIyCl6GTEigKimwq21tebB666Kv7wwS/nwCzceqyPshlrXQp -YYWoKfLd4SrC1z99//H93/IkN9dZfDJaWvMOlgO+/Tjnlr0tnVsIafnYaOA7Pb4c -QAx/tbPeiSH3QyRQw4wD2T1CaoLGPLaS4aOCjJXbNBPk+44suO0gUkU8duBwyK0p -fjFAJQJnJnVEsqWDh0KustQW3jdPvlqEe1eWmhnivXnmtvBk4U2BPkOG/NC9+r3n -xIWnrRhINWZLT85wM47WtQ2l5BRK71UKrgZDixOIbAR4H54FLa+vrwub6JjpOrQM -MYaxA/aiEv5byP38nWVvWRSaFDC+QpPyOHLnzBSoxaAHvm8bsNR+4KALcL4zyrUm -+qqQWbaOpikgBDhYyI/qteW6REZunofpkrpXZbyE+oFUxn7Vwz1ivEkiYPrEhTWr -HomA9eSIRgQTEQIABgUCUT5njAAKCRAWD1+3iz1IBic4AJ0VP0N+M3OHLK84zhnb -r7NV/OsepwCghhSEutr+LFoP8SIDFZGyGwWNZkWJAhwEEwECAAYFAlFj+x0ACgkQ -aIeeK0/t4b4XvBAAnQEaY8PFnZgegqdsNakq1gLr433h3WwQBGzba9CHhElS7VdF -c3+VnZ031zRXFFMWSFOovvQpyuRNsuGvgmvlr93+/OgP2jBZbgPFZy0B0KaTpvuE -3LD2XyPINajejIVJTMwNIuD2TTxz+zqRcdie4ExOdSmWHmjGNVCt2W7Xf2ZX18ex -FdH8jOVKtI2Hdm0YdfgNrfbcSLVgGr5MJMvaifsgGyQkPS/iDXVvLZxmSJiloupJ -ZfXrCcw5mzd8qodWwC7VJbZWIYkUBo5ir+tFAr1GuxD8D1l2U1RA3jRIgsmjd2CD -S6eKOmBXR3UVxFypOkHqfsHlST2vzTpvWGhzeQXAbo5ahjtI6m2c5mn6Tvb0V6BA -o6Fjw1id/iOWmfUSyI9byZkC7HJD/68jgvFha5eXixSo7v66MFptGl9B3sWG0gf5 -iSMbIj4EFzuBySv905kmXJ9VXnawQWalNC7n5JvJkIwAMC6bNU7aO84+9K7kh7bo -rGaBkiYfD5W09BgTipJAEgq5cVKLOGKaN47DhSszu3QAXl6Wk/VL/RTJfzWWGU13 -nZ7UY7f2uavA30mHOznAn+2v1GnMwq6ZhCQt2Y37YgDowBSR2PrFFZJOzZJhd6GN -5XWjq6A4QKZouIK19zRAA2Zsvi1TNDzUw01qGT4i+hsxPKXgEbp883D/ZMuJAhwE -EAEKAAYFAlV92zQACgkQIUyCwjYf1yjk7w/9FyPk/VEJsUYvG6Oap8Qh+bwCQRRm -vApZKVurqkMAXntN93GbCudWyPdt5igZDQf7CAHobvkUrn4fIGSMAUu6jmy7qoFf -AnGNKDMWLVYIUi5T/Sb5WCoV6DGpRJ46MjEkbplbnvQyemVsUVQLkB5GrnkO1WRV -UCk3vnsgSqrJ7B9HyLHAjsbEgm3L2OWe+1Nz9+Evg7etyVHyLLN5N2pMK3/ZMHKf -42p9SEh5x6JL9YlcxW6EseOnoy64MHDvVvnXnuUWxuTEsEpytvRXlJ7SkG+2lLcn -nbPNPY3zWfjOEI7j8RvXQJGU3FKt7NZNMGe/jdjq5nF1R5QtilRBnpVFboVmkWNN -/eiOT1Xy9/PEZKe0GUHLLh2t2ffI2du4FPKKmZ3i8sl2VTh70okKEO8zxTohs+7h -1bff6XgIFCqzpzVoiIMHLloN/Qxr27lywFzu42UISXIJBW34nSzJ1SUkaVdAdkE8 -TtXEk0xHmMkATTWTwDHoWmp0E2QcVugFpUlw85Dj1FkFNf6IvwaMw0wpE9aP9IKM -oPmKuarKzC1PUiGqm8o66Oh8I/ycQVv70VgvazeUY1f0GXV/49nT9tyj988/XKAT -T3OkyHmZIE0Q3HLlSK98bN1ddlVn35IABE7LSa9aJWN2QTOU0pw6D1Gc7pRD9smT -HAxs4LUP8TXOkGWJAjMEEwEIAB0WIQQ/Sysw6Ic29Fs6LAwiE6c8TiVp8QUCWKaU -mQAKCRAiE6c8TiVp8bY1D/476x3jkMpbkhg5wd6YlVH33kvxocqaMEdt9jIMj/Xr -xJbMZKQgHBAESf6XiIYqLRZOsIcdi8k/0goaqP+HENnUj/lK/vBii8P7Qtcct8F5 -55UEDC6GWCFaqEZn0l2qgbHjGWcwh8toq+NZ5VniPyhQErm3b7dToauqE7sOoibm -/RpkfwxNmtySd/nmmyanP4Q27AgZ7Csq8h68P1wiVTAnOuBJ28CW1z5XsJ5YRTq8 -ae/6kJs7g9eRoDtMkUr516EYmui10khYFUaZ87KjpsTXpgfiHUTtbbW73yGBdqwM -QD/s10UUCrlv7j8gJ1V8Z5NRSda8kwDyeorziwD+sfGIuxK86Q7NA5tjP9QY5tJA -m+yxgiwcv56XL12p7G82L3WRDujVm4pDs5NGFRGQNsmkb1T9DEFQMOnsBgVWH4sl -sjPsN51YNs/wHmu0jOv3CBbVDJAELxjqIroTZuT1yjG1xV5maPTqppMr3+gT16eR -SZ2nBy4ev8rYM4N4K9EEBjcbXWLNQOYeger1vz5S0bEzUuGeHY4ahMNB+dRTf1eN -UjRlhSzddlWpoNMbb1+PlYwtcTEIfh2vs2iJEbhZhuETVFye2RmBQ+MQ6oXDGEcg -fwbwrbyW0X+Z9KPIDhTRMrdXJiBui5RvQ1AxAuQ3sZglw/xySSvztqf5InRrt1lE -N4kCMwQTAQoAHRYhBBIb2i1Ky2NhazZ6DljhG7HkFNmtBQJYqPbkAAoJEFjhG7Hk -FNmt9cgP/2owqkabfUTz1Gf5BZn8cWlcZT0ePFJuXqceoyZfPj4VhwKSyRiXEu2U -LGi75TSUp1ESok6w3KG7chq2GoH2EITysqUhpcroOTAT5qjWGwf1WEP/zEYrmQb2 -ayFRBHdcoNNgRnJVd2HB7FlHF6fg5aPrM3P7o8ajYDneYSDwubajN2xnUsFV8yYv -liNV8DtFOsX2AHSf9ipsF3P5ArsjRJoMI6Z/PgZuECRiya8qzbxZoIZGgT+khcvC -SwxsX6YXmNImwhGpugUnSrjvBPdiyN4CilTOdaiEqPLwFDpFWEkByx3ewfJYfBfH -EOzTdSgtPEXJB0Xxb7ge5fpBtFunI45bPRwRIT6EM29WcYWwCp12HCTt4N2LHwu6 -h+JL3ikFucgtJsSO68h/oId7THD24ft4UpIfBR0zZ0/i+ier3SAB/gN0xE4Hpy4Q -YNcl9rkt/ApuHX2hQqcN8woUhGV9HV4n07Z6FIqs3qSj+o4w2hV5xaEqOiVoKdMC -p7DCECjR5ACmhvtLTI8ddS/2rXPK/8Kttg4e74LysK5WOSbCiX7M+GjNIuVh7aA8 -BVR7hLjQ1CRAu/c0/m6EsTEViHuNZjX4deJo/c70kWLbP5UVN9yXrJjwVXwBOz1O -XiZzzJCl+ICT2fu8K2P7nL4yqkSAuMZHz1sQxzIvLs8hjbMYbdqMiQIzBBMBCgAd -FiEE+ymKu+HQChyPpNwfqLUfXoAyzOQFAlimepUACgkQqLUfXoAyzOTxgA/7BZpk -HIlTGVobZ3drVXXLRVdydLbypAJ2d6KU37hY1xuCM1bQ36H/hQKtHBgdTVc87IvB -0iZTKfwxPHBloK4MBDl0zj0Nz+Y6OK5oaUccDCSIDyBuMnkwu+U3O94mWoftQZuB -FH9urpElmgLftknKE1PMsPT2PVEpLVKX82yXo28+aAhXjcO7W/FYQhHX5vqPZmjC -uJGS2DZJHUjF0Vem1Eh2a200+t47JfFSMRSFBm2S4Z1Bo5UUjSk83yJ66tCynJ3x -D5vhMTWJXRLhZd7DXjjPBMrp6MqDElL8tNF1w86Bk4kIwX/hMre6c0/+4b5rJBwF -mjRkAwfk/YLJPz5dfoMiTf0kqj93F86BKDnYZNQ4L0Yn1QWWKJSEf55ldmxvaxwz -ZE3NpOALdBwkG7yjhttsHIe5kpWgluxcuYTvWpX7KGIZnt1qSl+Cv0VAOY7eo2Zl -KTtpqAQeFqtCZL0tcLxj2Ce8LqViuraKGxNKi13FtpS74W4DgseXv8tnhdy0uqlP -gRQ2WCHpUhXUlU/KaXtXXmS6oRFnCzXikYXzH5ZFTHzNthg1gO5Fk3y2B+5eL71V -SHDeIpi0jTpiO3Mav6AtVlw6QRXXfn61cdF1M37k1XA5lFPb+ifkV0sF/rkFE5NL -r0NAFqcwB3CE7K0fgOidFhdnH9zi+qcfCiyMjpGJAjMEEwEKAB0WIQS7Pk4P+lsq -ogxkAaHalBBIg4QoJgUCWKeHoQAKCRDalBBIg4QoJnzFD/wNhcOyJURvQtQXcys2 -bSw93rubuZO2OUpIgs6CCcZgCKt4sES9Xv9Qt2qRdk6GBgnlsTdTfwDWEDla1NYf -+/894Kf+3dLhaiTmYkWVh3UhysE6rihKZ5SHeriNCFCyaOvflOfpGQn20TX17I04 -fLBPQ2tZLIZYELpHHr5OXDm0YiBR+1Rc7mj80cTdw2+1vNa1p2r72n2GzKz76Yl4 -BI7dWud4GAEW26yrwF3VtdGFacRcDsjSM5rR5pxREY2WGzONCCD1yuaJUqk8Q+QK -8g/2PybkAUJpzmNzWqgsn8FhPESfObl2FPuIbxIjR+N531QGeU4HcH62zJeJjCdR -XxJk+k1VRP7SIIg310q6J4WiHa6LU79BVTFEV/0gyHh8psLpySr6nJN9TAImdekd -2+BN6xdWcub6/JJTdJgg+g/VuD+2vUm9zPtcP7nnpadqen6k2pobiDfuGepa4k7s -1jdgSoyKdgntJNBEpBCCx/fQQeXlR6kcscjUP1aMa+XIgpeZhyKTWWcGfbzsf58u -YYOP2nMn1GvPvoKcW4AfbPui14eNh3m3hQ3numJKBZGLzBASJsdc10CkOJzLq448 -nhdJTp8ZLRGYl9mEbpVuHNrYQnxYe67OtGS9Nv/DlAJXR4fUiX/Yq/Z+w5zz7HMK -Pbu/XhRIZcfJWgmRkgr3DSwGdIkCMwQQAQgAHRYhBH/Z1lK/X9LsXxORsHmPHjXL -TTipBQJYqndrAAoJEHmPHjXLTTip1XkP/R2nPYovKt4/ytjOMRDfO7XSzpUn2d0g -hmKRn0MHe21n3IjBzDG+BapdTMQCOc4Ucs1UicPV2lxRD8TQa8hh1MYCp9gkZ0Hx -I9R4q8StipyPLq7B5TQJ4tsHqT4Vc8reuxRInV/2XZ6gdr412v9dsK08o9lYri59 -mv5YJaxZmdov5555oK0ieMAbIRXiSqSsONcA4ph/MPXpVRXZvmu8+IhKJZbAd0cw -iOhjTU8z0qCBcU4vYB0nxwp2AWbQG4QDpk5lTp40Tn7A1dL1XUbiXsK9h2jAF5zn -Rssb+drhNeafoqYfVRsB2ObZPhfqD9nq6isbj1ocDU1nQLOrFdYu1o9+JgMFs6F5 -NvavG7RY4RdVLlXDQuoMiX5e1PyGsBgLliy4Tz5gogKtqzm40nV0573pcEkUR7Um -rNEzEuPoC8PFr7W8lYEHx70Yhql6IZ7rGXKDQNBWLp4drmPKajhdH8xPOKn1Tocr -qdL8hkzWh6wqLcSzwhgR14/bjCZDj3AJr6bRdAAbcE1xqWt86XiJRM0upe0j/Q7E -s2eUybhUb/YPSe++llkUsePqvLGMSY2nUN1lwHST1/yI1gjJ0qTSdrHUDd/V1KkU -SY8CL122N61FoSAEy2Tk4hVNrSNEM0DUuYXaEFZFazJT5/QwfmCaE7lBFzHFRQFs -mbsPONxL6qjFiQIcBBMBAgAGBQJYrLRFAAoJEPaR/VwUa1eDkbsQAKFy6zUg6GQz -i3pSqoaWvwCh0rdQzlQJ0Rr+1k70AnGvGnPmtFpceT8AHsJkzfhH4AetZLYeuOpf -FlcMca9267VdyWgwInob8fcvAURW1ZN4qn8MvNPOBXudj5W5+8XowWmDES4qNr1/ -2Oj4IgHDlMRgUYhsql0ybYarpfZdRxxKKj3ZW4B55Qqds2mG1w40zTSeW9ErXQvJ -EYkqFsAhEme0Ii+tKP1oM/qRrHuCfKiQw8Zc99v0uU19KbdD2B8sCsBfgkIJpGny -6ne8BuNAJRDJa4JhzyRu0Aw7f+U/ewn4T+GYdzgsqnsqH6nEwEabeHUtEsChXxZp -7mu9nSww8fJUEgHuTonr/w8UcMtB7HVwhQ1/AuFxzaQx7uKkyU+uyJaElZ3LD30O -f20p9Z0v6LXpyiqxBUUytoPCsBtRi2aPQKvNmnkPbtH4P45nz0Nc7CVaWM3tvAGR -53WQMxowHcek/J3mtNVprhG1gn5V+NnF/a5cjVqGxQbs/G7lhqZXYBNeflW3mUFx -7DaO5C5KcqjJBN1h9W6a48qh0sqyIbuBFlWJFNdizV0eMi1ypsHXKSZcl7SZ7PB2 -QGMVLg6VW0RneL7zzpoaLHaey97bxeccP721rA0/6w5qCE+qlTUXgV5sZSXJkj9M -wwpVQWwqa6q/cG0G7iFCxbD+OPZ3/9jZiQGcBBMBCAAGBQJYrnXJAAoJEBzIdvEM -rJ+J7Q4MAKz8ITE6nKeltOLAJF3xHNNcvyIHFLcOF2BI4bJTinMS7hFwEM3tg8+s -fnClHe7Lu/YpJdtqJ+jz8+nZMEF9tpS49C4bA8sPDyBHVqBi75xivKDSchnogPql -jctZF6NWbOt3Bf21DqbJFnrrtg/aEDrHQIDdXZUIKM66artlELC1XmFUnzfUBYNB -vksoPD+ehG9Im4ugC5kQCGxMNDjHXGyw+DzSm5n+hyEtkjnOPq1x2uPaELrHweMZ -c06ivHndOBp3vU2EgkyuCvRebc4OLu94RSel/ANv2VRdt3ryRQrW5tqxQJhEwPLW -fWqNTmR3vZhuUrY5Bk/R6Spn+iNJE1qCUutbB89aIeT9KMV5Dl0Zes4gdK7PLnLJ -5rjEMoVvJ1Tdl4LUToKZk+7el+2jEMZpkv5jnXkeRqMZAB584wWVOA7+7pKDUGL4 -r7RJByaBz6wRFCGmSJ5DIZQ8HKSeF1ikCwUHqVDYfAWmlyR/t7ZH3ZgUT1ezi67/ -PLQrM9JPbLkCDQROfHxOARAA5hb6RwSG2oH8LMWk6rmPthWH5IBE8yw4InTPpsA8 -V7LyFlNUOH+BuHI8mTpTHk4aRfg3h8wxqw9VfnncWN/H69Y6bhgYp8XZ37esQjPr -kujaQ7QaLp9EB++96AvF+5pTvf1eBlkhprMXUolw/D3UpGnC6uXW2iCjKEjt4HGU -G/nJQum9U9fcmZJWrtKFOW8NK/DVJ3iIdh2RmR+DceBDXUJF2qL9DEQvhEDAO5uY -glC8CwYdHwbdQaWjgLyDMWjr65SQZGbYJ1e+ZxPGGpucfQR89lylNaZwIg/HkFgU -bIvGnezleSwfO93ayQ34HVtpecr14TMG/jouh85xCsbsX7znnTLtCKzti+EkWRXa -NV0D+FvaPKo4jv440vgQZajcPzD9tbYWUfylpg83URVaQqZZglg1gLPU166vkB4V -/ov6nBjQ+Z6YxJsGvgPVhfBZth8IrckFUINyH5JKAAcwPZBtKR0QfUSHW+SxHer4 -DMLHpsjO39wHO9CIk4EcbLYUJwoEYlFpcnNWNYBwjLqAWXuMA+mE2fX/+NoMY1/c -rOZ46y3dLq0zJfD+LBgORx10j1fFaAj9j36pg43DUewZSwLtBhlYJ/SExW0Rz0xU -MU+C/4EJjy7+3ycLV+M8gnJGVwp2+z1H1ESe5bH6hSgARqQ4pOfP9sbM7sNX/y17 -KMEAEQEAAYkCHwQYAQIACQUCTnx8TgIbDAAKCRDfb9lxMGA32aBIEADAGhbCehSj -Wv8SEw9gUpN+slmIDBnZ7uqQgXjWO5OnG2TrSJyPNAwfk6ESY6JeoGuiASL3EpqD -vRTVsIvDzzqhNBwVa+mi/q3lof9yNs74dmJYsH0P20+9lVzNfWATWUDA4cVYBvON -BloCK1cVvn9zqFvfjFBcRbZskcvMBVPxO2Fv4xAzX+omPDfCnweY8G7i71Z8Nnl/ -HVkSZMI9uXrtcde00oISHf5xUebJdx96dxnUCDLPUwPiIxxYN44KvIl3cnIB5qwu -BV8F2XXUtBdxZDJexqsCIoAD3rhRoWq6E2fRJKeqt/4TmxwjsJ8ZODp+ilXhqRe/ -shHttoOvbo5QBZNZMujxkqxXeu+j2E3Ry5mSiGX1SewwbT1iUppwGI15Uwhthhrc -PwbtWxxIyzPBU6awwlrTrYxNTB1n7WM99gcQctLWZpWnEaoAnEmIEcPjnM+c2NRw -UJmE/C5h9intY4fOa2a8hpUPx6UbMkfPl0bkIA2cduvQtAFKy/G/Jm4H+0trSmrD -c+o+rl7v9sMJ9wKkMUdAcqUgNP0TEHzDPbzvztcKBCLnNLoUTKNIN4eNJjMGk8Si -/OgiN1NKkuVz7I3i916mVxxlFjKEyLYU4tYYXsbB+ZJy4dTP/YWHbQulJYLgju6Z -ELphkzjc6eM3CaOZ73u4GVXotheeUabUHQ== -=drvb ------END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/coreutils.spec b/coreutils.spec index ecfd5fa..66c5340 100644 --- a/coreutils.spec +++ b/coreutils.spec @@ -1,333 +1,738 @@ # -# spec file for package coreutils%{?name_suffix} +# spec file for package coreutils (Version 6.7) # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2006 SUSE LINUX Products GmbH, Nuernberg, Germany. +# This file and all modifications and additions to the pristine +# package are under the same license as the package itself. # -# All modifications and additions to the file contributed by third parties -# remain the property of their copyright owners, unless otherwise agreed -# upon. The license for this file, and modifications and additions to the -# file, is the same license as for the pristine package itself (unless the -# license for the pristine package is not an Open Source License, in which -# case the license is the MIT License). An "Open Source License" is a -# license that conforms to the Open Source Definition (Version 1.9) -# published by the Open Source Initiative. - -# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# Please submit bugfixes or comments via http://bugs.opensuse.org/ # +# norootforbuild -%bcond_with ringdisabled - -# there are more fancy ways to define a package name using magic -# macros but OBS and the bots that rely on parser information from -# OBS can't deal with all of them -%define flavor @BUILD_FLAVOR@%{nil} -%if "%{flavor}" != "" -%define name_suffix -%{flavor} -%if %{with ringdisabled} -ExclusiveArch: do_not_build -%endif -%endif - -Name: coreutils%{?name_suffix} -Summary: GNU Core Utilities -License: GPL-3.0-or-later +Name: coreutils +BuildRequires: help2man libacl-devel pam-devel +URL: http://www.gnu.org/software/coreutils/ +License: GNU General Public License (GPL) Group: System/Base -URL: https://www.gnu.org/software/coreutils/ -Version: 8.32 -Release: 0 - -BuildRequires: automake -BuildRequires: gmp-devel -BuildRequires: libacl-devel -BuildRequires: libattr-devel -BuildRequires: libcap-devel -BuildRequires: libselinux-devel -BuildRequires: makeinfo -BuildRequires: perl -BuildRequires: xz -%if %{suse_version} > 1320 -BuildRequires: gcc-PIE -%endif -%if "%{name}" == "coreutils-testsuite" -BuildRequires: acl -BuildRequires: gdb -BuildRequires: perl-Expect -BuildRequires: python -BuildRequires: python3 -BuildRequires: python3-pyinotify -BuildRequires: strace -BuildRequires: timezone -# Some tests need the 'bin' user. -BuildRequires: user(bin) -%ifarch %ix86 x86_64 ppc ppc64 s390x armv7l armv7hl -BuildRequires: valgrind -%endif -%endif - -%if "%{name}" == "coreutils" || "%{name}" == "coreutils-single" -Provides: fileutils = %{version} -Provides: mktemp = %{version} -%if 0%{?usrmerged} -Provides: /bin/mktemp -%endif -Provides: sh-utils = %{version} -Provides: stat = %{version} -Provides: textutils = %{version} -%if "%{name}" == "coreutils-single" -Conflicts: coreutils -Provides: coreutils = %{version}-%{release} -%endif -%endif - -# this will create a cycle, broken up randomly - coreutils is just -# too core to have other prerequisites. -#PreReq: permissions - +Provides: fileutil fileutils sh-utils sh_utils shellutl stat textutil textutils textutl txtutils +Obsoletes: fileutil fileutils sh-utils sh_utils stat textutil textutils +Obsoletes: libselinux <= 1.23.11-3 libselinux-32bit >= 9 libselinux-64bit = 9 libselinux-x86 = 9 +Autoreqprov: on +PreReq: %{install_info_prereq} +Version: 6.7 +Release: 3 +Summary: GNU Core Utilities +Source: coreutils-%{version}.tar.bz2 +Source1: su.pamd +Source2: su.default +Patch: coreutils-%{version}.diff +Patch1: coreutils-xattr.diff +Patch30: coreutils-changelog.diff +Patch4: coreutils-5.3.0-i18n-0.1.patch +Patch5: i18n-uninit.diff +Patch6: i18n-infloop.diff +Patch7: coreutils-5.0-pam-env.patch +Patch8: coreutils-sysinfo.diff +Patch9: acl-test.diff +Patch10: getcwd.diff +Patch16: invalid-ids.diff +Patch17: no-no.diff +Patch20: coreutils-5.3.0-pie.diff +Patch21: coreutils-5.3.0-sbin4su.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build -#cgit-URL: https://git.savannah.gnu.org/cgit/coreutils.git/ -#Git-Clone: git://git.sv.gnu.org/coreutils -# For upgrading the upstream version, increase the version number (above), -# then remove the old tarball and signature files and let OSC download -# those files of the new version: -# osc rm coreutils-*.tar.xz coreutils-*.tar.xz.sig -# osc service localrun download_files -# osc addremove -# Then adjust the downstream patches (using quilt). -# Finally, add a changelog entry and commit: -# osc vc -# osc ci - -Source0: https://ftp.gnu.org/gnu/coreutils/coreutils-%{version}.tar.xz -Source1: https://ftp.gnu.org/gnu/coreutils/coreutils-%{version}.tar.xz.sig -Source2: https://savannah.gnu.org/project/release-gpgkeys.php?group=coreutils&download=1&file=./coreutils.keyring -Source3: baselibs.conf - -Patch1: coreutils-remove_hostname_documentation.patch -Patch3: coreutils-remove_kill_documentation.patch -Patch4: coreutils-i18n.patch -Patch8: coreutils-sysinfo.patch -Patch16: coreutils-invalid-ids.patch - -# OBS / RPMLINT require /usr/bin/timeout to be built with the -fpie option. -Patch100: coreutils-build-timeout-as-pie.patch - -# There is no network in the build root so make the test succeed -Patch112: coreutils-getaddrinfo.patch - -# Assorted fixes -Patch113: coreutils-misc.patch - -# Skip 2 valgrind'ed sort tests on ppc/ppc64 which would fail due to -# a glibc issue in mkstemp. -Patch300: coreutils-skip-some-sort-tests-on-ppc.patch - -Patch301: coreutils-skip-gnulib-test-tls.patch - -# tests: shorten extreme-expensive factor tests -Patch303: coreutils-tests-shorten-extreme-factor-tests.patch -# Stop using Python 2.x -Patch304: coreutils-use-python3.patch -Patch500: coreutils-disable_tests.patch -Patch501: coreutils-test_without_valgrind.patch - -# Upstream commits (squashed) after the release of coreutils-8.32: -# [PATCH 1/2] ls: restore 8.31 behavior on removed directories -# [PATCH 2/2] ls: improve removed-directory test -# Remove this patch with the next coreutils release. -Patch800: coreutils-ls-restore-8.31-behavior-on-removed-dirs.patch - -Patch820: coreutils-gnulib-disable-test-float.patch - -# Avoid FP error in gnulib tests 'test-perror2' and 'test-strerror_r'. -Patch840: gnulib-test-avoid-FP-perror-strerror.patch - -# Upstream patch - remove with version >8.32: -# avoid FP error in 'tests/ls/stat-free-color.sh'. -Patch860: coreutils-tests-fix-FP-in-ls-stat-free-color.patch - -# ================================================ %description -These are the GNU core utilities. This package is the union of -the GNU fileutils, sh-utils, and textutils packages. +Basic file, shell, and text manipulation utilities. The package +contains the following programs: - [ arch b2sum base32 base64 basename basenc cat chcon chgrp chmod chown chroot - cksum comm cp csplit cut date dd df dir dircolors dirname du echo env expand - expr factor false fmt fold groups head hostid id install join - link ln logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl nohup - nproc numfmt od paste pathchk pinky pr printenv printf ptx pwd readlink - realpath rm rmdir runcon seq sha1sum sha224sum sha256sum sha384sum sha512sum - shred shuf sleep sort split stat stdbuf stty sum sync tac tail tee test - timeout touch tr true truncate tsort tty uname unexpand uniq unlink - uptime users vdir wc who whoami yes +basename cat chgrp chmod chown chroot cksum comm cp csplit cut date dd +df dir dircolors dirname du echo env expand expr factor false fmt fold +install groups head id join kill link ln logname ls md5sum mkdir mkfifo +mknod mv nice nl nohup od paste pathchk pinky pr printenv printf ptx +pwd readlink rm rmdir seq sha1sum shred sleep sort split stat stty su +sum sync tac tail tee test touch tr true tsort tty uname unexpand uniq +unlink uptime users vdir wc who whoami yes -%package doc -Summary: Documentation for the GNU Core Utilities -Group: Documentation/Man -Provides: coreutils:%{_infodir}/coreutils.info.gz -Supplements: (coreutils-single and patterns-base-documentation) -Supplements: (coreutils and patterns-base-documentation) -BuildArch: noarch -%description doc -This package contains the documentation for the GNU Core Utilities. -# ================================================ -%lang_package +Authors: +-------- + Arnold Robbins + Colin Plumb + David M. Ihnat + David MacKenzie + François Pinard + H. Peter Anvin + Ian Lance Taylor + Jay Lepreau + Jim Kingdon + Jim Meyering + Joseph Arceneaux + Kaveh Ghazi + Kayvan Aghaiepour + Larry McVoy + Mark Kettenis + Michael Meskes + Michael Stone + Mike Haertel + Mike Parker + Paul Eggert + Paul Rubin + Pete TerMaat + Randy Smith + Richard M. Stallman + Richard Mlynarik + Roland Huebner + Roland McGrath + Ross Paterson + Scott Bartram + Scott Miller + Stuart Kemp + Torbjorn Granlund + Ulrich Drepper %prep -%setup -q -n coreutils-%{version} -%patch4 -%patch1 -%patch3 -%patch8 -%patch16 -# -%if %{suse_version} <= 1320 -%patch100 -%endif -%patch112 -%patch113 +%setup -q +%patch1 -p1 +%patch4 -p1 +%patch5 +%patch6 +%patch +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 +%patch16 -p1 +%patch17 +%patch20 +%patch21 +rm -f po/no.* -%patch300 - -%ifarch %ix86 x86_64 ppc ppc64 -%patch301 -%endif - -%patch303 -%patch304 -%patch500 -%patch501 - -%patch800 - -%ifarch ppc ppc64le -# Disable gnulib test 'test-float' temporarily as it fails on ppc and ppc64le. -%patch820 -%endif - -%patch840 -%patch860 - -# ================================================ %build -%if 0%{suse_version} >= 1200 AUTOPOINT=true autoreconf -fi -%endif -export CFLAGS="%optflags" -%configure --libexecdir=%{_libdir} \ - --enable-install-program=arch \ - --enable-no-install-program=kill \ -%if "%{name}" == "coreutils-single" - --enable-single-binary \ - --without-openssl \ - --without-gmp \ -%endif - DEFAULT_POSIX2_VERSION=200112 \ - alternative=199209 - -make -C po update-po - -# Regenerate manpages -touch man/*.x - -make all %{?_smp_mflags} V=1 - -# make sure that parse-datetime.{c,y} ends up in debuginfo (rh#1555079) -ln -v lib/parse-datetime.{c,y} . - -# ================================================ -%check -%if "%{name}" == "coreutils-testsuite" - # Make our multi-byte test for sort executable - chmod a+x tests/misc/sort-mb-tests.sh - # Avoid parallel make, because otherwise some timeout based tests like - # rm/ext3-perf may fail due to high CPU or IO load. - make check-very-expensive \ - && install -d -m 755 %{buildroot}%{_docdir}/%{name} \ - && xz -c tests/test-suite.log \ - > %{buildroot}%{_docdir}/%{name}/test-suite.log.xz +./configure CFLAGS="-DUSE_PAM $RPM_OPT_FLAGS -Wall" \ + DEFAULT_POSIX2_VERSION=199209 \ + --prefix=%{_prefix} --mandir=%{_mandir} \ + --infodir=%{_infodir} --without-included-regex +make %{?jobs:-j%jobs} PAMLIBS="-lpam -ldl" +if test $EUID -eq 0; then + su nobody -c make check + make check-root VERBOSE=yes +else +%ifarch %arm + make -k check VERBOSE=yes || echo make check failed %else - # Run the shorter check otherwise. - make check + make check VERBOSE=yes %endif +fi -# ================================================ %install -%if "%{name}" == "coreutils" || "%{name}" == "coreutils-single" -make install DESTDIR="%buildroot" pkglibexecdir=%{_libdir}/%{name} - -#UsrMerge -%if !0%{?usrmerged} -install -d %{buildroot}/bin -for i in arch basename cat chgrp chmod chown cp date dd df echo \ - false ln ls mkdir mknod mktemp mv pwd rm rmdir sleep sort stat \ - stty sync touch true uname readlink md5sum +make DESTDIR="$RPM_BUILD_ROOT" install +test -f $RPM_BUILD_ROOT%{_bindir}/su || \ + install src/su $RPM_BUILD_ROOT%{_bindir}/su +install -d $RPM_BUILD_ROOT/bin +for i in basename cat chgrp chmod chown cp date dd df echo false kill ln ls mkdir mknod mv pwd rm rmdir sleep sort stty su sync touch true uname do - ln -sf %{_bindir}/$i %{buildroot}/bin/$i -done -%endif -#EndUsrMerge -echo '.so man1/test.1' > %{buildroot}/%{_mandir}/man1/\[.1 -%if "%{name}" == "coreutils" -%find_lang coreutils -# add LC_TIME directories to lang package -awk '/LC_TIME/ {a=$2; gsub(/\/[^\/]+\.mo/,"", a); print "%%dir", a} {print}' < coreutils.lang > tmp -mv tmp coreutils.lang -%else -rm -rf %{buildroot}%{_mandir} -rm -rf %{buildroot}%{_infodir} -rm -rf %{buildroot}%{_datadir}/locale -> coreutils.lang -%endif -%endif + mv $RPM_BUILD_ROOT%{_bindir}/$i $RPM_BUILD_ROOT/bin/$i + test $i = su && echo -n '%%attr(4755,root,root) ' + echo /bin/$i +done > bin.files +ln -sf ../../bin/basename ../../bin/sort ../../bin/touch $RPM_BUILD_ROOT%{_bindir} +install -d -m 755 $RPM_BUILD_ROOT/etc/pam.d +install -m 644 $RPM_SOURCE_DIR/su.pamd $RPM_BUILD_ROOT/etc/pam.d/su +install -d -m 755 $RPM_BUILD_ROOT/etc/default +install -m 644 $RPM_SOURCE_DIR/su.default $RPM_BUILD_ROOT/etc/default/su +ln -sf /bin/su $RPM_BUILD_ROOT%{_bindir}/sux +rm -f $RPM_BUILD_ROOT%{_bindir}/hostid +rm -f $RPM_BUILD_ROOT%{_bindir}/hostname +rm -f $RPM_BUILD_ROOT%{_mandir}/man1/hostid.1 +rm -f $RPM_BUILD_ROOT%{_mandir}/man1/hostname.1 +%find_lang %name +cat bin.files %name.lang > extra-files -# ================================================ %post -%if "%{name}" == "coreutils" || "%{name}" == "coreutils-single" -%{?regenerate_initrd_post} -%endif +%install_info --info-dir=%{_infodir} %{_infodir}/coreutils.info.gz -# ================================================ -%posttrans -%if "%{name}" == "coreutils" || "%{name}" == "coreutils-single" -%{?regenerate_initrd_posttrans} -%endif +%postun +%install_info_delete --info-dir=%{_infodir} %{_infodir}/coreutils.info.gz -# ================================================ -%files -%if "%{name}" == "coreutils" || "%{name}" == "coreutils-single" +%clean +rm -rf $RPM_BUILD_ROOT +%files -f extra-files %defattr(-,root,root) -%license COPYING -%doc NEWS README THANKS +%doc README NEWS +%config /etc/pam.d/su +%config(noreplace) /etc/default/su %{_bindir}/* -#UsrMerge -%if !0%{?usrmerged} -/bin/* -%endif -#EndUsrMerge -%{_libdir}/%{name} - -%if "%{name}" == "coreutils" -%files lang -f coreutils.lang -%defattr(-,root,root) - -%files doc %doc %{_infodir}/coreutils.info*.gz %doc %{_mandir}/man1/*.1.gz -%endif +%dir %{_prefix}/share/locale/*/LC_TIME -%else - -# test-suite -%dir %{_docdir}/%{name} -%doc %{_docdir}/%{name}/test-suite.log.xz - -%endif - -# ================================================ - -%changelog +%changelog -n coreutils +* Wed Dec 13 2006 - schwab@suse.de +- Fix acl tests. +* Sat Dec 09 2006 - schwab@suse.de +- Update to coreutils 6.7. + ** Bug fixes + When cp -p copied a file with special mode bits set, the same bits + were set on the copy even when ownership could not be preserved. + This could result in files that were setuid to the wrong user. + To fix this, special mode bits are now set in the copy only if its + ownership is successfully preserved. Similar problems were fixed + with mv when copying across file system boundaries. This problem + affects all versions of coreutils through 6.6. + cp --preserve=ownership would create output files that temporarily + had too-generous permissions in some cases. For example, when + copying a file with group A and mode 644 into a group-B sticky + directory, the output file was briefly readable by group B. + Fix similar problems with cp options like -p that imply + --preserve=ownership, with install -d when combined with either -o + or -g, and with mv when copying across file system boundaries. + This bug affects coreutils 6.0 through 6.6. + du --one-file-system (-x) would skip subdirectories of any directory + listed as second or subsequent command line argument. This bug affects + coreutils-6.4, 6.5 and 6.6. +* Wed Nov 22 2006 - schwab@suse.de +- Update to coreutils 6.6. + ** Bug fixes + ls would segfault (dereference a NULL pointer) for a file with a + nameless group or owner. This bug was introduced in coreutils-6.5. + A bug in the latest official m4/gettext.m4 (from gettext-0.15) + made configure fail to detect gettext support, due to the unusual + way in which coreutils uses AM_GNU_GETTEXT. + ** Improved robustness + Now, du (and the other fts clients: chmod, chgrp, chown) honor a + trailing slash in the name of a symlink-to-directory even on + Solaris 9, by working around its buggy fstatat implementation. +* Mon Nov 20 2006 - schwab@suse.de +- Update to coreutils 6.5. + ** Bug fixes + du (and the other fts clients: chmod, chgrp, chown) would exit early + when encountering an inaccessible directory on a system with native + openat support (i.e., linux-2.6.16 or newer along with glibc-2.4 + or newer). This bug was introduced with the switch to gnulib's + openat-based variant of fts, for coreutils-6.0. + "ln --backup f f" now produces a sensible diagnostic + ** New features + rm accepts a new option: --one-file-system +* Mon Oct 23 2006 - schwab@suse.de +- Update to coreutils 6.4. + ** Bug fixes + chgrp and chown would malfunction when invoked with both -R and -H and + with one or more of the following: --preserve-root, --verbose, --changes, + --from=o:g (chown only). This bug was introduced with the switch to + gnulib's openat-based variant of fts, for coreutils-6.0. + cp --backup dir1 dir2, would rename an existing dir2/dir1 to dir2/dir1~. + This bug was introduced in coreutils-6.0. + With --force (-f), rm no longer fails for ENOTDIR. + For example, "rm -f existing-non-directory/anything" now exits + successfully, ignoring the error about a nonexistent file. +* Mon Oct 09 2006 - schwab@suse.de +- Update to coreutils 6.3. + ** Improved robustness + pinky no longer segfaults on Darwin 7.9.0 (MacOS X 10.3.9) due to a + buggy native getaddrinfo function. + rm works around a bug in Darwin 7.9.0 (MacOS X 10.3.9) that would + sometimes keep it from removing all entries in a directory on an HFS+ + or NFS-mounted partition. + sort would fail to handle very large input (around 40GB) on systems with a + mkstemp function that returns a file descriptor limited to 32-bit offsets. + ** Bug fixes + chmod would fail unnecessarily in an unusual case: when an initially- + inaccessible argument is rendered accessible by chmod's action on a + preceding command line argument. This bug also affects chgrp, but + it is harder to demonstrate. It does not affect chown. The bug was + introduced with the switch from explicit recursion to the use of fts + in coreutils-5.1.0 (2003-10-15). + cp -i and mv -i occasionally neglected to prompt when the copy or move + action was bound to fail. This bug dates back to before fileutils-4.0. + With --verbose (-v), cp and mv would sometimes generate no output, + or neglect to report file removal. + For the "groups" command: + "groups" no longer prefixes the output with "user :" unless more + than one user is specified; this is for compatibility with BSD. + "groups user" now exits nonzero when it gets a write error. + "groups" now processes options like --help more compatibly. + shuf would infloop, given 8KB or more of piped input + ** Portability + Versions of chmod, chown, chgrp, du, and rm (tools that use openat etc.) + compiled for Solaris 8 now also work when run on Solaris 10. +* Thu Oct 05 2006 - agruen@suse.de +- cp: Replace the old --attributes=regex option with + --preserve=xattrs. Only copy extended attributes if this + option is given. Use libattr's new copy_attr_action() function + to check which attributes to copy in /etc/xattr.conf. +* Tue Sep 19 2006 - schwab@suse.de +- Disable broken autopoint. +* Mon Sep 18 2006 - schwab@suse.de +- Update to coreutils 6.2. + ** Changes in behavior + mkdir -p and install -d (or -D) now use a method that forks a child + process if the working directory is unreadable and a later argument + uses a relative file name. This avoids some race conditions, but it + means you may need to kill two processes to stop these programs. + rm now rejects attempts to remove the root directory, e.g., `rm -fr /' + now fails without removing anything. Likewise for any file name with + a final `./' or `../' component. + tail now ignores the -f option if POSIXLY_CORRECT is set, no file + operand is given, and standard input is any FIFO; formerly it did + this only for pipes. + ** Infrastructure changes + Coreutils now uses gnulib via the gnulib-tool script. + If you check the source out from CVS, then follow the instructions + in README-cvs. Although this represents a large change to the + infrastructure, it should cause no change in how the tools work. + ** Bug fixes + cp --backup no longer fails when the last component of a source file + name is "." or "..". + "ls --color" would highlight other-writable and sticky directories + no differently than regular directories on a file system with + dirent.d_type support. + "mv -T --verbose --backup=t A B" now prints the " (backup: B.~1~)" + suffix when A and B are directories as well as when they are not. + mv and "cp -r" no longer fail when invoked with two arguments + where the first one names a directory and the second name ends in + a slash and doesn't exist. E.g., "mv dir B/", for nonexistent B, + now succeeds, once more. This bug was introduced in coreutils-5.3.0. +* Fri Sep 01 2006 - schwab@suse.de +- Fix sbin patch [#202632]. +* Mon Aug 21 2006 - schwab@suse.de +- Update to coreutils 6.1. + ** Changes in behavior + df now considers BSD "kernfs" file systems to be dummies + ** Bug fixes + cp --sparse preserves sparseness at the end of a file, even when + the file's apparent size is not a multiple of its block size. + [introduced with the original design, in fileutils-4.0r, 2000-04-29] + df (with a command line argument) once again prints its header + [introduced in coreutils-6.0] + ls -CF would misalign columns in some cases involving non-stat'able files + [introduced in coreutils-6.0] +* Tue Aug 15 2006 - schwab@suse.de +- Update to coreutils 6.0. + ** Improved robustness + df: if the file system claims to have more available than total blocks, + report the number of used blocks as being "total - available" + (a negative number) rather than as garbage. + dircolors: a new autoconf run-test for AIX's buggy strndup function + prevents malfunction on that system; may also affect cut, expand, + and unexpand. + fts no longer changes the current working directory, so its clients + (chmod, chown, chgrp, du) no longer malfunction under extreme conditions. + pwd and other programs using lib/getcwd.c work even on file systems + where dirent.d_ino values are inconsistent with those from stat.st_ino. + rm's core is now reentrant: rm --recursive (-r) now processes + hierarchies without changing the working directory at all. + ** Changes in behavior + basename and dirname now treat // as different from / on platforms + where the two are distinct. + chmod, install, and mkdir now preserve a directory's set-user-ID and + set-group-ID bits unless you explicitly request otherwise. E.g., + `chmod 755 DIR' and `chmod u=rwx,go=rx DIR' now preserve DIR's + set-user-ID and set-group-ID bits instead of clearing them, and + similarly for `mkdir -m 755 DIR' and `mkdir -m u=rwx,go=rx DIR'. To + clear the bits, mention them explicitly in a symbolic mode, e.g., + `mkdir -m u=rwx,go=rx,-s DIR'. To set them, mention them explicitly + in either a symbolic or a numeric mode, e.g., `mkdir -m 2755 DIR', + `mkdir -m u=rwx,go=rx,g+s' DIR. This change is for convenience on + systems where these bits inherit from parents. Unfortunately other + operating systems are not consistent here, and portable scripts + cannot assume the bits are set, cleared, or preserved, even when the + bits are explicitly mentioned. For example, OpenBSD 3.9 `mkdir -m + 777 D' preserves D's setgid bit but `chmod 777 D' clears it. + Conversely, Solaris 10 `mkdir -m 777 D', `mkdir -m g-s D', and + `chmod 0777 D' all preserve D's setgid bit, and you must use + something like `chmod g-s D' to clear it. + `cp --link --no-dereference' now works also on systems where the + link system call cannot create a hard link to a symbolic link. + This change has no effect on systems with a Linux-based kernel. + csplit and nl now use POSIX syntax for regular expressions, not + Emacs syntax. As a result, character classes like [[:print:]] and + interval expressions like A\{1,9\} now have their usual meaning, + . no longer matches the null character, and \ must precede the + and + ? operators. + date: a command like date -d '2006-04-23 21 days ago' would print + the wrong date in some time zones. (see the test for an example) + df now considers "none" and "proc" file systems to be dummies and + therefore does not normally display them. Also, inaccessible file + systems (which can be caused by shadowed mount points or by chrooted + bind mounts) are now dummies, too. + expr no longer complains about leading ^ in a regular expression + (the anchor is ignored), or about regular expressions like A** (the + second "*" is ignored). expr now exits with status 2 (not 3) for + errors it detects in the expression's values; exit status 3 is now + used only for internal errors (such as integer overflow, which expr + now checks for). + install and mkdir now implement the X permission symbol correctly, + e.g., `mkdir -m a+X dir'; previously the X was ignored. + install now creates parent directories with mode u=rwx,go=rx (755) + instead of using the mode specified by the -m option; and it does + not change the owner or group of parent directories. This is for + compatibility with BSD and closes some race conditions. + ln now uses different (and we hope clearer) diagnostics when it fails. + ln -v now acts more like FreeBSD, so it generates output only when + successful and the output is easier to parse. + ls now defaults to --time-style='locale', not --time-style='posix-long-iso'. + However, the 'locale' time style now behaves like 'posix-long-iso' + if your locale settings appear to be messed up. This change + attempts to have the default be the best of both worlds. + mkfifo and mknod no longer set special mode bits (setuid, setgid, + and sticky) with the -m option. + nohup's usual diagnostic now more precisely specifies the I/O + redirections, e.g., "ignoring input and appending output to + nohup.out". Also, nohup now redirects stderr to nohup.out (or + $HOME/nohup.out) if stdout is closed and stderr is a tty; this is in + response to Open Group XCU ERN 71. + rm --interactive now takes an optional argument, although the + default of using no argument still acts like -i. + rm no longer fails to remove an empty, unreadable directory + seq changes: + seq defaults to a minimal fixed point format that does not lose + information if seq's operands are all fixed point decimal numbers. + You no longer need the `-f%%.f' in `seq -f%%.f 1048575 1024 1050623', + for example, since the default format now has the same effect. + seq now lets you use %%a, %%A, %%E, %%F, and %%G formats. + seq now uses long double internally rather than double. + sort now reports incompatible options (e.g., -i and -n) rather than + silently ignoring one of them. + stat's --format=FMT option now works the way it did before 5.3.0: + FMT is automatically newline terminated. The first stable release + containing this change was 5.92. + stat accepts the new option --printf=FMT, where FMT is *not* + automatically newline terminated. + stat: backslash escapes are interpreted in a format string specified + via --printf=FMT, but not one specified via --format=FMT. That includes + octal (\ooo, at most three octal digits), hexadecimal (\xhh, one or + two hex digits), and the standard sequences (\a, \b, \f, \n, \r, \t, + \v, \", \\). + With no operand, 'tail -f' now silently ignores the '-f' only if + standard input is a FIFO or pipe and POSIXLY_CORRECT is set. + Formerly, it ignored the '-f' when standard input was a FIFO, pipe, + or socket. + ** Scheduled for removal + ptx's --copyright (-C) option is scheduled for removal in 2007, and + now evokes a warning. Use --version instead. + rm's --directory (-d) option is scheduled for removal in 2006. This + option has been silently ignored since coreutils 5.0. On systems + that support unlinking of directories, you can use the "unlink" + command to unlink a directory. + Similarly, we are considering the removal of ln's --directory (-d, + -F) option in 2006. Please write to if this + would cause a problem for you. On systems that support hard links + to directories, you can use the "link" command to create one. + ** New programs + base64: base64 encoding and decoding (RFC 3548) functionality. + sha224sum: print or check a SHA224 (224-bit) checksum + sha256sum: print or check a SHA256 (256-bit) checksum + sha384sum: print or check a SHA384 (384-bit) checksum + sha512sum: print or check a SHA512 (512-bit) checksum + shuf: Shuffle lines of text. + ** New features + chgrp now supports --preserve-root, --no-preserve-root (default), + as it was documented to do, and just as chmod, chown, and rm do. + New dd iflag= and oflag= flags: + 'directory' causes dd to fail unless the file is a directory, on + hosts that support this (e.g., Linux kernels, version 2.1.126 and + later). This has limited utility but is present for completeness. + 'noatime' causes dd to read a file without updating its access + time, on hosts that support this (e.g., Linux kernels, version + 2.6.8 and later). + 'nolinks' causes dd to fail if the file has multiple hard links, + on hosts that support this (e.g., Solaris 10 and later). + ls accepts the new option --group-directories-first, to make it + list directories before files. + rm now accepts the -I (--interactive=once) option. This new option + prompts once if rm is invoked recursively or if more than three + files are being deleted, which is less intrusive than -i prompting + for every file, but provides almost the same level of protection + against mistakes. + shred and sort now accept the --random-source option. + sort now accepts the --random-sort (-R) option and `R' ordering option. + sort now supports obsolete usages like "sort +1 -2" unless + POSIXLY_CORRECT is set. However, when conforming to POSIX + 1003.1-2001 "sort +1" still sorts the file named "+1". + wc accepts a new option --files0-from=FILE, where FILE contains a + list of NUL-terminated file names. + ** Bug fixes + cat with any of the options, -A -v -e -E -T, when applied to a + file in /proc or /sys (linux-specific), would truncate its output, + usually printing nothing. + cp -p would fail in a /proc-less chroot, on some systems + When `cp -RL' encounters the same directory more than once in the + hierarchy beneath a single command-line argument, it no longer confuses + them with hard-linked directories. + fts-using tools (chmod, chown, chgrp, du) no longer fail due to + a double-free bug -- it could be triggered by making a directory + inaccessible while e.g., du is traversing the hierarchy under it. + fts-using tools (chmod, chown, chgrp, du) no longer misinterpret + a very long symlink chain as a dangling symlink. Before, such a + misinterpretation would cause these tools not to diagnose an ELOOP error. + ls --indicator-style=file-type would sometimes stat a symlink + unnecessarily. + ls --file-type worked like --indicator-style=slash (-p), + rather than like --indicator-style=file-type. + mv: moving a symlink into the place of an existing non-directory is + now done atomically; before, mv would first unlink the destination. + mv -T DIR EMPTY_DIR no longer fails unconditionally. Also, mv can + now remove an empty destination directory: mkdir -p a b/a; mv a b + rm (on systems with openat) can no longer exit before processing + all command-line arguments. + rm is no longer susceptible to a few low-probability memory leaks. + rm -r no longer fails to remove an inaccessible and empty directory + rm -r's cycle detection code can no longer be tricked into reporting + a false positive (introduced in fileutils-4.1.9). + shred --remove FILE no longer segfaults on Gentoo systems + sort would fail for large inputs (~50MB) on systems with a buggy + mkstemp function. sort and tac now use the replacement mkstemp + function, and hence are no longer subject to limitations (of 26 or 32, + on the maximum number of files from a given template) on HP-UX 10.20, + SunOS 4.1.4, Solaris 2.5.1 and OSF1/Tru64 V4.0F&V5.1. + tail -f once again works on a file with the append-only + attribute (affects at least Linux ext2, ext3, xfs file systems) +* Tue Aug 08 2006 - schwab@suse.de +- Move sux to %%{_bindir}. +* Mon Jun 26 2006 - schwab@suse.de +- Update to coreutils 5.97. + ** Bug fixes + rebuild with better autoconf test for when the lstat replacement + function is needed -- required for Solaris 9 + cat with any of the options, -A -v -e -E -T, when applied to a + file in /proc or /sys (linux-specific), would truncate its output, + usually printing nothing. + ** Improved robustness + dircolors: a new autoconf run-test for AIX's buggy strndup function + prevents malfunction on that system; may also affect cut, expand, + and unexpand. + ** New features + chgrp now supports --preserve-root, --no-preserve-root (default), + as it was documented to do, and just as chmod, chown, and rm do. +* Thu Jun 22 2006 - schwab@suse.de +- Fix conflict with . +* Mon May 22 2006 - schwab@suse.de +- Update to coreutils 5.96. +* Sat May 13 2006 - schwab@suse.de +- Update to coreutils 5.95. +* Fri Apr 07 2006 - cthiel@suse.de +- added Obsoletes: libselinux (hack for bug #156519) +* Mon Feb 13 2006 - schwab@suse.de +- Fix spurious failure with cp -LR. +- Move check for /proc. +* Mon Jan 30 2006 - schwab@suse.de +- Always print newline after format in stat [#145905]. +- Barf if /proc is not mounted. +* Wed Jan 25 2006 - mls@suse.de +- converted neededforbuild to BuildRequires +* Thu Jan 19 2006 - meissner@suse.de +- Do not strip /bin/su. +* Wed Jan 11 2006 - schwab@suse.de +- Fix infloop when ignoring characters [#141756]. +* Mon Dec 19 2005 - kukuk@suse.de +- Add fallback if futimesat does not work +* Mon Dec 05 2005 - ke@suse.de +- Fix typo in German translation file; reported by Olaf Hering + [#105863]. +* Mon Dec 05 2005 - schwab@suse.de +- Drop SELinux support. +* Tue Nov 15 2005 - uli@suse.de +- some tests fail on ARM (QEMU problem?); ignore for now +* Sun Nov 06 2005 - schwab@suse.de +- Update to coreutils 5.93. +* Wed Nov 02 2005 - schwab@suse.de +- Update to coreutils 5.92. +- Fix invalid use of va_list. +- Add some fixes from cvs. +* Thu Oct 20 2005 - schwab@suse.de +- Reenable DEFAULT_POSIX2_VERSION. +* Wed Oct 19 2005 - agruen@suse.de +- Add acl and xattr patches. +* Mon Oct 17 2005 - schwab@suse.de +- Update to coreutils 5.91. +* Sat Oct 01 2005 - schwab@suse.de +- Update to coreutils 5.90. +- Disable acl patches for now. +* Sun Sep 25 2005 - schwab@suse.de +- Fix warning. +* Wed Aug 24 2005 - werner@suse.de +- Let `su' handle /sbin and /usr/sbin in path +* Mon Aug 01 2005 - kukuk@suse.de +- And yet another uninitialized variable fix. +* Fri Jul 29 2005 - schwab@suse.de +- Fix another uninitialized variable. +* Wed Jul 06 2005 - schwab@suse.de +- Fix uninitialized variable. +* Mon Jul 04 2005 - schwab@suse.de +- Update i18n patch. +* Mon Jun 20 2005 - schwab@suse.de +- Fix last change. +* Wed Jun 15 2005 - kukuk@suse.de +- Compile/link su with -fpie/-pie +* Sat May 21 2005 - kukuk@suse.de +- Add support for /etc/default/su +* Mon May 02 2005 - kukuk@suse.de +- Don't overwrite PATH if su is called with "-" option. +* Wed Mar 02 2005 - schwab@suse.de +- Fix merge error [#67103]. +* Mon Feb 28 2005 - schwab@suse.de +- Call pam_getenvlist before pam_end. +* Mon Feb 28 2005 - schwab@suse.de +- Link su to sux [#66830]. +* Wed Feb 02 2005 - schwab@suse.de +- Handle xfs and jfs in stat [#50415]. +* Wed Feb 02 2005 - schwab@suse.de +- Handle subfs like autofs. +* Tue Jan 25 2005 - schwab@suse.de +- Fix path_concat. +* Thu Jan 20 2005 - schwab@suse.de +- Use pam_xauth [#42238]. +* Fri Jan 14 2005 - schwab@suse.de +- Fix merge error [#49853]. +* Tue Jan 11 2005 - schwab@suse.de +- Update to coreutils 5.3.0. +* Mon Nov 08 2004 - kukuk@suse.de +- Use common-* PAM config files for su PAM configuration +* Mon Oct 25 2004 - schwab@suse.de +- Fix last change. +- Fix selinux patch. +* Wed Oct 20 2004 - ro@suse.de +- remove no language support (nb is already there) +* Sat Oct 02 2004 - agruen@suse.de +- #46609: Fix chown and chgrp utilities for uid == (uid_t) -1 and + gid == (gid_t) -1 case. +- Add missing #include to have NULL defined in lib/acl.c +* Fri Sep 10 2004 - schwab@suse.de +- Fix uninitialized variable [#44929]. +- Fix selinux patch. +* Wed Aug 25 2004 - schwab@suse.de +- Fix hardlink accounting patch. +* Mon May 24 2004 - schwab@suse.de +- Update testsuite for change in chown. +* Mon May 24 2004 - schwab@suse.de +- Precompute length in caller of ismbblank to avoid quadratic behaviour + [#40741]. +* Mon May 17 2004 - schwab@suse.de +- Fix handling of symlinks in chown [#40691]. +* Sat Apr 17 2004 - schwab@suse.de +- Pacify autobuild. +* Fri Apr 02 2004 - schwab@suse.de +- Add support for IUTF8 in stty. +* Tue Mar 30 2004 - schwab@suse.de +- Fix merge error in selinux patch [#37431]. +* Mon Mar 29 2004 - schwab@suse.de +- Fix hardlink accounting in du. +* Mon Mar 22 2004 - schwab@suse.de +- Fix race in the testsuite. +* Mon Mar 15 2004 - kukuk@suse.de +- Update SELinux patch to new libselinux interface +* Mon Mar 15 2004 - schwab@suse.de +- Fix date parsing. +* Sat Mar 13 2004 - schwab@suse.de +- Update to coreutils 5.2.1. + * Includes mv fix. + * Fix sparse handling in cp. + * Fix descriptor leak in nohup. + * Fix POSIX issues in expr. + * Always allow user.group in chown. +* Fri Mar 12 2004 - schwab@suse.de +- Fix sysinfo patch [#35337]. +* Fri Mar 12 2004 - schwab@suse.de +- Fix preserving links in mv. +* Wed Mar 03 2004 - schwab@suse.de +- Fix help output from mkdir. +* Fri Feb 20 2004 - schwab@suse.de +- Update to coreutils 5.2.0. +* Mon Feb 09 2004 - schwab@suse.de +- Update to coreutils 5.1.3. +* Mon Feb 02 2004 - agruen@suse.de +- Update acl and xattr patches, and add some Changelog text. +* Mon Jan 26 2004 - schwab@suse.de +- Update to coreutils 5.1.2. +* Fri Jan 23 2004 - schwab@suse.de +- Don't link [ to test. +* Mon Jan 19 2004 - schwab@suse.de +- Update to coreutils 5.1.1. +- Default to POSIX.2-1992. +* Fri Jan 16 2004 - kukuk@suse.de +- Add pam-devel to neededforbuild +* Fri Jan 09 2004 - schwab@suse.de +- Fix spurious test failure. +* Thu Jan 08 2004 - schwab@suse.de +- Update to coreutils 5.1.0. +* Fri Dec 12 2003 - schwab@suse.de +- Fix use of AC_SEARCH_LIBS. +* Tue Dec 09 2003 - schwab@suse.de +- Cleanup SELinux patch. +* Tue Dec 09 2003 - kukuk@suse.de +- Add SELinux patch. +* Wed Nov 26 2003 - schwab@suse.de +- Fix sorting of months in multibyte case [#33299]. +* Wed Oct 22 2003 - schwab@suse.de +- Fix building without extended attributes. +* Wed Oct 15 2003 - schwab@suse.de +- Cleanup sysinfo patch. +* Fri Sep 19 2003 - kukuk@suse.de +- Add missing textutil to Provides +* Mon Aug 25 2003 - agruen@suse.de +- Fix uname command to report reasonable processor and platform + information (coreutils-sysinfo.diff: based on similar RedHat + patch). +* Mon Jul 21 2003 - schwab@suse.de +- Fix typo in i18n patch for join. +* Fri Jul 18 2003 - schwab@suse.de +- Avoid abort in sort on inconsistent locales [#26506]. +* Tue Jul 15 2003 - okir@suse.de +- make su export variables declared via pam_putenv +* Wed May 28 2003 - kukuk@suse.de +- PAM fixes for su: + - Move pam_open_session call before dropping privilegs, session + management needs max. possible credentials and needs to be done + before we change into the home directory of the user. + - Don't set PAM_TTY and PAM_RUSER to fake names. + - Use conversion function from libpam_misc. +* Fri May 16 2003 - schwab@suse.de +- Fix exit status from su. +* Thu Apr 24 2003 - ro@suse.de +- fix head calling syntax +* Mon Apr 07 2003 - schwab@suse.de +- Only delete info entries when removing last version. +* Fri Apr 04 2003 - schwab@suse.de +- Update to coreutils 5.0. +* Mon Mar 31 2003 - schwab@suse.de +- Update to coreutils 4.5.12. +* Thu Mar 20 2003 - schwab@suse.de +- Update to coreutils 4.5.11. +* Mon Mar 10 2003 - schwab@suse.de +- Fix LFS bug in du [#24960]. +* Thu Feb 27 2003 - schwab@suse.de +- Readd textutils i18n patches. +* Thu Feb 27 2003 - agruen@suse.de +- Per hint from Andreas Schwab, don't use awk in autoconf. (The + improved test is simpler, too.) +* Thu Feb 27 2003 - agruen@suse.de +- Fix autoconf test for attr_copy_file that caused all binaries + to be linked needlessly against libattr.so. +* Tue Feb 25 2003 - agruen@suse.de +- Extended attribute copying: Use the newly exported + attr_copy_check_permissions() callback exported by libattr.so, + so that the EA copying done by coreutils is consistent with + other apps [#24244]. +* Mon Feb 24 2003 - schwab@suse.de +- Update to coreutils 4.5.8. + * Fixes bugs in du. +* Mon Feb 17 2003 - agruen@suse.de +- Add extended attribute copying patch: Affects cp, mv, install. + See the cp manual page for details on the changes in cp. The + mv utility always tries to copy extended attributes; install + never does. +* Mon Feb 10 2003 - schwab@suse.de +- Update to coreutils 4.5.7. +* Fri Feb 07 2003 - kukuk@suse.de +- Use pam_unix2.so instead of pam_unix.so, use same rules for + password changing as passwd. +* Thu Feb 06 2003 - schwab@suse.de +- Use %%install_info. +* Thu Feb 06 2003 - schwab@suse.de +- Update to coreutils 4.5.6. +* Mon Feb 03 2003 - schwab@suse.de +- Package created, combining textutils, sh-utils and fileutils. diff --git a/getcwd.diff b/getcwd.diff new file mode 100644 index 0000000..950f14e --- /dev/null +++ b/getcwd.diff @@ -0,0 +1,11 @@ +--- lib/getcwd.c ++++ lib/getcwd.c +@@ -137,7 +137,7 @@ + size_t allocated = size; + size_t used; + +-#if HAVE_PARTLY_WORKING_GETCWD && !defined AT_FDCWD ++#if HAVE_PARTLY_WORKING_GETCWD + /* The system getcwd works, except it sometimes fails when it + shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT. If + AT_FDCWD is not defined, the algorithm below is O(N**2) and this diff --git a/gnulib-test-avoid-FP-perror-strerror.patch b/gnulib-test-avoid-FP-perror-strerror.patch deleted file mode 100644 index 482a45d..0000000 --- a/gnulib-test-avoid-FP-perror-strerror.patch +++ /dev/null @@ -1,101 +0,0 @@ -Avoid false-positive error in gnulib tests 'test-perror2' and 'test-strerror_r'. - -On openSUSE OBS, the above gnulib tests fail on armv7l. - -Corresponding report on the gnulib mailing list: - - https://lists.gnu.org/r/bug-gnulib/2020-08/msg00220.html - - From: Florian Weimer - Date: Thu, 27 Aug 2020 09:41:34 +0200 - Subject: Use-after-free in test-perror2, test-strerror_r - - The problem is visible with glibc 2.32 under valgrind: - - ==20== Invalid read of size 1 - ==20== at 0x483DAB4: strcmp (vg_replace_strmem.c:847) - ==20== by 0x109414: main (test-perror2.c:84) - ==20== Address 0x4a1a3d0 is 0 bytes inside a block of size 17 free'd - ==20== at 0x483A9F5: free (vg_replace_malloc.c:538) - ==20== by 0x48E2134: strerror_l (in /usr/lib64/libc-2.32.so) - ==20== by 0x109328: main (test-perror2.c:72) - ==20== Block was alloc'd at - ==20== at 0x4839809: malloc (vg_replace_malloc.c:307) - ==20== by 0x48CA03F: __vasprintf_internal (in /usr/lib64/libc-2.32.so) - ==20== by 0x48A46F9: asprintf (in /usr/lib64/libc-2.32.so) - ==20== by 0x48E2184: strerror_l (in /usr/lib64/libc-2.32.so) - ==20== by 0x1092E2: main (test-perror2.c:67) - ==20== - ==20== Invalid read of size 1 - ==20== at 0x483DAC8: strcmp (vg_replace_strmem.c:847) - ==20== by 0x109414: main (test-perror2.c:84) - ==20== Address 0x4a1a3d1 is 1 bytes inside a block of size 17 free'd - ==20== at 0x483A9F5: free (vg_replace_malloc.c:538) - ==20== by 0x48E2134: strerror_l (in /usr/lib64/libc-2.32.so) - ==20== by 0x109328: main (test-perror2.c:72) - ==20== Block was alloc'd at - ==20== at 0x4839809: malloc (vg_replace_malloc.c:307) - ==20== by 0x48CA03F: __vasprintf_internal (in /usr/lib64/libc-2.32.so) - ==20== by 0x48A46F9: asprintf (in /usr/lib64/libc-2.32.so) - ==20== by 0x48E2184: strerror_l (in /usr/lib64/libc-2.32.so) - ==20== by 0x1092E2: main (test-perror2.c:67) - - I think it's the test that's invalid. - - This was reported as an actual grep test failure (without valgrind) on - 32-bit Arm, where glibc malloc happens to return a different buffer - address for the internal allocation (so that msg3 != msg4). - - test-strerror_r has the same issue. - - Thanks, - Florian - -Upstream patch: - - https://git.sv.gnu.org/cgit/gnulib.git/commit/?id=175e0bc72808 - - From 175e0bc72808d564074c4adcc72aeadb74adfcc6 Mon Sep 17 00:00:00 2001 - From: Paul Eggert - Date: Thu, 27 Aug 2020 17:52:58 -0700 - Subject: [PATCH] perror, strerror_r: remove unportable tests - - Problem reported by Florian Weimer in: - https://lists.gnu.org/r/bug-gnulib/2020-08/msg00220.html - * tests/test-perror2.c (main): - * tests/test-strerror_r.c (main): Omit unportable tests. - -This downstream patch is identical to upstream one modulo the ChangeLog entry. ---- - gnulib-tests/test-perror2.c | 3 --- - gnulib-tests/test-strerror_r.c | 3 --- - 2 files changed, 6 deletions(-) - -Index: gnulib-tests/test-perror2.c -=================================================================== ---- gnulib-tests/test-perror2.c.orig -+++ gnulib-tests/test-perror2.c -@@ -79,9 +79,6 @@ main (void) - errno = -5; - perror (""); - ASSERT (!ferror (stderr)); -- ASSERT (msg1 == msg2 || msg1 == msg4 || STREQ (msg1, str1)); -- ASSERT (msg2 == msg4 || STREQ (msg2, str2)); -- ASSERT (msg3 == msg4 || STREQ (msg3, str3)); - ASSERT (STREQ (msg4, str4)); - - free (str1); -Index: gnulib-tests/test-strerror_r.c -=================================================================== ---- gnulib-tests/test-strerror_r.c.orig -+++ gnulib-tests/test-strerror_r.c -@@ -165,9 +165,6 @@ main (void) - - strerror_r (EACCES, buf, sizeof buf); - strerror_r (-5, buf, sizeof buf); -- ASSERT (msg1 == msg2 || msg1 == msg4 || STREQ (msg1, str1)); -- ASSERT (msg2 == msg4 || STREQ (msg2, str2)); -- ASSERT (msg3 == msg4 || STREQ (msg3, str3)); - ASSERT (STREQ (msg4, str4)); - - free (str1); diff --git a/i18n-infloop.diff b/i18n-infloop.diff new file mode 100644 index 0000000..f51a60e --- /dev/null +++ b/i18n-infloop.diff @@ -0,0 +1,12 @@ +--- src/sort.c ++++ src/sort.c +@@ -1838,7 +1838,8 @@ + if (MBLENGTH == (size_t)-2 || MBLENGTH == (size_t)-1) \ + STATE = state_bak; \ + if (!ignore) \ +- COPY[NEW_LEN++] = TEXT[i++]; \ ++ COPY[NEW_LEN++] = TEXT[i]; \ ++ i++; \ + continue; \ + } \ + \ diff --git a/i18n-uninit.diff b/i18n-uninit.diff new file mode 100644 index 0000000..a093822 --- /dev/null +++ b/i18n-uninit.diff @@ -0,0 +1,25 @@ +--- src/cut.c ++++ src/cut.c +@@ -869,7 +869,10 @@ + c = getc (stream); + empty_input = (c == EOF); + if (c != EOF) +- ungetc (c, stream); ++ { ++ ungetc (c, stream); ++ wc = 0; ++ } + else + wc = WEOF; + +--- src/expand.c ++++ src/expand.c +@@ -414,7 +414,7 @@ + for (;;) + { + /* Input character, or EOF. */ +- wint_t wc; ++ wint_t wc = 0; + + /* If true, perform translations. */ + bool convert = true; diff --git a/invalid-ids.diff b/invalid-ids.diff new file mode 100644 index 0000000..66063cf --- /dev/null +++ b/invalid-ids.diff @@ -0,0 +1,47 @@ +While uid_t and gid_t are both unsigned, the values (uid_t) -1 and +(gid_t) -1 are reserved. A uid or gid argument of -1 to the chown(2) +system call means to leave the uid/gid unchanged. Catch this case +so that trying to set a uid or gid to -1 will result in an error. + +Test cases: + + chown 4294967295 file + chown :4294967295 file + chgrp 4294967295 file + +Andreas Gruenbacher + +Index: coreutils-5.2.1/lib/userspec.c +================================================================================ +--- coreutils-5.3.0/lib/userspec.c ++++ coreutils-5.3.0/lib/userspec.c +@@ -184,7 +184,7 @@ + { + unsigned long int tmp; + if (xstrtoul (u, NULL, 10, &tmp, "") == LONGINT_OK +- && tmp <= MAXUID) ++ && tmp <= MAXUID && tmp != (uid_t) -1) + unum = tmp; + else + error_msg = E_invalid_user; +@@ -214,7 +214,8 @@ + if (grp == NULL) + { + unsigned long int tmp; +- if (xstrtoul (g, NULL, 10, &tmp, "") == LONGINT_OK && tmp <= MAXGID) ++ if (xstrtoul (g, NULL, 10, &tmp, "") == LONGINT_OK && tmp <= MAXGID ++ && tmp != (gid_t) -1) + gnum = tmp; + else + error_msg = E_invalid_group; +--- coreutils-5.3.0/src/chgrp.c ++++ coreutils-5.3.0/src/chgrp.c +@@ -91,7 +91,7 @@ + { + unsigned long int tmp; + if (! (xstrtoul (name, NULL, 10, &tmp, "") == LONGINT_OK +- && tmp <= GID_T_MAX)) ++ && tmp <= GID_T_MAX && tmp != (gid_t) -1)) + error (EXIT_FAILURE, 0, _("invalid group %s"), quote (name)); + gid = tmp; + } diff --git a/no-no.diff b/no-no.diff new file mode 100644 index 0000000..67aef34 --- /dev/null +++ b/no-no.diff @@ -0,0 +1,10 @@ +--- po/LINGUAS ++++ po/LINGUAS +@@ -19,7 +19,6 @@ + ms + nb + nl +-no + pl + pt + pt_BR diff --git a/ready b/ready new file mode 100644 index 0000000..473a0f4 diff --git a/su.default b/su.default new file mode 100644 index 0000000..d9758a8 --- /dev/null +++ b/su.default @@ -0,0 +1,11 @@ +# Per default, only "su -" will set a new PATH. +# If this variable is changed to "yes" (default is "no"), +# every su call will overwrite the PATH variable. +ALWAYS_SET_PATH=no + +# Default path. +PATH=/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin + +# Default path for a user invoking su to root. +SUPATH=/usr/sbin:/bin:/usr/bin:/sbin:/usr/X11R6/bin + diff --git a/su.pamd b/su.pamd new file mode 100644 index 0000000..b729046 --- /dev/null +++ b/su.pamd @@ -0,0 +1,7 @@ +#%PAM-1.0 +auth sufficient pam_rootok.so +auth include common-auth +account include common-account +password include common-password +session include common-session +session optional pam_xauth.so