diff --git a/.coreutils.metadata b/.coreutils.metadata deleted file mode 100644 index 48c2731..0000000 --- a/.coreutils.metadata +++ /dev/null @@ -1 +0,0 @@ -bd5d495c162730873a2774acd1c5091fbf0c55a4 SOURCES/coreutils-8.30.tar.xz diff --git a/.gitignore b/.gitignore index 7c41bb0..db318ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/coreutils-8.30.tar.xz +coreutils-9.5.tar.xz diff --git a/SOURCES/coreutils-4.5.3-langinfo.patch b/SOURCES/coreutils-4.5.3-langinfo.patch deleted file mode 100644 index a8af3bd..0000000 --- a/SOURCES/coreutils-4.5.3-langinfo.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/src/date.c b/src/date.c -index ddb011e..619a72b 100644 ---- a/src/date.c -+++ b/src/date.c -@@ -490,14 +490,7 @@ main (int argc, char **argv) - format = DATE_FMT_LANGINFO (); - if (! *format) - { -- /* Do not wrap the following literal format string with _(...). -- For example, suppose LC_ALL is unset, LC_TIME=POSIX, -- and LANG="ko_KR". In that case, POSIX says that LC_TIME -- determines the format and contents of date and time strings -- written by date, which means "date" must generate output -- using the POSIX locale; but adding _() would cause "date" -- to use a Korean translation of the format. */ -- format = "%a %b %e %H:%M:%S %Z %Y"; -+ format = dcgettext(NULL, N_("%a %b %e %H:%M:%S %Z %Y"), LC_TIME); - } - } - diff --git a/SOURCES/coreutils-8.2-uname-processortype.patch b/SOURCES/coreutils-8.2-uname-processortype.patch deleted file mode 100644 index ed01ab8..0000000 --- a/SOURCES/coreutils-8.2-uname-processortype.patch +++ /dev/null @@ -1,49 +0,0 @@ -diff --git a/src/uname.c b/src/uname.c -index 6371ca2..1ad8fd7 100644 ---- a/src/uname.c -+++ b/src/uname.c -@@ -300,13 +300,19 @@ main (int argc, char **argv) - - if (toprint & PRINT_PROCESSOR) - { -- char const *element = unknown; -+ char *element = unknown; - #if HAVE_SYSINFO && defined SI_ARCHITECTURE - { - static char processor[257]; - if (0 <= sysinfo (SI_ARCHITECTURE, processor, sizeof processor)) - element = processor; - } -+#else -+ { -+ static struct utsname u; -+ uname(&u); -+ element = u.machine; -+ } - #endif - #ifdef UNAME_PROCESSOR - if (element == unknown) -@@ -344,7 +350,7 @@ main (int argc, char **argv) - - if (toprint & PRINT_HARDWARE_PLATFORM) - { -- char const *element = unknown; -+ char *element = unknown; - #if HAVE_SYSINFO && defined SI_PLATFORM - { - static char hardware_platform[257]; -@@ -352,6 +358,14 @@ main (int argc, char **argv) - hardware_platform, sizeof hardware_platform)) - element = hardware_platform; - } -+#else -+ { -+ static struct utsname u; -+ uname(&u); -+ element = u.machine; -+ if(strlen(element)==4 && element[0]=='i' && element[2]=='8' && element[3]=='6') -+ element[1]='3'; -+ } - #endif - #ifdef UNAME_HARDWARE_PLATFORM - if (element == unknown) diff --git a/SOURCES/coreutils-8.22-doc-ls-kibibytes.patch b/SOURCES/coreutils-8.22-doc-ls-kibibytes.patch deleted file mode 100644 index 207fa12..0000000 --- a/SOURCES/coreutils-8.22-doc-ls-kibibytes.patch +++ /dev/null @@ -1,32 +0,0 @@ -From c6418e3a5cb3a65af79117162a93a66026cc8c36 Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Thu, 6 Dec 2018 14:28:00 +0100 -Subject: [PATCH] doc: improve wording of the --kibibytes option description - -Bug: https://bugzilla.redhat.com/1527391 ---- - doc/coreutils.texi | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/doc/coreutils.texi b/doc/coreutils.texi -index 88d6506..772aab6 100644 ---- a/doc/coreutils.texi -+++ b/doc/coreutils.texi -@@ -7615,9 +7615,11 @@ Append @samp{*} for executable regular files, otherwise behave as for - @opindex --kibibytes - Set the default block size to its normal value of 1024 bytes, - overriding any contrary specification in environment variables --(@pxref{Block size}). This option is in turn overridden by the --@option{--block-size}, @option{-h} or @option{--human-readable}, and --@option{--si} options. -+(@pxref{Block size}). If @option{--block-size}, @option{-h}, -+@option{--human-readable}, or @option{--si} options are used, -+they take precedence over @option{-k} or @option{--kibibytes} -+even if @option{-k} or @option{--kibibytes} is placed after -+the other options. - - The @option{-k} or @option{--kibibytes} option affects the - per-directory block count written by the @option{-l} and similar --- -2.17.2 - diff --git a/SOURCES/coreutils-8.25-DIR_COLORS.patch b/SOURCES/coreutils-8.25-DIR_COLORS.patch deleted file mode 100644 index 5490258..0000000 --- a/SOURCES/coreutils-8.25-DIR_COLORS.patch +++ /dev/null @@ -1,686 +0,0 @@ -From a13bc34f1eeebdf8b87e4b5a570341bb77a62f76 Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Fri, 17 Jun 2016 16:58:18 +0200 -Subject: [PATCH] downstream changes to default DIR_COLORS - ---- - DIR_COLORS | 41 ++++--- - DIR_COLORS.256color | 300 ++++++++++++++++++++++++------------------------ - DIR_COLORS.lightbgcolor | 211 ++++++++++++++++++---------------- - 3 files changed, 283 insertions(+), 269 deletions(-) - -diff --git a/DIR_COLORS b/DIR_COLORS -index d2ea453..27af9d7 100644 ---- a/DIR_COLORS -+++ b/DIR_COLORS -@@ -1,6 +1,10 @@ - # Configuration file for dircolors, a utility to help you set the - # LS_COLORS environment variable used by GNU ls with the --color option. - -+# This file goes in the /etc directory, and must be world readable. -+# You can copy this file to .dir_colors in your $HOME directory to override -+# the system defaults. -+ - # Copyright (C) 1996-2018 Free Software Foundation, Inc. - # Copying and distribution of this file, with or without modification, - # are permitted provided the copyright notice and this notice are preserved. -@@ -8,6 +12,9 @@ - # The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the - # slackware version of dircolors) are recognized but ignored. - -+# For compatibility, the pattern "^COLOR.*none" is recognized as a way to -+# disable colorization. See https://bugzilla.redhat.com/1349579 for details. -+ - # Below are TERM entries, which can be a glob patterns, to match - # against the TERM environment variable to determine if it is colorizable. - TERM Eterm -@@ -56,7 +63,7 @@ DOOR 01;35 # door - BLK 40;33;01 # block device driver - CHR 40;33;01 # character device driver - ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file ... --MISSING 00 # ... and the files they point to -+MISSING 01;05;37;41 # ... and the files they point to - SETUID 37;41 # file that is setuid (u+s) - SETGID 30;43 # file that is setgid (g+s) - CAPABILITY 30;41 # file with capability -@@ -184,21 +191,21 @@ EXEC 01;32 - .ogx 01;35 - - # audio formats --.aac 00;36 --.au 00;36 --.flac 00;36 --.m4a 00;36 --.mid 00;36 --.midi 00;36 --.mka 00;36 --.mp3 00;36 --.mpc 00;36 --.ogg 00;36 --.ra 00;36 --.wav 00;36 -+.aac 01;36 -+.au 01;36 -+.flac 01;36 -+.m4a 01;36 -+.mid 01;36 -+.midi 01;36 -+.mka 01;36 -+.mp3 01;36 -+.mpc 01;36 -+.ogg 01;36 -+.ra 01;36 -+.wav 01;36 - - # https://wiki.xiph.org/MIME_Types_and_File_Extensions --.oga 00;36 --.opus 00;36 --.spx 00;36 --.xspf 00;36 -+.oga 01;36 -+.opus 01;36 -+.spx 01;36 -+.xspf 01;36 -diff --git a/DIR_COLORS.256color b/DIR_COLORS.256color -index d2ea453..74c34ba 100644 ---- a/DIR_COLORS.256color -+++ b/DIR_COLORS.256color -@@ -1,3 +1,9 @@ -+# Configuration file for the 256color ls utility -+ -+# This file goes in the /etc directory, and must be world readable. -+# You can copy this file to .dir_colors in your $HOME directory to override -+# the system defaults. -+ - # Configuration file for dircolors, a utility to help you set the - # LS_COLORS environment variable used by GNU ls with the --color option. - -@@ -8,32 +14,13 @@ - # The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the - # slackware version of dircolors) are recognized but ignored. - -+# For compatibility, the pattern "^COLOR.*none" is recognized as a way to -+# disable colorization. See https://bugzilla.redhat.com/1349579 for details. -+ - # Below are TERM entries, which can be a glob patterns, to match - # against the TERM environment variable to determine if it is colorizable. --TERM Eterm --TERM ansi --TERM *color* --TERM con[0-9]*x[0-9]* --TERM cons25 --TERM console --TERM cygwin --TERM dtterm --TERM gnome --TERM hurd --TERM jfbterm --TERM konsole --TERM kterm --TERM linux --TERM linux-c --TERM mlterm --TERM putty --TERM rxvt* --TERM screen* --TERM st --TERM terminator --TERM tmux* --TERM vt100 --TERM xterm* -+TERM *256color* -+TERM rxvt-unicode256 - - # Below are the color init strings for the basic file types. A color init - # string consists of one or more of the following numeric codes: -@@ -43,29 +30,40 @@ TERM xterm* - # 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white - # Background color codes: - # 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white -+# Text color(256 colors mode) codes: -+# Valid syntax for text 256color is 38;5; , where color number -+# is number between 0 and 255. -+# You may find following command useful to search the best one for you: -+# for ((x=0; x<=255; x++));do echo -e "${x}:\033[38;5;${x}mcolor\033[000m";done -+# Background color(256 colors mode) codes: -+# Valid syntax for background 256color is 48;5; , where -+# color number is number between 0 and 255. -+# You may find following command useful to search the best one for you: -+# for ((x=0; x<=255; x++));do echo -e "${x}:\033[48;5;${x}mcolor\033[000m";done -+ - #NORMAL 00 # no color code at all - #FILE 00 # regular file: use no color at all - RESET 0 # reset to "normal" color --DIR 01;34 # directory --LINK 01;36 # symbolic link. (If you set this to 'target' instead of a -+DIR 38;5;33 # directory -+LINK 38;5;51 # symbolic link. (If you set this to 'target' instead of a - # numerical value, the color is as for the file pointed to.) - MULTIHARDLINK 00 # regular file with more than one link --FIFO 40;33 # pipe --SOCK 01;35 # socket --DOOR 01;35 # door --BLK 40;33;01 # block device driver --CHR 40;33;01 # character device driver --ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file ... --MISSING 00 # ... and the files they point to --SETUID 37;41 # file that is setuid (u+s) --SETGID 30;43 # file that is setgid (g+s) --CAPABILITY 30;41 # file with capability --STICKY_OTHER_WRITABLE 30;42 # dir that is sticky and other-writable (+t,o+w) --OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky --STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable -+FIFO 40;38;5;11 # pipe -+SOCK 38;5;13 # socket -+DOOR 38;5;5 # door -+BLK 48;5;232;38;5;11 # block device driver -+CHR 48;5;232;38;5;3 # character device driver -+ORPHAN 48;5;232;38;5;9 # symlink to nonexistent file, or non-stat'able file ... -+MISSING 01;05;37;41 # ... and the files they point to -+SETUID 48;5;196;38;5;15 # file that is setuid (u+s) -+SETGID 48;5;11;38;5;16 # file that is setgid (g+s) -+CAPABILITY 48;5;196;38;5;226 # file with capability -+STICKY_OTHER_WRITABLE 48;5;10;38;5;16 # dir that is sticky and other-writable (+t,o+w) -+OTHER_WRITABLE 48;5;10;38;5;21 # dir that is other-writable (o+w) and not sticky -+STICKY 48;5;21;38;5;15 # dir with the sticky bit set (+t) and not other-writable - - # This is for files with execute permission: --EXEC 01;32 -+EXEC 38;5;40 - - # List any file extensions like '.gz' or '.tar' that you would like ls - # to colorize below. Put the extension, a space, and the color init string. -@@ -83,122 +81,122 @@ EXEC 01;32 - #.csh 01;32 - - # archives or compressed (bright red) --.tar 01;31 --.tgz 01;31 --.arc 01;31 --.arj 01;31 --.taz 01;31 --.lha 01;31 --.lz4 01;31 --.lzh 01;31 --.lzma 01;31 --.tlz 01;31 --.txz 01;31 --.tzo 01;31 --.t7z 01;31 --.zip 01;31 --.z 01;31 --.dz 01;31 --.gz 01;31 --.lrz 01;31 --.lz 01;31 --.lzo 01;31 --.xz 01;31 --.zst 01;31 --.tzst 01;31 --.bz2 01;31 --.bz 01;31 --.tbz 01;31 --.tbz2 01;31 --.tz 01;31 --.deb 01;31 --.rpm 01;31 --.jar 01;31 --.war 01;31 --.ear 01;31 --.sar 01;31 --.rar 01;31 --.alz 01;31 --.ace 01;31 --.zoo 01;31 --.cpio 01;31 --.7z 01;31 --.rz 01;31 --.cab 01;31 --.wim 01;31 --.swm 01;31 --.dwm 01;31 --.esd 01;31 -+.tar 38;5;9 -+.tgz 38;5;9 -+.arc 38;5;9 -+.arj 38;5;9 -+.taz 38;5;9 -+.lha 38;5;9 -+.lz4 38;5;9 -+.lzh 38;5;9 -+.lzma 38;5;9 -+.tlz 38;5;9 -+.txz 38;5;9 -+.tzo 38;5;9 -+.t7z 38;5;9 -+.zip 38;5;9 -+.z 38;5;9 -+.dz 38;5;9 -+.gz 38;5;9 -+.lrz 38;5;9 -+.lz 38;5;9 -+.lzo 38;5;9 -+.xz 38;5;9 -+.zst 38;5;9 -+.tzst 38;5;9 -+.bz2 38;5;9 -+.bz 38;5;9 -+.tbz 38;5;9 -+.tbz2 38;5;9 -+.tz 38;5;9 -+.deb 38;5;9 -+.rpm 38;5;9 -+.jar 38;5;9 -+.war 38;5;9 -+.ear 38;5;9 -+.sar 38;5;9 -+.rar 38;5;9 -+.alz 38;5;9 -+.ace 38;5;9 -+.zoo 38;5;9 -+.cpio 38;5;9 -+.7z 38;5;9 -+.rz 38;5;9 -+.cab 38;5;9 -+.wim 38;5;9 -+.swm 38;5;9 -+.dwm 38;5;9 -+.esd 38;5;9 - - # image formats --.jpg 01;35 --.jpeg 01;35 --.mjpg 01;35 --.mjpeg 01;35 --.gif 01;35 --.bmp 01;35 --.pbm 01;35 --.pgm 01;35 --.ppm 01;35 --.tga 01;35 --.xbm 01;35 --.xpm 01;35 --.tif 01;35 --.tiff 01;35 --.png 01;35 --.svg 01;35 --.svgz 01;35 --.mng 01;35 --.pcx 01;35 --.mov 01;35 --.mpg 01;35 --.mpeg 01;35 --.m2v 01;35 --.mkv 01;35 --.webm 01;35 --.ogm 01;35 --.mp4 01;35 --.m4v 01;35 --.mp4v 01;35 --.vob 01;35 --.qt 01;35 --.nuv 01;35 --.wmv 01;35 --.asf 01;35 --.rm 01;35 --.rmvb 01;35 --.flc 01;35 --.avi 01;35 --.fli 01;35 --.flv 01;35 --.gl 01;35 --.dl 01;35 --.xcf 01;35 --.xwd 01;35 --.yuv 01;35 --.cgm 01;35 --.emf 01;35 -+.jpg 38;5;13 -+.jpeg 38;5;13 -+.mjpg 38;5;13 -+.mjpeg 38;5;13 -+.gif 38;5;13 -+.bmp 38;5;13 -+.pbm 38;5;13 -+.pgm 38;5;13 -+.ppm 38;5;13 -+.tga 38;5;13 -+.xbm 38;5;13 -+.xpm 38;5;13 -+.tif 38;5;13 -+.tiff 38;5;13 -+.png 38;5;13 -+.svg 38;5;13 -+.svgz 38;5;13 -+.mng 38;5;13 -+.pcx 38;5;13 -+.mov 38;5;13 -+.mpg 38;5;13 -+.mpeg 38;5;13 -+.m2v 38;5;13 -+.mkv 38;5;13 -+.webm 38;5;13 -+.ogm 38;5;13 -+.mp4 38;5;13 -+.m4v 38;5;13 -+.mp4v 38;5;13 -+.vob 38;5;13 -+.qt 38;5;13 -+.nuv 38;5;13 -+.wmv 38;5;13 -+.asf 38;5;13 -+.rm 38;5;13 -+.rmvb 38;5;13 -+.flc 38;5;13 -+.avi 38;5;13 -+.fli 38;5;13 -+.flv 38;5;13 -+.gl 38;5;13 -+.dl 38;5;13 -+.xcf 38;5;13 -+.xwd 38;5;13 -+.yuv 38;5;13 -+.cgm 38;5;13 -+.emf 38;5;13 - - # https://wiki.xiph.org/MIME_Types_and_File_Extensions --.ogv 01;35 --.ogx 01;35 -+.ogv 38;5;13 -+.ogx 38;5;13 - - # audio formats --.aac 00;36 --.au 00;36 --.flac 00;36 --.m4a 00;36 --.mid 00;36 --.midi 00;36 --.mka 00;36 --.mp3 00;36 --.mpc 00;36 --.ogg 00;36 --.ra 00;36 --.wav 00;36 -+.aac 38;5;45 -+.au 38;5;45 -+.flac 38;5;45 -+.m4a 38;5;45 -+.mid 38;5;45 -+.midi 38;5;45 -+.mka 38;5;45 -+.mp3 38;5;45 -+.mpc 38;5;45 -+.ogg 38;5;45 -+.ra 38;5;45 -+.wav 38;5;45 - - # https://wiki.xiph.org/MIME_Types_and_File_Extensions --.oga 00;36 --.opus 00;36 --.spx 00;36 --.xspf 00;36 -+.oga 38;5;45 -+.opus 38;5;45 -+.spx 38;5;45 -+.xspf 38;5;45 -diff --git a/DIR_COLORS.lightbgcolor b/DIR_COLORS.lightbgcolor -index d2ea453..95d6879 100644 ---- a/DIR_COLORS.lightbgcolor -+++ b/DIR_COLORS.lightbgcolor -@@ -1,3 +1,9 @@ -+# Configuration file for the color ls utility - modified for lighter backgrounds -+ -+# This file goes in the /etc directory, and must be world readable. -+# You can copy this file to .dir_colors in your $HOME directory to override -+# the system defaults. -+ - # Configuration file for dircolors, a utility to help you set the - # LS_COLORS environment variable used by GNU ls with the --color option. - -@@ -8,6 +14,9 @@ - # The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the - # slackware version of dircolors) are recognized but ignored. - -+# For compatibility, the pattern "^COLOR.*none" is recognized as a way to -+# disable colorization. See https://bugzilla.redhat.com/1349579 for details. -+ - # Below are TERM entries, which can be a glob patterns, to match - # against the TERM environment variable to determine if it is colorizable. - TERM Eterm -@@ -46,17 +55,17 @@ TERM xterm* - #NORMAL 00 # no color code at all - #FILE 00 # regular file: use no color at all - RESET 0 # reset to "normal" color --DIR 01;34 # directory --LINK 01;36 # symbolic link. (If you set this to 'target' instead of a -+DIR 00;34 # directory -+LINK 00;36 # symbolic link. (If you set this to 'target' instead of a - # numerical value, the color is as for the file pointed to.) - MULTIHARDLINK 00 # regular file with more than one link - FIFO 40;33 # pipe --SOCK 01;35 # socket --DOOR 01;35 # door -+SOCK 00;35 # socket -+DOOR 00;35 # door - BLK 40;33;01 # block device driver - CHR 40;33;01 # character device driver - ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file ... --MISSING 00 # ... and the files they point to -+MISSING 01;05;37;41 # ... and the files they point to - SETUID 37;41 # file that is setuid (u+s) - SETGID 30;43 # file that is setgid (g+s) - CAPABILITY 30;41 # file with capability -@@ -65,7 +74,7 @@ OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky - STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable - - # This is for files with execute permission: --EXEC 01;32 -+EXEC 00;32 - - # List any file extensions like '.gz' or '.tar' that you would like ls - # to colorize below. Put the extension, a space, and the color init string. -@@ -83,105 +92,105 @@ EXEC 01;32 - #.csh 01;32 - - # archives or compressed (bright red) --.tar 01;31 --.tgz 01;31 --.arc 01;31 --.arj 01;31 --.taz 01;31 --.lha 01;31 --.lz4 01;31 --.lzh 01;31 --.lzma 01;31 --.tlz 01;31 --.txz 01;31 --.tzo 01;31 --.t7z 01;31 --.zip 01;31 --.z 01;31 --.dz 01;31 --.gz 01;31 --.lrz 01;31 --.lz 01;31 --.lzo 01;31 --.xz 01;31 --.zst 01;31 --.tzst 01;31 --.bz2 01;31 --.bz 01;31 --.tbz 01;31 --.tbz2 01;31 --.tz 01;31 --.deb 01;31 --.rpm 01;31 --.jar 01;31 --.war 01;31 --.ear 01;31 --.sar 01;31 --.rar 01;31 --.alz 01;31 --.ace 01;31 --.zoo 01;31 --.cpio 01;31 --.7z 01;31 --.rz 01;31 --.cab 01;31 --.wim 01;31 --.swm 01;31 --.dwm 01;31 --.esd 01;31 -+.tar 00;31 -+.tgz 00;31 -+.arc 00;31 -+.arj 00;31 -+.taz 00;31 -+.lha 00;31 -+.lz4 00;31 -+.lzh 00;31 -+.lzma 00;31 -+.tlz 00;31 -+.txz 00;31 -+.tzo 00;31 -+.t7z 00;31 -+.zip 00;31 -+.z 00;31 -+.dz 00;31 -+.gz 00;31 -+.lrz 00;31 -+.lz 00;31 -+.lzo 00;31 -+.xz 00;31 -+.zst 00;31 -+.tzst 00;31 -+.bz2 00;31 -+.bz 00;31 -+.tbz 00;31 -+.tbz2 00;31 -+.tz 00;31 -+.deb 00;31 -+.rpm 00;31 -+.jar 00;31 -+.war 00;31 -+.ear 00;31 -+.sar 00;31 -+.rar 00;31 -+.alz 00;31 -+.ace 00;31 -+.zoo 00;31 -+.cpio 00;31 -+.7z 00;31 -+.rz 00;31 -+.cab 00;31 -+.wim 00;31 -+.swm 00;31 -+.dwm 00;31 -+.esd 00;31 - - # image formats --.jpg 01;35 --.jpeg 01;35 --.mjpg 01;35 --.mjpeg 01;35 --.gif 01;35 --.bmp 01;35 --.pbm 01;35 --.pgm 01;35 --.ppm 01;35 --.tga 01;35 --.xbm 01;35 --.xpm 01;35 --.tif 01;35 --.tiff 01;35 --.png 01;35 --.svg 01;35 --.svgz 01;35 --.mng 01;35 --.pcx 01;35 --.mov 01;35 --.mpg 01;35 --.mpeg 01;35 --.m2v 01;35 --.mkv 01;35 --.webm 01;35 --.ogm 01;35 --.mp4 01;35 --.m4v 01;35 --.mp4v 01;35 --.vob 01;35 --.qt 01;35 --.nuv 01;35 --.wmv 01;35 --.asf 01;35 --.rm 01;35 --.rmvb 01;35 --.flc 01;35 --.avi 01;35 --.fli 01;35 --.flv 01;35 --.gl 01;35 --.dl 01;35 --.xcf 01;35 --.xwd 01;35 --.yuv 01;35 --.cgm 01;35 --.emf 01;35 -+.jpg 00;35 -+.jpeg 00;35 -+.mjpg 00;35 -+.mjpeg 00;35 -+.gif 00;35 -+.bmp 00;35 -+.pbm 00;35 -+.pgm 00;35 -+.ppm 00;35 -+.tga 00;35 -+.xbm 00;35 -+.xpm 00;35 -+.tif 00;35 -+.tiff 00;35 -+.png 00;35 -+.svg 00;35 -+.svgz 00;35 -+.mng 00;35 -+.pcx 00;35 -+.mov 00;35 -+.mpg 00;35 -+.mpeg 00;35 -+.m2v 00;35 -+.mkv 00;35 -+.webm 00;35 -+.ogm 00;35 -+.mp4 00;35 -+.m4v 00;35 -+.mp4v 00;35 -+.vob 00;35 -+.qt 00;35 -+.nuv 00;35 -+.wmv 00;35 -+.asf 00;35 -+.rm 00;35 -+.rmvb 00;35 -+.flc 00;35 -+.avi 00;35 -+.fli 00;35 -+.flv 00;35 -+.gl 00;35 -+.dl 00;35 -+.xcf 00;35 -+.xwd 00;35 -+.yuv 00;35 -+.cgm 00;35 -+.emf 00;35 - - # https://wiki.xiph.org/MIME_Types_and_File_Extensions --.ogv 01;35 --.ogx 01;35 -+.ogv 00;35 -+.ogx 00;35 - - # audio formats - .aac 00;36 --- -2.5.5 - diff --git a/SOURCES/coreutils-8.30-CVE-2018-17942.patch b/SOURCES/coreutils-8.30-CVE-2018-17942.patch deleted file mode 100644 index 409fe0c..0000000 --- a/SOURCES/coreutils-8.30-CVE-2018-17942.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 6d059cebfdefbdf56910a858f8b603d37f10ef6d Mon Sep 17 00:00:00 2001 -From: Bruno Haible -Date: Sun, 23 Sep 2018 14:13:52 +0200 -Subject: [PATCH] vasnprintf: Fix heap memory overrun bug. - -Reported by Ben Pfaff in -. - -* lib/vasnprintf.c (convert_to_decimal): Allocate one more byte of -memory. -* tests/test-vasnprintf.c (test_function): Add another test. - -Upstream-commit: 278b4175c9d7dd47c1a3071554aac02add3b3c35 -Signed-off-by: Kamil Dudka ---- - gnulib-tests/test-vasnprintf.c | 21 ++++++++++++++++++++- - lib/vasnprintf.c | 4 +++- - 2 files changed, 23 insertions(+), 2 deletions(-) - -diff --git a/gnulib-tests/test-vasnprintf.c b/gnulib-tests/test-vasnprintf.c -index 19731bc..93d81d7 100644 ---- a/gnulib-tests/test-vasnprintf.c -+++ b/gnulib-tests/test-vasnprintf.c -@@ -53,7 +53,26 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) - ASSERT (result != NULL); - ASSERT (strcmp (result, "12345") == 0); - ASSERT (length == 5); -- if (size < 6) -+ if (size < 5 + 1) -+ ASSERT (result != buf); -+ ASSERT (memcmp (buf + size, &"DEADBEEF"[size], 8 - size) == 0); -+ if (result != buf) -+ free (result); -+ } -+ -+ /* Note: This test assumes IEEE 754 representation of 'double' floats. */ -+ for (size = 0; size <= 8; size++) -+ { -+ size_t length; -+ char *result; -+ -+ memcpy (buf, "DEADBEEF", 8); -+ length = size; -+ result = my_asnprintf (buf, &length, "%2.0f", 1.6314159265358979e+125); -+ ASSERT (result != NULL); -+ ASSERT (strcmp (result, "163141592653589790215729350939528493057529598899734151772468186268423257777068536614838678161083520756952076273094236944990208") == 0); -+ ASSERT (length == 126); -+ if (size < 126 + 1) - ASSERT (result != buf); - ASSERT (memcmp (buf + size, &"DEADBEEF"[size], 8 - size) == 0); - if (result != buf) -diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c -index 3b441d0..48ef7a6 100644 ---- a/lib/vasnprintf.c -+++ b/lib/vasnprintf.c -@@ -860,7 +860,9 @@ convert_to_decimal (mpn_t a, size_t extra_zeroes) - size_t a_len = a.nlimbs; - /* 0.03345 is slightly larger than log(2)/(9*log(10)). */ - size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1); -- char *c_ptr = (char *) malloc (xsum (c_len, extra_zeroes)); -+ /* We need extra_zeroes bytes for zeroes, followed by c_len bytes for the -+ digits of a, followed by 1 byte for the terminating NUL. */ -+ char *c_ptr = (char *) malloc (xsum (xsum (extra_zeroes, c_len), 1)); - if (c_ptr != NULL) - { - char *d_ptr = c_ptr; --- -2.17.1 - diff --git a/SOURCES/coreutils-8.30-chcon-invalid-context.patch b/SOURCES/coreutils-8.30-chcon-invalid-context.patch deleted file mode 100644 index 96a38f6..0000000 --- a/SOURCES/coreutils-8.30-chcon-invalid-context.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 5d6c2c9b3869938592025ce169659f0c7e9970fc Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Mon, 2 Dec 2019 14:02:02 +0100 -Subject: [PATCH] chcon: do not validate security context if SELinux is - disabled - -* src/chcon.c (main): Skip call of security_check_context() -in case SELinux is disabled to avoid unnecessary failure. - -Bug: https://bugzilla.redhat.com/1777831 - -Upstream-commit: 5118a2e392c8cffb3c26eaffbb75e2b1ef7607f9 -Signed-off-by: Kamil Dudka ---- - src/chcon.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/chcon.c b/src/chcon.c -index 6414406..eea4235 100644 ---- a/src/chcon.c -+++ b/src/chcon.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - - #include "system.h" - #include "dev-ino.h" -@@ -557,7 +558,8 @@ main (int argc, char **argv) - else - { - specified_context = argv[optind++]; -- if (security_check_context (se_const (specified_context)) < 0) -+ if (0 < is_selinux_enabled () -+ && security_check_context (se_const (specified_context)) < 0) - die (EXIT_FAILURE, errno, _("invalid context: %s"), - quote (specified_context)); - } --- -2.21.1 - diff --git a/SOURCES/coreutils-8.30-cp-preserve-xattr-NFSv4-ACL.patch b/SOURCES/coreutils-8.30-cp-preserve-xattr-NFSv4-ACL.patch deleted file mode 100644 index 723c4b1..0000000 --- a/SOURCES/coreutils-8.30-cp-preserve-xattr-NFSv4-ACL.patch +++ /dev/null @@ -1,69 +0,0 @@ -From ce137aaf4b0d62b3e4c88816485a3ab0f5c4b3f3 Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Thu, 6 Dec 2018 13:14:00 +0100 -Subject: [PATCH] cp --preserve=xattr: preserve NFSv4 ACL extended attributes - -... that cannot be preserved by other means ---- - src/copy.c | 22 +++++++++++++++++----- - 1 file changed, 17 insertions(+), 5 deletions(-) - -diff --git a/src/copy.c b/src/copy.c -index 1a9cdd1..d227e3e 100644 ---- a/src/copy.c -+++ b/src/copy.c -@@ -640,6 +640,17 @@ copy_attr_free (struct error_context *ctx _GL_UNUSED, - { - } - -+/* Include NFSv4 ACL extended attributes that cannot be preserved by -+ other means. Otherwise honor attributes configured for exclusion -+ in /etc/xattr.conf. Return zero to skip. */ -+static int -+check_not_nfs4_acl (const char *name, struct error_context *ctx) -+{ -+ return attr_copy_check_permissions(name, ctx) -+ || !STRNCMP_LIT (name, "system.nfs4_acl") -+ || !STRNCMP_LIT (name, "system.nfs4acl"); -+} -+ - /* Exclude SELinux extended attributes that are otherwise handled, - and are problematic to copy again. Also honor attributes - configured for exclusion in /etc/xattr.conf. -@@ -649,7 +660,7 @@ static int - check_selinux_attr (const char *name, struct error_context *ctx) - { - return STRNCMP_LIT (name, "security.selinux") -- && attr_copy_check_permissions (name, ctx); -+ && check_not_nfs4_acl (name, ctx); - } - - /* If positive SRC_FD and DST_FD descriptors are passed, -@@ -663,6 +674,9 @@ copy_attr (char const *src_path, int src_fd, - bool all_errors = (!x->data_copy_required || x->require_preserve_xattr); - bool some_errors = (!all_errors && !x->reduce_diagnostics); - bool selinux_done = (x->preserve_security_context || x->set_security_context); -+ int (*check) (const char *, struct error_context *) = (selinux_done) -+ ? check_selinux_attr -+ : check_not_nfs4_acl; - struct error_context ctx = - { - .error = all_errors ? copy_attr_allerror : copy_attr_error, -@@ -670,12 +684,10 @@ copy_attr (char const *src_path, int src_fd, - .quote_free = copy_attr_free - }; - if (0 <= src_fd && 0 <= dst_fd) -- ret = attr_copy_fd (src_path, src_fd, dst_path, dst_fd, -- selinux_done ? check_selinux_attr : NULL, -+ ret = attr_copy_fd (src_path, src_fd, dst_path, dst_fd, check, - (all_errors || some_errors ? &ctx : NULL)); - else -- ret = attr_copy_file (src_path, dst_path, -- selinux_done ? check_selinux_attr : NULL, -+ ret = attr_copy_file (src_path, dst_path, check, - (all_errors || some_errors ? &ctx : NULL)); - - return ret == 0; --- -2.17.2 - diff --git a/SOURCES/coreutils-8.30-df-local-fs.patch b/SOURCES/coreutils-8.30-df-local-fs.patch deleted file mode 100644 index fdf4d88..0000000 --- a/SOURCES/coreutils-8.30-df-local-fs.patch +++ /dev/null @@ -1,74 +0,0 @@ -From b60a61d7e5f6504518095d9ee8c7c8b185bedb23 Mon Sep 17 00:00:00 2001 -From: Marc Dionne -Date: Wed, 5 Feb 2020 13:35:12 -0800 -Subject: [PATCH 1/2] mountlist: Consider AFS filesystems as remote - -df --local relies on the ME_REMOTE macro to determine if a given -mount entry should be considered "local". There is special logic -for nfs and smb/cifs mounts, but /afs as mounted by OpenAFS, the -kernel's kafs module or AuriStorFS is treated as a local mount. -* lib/mountlist.c (ME_REMOTE): Treat mounts of type 'afs' -(OpenAFS, kernel kafs) and 'auristorfs' (AuriStorFS) as remote. - -Copyright-paperwork-exempt: yes - -Upstream-commit: 7a15069b68a376f26c5dca34ae2689c5bf8adc99 -Signed-off-by: Kamil Dudka ---- - lib/mountlist.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/lib/mountlist.c b/lib/mountlist.c -index b691f38..1b1e5e4 100644 ---- a/lib/mountlist.c -+++ b/lib/mountlist.c -@@ -224,6 +224,7 @@ me_remote (char const *fs_name, char const *fs_type _GL_UNUSED) - #ifndef ME_REMOTE - /* A file system is "remote" if its Fs_name contains a ':' - or if (it is of type (smbfs or cifs) and its Fs_name starts with '//') -+ or if it is of type (afs or auristorfs) - or Fs_name is equal to "-hosts" (used by autofs to mount remote fs). */ - # define ME_REMOTE(Fs_name, Fs_type) \ - (strchr (Fs_name, ':') != NULL \ -@@ -231,6 +232,8 @@ me_remote (char const *fs_name, char const *fs_type _GL_UNUSED) - && (Fs_name)[1] == '/' \ - && (strcmp (Fs_type, "smbfs") == 0 \ - || strcmp (Fs_type, "cifs") == 0)) \ -+ || strcmp (Fs_type, "afs") == 0 \ -+ || strcmp (Fs_type, "auristorfs") == 0 \ - || (strcmp("-hosts", Fs_name) == 0)) - #endif - --- -2.21.1 - - -From 41010dfb0cc100f41fb16d93f9fa36dc07e63ac6 Mon Sep 17 00:00:00 2001 -From: Kenneth D'souza -Date: Sat, 8 Feb 2020 13:54:35 +0000 -Subject: [PATCH 2/2] mountlist: consider smb3 file systems as remote - -* lib/mountlist.c (ME_REMOTE): Recognize file systems of type -"smb3" as remote. - -Upstream-commit: 4d4a22ab1f719b7c6c3fe3dbf45d11baafd3c563 -Signed-off-by: Kamil Dudka ---- - lib/mountlist.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/lib/mountlist.c b/lib/mountlist.c -index 1b1e5e4..8ad74a2 100644 ---- a/lib/mountlist.c -+++ b/lib/mountlist.c -@@ -231,6 +231,7 @@ me_remote (char const *fs_name, char const *fs_type _GL_UNUSED) - || ((Fs_name)[0] == '/' \ - && (Fs_name)[1] == '/' \ - && (strcmp (Fs_type, "smbfs") == 0 \ -+ || strcmp (Fs_type, "smb3") == 0 \ - || strcmp (Fs_type, "cifs") == 0)) \ - || strcmp (Fs_type, "afs") == 0 \ - || strcmp (Fs_type, "auristorfs") == 0 \ --- -2.21.1 - diff --git a/SOURCES/coreutils-8.30-fsync-fallback.patch b/SOURCES/coreutils-8.30-fsync-fallback.patch deleted file mode 100644 index 110da10..0000000 --- a/SOURCES/coreutils-8.30-fsync-fallback.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 2eabfbee57be82f755c74cbb05755dce1469ea7c Mon Sep 17 00:00:00 2001 -From: Paul Eggert -Date: Tue, 6 Nov 2018 10:35:16 -0800 -Subject: [PATCH 1/2] sync: fix open fallback bug - -Problem caught by Coverity Analysis -and reported by Kamil Dudka (Bug#33287). -* src/sync.c (sync_arg): Fix typo in fallback code. - -Upstream-commit: 94d364f157f007f2b23c70863ac8eefe9b21229d -Signed-off-by: Kamil Dudka ---- - src/sync.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/src/sync.c b/src/sync.c -index bd3671a..607fa8f 100644 ---- a/src/sync.c -+++ b/src/sync.c -@@ -111,8 +111,10 @@ sync_arg (enum sync_mode mode, char const *file) - if (open_flags != (O_WRONLY | O_NONBLOCK)) - fd = open (file, O_WRONLY | O_NONBLOCK); - if (fd < 0) -- error (0, rd_errno, _("error opening %s"), quoteaf (file)); -- return false; -+ { -+ error (0, rd_errno, _("error opening %s"), quoteaf (file)); -+ return false; -+ } - } - - /* We used O_NONBLOCK above to not hang with fifos, --- -2.17.2 - - -From e62ff3068f1f1b1e84d3319f54f1b869bb0bf6cc Mon Sep 17 00:00:00 2001 -From: Bernhard Voelker -Date: Wed, 7 Nov 2018 00:26:01 +0100 -Subject: [PATCH 2/2] sync: add test for the fix in the previous commit - -* tests/misc/sync.sh: Add a test with a write-only file for the fix. - -Upstream-commit: 4711c49312d54e84996c13c612f7081c95f821a6 -Signed-off-by: Kamil Dudka ---- - tests/misc/sync.sh | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/tests/misc/sync.sh b/tests/misc/sync.sh -index f60d28c..3bb6e17 100755 ---- a/tests/misc/sync.sh -+++ b/tests/misc/sync.sh -@@ -19,7 +19,7 @@ - . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src - print_ver_ sync - --touch file -+touch file || framework_failure_ - - # fdatasync+syncfs is nonsensical - returns_ 1 sync --data --file-system || fail=1 -@@ -30,6 +30,11 @@ returns_ 1 sync -d || fail=1 - # Test syncing of file (fsync) (little side effects) - sync file || fail=1 - -+# Test syncing of write-only file - which failed since adding argument -+# support to sync in coreutils-8.24. -+chmod 0200 file || framework_failure_ -+sync file || fail=1 -+ - # Ensure multiple args are processed and diagnosed - returns_ 1 sync file nofile || fail=1 - --- -2.17.2 - diff --git a/SOURCES/coreutils-8.30-renameatu.patch b/SOURCES/coreutils-8.30-renameatu.patch deleted file mode 100644 index a5aa48f..0000000 --- a/SOURCES/coreutils-8.30-renameatu.patch +++ /dev/null @@ -1,451 +0,0 @@ -From 57ee8db4fee8eb6772df1ff18d275594c0b034d4 Mon Sep 17 00:00:00 2001 -From: Paul Eggert -Date: Thu, 5 Jul 2018 09:22:09 -0700 -Subject: [PATCH 1/2] renameatu: rename from renameat2 - -It's looking like Glibc will add a renameat2 function -that is incompatible with Gnulib renameat2; see: -https://sourceware.org/ml/libc-alpha/2018-07/msg00064.html -To help avoid future confusion, rename renameat2 to something else. -Use the name 'renameatu', as the Gnulib function is close to the -Glibc function. Perhaps someday there will also be a renameat2 -Gnulib module, which mimicks the future glibc renameat2, but that -can wait as nobody seems to need such a module now. -* NEWS: Mention this. -* lib/renameatu.c: Rename from lib/renameat2.c. -* lib/renameatu.h: Rename from lib/renameat2.h. -* modules/renameatu: Rename from modules/renameat2. -* modules/renameatu-tests: Rename from modules/renameat2-tests. -All uses of "renameat2" in identifiers or file name -changed to "renameatu", except for two instances in -lib/renameatu.c that deal with the Linux kernel's -renameat2 syscall. - -Upstream-commit: 2522322e5304e7d86c63e607e2bc83c8d8b0a889 -Signed-off-by: Kamil Dudka ---- - gnulib-tests/gnulib.mk | 12 +++--- - .../{test-renameat2.c => test-renameatu.c} | 48 +++++++++++----------- - lib/backupfile.c | 4 +- - lib/gnulib.mk | 10 ++--- - lib/renameat.c | 4 +- - lib/{renameat2.c => renameatu.c} | 9 ++-- - lib/{renameat2.h => renameatu.h} | 8 ++-- - 7 files changed, 48 insertions(+), 47 deletions(-) - rename gnulib-tests/{test-renameat2.c => test-renameatu.c} (80%) - rename lib/{renameat2.c => renameatu.c} (94%) - rename lib/{renameat2.h => renameatu.h} (84%) - -diff --git a/gnulib-tests/gnulib.mk b/gnulib-tests/gnulib.mk -index be2b99e..891425b 100644 ---- a/gnulib-tests/gnulib.mk -+++ b/gnulib-tests/gnulib.mk -@@ -1750,14 +1750,14 @@ EXTRA_DIST += test-rename.h test-renameat.c signature.h macros.h - - ## end gnulib module renameat-tests - --## begin gnulib module renameat2-tests -+## begin gnulib module renameatu-tests - --TESTS += test-renameat2 --check_PROGRAMS += test-renameat2 --test_renameat2_LDADD = $(LDADD) @LIBINTL@ --EXTRA_DIST += test-rename.h test-renameat2.c signature.h macros.h -+TESTS += test-renameatu -+check_PROGRAMS += test-renameatu -+test_renameatu_LDADD = $(LDADD) @LIBINTL@ -+EXTRA_DIST += test-rename.h test-renameatu.c signature.h macros.h - --## end gnulib module renameat2-tests -+## end gnulib module renameatu-tests - - ## begin gnulib module rmdir-tests - -diff --git a/gnulib-tests/test-renameat2.c b/gnulib-tests/test-renameatu.c -similarity index 80% -rename from gnulib-tests/test-renameat2.c -rename to gnulib-tests/test-renameatu.c -index 0104890..988428b 100644 ---- a/gnulib-tests/test-renameat2.c -+++ b/gnulib-tests/test-renameatu.c -@@ -1,4 +1,4 @@ --/* Test renameat2. -+/* Test renameatu. - Copyright (C) 2009-2018 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify -@@ -18,12 +18,12 @@ - - #include - --#include -+#include - - #include - - #include "signature.h" --SIGNATURE_CHECK (renameat2, int, -+SIGNATURE_CHECK (renameatu, int, - (int, char const *, int, char const *, unsigned int)); - - #include -@@ -39,18 +39,18 @@ SIGNATURE_CHECK (renameat2, int, - #include "ignore-value.h" - #include "macros.h" - --#define BASE "test-renameat2.t" -+#define BASE "test-renameatu.t" - - #include "test-rename.h" - - static int dfd1 = AT_FDCWD; - static int dfd2 = AT_FDCWD; - --/* Wrapper to test renameat2 like rename. */ -+/* Wrapper to test renameatu like rename. */ - static int - do_rename (char const *name1, char const *name2) - { -- return renameat2 (dfd1, name1, dfd2, name2, 0); -+ return renameatu (dfd1, name1, dfd2, name2, 0); - } - - int -@@ -67,24 +67,24 @@ main (void) - /* Test behaviour for invalid file descriptors. */ - { - errno = 0; -- ASSERT (renameat2 (-1, "foo", AT_FDCWD, "bar", 0) == -1); -+ ASSERT (renameatu (-1, "foo", AT_FDCWD, "bar", 0) == -1); - ASSERT (errno == EBADF); - } - { - close (99); - errno = 0; -- ASSERT (renameat2 (99, "foo", AT_FDCWD, "bar", 0) == -1); -+ ASSERT (renameatu (99, "foo", AT_FDCWD, "bar", 0) == -1); - ASSERT (errno == EBADF); - } - ASSERT (close (creat (BASE "oo", 0600)) == 0); - { - errno = 0; -- ASSERT (renameat2 (AT_FDCWD, BASE "oo", -1, "bar", 0) == -1); -+ ASSERT (renameatu (AT_FDCWD, BASE "oo", -1, "bar", 0) == -1); - ASSERT (errno == EBADF); - } - { - errno = 0; -- ASSERT (renameat2 (AT_FDCWD, BASE "oo", 99, "bar", 0) == -1); -+ ASSERT (renameatu (AT_FDCWD, BASE "oo", 99, "bar", 0) == -1); - ASSERT (errno == EBADF); - } - ASSERT (unlink (BASE "oo") == 0); -@@ -133,13 +133,13 @@ main (void) - - ASSERT (sprintf (strchr (file1, '\0') - 2, "%02d", i) == 2); - ASSERT (sprintf (strchr (file2, '\0') - 2, "%02d", i + 1) == 2); -- ASSERT (renameat2 (fd1, file1, fd2, file2, 0) == 0); -+ ASSERT (renameatu (fd1, file1, fd2, file2, 0) == 0); - free (file1); - free (file2); - } - dfd2 = open ("..", O_RDONLY); - ASSERT (0 <= dfd2); -- ASSERT (renameat2 (dfd, "../" BASE "16", dfd2, BASE "17", 0) == 0); -+ ASSERT (renameatu (dfd, "../" BASE "16", dfd2, BASE "17", 0) == 0); - ASSERT (close (dfd2) == 0); - - /* Now we change back to the parent directory, and set dfd to "."; -@@ -152,47 +152,47 @@ main (void) - - ASSERT (close (creat (BASE "sub2/file", 0600)) == 0); - errno = 0; -- ASSERT (renameat2 (dfd, BASE "sub1", dfd, BASE "sub2", 0) == -1); -+ ASSERT (renameatu (dfd, BASE "sub1", dfd, BASE "sub2", 0) == -1); - ASSERT (errno == EEXIST || errno == ENOTEMPTY); - ASSERT (unlink (BASE "sub2/file") == 0); - errno = 0; -- ASSERT (renameat2 (dfd, BASE "sub2", dfd, BASE "sub1/.", 0) == -1); -+ ASSERT (renameatu (dfd, BASE "sub2", dfd, BASE "sub1/.", 0) == -1); - ASSERT (errno == EINVAL || errno == EISDIR || errno == EBUSY - || errno == ENOTEMPTY || errno == EEXIST - || errno == ENOENT /* WSL */); - errno = 0; -- ASSERT (renameat2 (dfd, BASE "sub2/.", dfd, BASE "sub1", 0) == -1); -+ ASSERT (renameatu (dfd, BASE "sub2/.", dfd, BASE "sub1", 0) == -1); - ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST - || errno == ENOENT /* WSL */); - errno = 0; -- ASSERT (renameat2 (dfd, BASE "17", dfd, BASE "sub1", 0) == -1); -+ ASSERT (renameatu (dfd, BASE "17", dfd, BASE "sub1", 0) == -1); - ASSERT (errno == EISDIR); - errno = 0; -- ASSERT (renameat2 (dfd, BASE "nosuch", dfd, BASE "18", 0) == -1); -+ ASSERT (renameatu (dfd, BASE "nosuch", dfd, BASE "18", 0) == -1); - ASSERT (errno == ENOENT); - errno = 0; -- ASSERT (renameat2 (dfd, "", dfd, BASE "17", 0) == -1); -+ ASSERT (renameatu (dfd, "", dfd, BASE "17", 0) == -1); - ASSERT (errno == ENOENT); - errno = 0; -- ASSERT (renameat2 (dfd, BASE "17", dfd, "", 0) == -1); -+ ASSERT (renameatu (dfd, BASE "17", dfd, "", 0) == -1); - ASSERT (errno == ENOENT); - errno = 0; -- ASSERT (renameat2 (dfd, BASE "sub2", dfd, BASE "17", 0) == -1); -+ ASSERT (renameatu (dfd, BASE "sub2", dfd, BASE "17", 0) == -1); - ASSERT (errno == ENOTDIR); - errno = 0; -- ASSERT (renameat2 (dfd, BASE "17/", dfd, BASE "18", 0) == -1); -+ ASSERT (renameatu (dfd, BASE "17/", dfd, BASE "18", 0) == -1); - ASSERT (errno == ENOTDIR); - errno = 0; -- ASSERT (renameat2 (dfd, BASE "17", dfd, BASE "18/", 0) == -1); -+ ASSERT (renameatu (dfd, BASE "17", dfd, BASE "18/", 0) == -1); - ASSERT (errno == ENOTDIR || errno == ENOENT); - - /* Finally, make sure we cannot overwrite existing files. */ - ASSERT (close (creat (BASE "sub2/file", 0600)) == 0); - errno = 0; -- ASSERT ((renameat2 (dfd, BASE "sub2", dfd, BASE "sub1", RENAME_NOREPLACE) -+ ASSERT ((renameatu (dfd, BASE "sub2", dfd, BASE "sub1", RENAME_NOREPLACE) - == -1) - && errno == EEXIST); -- ASSERT ((renameat2 (dfd, BASE "sub2/file", dfd, BASE "17", RENAME_NOREPLACE) -+ ASSERT ((renameatu (dfd, BASE "sub2/file", dfd, BASE "17", RENAME_NOREPLACE) - == -1) - && errno == EEXIST); - -diff --git a/lib/backupfile.c b/lib/backupfile.c -index d438455..637be6c 100644 ---- a/lib/backupfile.c -+++ b/lib/backupfile.c -@@ -23,7 +23,7 @@ - #include "backup-internal.h" - - #include "dirname.h" --#include "renameat2.h" -+#include "renameatu.h" - #include "xalloc-oversized.h" - - #include -@@ -353,7 +353,7 @@ backupfile_internal (char const *file, enum backup_type backup_type, bool rename - base_offset = 0; - } - unsigned flags = backup_type == simple_backups ? 0 : RENAME_NOREPLACE; -- if (renameat2 (AT_FDCWD, file, sdir, s + base_offset, flags) == 0) -+ if (renameatu (AT_FDCWD, file, sdir, s + base_offset, flags) == 0) - break; - int e = errno; - if (e != EEXIST) -diff --git a/lib/gnulib.mk b/lib/gnulib.mk -index 04473d5..0b747e3 100644 ---- a/lib/gnulib.mk -+++ b/lib/gnulib.mk -@@ -21,7 +21,7 @@ - # the same distribution terms as the rest of that program. - # - # Generated by gnulib-tool. --# Reproduce by: gnulib-tool --import --local-dir=gl --lib=libcoreutils --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=gnulib-tests --aux-dir=build-aux --with-tests --avoid=canonicalize-lgpl --avoid=dummy --makefile-name=gnulib.mk --no-conditional-dependencies --no-libtool --macro-prefix=gl acl alignof alloca announce-gen areadlink-with-size argmatch argv-iter assert autobuild backup-rename backupfile base32 base64 buffer-lcm c-strcase c-strtod c-strtold calloc-gnu canon-host canonicalize chown cloexec closein closeout config-h configmake crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 cycle-check d-ino d-type di-set diacrit dirfd dirname do-release-commit-and-tag dtoastr dup2 environ error euidaccess exclude exitfail explicit_bzero faccessat fadvise fchdir fchmodat fchownat fclose fcntl fcntl-safer fd-reopen fdatasync fdl fdopen fdutimensat file-has-acl file-type fileblocks filemode filenamecat filevercmp flexmember fnmatch-gnu fopen-safer fprintftime freopen freopen-safer fseeko fstatat fsusage fsync ftoastr ftruncate fts full-read full-write getgroups gethrxtime getline getloadavg getlogin getndelim2 getopt-gnu getpagesize getpass-gnu gettext-h gettime gettimeofday getugroups getusershell git-version-gen gitlog-to-changelog gnu-make gnu-web-doc-update gnumakefile gnupload group-member hard-locale hash hash-pjw heap host-os human idcache ignore-value inttostr inttypes isapipe isatty isblank largefile lchmod lchown ldtoastr lib-ignore linebuffer link link-follow linkat long-options lstat maintainer-makefile malloc-gnu manywarnings mbrlen mbrtowc mbsalign mbschr mbslen mbswidth memcasecmp memchr memcmp2 mempcpy memrchr mgetgroups mkancesdirs mkdir mkdir-p mkfifo mknod mkostemp mkstemp mktime modechange mountlist mpsort netinet_in non-recursive-gnulib-prefix-hack nproc nstrftime obstack open parse-datetime pathmax perl physmem pipe-posix pipe2 posix-shell posixtm posixver priv-set progname propername pthread putenv quote quotearg randint randperm read-file readlink readtokens readtokens0 readutmp realloc-gnu regex remove rename renameat renameat2 rmdir root-dev-ino rpmatch safe-read same save-cwd savedir savewd selinux-at setenv settime sig2str sigaction smack ssize_t stat-macros stat-size stat-time statat stdbool stdlib-safer stpcpy stpncpy strdup-posix strncat strnumcmp strsignal strtod strtoimax strtoumax symlinkat sys_ioctl sys_resource sys_stat sys_wait tempname termios time_rz timer-time timespec tzset uname unicodeio unistd-safer unlink-busy unlinkat unlocked-io unsetenv update-copyright uptime useless-if-before-free userspec utimecmp utimens vasprintf-posix vc-list-files verify verror version-etc-fsf wchar-single wcswidth wcwidth winsz-ioctl winsz-termios write-any-file xalloc xbinary-io xdectoint xfts xgetcwd xgetgroups xgethostname xmemcoll xnanosleep xprintf xprintf-posix xreadlink xstrtod xstrtoimax xstrtol xstrtold xstrtoumax year2038 yesno -+# Reproduce by: gnulib-tool --import --local-dir=gl --lib=libcoreutils --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=gnulib-tests --aux-dir=build-aux --with-tests --avoid=canonicalize-lgpl --avoid=dummy --makefile-name=gnulib.mk --no-conditional-dependencies --no-libtool --macro-prefix=gl acl alignof alloca announce-gen areadlink-with-size argmatch argv-iter assert autobuild backup-rename backupfile base32 base64 buffer-lcm c-strcase c-strtod c-strtold calloc-gnu canon-host canonicalize chown cloexec closein closeout config-h configmake crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 cycle-check d-ino d-type di-set diacrit dirfd dirname do-release-commit-and-tag dtoastr dup2 environ error euidaccess exclude exitfail explicit_bzero faccessat fadvise fchdir fchmodat fchownat fclose fcntl fcntl-safer fd-reopen fdatasync fdl fdopen fdutimensat file-has-acl file-type fileblocks filemode filenamecat filevercmp flexmember fnmatch-gnu fopen-safer fprintftime freopen freopen-safer fseeko fstatat fsusage fsync ftoastr ftruncate fts full-read full-write getgroups gethrxtime getline getloadavg getlogin getndelim2 getopt-gnu getpagesize getpass-gnu gettext-h gettime gettimeofday getugroups getusershell git-version-gen gitlog-to-changelog gnu-make gnu-web-doc-update gnumakefile gnupload group-member hard-locale hash hash-pjw heap host-os human idcache ignore-value inttostr inttypes isapipe isatty isblank largefile lchmod lchown ldtoastr lib-ignore linebuffer link link-follow linkat long-options lstat maintainer-makefile malloc-gnu manywarnings mbrlen mbrtowc mbsalign mbschr mbslen mbswidth memcasecmp memchr memcmp2 mempcpy memrchr mgetgroups mkancesdirs mkdir mkdir-p mkfifo mknod mkostemp mkstemp mktime modechange mountlist mpsort netinet_in non-recursive-gnulib-prefix-hack nproc nstrftime obstack open parse-datetime pathmax perl physmem pipe-posix pipe2 posix-shell posixtm posixver priv-set progname propername pthread putenv quote quotearg randint randperm read-file readlink readtokens readtokens0 readutmp realloc-gnu regex remove rename renameat renameatu rmdir root-dev-ino rpmatch safe-read same save-cwd savedir savewd selinux-at setenv settime sig2str sigaction smack ssize_t stat-macros stat-size stat-time statat stdbool stdlib-safer stpcpy stpncpy strdup-posix strncat strnumcmp strsignal strtod strtoimax strtoumax symlinkat sys_ioctl sys_resource sys_stat sys_wait tempname termios time_rz timer-time timespec tzset uname unicodeio unistd-safer unlink-busy unlinkat unlocked-io unsetenv update-copyright uptime useless-if-before-free userspec utimecmp utimens vasprintf-posix vc-list-files verify verror version-etc-fsf wchar-single wcswidth wcwidth winsz-ioctl winsz-termios write-any-file xalloc xbinary-io xdectoint xfts xgetcwd xgetgroups xgethostname xmemcoll xnanosleep xprintf xprintf-posix xreadlink xstrtod xstrtoimax xstrtol xstrtold xstrtoumax year2038 yesno - - - MOSTLYCLEANFILES += lib/core lib/*.stackdump -@@ -3218,15 +3218,15 @@ EXTRA_lib_libcoreutils_a_SOURCES += lib/renameat.c - - ## end gnulib module renameat - --## begin gnulib module renameat2 -+## begin gnulib module renameatu - --lib_libcoreutils_a_SOURCES += lib/renameat2.c -+lib_libcoreutils_a_SOURCES += lib/renameatu.c - --EXTRA_DIST += lib/at-func2.c lib/renameat2.h -+EXTRA_DIST += lib/at-func2.c lib/renameatu.h - - EXTRA_lib_libcoreutils_a_SOURCES += lib/at-func2.c - --## end gnulib module renameat2 -+## end gnulib module renameatu - - ## begin gnulib module rewinddir - -diff --git a/lib/renameat.c b/lib/renameat.c -index 0cb7d33..67be22b 100644 ---- a/lib/renameat.c -+++ b/lib/renameat.c -@@ -16,10 +16,10 @@ - - #include - #include --#include "renameat2.h" -+#include "renameatu.h" - - int - renameat (int fd1, char const *src, int fd2, char const *dst) - { -- return renameat2 (fd1, src, fd2, dst, 0); -+ return renameatu (fd1, src, fd2, dst, 0); - } -diff --git a/lib/renameat2.c b/lib/renameatu.c -similarity index 94% -rename from lib/renameat2.c -rename to lib/renameatu.c -index a295ec3..b013ad6 100644 ---- a/lib/renameat2.c -+++ b/lib/renameatu.c -@@ -18,7 +18,7 @@ - - #include - --#include "renameat2.h" -+#include "renameatu.h" - - #include - #include -@@ -68,10 +68,13 @@ rename_noreplace (char const *src, char const *dst) - the restore_cwd fails, then give a diagnostic and exit nonzero. - - Obey FLAGS when doing the renaming. If FLAGS is zero, this -- function is equivalent to renameat (FD1, SRC, FD2, DST). */ -+ function is equivalent to renameat (FD1, SRC, FD2, DST). -+ Otherwise, attempt to implement FLAGS even if the implementation is -+ not atomic; this differs from the GNU/Linux native renameat2, -+ which fails if it cannot guarantee atomicity. */ - - int --renameat2 (int fd1, char const *src, int fd2, char const *dst, -+renameatu (int fd1, char const *src, int fd2, char const *dst, - unsigned int flags) - { - int ret_val = -1; -diff --git a/lib/renameat2.h b/lib/renameatu.h -similarity index 84% -rename from lib/renameat2.h -rename to lib/renameatu.h -index aba7966..7d79775 100644 ---- a/lib/renameat2.h -+++ b/lib/renameatu.h -@@ -16,15 +16,13 @@ - - /* written by Paul Eggert */ - --/* Get RENAME_* macros from linux/fs.h if present, otherwise supply -+/* Get RENAME_* macros from if present, otherwise supply - the traditional Linux values. */ --#if HAVE_LINUX_FS_H --# include --#endif -+#include - #ifndef RENAME_NOREPLACE - # define RENAME_NOREPLACE (1 << 0) - # define RENAME_EXCHANGE (1 << 1) - # define RENAME_WHITEOUT (1 << 2) - #endif - --extern int renameat2 (int, char const *, int, char const *, unsigned int); -+extern int renameatu (int, char const *, int, char const *, unsigned int); --- -2.14.4 - - -From a6b7ff5ef538bbdff4550a56fed878e9cd951d6d Mon Sep 17 00:00:00 2001 -From: Paul Eggert -Date: Thu, 5 Jul 2018 09:33:48 -0700 -Subject: [PATCH 2/2] build: update gnulib submodule to latest - -* bootstrap.conf, src/copy.c, src/mv.c, src/shred.c: -Adjust to renaming of renameat2 to renameatu. - -Upstream-commit: 439741053256618eb651e6d43919df29625b8714 -Signed-off-by: Kamil Dudka ---- - bootstrap.conf | 2 +- - src/copy.c | 4 ++-- - src/mv.c | 4 ++-- - src/shred.c | 4 ++-- - 4 files changed, 7 insertions(+), 7 deletions(-) - -diff --git a/bootstrap.conf b/bootstrap.conf -index 4da4f94..fcf29dc 100644 ---- a/bootstrap.conf -+++ b/bootstrap.conf -@@ -210,7 +210,7 @@ gnulib_modules=" - remove - rename - renameat -- renameat2 -+ renameatu - rmdir - root-dev-ino - rpmatch -diff --git a/src/copy.c b/src/copy.c -index 58d2f6e..1a9cdd1 100644 ---- a/src/copy.c -+++ b/src/copy.c -@@ -53,7 +53,7 @@ - #include "ignore-value.h" - #include "ioblksize.h" - #include "quote.h" --#include "renameat2.h" -+#include "renameatu.h" - #include "root-uid.h" - #include "same.h" - #include "savedir.h" -@@ -1873,7 +1873,7 @@ copy_internal (char const *src_name, char const *dst_name, - if (x->move_mode) - { - if (rename_errno < 0) -- rename_errno = (renameat2 (AT_FDCWD, src_name, AT_FDCWD, dst_name, -+ rename_errno = (renameatu (AT_FDCWD, src_name, AT_FDCWD, dst_name, - RENAME_NOREPLACE) - ? errno : 0); - new_dst = rename_errno == 0; -diff --git a/src/mv.c b/src/mv.c -index b6dd72d..36fd1af 100644 ---- a/src/mv.c -+++ b/src/mv.c -@@ -31,7 +31,7 @@ - #include "error.h" - #include "filenamecat.h" - #include "remove.h" --#include "renameat2.h" -+#include "renameatu.h" - #include "root-dev-ino.h" - #include "priv-set.h" - -@@ -456,7 +456,7 @@ main (int argc, char **argv) - { - assert (2 <= n_files); - if (n_files == 2) -- x.rename_errno = (renameat2 (AT_FDCWD, file[0], AT_FDCWD, file[1], -+ x.rename_errno = (renameatu (AT_FDCWD, file[0], AT_FDCWD, file[1], - RENAME_NOREPLACE) - ? errno : 0); - if (x.rename_errno != 0 && target_directory_operand (file[n_files - 1])) -diff --git a/src/shred.c b/src/shred.c -index 2ddaadd..270b1e9 100644 ---- a/src/shred.c -+++ b/src/shred.c -@@ -93,7 +93,7 @@ - #include "human.h" - #include "randint.h" - #include "randread.h" --#include "renameat2.h" -+#include "renameatu.h" - #include "stat-size.h" - - /* Default number of times to overwrite. */ -@@ -1096,7 +1096,7 @@ wipename (char *oldname, char const *qoldname, struct Options const *flags) - memset (base, nameset[0], len); - base[len] = 0; - bool rename_ok; -- while (! (rename_ok = (renameat2 (AT_FDCWD, oldname, AT_FDCWD, newname, -+ while (! (rename_ok = (renameatu (AT_FDCWD, oldname, AT_FDCWD, newname, - RENAME_NOREPLACE) - == 0)) - && errno == EEXIST && incname (base, len)) --- -2.14.4 - diff --git a/SOURCES/coreutils-8.30-statx.patch b/SOURCES/coreutils-8.30-statx.patch deleted file mode 100644 index 7cda82d..0000000 --- a/SOURCES/coreutils-8.30-statx.patch +++ /dev/null @@ -1,1358 +0,0 @@ -From b6a4efe4347a061161054698857b6dde0f3ed67c Mon Sep 17 00:00:00 2001 -From: Martin Bukatovic -Date: Sat, 2 Mar 2019 19:57:17 -0800 -Subject: [PATCH 1/5] stat: print birth time on systems supporting statx - -* configure.ac: Check for statx(), available on glibc >= 2.28. -* src/stat.c (get_birthtime): Call statx() when available. -* NEWS: Mention the improvement. - -Upstream-commit: 186896d65f6182dff15cad6c1045d22ad2004962 -Signed-off-by: Kamil Dudka ---- - configure.ac | 3 +++ - src/stat.c | 19 +++++++++++++++++++ - 2 files changed, 22 insertions(+) - -diff --git a/configure.ac b/configure.ac -index 9f7a8a5..c24ce2a 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -318,6 +318,9 @@ if test $ac_cv_func_getattrat = yes; then - AC_SUBST([LIB_NVPAIR]) - fi - -+# glibc >= 2.28 and linux kernel >= 4.11 -+AC_CHECK_FUNCS([statx]) -+ - # SCO-ODT-3.0 is reported to need -los to link programs using initgroups - AC_CHECK_FUNCS([initgroups]) - if test $ac_cv_func_initgroups = no; then -diff --git a/src/stat.c b/src/stat.c -index 0a5ef3c..9e71cbe 100644 ---- a/src/stat.c -+++ b/src/stat.c -@@ -1007,6 +1007,25 @@ get_birthtime (int fd, char const *filename, struct stat const *st) - } - #endif - -+#if HAVE_STATX -+ if (ts.tv_nsec < 0) -+ { -+ struct statx stx; -+ if ((fd < 0 -+ ? statx (AT_FDCWD, filename, -+ follow_links ? 0 : AT_SYMLINK_NOFOLLOW, -+ STATX_BTIME, &stx) -+ : statx (fd, "", AT_EMPTY_PATH, STATX_BTIME, &stx)) == 0) -+ { -+ if ((stx.stx_mask & STATX_BTIME) && stx.stx_btime.tv_sec != 0) -+ { -+ ts.tv_sec = stx.stx_btime.tv_sec; -+ ts.tv_nsec = stx.stx_btime.tv_nsec; -+ } -+ } -+ } -+#endif -+ - return ts; - } - --- -2.20.1 - - -From 21ff41c1e5ef4668669f92d04c69a258708ba20e Mon Sep 17 00:00:00 2001 -From: Jeff Layton -Date: Tue, 28 May 2019 08:21:42 -0400 -Subject: [PATCH 2/5] stat: Use statx where available and support --cached - -* src/stat.c: Drop statbuf argument from out_epoch_sec(). -Use statx() rather than [lf]stat() where available, -so a separate call is not required to get birth time. -Set STATX_* mask bits only for things we want to print, -which can be more efficient on some file systems. -Add a new --cache= command-line option that sets the appropriate hint -flags in the statx call. These are primarily used with network -file systems to indicate what level of cache coherency is desired. -The new option is available unconditionally for better portability, -and ignored where not implemented. -* doc/coreutils.texi: Add documention for --cached. -* man/stat.x (SEE ALSO): Mention statx(). - -Upstream-commit: 6cc35de16fdc52d417602b66d5e90694d7e02994 -Signed-off-by: Kamil Dudka ---- - doc/coreutils.texi | 21 ++ - man/stat.x | 2 +- - src/stat.c | 623 ++++++++++++++++++++++++++++++--------------- - 3 files changed, 444 insertions(+), 202 deletions(-) - -diff --git a/doc/coreutils.texi b/doc/coreutils.texi -index 6ac99be..547d17b 100644 ---- a/doc/coreutils.texi -+++ b/doc/coreutils.texi -@@ -12201,6 +12201,27 @@ Report information about the file systems where the given files are located - instead of information about the files themselves. - This option implies the @option{-L} option. - -+@item --cached=@var{mode} -+@opindex --cached=@var{mode} -+@cindex attribute caching -+Control how attributes are read from the file system; -+if supported by the system. This allows one to -+control the trade-off between freshness and efficiency -+of attribute access, especially useful with remote file systems. -+@var{mode} can be: -+ -+@table @samp -+@item always -+Always read the already cached attributes if available. -+ -+@item never -+Always sychronize with the latest file system attributes. -+ -+@item default -+Leave the caching behavior to the underlying file system. -+ -+@end table -+ - @item -c - @itemx --format=@var{format} - @opindex -c -diff --git a/man/stat.x b/man/stat.x -index dc3781e..b9f8c68 100644 ---- a/man/stat.x -+++ b/man/stat.x -@@ -3,4 +3,4 @@ stat \- display file or file system status - [DESCRIPTION] - .\" Add any additional description here - [SEE ALSO] --stat(2), statfs(2) -+stat(2), statfs(2), statx(2) -diff --git a/src/stat.c b/src/stat.c -index 9e71cbe..32ffb6d 100644 ---- a/src/stat.c -+++ b/src/stat.c -@@ -28,6 +28,12 @@ - # define USE_STATVFS 0 - #endif - -+#if HAVE_STATX && defined STATX_INO -+# define USE_STATX 1 -+#else -+# define USE_STATX 0 -+#endif -+ - #include - #include - #include -@@ -194,6 +200,23 @@ enum - PRINTF_OPTION = CHAR_MAX + 1 - }; - -+enum cached_mode -+{ -+ cached_default, -+ cached_never, -+ cached_always -+}; -+ -+static char const *const cached_args[] = -+{ -+ "default", "never", "always", NULL -+}; -+ -+static enum cached_mode const cached_modes[] = -+{ -+ cached_default, cached_never, cached_always -+}; -+ - static struct option const long_options[] = - { - {"dereference", no_argument, NULL, 'L'}, -@@ -201,6 +224,7 @@ static struct option const long_options[] = - {"format", required_argument, NULL, 'c'}, - {"printf", required_argument, NULL, PRINTF_OPTION}, - {"terse", no_argument, NULL, 't'}, -+ {"cached", required_argument, NULL, 0}, - {GETOPT_HELP_OPTION_DECL}, - {GETOPT_VERSION_OPTION_DECL}, - {NULL, 0, NULL, 0} -@@ -221,6 +245,10 @@ static char const *trailing_delim = ""; - static char const *decimal_point; - static size_t decimal_point_len; - -+static bool -+print_stat (char *pformat, size_t prefix_len, unsigned int m, -+ int fd, char const *filename, void const *data); -+ - /* Return the type of the specified file system. - Some systems have statfvs.f_basetype[FSTYPSZ] (AIX, HP-UX, and Solaris). - Others have statvfs.f_fstypename[_VFS_NAMELEN] (NetBSD 3.0). -@@ -674,7 +702,6 @@ out_minus_zero (char *pformat, size_t prefix_len) - acts like printf's %f format. */ - static void - out_epoch_sec (char *pformat, size_t prefix_len, -- struct stat const *statbuf _GL_UNUSED, - struct timespec arg) - { - char *dot = memchr (pformat, '.', prefix_len); -@@ -978,57 +1005,6 @@ print_mount_point: - return fail; - } - --static struct timespec --get_birthtime (int fd, char const *filename, struct stat const *st) --{ -- struct timespec ts = get_stat_birthtime (st); -- --#if HAVE_GETATTRAT -- if (ts.tv_nsec < 0) -- { -- nvlist_t *response; -- if ((fd < 0 -- ? getattrat (AT_FDCWD, XATTR_VIEW_READWRITE, filename, &response) -- : fgetattr (fd, XATTR_VIEW_READWRITE, &response)) -- == 0) -- { -- uint64_t *val; -- uint_t n; -- if (nvlist_lookup_uint64_array (response, A_CRTIME, &val, &n) == 0 -- && 2 <= n -- && val[0] <= TYPE_MAXIMUM (time_t) -- && val[1] < 1000000000 * 2 /* for leap seconds */) -- { -- ts.tv_sec = val[0]; -- ts.tv_nsec = val[1]; -- } -- nvlist_free (response); -- } -- } --#endif -- --#if HAVE_STATX -- if (ts.tv_nsec < 0) -- { -- struct statx stx; -- if ((fd < 0 -- ? statx (AT_FDCWD, filename, -- follow_links ? 0 : AT_SYMLINK_NOFOLLOW, -- STATX_BTIME, &stx) -- : statx (fd, "", AT_EMPTY_PATH, STATX_BTIME, &stx)) == 0) -- { -- if ((stx.stx_mask & STATX_BTIME) && stx.stx_btime.tv_sec != 0) -- { -- ts.tv_sec = stx.stx_btime.tv_sec; -- ts.tv_nsec = stx.stx_btime.tv_nsec; -- } -- } -- } --#endif -- -- return ts; --} -- - /* Map a TS with negative TS.tv_nsec to {0,0}. */ - static inline struct timespec - neg_to_zero (struct timespec ts) -@@ -1065,139 +1041,6 @@ getenv_quoting_style (void) - /* Equivalent to quotearg(), but explicit to avoid syntax checks. */ - #define quoteN(x) quotearg_style (get_quoting_style (NULL), x) - --/* Print stat info. Return zero upon success, nonzero upon failure. */ --static bool --print_stat (char *pformat, size_t prefix_len, unsigned int m, -- int fd, char const *filename, void const *data) --{ -- struct stat *statbuf = (struct stat *) data; -- struct passwd *pw_ent; -- struct group *gw_ent; -- bool fail = false; -- -- switch (m) -- { -- case 'n': -- out_string (pformat, prefix_len, filename); -- break; -- case 'N': -- out_string (pformat, prefix_len, quoteN (filename)); -- if (S_ISLNK (statbuf->st_mode)) -- { -- char *linkname = areadlink_with_size (filename, statbuf->st_size); -- if (linkname == NULL) -- { -- error (0, errno, _("cannot read symbolic link %s"), -- quoteaf (filename)); -- return true; -- } -- printf (" -> "); -- out_string (pformat, prefix_len, quoteN (linkname)); -- free (linkname); -- } -- break; -- case 'd': -- out_uint (pformat, prefix_len, statbuf->st_dev); -- break; -- case 'D': -- out_uint_x (pformat, prefix_len, statbuf->st_dev); -- break; -- case 'i': -- out_uint (pformat, prefix_len, statbuf->st_ino); -- break; -- case 'a': -- out_uint_o (pformat, prefix_len, statbuf->st_mode & CHMOD_MODE_BITS); -- break; -- case 'A': -- out_string (pformat, prefix_len, human_access (statbuf)); -- break; -- case 'f': -- out_uint_x (pformat, prefix_len, statbuf->st_mode); -- break; -- case 'F': -- out_string (pformat, prefix_len, file_type (statbuf)); -- break; -- case 'h': -- out_uint (pformat, prefix_len, statbuf->st_nlink); -- break; -- case 'u': -- out_uint (pformat, prefix_len, statbuf->st_uid); -- break; -- case 'U': -- pw_ent = getpwuid (statbuf->st_uid); -- out_string (pformat, prefix_len, -- pw_ent ? pw_ent->pw_name : "UNKNOWN"); -- break; -- case 'g': -- out_uint (pformat, prefix_len, statbuf->st_gid); -- break; -- case 'G': -- gw_ent = getgrgid (statbuf->st_gid); -- out_string (pformat, prefix_len, -- gw_ent ? gw_ent->gr_name : "UNKNOWN"); -- break; -- case 't': -- out_uint_x (pformat, prefix_len, major (statbuf->st_rdev)); -- break; -- case 'm': -- fail |= out_mount_point (filename, pformat, prefix_len, statbuf); -- break; -- case 'T': -- out_uint_x (pformat, prefix_len, minor (statbuf->st_rdev)); -- break; -- case 's': -- out_int (pformat, prefix_len, statbuf->st_size); -- break; -- case 'B': -- out_uint (pformat, prefix_len, ST_NBLOCKSIZE); -- break; -- case 'b': -- out_uint (pformat, prefix_len, ST_NBLOCKS (*statbuf)); -- break; -- case 'o': -- out_uint (pformat, prefix_len, ST_BLKSIZE (*statbuf)); -- break; -- case 'w': -- { -- struct timespec t = get_birthtime (fd, filename, statbuf); -- if (t.tv_nsec < 0) -- out_string (pformat, prefix_len, "-"); -- else -- out_string (pformat, prefix_len, human_time (t)); -- } -- break; -- case 'W': -- out_epoch_sec (pformat, prefix_len, statbuf, -- neg_to_zero (get_birthtime (fd, filename, statbuf))); -- break; -- case 'x': -- out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf))); -- break; -- case 'X': -- out_epoch_sec (pformat, prefix_len, statbuf, get_stat_atime (statbuf)); -- break; -- case 'y': -- out_string (pformat, prefix_len, human_time (get_stat_mtime (statbuf))); -- break; -- case 'Y': -- out_epoch_sec (pformat, prefix_len, statbuf, get_stat_mtime (statbuf)); -- break; -- case 'z': -- out_string (pformat, prefix_len, human_time (get_stat_ctime (statbuf))); -- break; -- case 'Z': -- out_epoch_sec (pformat, prefix_len, statbuf, get_stat_ctime (statbuf)); -- break; -- case 'C': -- fail |= out_file_context (pformat, prefix_len, filename); -- break; -- default: -- fputc ('?', stdout); -- break; -- } -- return fail; --} -- - /* Output a single-character \ escape. */ - - static void -@@ -1239,6 +1082,17 @@ print_esc_char (char c) - putchar (c); - } - -+static size_t _GL_ATTRIBUTE_PURE -+format_code_offset (char const* directive) -+{ -+ size_t len = strspn (directive + 1, printf_flags); -+ char const *fmt_char = directive + len + 1; -+ fmt_char += strspn (fmt_char, digits); -+ if (*fmt_char == '.') -+ fmt_char += 1 + strspn (fmt_char + 1, digits); -+ return fmt_char - directive; -+} -+ - /* Print the information specified by the format string, FORMAT, - calling PRINT_FUNC for each %-directive encountered. - Return zero upon success, nonzero upon failure. */ -@@ -1268,33 +1122,28 @@ print_it (char const *format, int fd, char const *filename, - { - case '%': - { -- size_t len = strspn (b + 1, printf_flags); -- char const *fmt_char = b + len + 1; -- fmt_char += strspn (fmt_char, digits); -- if (*fmt_char == '.') -- fmt_char += 1 + strspn (fmt_char + 1, digits); -- len = fmt_char - (b + 1); -- unsigned int fmt_code = *fmt_char; -- memcpy (dest, b, len + 1); -- -- b = fmt_char; -- switch (fmt_code) -+ size_t len = format_code_offset (b); -+ char const *fmt_char = b + len; -+ memcpy (dest, b, len); -+ b += len; -+ -+ switch (*fmt_char) - { - case '\0': - --b; - FALLTHROUGH; - case '%': -- if (0 < len) -+ if (1 < len) - { -- dest[len + 1] = *fmt_char; -- dest[len + 2] = '\0'; -+ dest[len] = *fmt_char; -+ dest[len + 1] = '\0'; - die (EXIT_FAILURE, 0, _("%s: invalid directive"), - quote (dest)); - } - putchar ('%'); - break; - default: -- fail |= print_func (dest, len + 1, fmt_code, -+ fail |= print_func (dest, len, to_uchar (*fmt_char), - fd, filename, data); - break; - } -@@ -1382,6 +1231,204 @@ do_statfs (char const *filename, char const *format) - return ! fail; - } - -+struct print_args { -+ struct stat *st; -+ struct timespec btime; -+}; -+ -+/* Ask statx to avoid syncing? */ -+static bool dont_sync; -+ -+/* Ask statx to force sync? */ -+static bool force_sync; -+ -+#if USE_STATX -+/* Much of the format printing requires a struct stat or timespec */ -+static struct timespec -+statx_timestamp_to_timespec (struct statx_timestamp tsx) -+{ -+ struct timespec ts; -+ -+ ts.tv_sec = tsx.tv_sec; -+ ts.tv_nsec = tsx.tv_nsec; -+ return ts; -+} -+ -+static void -+statx_to_stat (struct statx *stx, struct stat *stat) -+{ -+ stat->st_dev = makedev (stx->stx_dev_major, stx->stx_dev_minor); -+ stat->st_ino = stx->stx_ino; -+ stat->st_mode = stx->stx_mode; -+ stat->st_nlink = stx->stx_nlink; -+ stat->st_uid = stx->stx_uid; -+ stat->st_gid = stx->stx_gid; -+ stat->st_rdev = makedev (stx->stx_rdev_major, stx->stx_rdev_minor); -+ stat->st_size = stx->stx_size; -+ stat->st_blksize = stx->stx_blksize; -+/* define to avoid sc_prohibit_stat_st_blocks. */ -+# define SC_ST_BLOCKS st_blocks -+ stat->SC_ST_BLOCKS = stx->stx_blocks; -+ stat->st_atim = statx_timestamp_to_timespec (stx->stx_atime); -+ stat->st_mtim = statx_timestamp_to_timespec (stx->stx_mtime); -+ stat->st_ctim = statx_timestamp_to_timespec (stx->stx_ctime); -+} -+ -+static unsigned int -+fmt_to_mask (char fmt) -+{ -+ switch (fmt) -+ { -+ case 'N': -+ return STATX_MODE|STATX_SIZE; -+ case 'd': -+ case 'D': -+ return STATX_MODE; -+ case 'i': -+ return STATX_INO; -+ case 'a': -+ case 'A': -+ return STATX_MODE; -+ case 'f': -+ return STATX_MODE|STATX_TYPE; -+ case 'F': -+ return STATX_TYPE; -+ case 'h': -+ return STATX_NLINK; -+ case 'u': -+ case 'U': -+ return STATX_UID; -+ case 'g': -+ case 'G': -+ return STATX_GID; -+ case 'm': -+ return STATX_MODE|STATX_INO; -+ case 's': -+ return STATX_SIZE; -+ case 't': -+ case 'T': -+ return STATX_MODE; -+ case 'b': -+ return STATX_BLOCKS; -+ case 'w': -+ case 'W': -+ return STATX_BTIME; -+ case 'x': -+ case 'X': -+ return STATX_ATIME; -+ case 'y': -+ case 'Y': -+ return STATX_MTIME; -+ case 'z': -+ case 'Z': -+ return STATX_CTIME; -+ } -+ return 0; -+} -+ -+static unsigned int _GL_ATTRIBUTE_PURE -+format_to_mask (char const *format) -+{ -+ unsigned int mask = 0; -+ char const *b; -+ -+ for (b = format; *b; b++) -+ { -+ if (*b != '%') -+ continue; -+ -+ b += format_code_offset (b); -+ if (*b == '\0') -+ break; -+ mask |= fmt_to_mask (*b); -+ } -+ return mask; -+} -+ -+/* statx the file and print what we find */ -+static bool ATTRIBUTE_WARN_UNUSED_RESULT -+do_stat (char const *filename, char const *format, char const *format2) -+{ -+ int fd = STREQ (filename, "-") ? 0 : AT_FDCWD; -+ int flags = 0; -+ struct stat st; -+ struct statx stx; -+ const char *pathname = filename; -+ struct print_args pa; -+ pa.st = &st; -+ pa.btime = (struct timespec) {-1, -1}; -+ -+ if (AT_FDCWD != fd) -+ { -+ pathname = ""; -+ flags = AT_EMPTY_PATH; -+ } -+ else if (!follow_links) -+ { -+ flags = AT_SYMLINK_NOFOLLOW; -+ } -+ -+ if (dont_sync) -+ flags |= AT_STATX_DONT_SYNC; -+ else if (force_sync) -+ flags |= AT_STATX_FORCE_SYNC; -+ -+ fd = statx (fd, pathname, flags, format_to_mask (format), &stx); -+ if (fd < 0) -+ { -+ if (flags & AT_EMPTY_PATH) -+ error (0, errno, _("cannot stat standard input")); -+ else -+ error (0, errno, _("cannot statx %s"), quoteaf (filename)); -+ return false; -+ } -+ -+ if (S_ISBLK (stx.stx_mode) || S_ISCHR (stx.stx_mode)) -+ format = format2; -+ -+ statx_to_stat (&stx, &st); -+ if (stx.stx_mask & STATX_BTIME) -+ pa.btime = statx_timestamp_to_timespec (stx.stx_btime); -+ -+ bool fail = print_it (format, fd, filename, print_stat, &pa); -+ return ! fail; -+} -+ -+#else /* USE_STATX */ -+ -+static struct timespec -+get_birthtime (int fd, char const *filename, struct stat const *st) -+{ -+ struct timespec ts = get_stat_birthtime (st); -+ -+# if HAVE_GETATTRAT -+ if (ts.tv_nsec < 0) -+ { -+ nvlist_t *response; -+ if ((fd < 0 -+ ? getattrat (AT_FDCWD, XATTR_VIEW_READWRITE, filename, &response) -+ : fgetattr (fd, XATTR_VIEW_READWRITE, &response)) -+ == 0) -+ { -+ uint64_t *val; -+ uint_t n; -+ if (nvlist_lookup_uint64_array (response, A_CRTIME, &val, &n) == 0 -+ && 2 <= n -+ && val[0] <= TYPE_MAXIMUM (time_t) -+ && val[1] < 1000000000 * 2 /* for leap seconds */) -+ { -+ ts.tv_sec = val[0]; -+ ts.tv_nsec = val[1]; -+ } -+ nvlist_free (response); -+ } -+ } -+# endif -+ -+ return ts; -+} -+ -+ - /* stat the file and print what we find */ - static bool ATTRIBUTE_WARN_UNUSED_RESULT - do_stat (char const *filename, char const *format, -@@ -1389,6 +1436,9 @@ do_stat (char const *filename, char const *format, - { - int fd = STREQ (filename, "-") ? 0 : -1; - struct stat statbuf; -+ struct print_args pa; -+ pa.st = &statbuf; -+ pa.btime = (struct timespec) {-1, -1}; - - if (0 <= fd) - { -@@ -1412,9 +1462,152 @@ do_stat (char const *filename, char const *format, - if (S_ISBLK (statbuf.st_mode) || S_ISCHR (statbuf.st_mode)) - format = format2; - -- bool fail = print_it (format, fd, filename, print_stat, &statbuf); -+ bool fail = print_it (format, fd, filename, print_stat, &pa); - return ! fail; - } -+#endif /* USE_STATX */ -+ -+ -+/* Print stat info. Return zero upon success, nonzero upon failure. */ -+static bool -+print_stat (char *pformat, size_t prefix_len, unsigned int m, -+ int fd, char const *filename, void const *data) -+{ -+ struct print_args *parg = (struct print_args *) data; -+ struct stat *statbuf = parg->st; -+ struct timespec btime = parg->btime; -+ struct passwd *pw_ent; -+ struct group *gw_ent; -+ bool fail = false; -+ -+ switch (m) -+ { -+ case 'n': -+ out_string (pformat, prefix_len, filename); -+ break; -+ case 'N': -+ out_string (pformat, prefix_len, quoteN (filename)); -+ if (S_ISLNK (statbuf->st_mode)) -+ { -+ char *linkname = areadlink_with_size (filename, statbuf->st_size); -+ if (linkname == NULL) -+ { -+ error (0, errno, _("cannot read symbolic link %s"), -+ quoteaf (filename)); -+ return true; -+ } -+ printf (" -> "); -+ out_string (pformat, prefix_len, quoteN (linkname)); -+ free (linkname); -+ } -+ break; -+ case 'd': -+ out_uint (pformat, prefix_len, statbuf->st_dev); -+ break; -+ case 'D': -+ out_uint_x (pformat, prefix_len, statbuf->st_dev); -+ break; -+ case 'i': -+ out_uint (pformat, prefix_len, statbuf->st_ino); -+ break; -+ case 'a': -+ out_uint_o (pformat, prefix_len, statbuf->st_mode & CHMOD_MODE_BITS); -+ break; -+ case 'A': -+ out_string (pformat, prefix_len, human_access (statbuf)); -+ break; -+ case 'f': -+ out_uint_x (pformat, prefix_len, statbuf->st_mode); -+ break; -+ case 'F': -+ out_string (pformat, prefix_len, file_type (statbuf)); -+ break; -+ case 'h': -+ out_uint (pformat, prefix_len, statbuf->st_nlink); -+ break; -+ case 'u': -+ out_uint (pformat, prefix_len, statbuf->st_uid); -+ break; -+ case 'U': -+ pw_ent = getpwuid (statbuf->st_uid); -+ out_string (pformat, prefix_len, -+ pw_ent ? pw_ent->pw_name : "UNKNOWN"); -+ break; -+ case 'g': -+ out_uint (pformat, prefix_len, statbuf->st_gid); -+ break; -+ case 'G': -+ gw_ent = getgrgid (statbuf->st_gid); -+ out_string (pformat, prefix_len, -+ gw_ent ? gw_ent->gr_name : "UNKNOWN"); -+ break; -+ case 'm': -+ fail |= out_mount_point (filename, pformat, prefix_len, statbuf); -+ break; -+ case 's': -+ out_int (pformat, prefix_len, statbuf->st_size); -+ break; -+ case 't': -+ out_uint_x (pformat, prefix_len, major (statbuf->st_rdev)); -+ break; -+ case 'T': -+ out_uint_x (pformat, prefix_len, minor (statbuf->st_rdev)); -+ break; -+ case 'B': -+ out_uint (pformat, prefix_len, ST_NBLOCKSIZE); -+ break; -+ case 'b': -+ out_uint (pformat, prefix_len, ST_NBLOCKS (*statbuf)); -+ break; -+ case 'o': -+ out_uint (pformat, prefix_len, ST_BLKSIZE (*statbuf)); -+ break; -+ case 'w': -+ { -+#if ! USE_STATX -+ btime = get_birthtime (fd, filename, statbuf); -+#endif -+ if (btime.tv_nsec < 0) -+ out_string (pformat, prefix_len, "-"); -+ else -+ out_string (pformat, prefix_len, human_time (btime)); -+ } -+ break; -+ case 'W': -+ { -+#if ! USE_STATX -+ btime = get_birthtime (fd, filename, statbuf); -+#endif -+ out_epoch_sec (pformat, prefix_len, neg_to_zero (btime)); -+ } -+ break; -+ case 'x': -+ out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf))); -+ break; -+ case 'X': -+ out_epoch_sec (pformat, prefix_len, get_stat_atime (statbuf)); -+ break; -+ case 'y': -+ out_string (pformat, prefix_len, human_time (get_stat_mtime (statbuf))); -+ break; -+ case 'Y': -+ out_epoch_sec (pformat, prefix_len, get_stat_mtime (statbuf)); -+ break; -+ case 'z': -+ out_string (pformat, prefix_len, human_time (get_stat_ctime (statbuf))); -+ break; -+ case 'Z': -+ out_epoch_sec (pformat, prefix_len, get_stat_ctime (statbuf)); -+ break; -+ case 'C': -+ fail |= out_file_context (pformat, prefix_len, filename); -+ break; -+ default: -+ fputc ('?', stdout); -+ break; -+ } -+ return fail; -+} - - /* Return an allocated format string in static storage that - corresponds to whether FS and TERSE options were declared. */ -@@ -1523,6 +1716,10 @@ Display file or file system status.\n\ - fputs (_("\ - -L, --dereference follow links\n\ - -f, --file-system display file system status instead of file status\n\ -+"), stdout); -+ fputs (_("\ -+ --cached=MODE specify how to use cached attributes;\n\ -+ useful on remote file systems. See MODE below\n\ - "), stdout); - fputs (_("\ - -c --format=FORMAT use the specified FORMAT instead of the default;\n\ -@@ -1535,6 +1732,13 @@ Display file or file system status.\n\ - fputs (HELP_OPTION_DESCRIPTION, stdout); - fputs (VERSION_OPTION_DESCRIPTION, stdout); - -+ fputs (_("\n\ -+The --cached MODE argument can be; always, never, or default.\n\ -+`always` will use cached attributes if available, while\n\ -+`never` will try to synchronize with the latest attributes, and\n\ -+`default` will leave it up to the underlying file system.\n\ -+"), stdout); -+ - fputs (_("\n\ - The valid format sequences for files (without --file-system):\n\ - \n\ -@@ -1668,6 +1872,23 @@ main (int argc, char *argv[]) - terse = true; - break; - -+ case 0: -+ switch (XARGMATCH ("--cached", optarg, cached_args, cached_modes)) -+ { -+ case cached_never: -+ force_sync = true; -+ dont_sync = false; -+ break; -+ case cached_always: -+ force_sync = false; -+ dont_sync = true; -+ break; -+ case cached_default: -+ force_sync = false; -+ dont_sync = false; -+ } -+ break; -+ - case_GETOPT_HELP_CHAR; - - case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); --- -2.20.1 - - -From b9d6d0b4902cfa5ff3edf5ac7a082138f3237847 Mon Sep 17 00:00:00 2001 -From: Jeff Layton -Date: Fri, 14 Jun 2019 14:37:43 -0400 -Subject: [PATCH 3/5] stat: fix enabling of statx logic - -* src/stat.c: STATX_INO isn't defined until stat.h is included. -Move the test down so it works properly. - -Upstream-commit: 0b9bac90d8283c1262e74f0dbda87583508de9a3 -Signed-off-by: Kamil Dudka ---- - src/stat.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/stat.c b/src/stat.c -index 32ffb6d..1d9d83a 100644 ---- a/src/stat.c -+++ b/src/stat.c -@@ -28,12 +28,6 @@ - # define USE_STATVFS 0 - #endif - --#if HAVE_STATX && defined STATX_INO --# define USE_STATX 1 --#else --# define USE_STATX 0 --#endif -- - #include - #include - #include -@@ -80,6 +74,12 @@ - #include "find-mount-point.h" - #include "xvasprintf.h" - -+#if HAVE_STATX && defined STATX_INO -+# define USE_STATX 1 -+#else -+# define USE_STATX 0 -+#endif -+ - #if USE_STATVFS - # define STRUCT_STATXFS_F_FSID_IS_INTEGER STRUCT_STATVFS_F_FSID_IS_INTEGER - # define HAVE_STRUCT_STATXFS_F_TYPE HAVE_STRUCT_STATVFS_F_TYPE --- -2.20.1 - - -From 987cb69ae212a257b5f8d1582dac03c2aa1aa399 Mon Sep 17 00:00:00 2001 -From: Andreas Dilger -Date: Thu, 27 Jun 2019 02:25:55 -0600 -Subject: [PATCH 4/5] stat: don't explicitly request file size for filenames - -When calling 'stat -c %N' to print the filename, don't explicitly -request the size of the file via statx(), as it may add overhead on -some filesystems. The size is only needed to optimize an allocation -for the relatively rare case of reading a symlink name, and the worst -effect is a somewhat-too-large temporary buffer may be allocated for -areadlink_with_size(), or internal retries if buffer is too small. - -The file size will be returned by statx() on most filesystems, even -if not requested, unless the filesystem considers this to be too -expensive for that file, in which case the tradeoff is worthwhile. - -* src/stat.c: Don't explicitly request STATX_SIZE for filenames. - -Upstream-commit: a1a5e9a32eb9525680edd02fd127240c27ba0999 -Signed-off-by: Kamil Dudka ---- - src/stat.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/stat.c b/src/stat.c -index 1d9d83a..32bb5f0 100644 ---- a/src/stat.c -+++ b/src/stat.c -@@ -1280,7 +1280,7 @@ fmt_to_mask (char fmt) - switch (fmt) - { - case 'N': -- return STATX_MODE|STATX_SIZE; -+ return STATX_MODE; - case 'd': - case 'D': - return STATX_MODE; -@@ -1352,7 +1352,7 @@ do_stat (char const *filename, char const *format, char const *format2) - int fd = STREQ (filename, "-") ? 0 : AT_FDCWD; - int flags = 0; - struct stat st; -- struct statx stx; -+ struct statx stx = { 0, }; - const char *pathname = filename; - struct print_args pa; - pa.st = &st; --- -2.20.1 - - -From 5da6c36dacac4fd610ddad1bc0b2547a9cdfdf2f Mon Sep 17 00:00:00 2001 -From: Jeff Layton -Date: Thu, 19 Sep 2019 11:59:45 -0400 -Subject: [PATCH 5/5] ls: use statx instead of stat when available - -statx allows ls to indicate interest in only certain inode metadata. -This is potentially a win on networked/clustered/distributed -file systems. In cases where we'd have to do a full, heavyweight stat() -call we can now do a much lighter statx() call. - -As a real-world example, consider a file system like CephFS where one -client is actively writing to a file and another client does an -ls --color in the same directory. --color means that we need to fetch -the mode of the file. - -Doing that with a stat() call means that we have to fetch the size and -mtime in addition to the mode. The MDS in that situation will have to -revoke caps in order to ensure that it has up-to-date values to report, -which disrupts the writer. - -This has a measurable affect on performance. I ran a fio sequential -write test on one cephfs client and had a second client do "ls --color" -in a tight loop on the directory that held the file: - -Baseline -- no activity on the second client: - -WRITE: bw=76.7MiB/s (80.4MB/s), 76.7MiB/s-76.7MiB/s (80.4MB/s-80.4MB/s), - io=4600MiB (4824MB), run=60016-60016msec - -Without this patch series, we see a noticable performance hit: - -WRITE: bw=70.4MiB/s (73.9MB/s), 70.4MiB/s-70.4MiB/s (73.9MB/s-73.9MB/s), - io=4228MiB (4433MB), run=60012-60012msec - -With this patch series, we gain most of that ground back: - -WRITE: bw=75.9MiB/s (79.6MB/s), 75.9MiB/s-75.9MiB/s (79.6MB/s-79.6MB/s), - io=4555MiB (4776MB), run=60019-60019msec - -* src/stat.c: move statx to stat struct conversion to new header... -* src/statx.h: ...here. -* src/ls.c: Add wrapper functions for stat/lstat/fstat calls, -and add variants for when we are only interested in specific info. -Add statx-enabled functions and set the request mask based on the -output format and what values are needed. - -Upstream-commit: a99ab266110795ed94a9cb4d2765ddad9c4310da -Signed-off-by: Kamil Dudka ---- - src/local.mk | 1 + - src/ls.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++--- - src/stat.c | 32 +----------- - src/statx.h | 52 ++++++++++++++++++ - 4 files changed, 192 insertions(+), 38 deletions(-) - create mode 100644 src/statx.h - -diff --git a/src/local.mk b/src/local.mk -index 7a587bb..c013590 100644 ---- a/src/local.mk -+++ b/src/local.mk -@@ -58,6 +58,7 @@ noinst_HEADERS = \ - src/prog-fprintf.h \ - src/remove.h \ - src/set-fields.h \ -+ src/statx.h \ - src/system.h \ - src/uname.h - -diff --git a/src/ls.c b/src/ls.c -index bf0c594..7f68e3c 100644 ---- a/src/ls.c -+++ b/src/ls.c -@@ -114,6 +114,7 @@ - #include "xgethostname.h" - #include "c-ctype.h" - #include "canonicalize.h" -+#include "statx.h" - - /* Include last to avoid a clash of - include guards with some premature versions of libcap. -@@ -1063,6 +1064,136 @@ dired_dump_obstack (const char *prefix, struct obstack *os) - } - } - -+#if HAVE_STATX && defined STATX_INO -+static unsigned int _GL_ATTRIBUTE_PURE -+time_type_to_statx (void) -+{ -+ switch (time_type) -+ { -+ case time_ctime: -+ return STATX_CTIME; -+ case time_mtime: -+ return STATX_MTIME; -+ case time_atime: -+ return STATX_ATIME; -+ default: -+ abort (); -+ } -+ return 0; -+} -+ -+static unsigned int _GL_ATTRIBUTE_PURE -+calc_req_mask (void) -+{ -+ unsigned int mask = STATX_MODE; -+ -+ if (print_inode) -+ mask |= STATX_INO; -+ -+ if (print_block_size) -+ mask |= STATX_BLOCKS; -+ -+ if (format == long_format) { -+ mask |= STATX_NLINK | STATX_SIZE | time_type_to_statx (); -+ if (print_owner || print_author) -+ mask |= STATX_UID; -+ if (print_group) -+ mask |= STATX_GID; -+ } -+ -+ switch (sort_type) -+ { -+ case sort_none: -+ case sort_name: -+ case sort_version: -+ case sort_extension: -+ break; -+ case sort_time: -+ mask |= time_type_to_statx (); -+ break; -+ case sort_size: -+ mask |= STATX_SIZE; -+ break; -+ default: -+ abort (); -+ } -+ -+ return mask; -+} -+ -+static int -+do_statx (int fd, const char *name, struct stat *st, int flags, -+ unsigned int mask) -+{ -+ struct statx stx; -+ int ret = statx (fd, name, flags, mask, &stx); -+ if (ret >= 0) -+ statx_to_stat (&stx, st); -+ return ret; -+} -+ -+static inline int -+do_stat (const char *name, struct stat *st) -+{ -+ return do_statx (AT_FDCWD, name, st, 0, calc_req_mask ()); -+} -+ -+static inline int -+do_lstat (const char *name, struct stat *st) -+{ -+ return do_statx (AT_FDCWD, name, st, AT_SYMLINK_NOFOLLOW, calc_req_mask ()); -+} -+ -+static inline int -+stat_for_mode (const char *name, struct stat *st) -+{ -+ return do_statx (AT_FDCWD, name, st, 0, STATX_MODE); -+} -+ -+/* dev+ino should be static, so no need to sync with backing store */ -+static inline int -+stat_for_ino (const char *name, struct stat *st) -+{ -+ return do_statx (AT_FDCWD, name, st, 0, STATX_INO); -+} -+ -+static inline int -+fstat_for_ino (int fd, struct stat *st) -+{ -+ return do_statx (fd, "", st, AT_EMPTY_PATH, STATX_INO); -+} -+#else -+static inline int -+do_stat (const char *name, struct stat *st) -+{ -+ return stat (name, st); -+} -+ -+static inline int -+do_lstat (const char *name, struct stat *st) -+{ -+ return lstat (name, st); -+} -+ -+static inline int -+stat_for_mode (const char *name, struct stat *st) -+{ -+ return stat (name, st); -+} -+ -+static inline int -+stat_for_ino (const char *name, struct stat *st) -+{ -+ return stat (name, st); -+} -+ -+static inline int -+fstat_for_ino (int fd, struct stat *st) -+{ -+ return fstat (fd, st); -+} -+#endif -+ - /* Return the address of the first plain %b spec in FMT, or NULL if - there is no such spec. %5b etc. do not match, so that user - widths/flags are honored. */ -@@ -2733,10 +2864,10 @@ print_dir (char const *name, char const *realname, bool command_line_arg) - struct stat dir_stat; - int fd = dirfd (dirp); - -- /* If dirfd failed, endure the overhead of using stat. */ -+ /* If dirfd failed, endure the overhead of stat'ing by path */ - if ((0 <= fd -- ? fstat (fd, &dir_stat) -- : stat (name, &dir_stat)) < 0) -+ ? fstat_for_ino (fd, &dir_stat) -+ : stat_for_ino (name, &dir_stat)) < 0) - { - file_failure (command_line_arg, - _("cannot determine device and inode of %s"), name); -@@ -3198,7 +3329,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode, - switch (dereference) - { - case DEREF_ALWAYS: -- err = stat (full_name, &f->stat); -+ err = do_stat (full_name, &f->stat); - do_deref = true; - break; - -@@ -3207,7 +3338,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode, - if (command_line_arg) - { - bool need_lstat; -- err = stat (full_name, &f->stat); -+ err = do_stat (full_name, &f->stat); - do_deref = true; - - if (dereference == DEREF_COMMAND_LINE_ARGUMENTS) -@@ -3227,7 +3358,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode, - FALLTHROUGH; - - default: /* DEREF_NEVER */ -- err = lstat (full_name, &f->stat); -+ err = do_lstat (full_name, &f->stat); - do_deref = false; - break; - } -@@ -3316,7 +3447,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode, - they won't be traced and when no indicator is needed. */ - if (linkname - && (file_type <= indicator_style || check_symlink_color) -- && stat (linkname, &linkstats) == 0) -+ && stat_for_mode (linkname, &linkstats) == 0) - { - f->linkok = true; - -diff --git a/src/stat.c b/src/stat.c -index 32bb5f0..03fecc3 100644 ---- a/src/stat.c -+++ b/src/stat.c -@@ -73,6 +73,7 @@ - #include "strftime.h" - #include "find-mount-point.h" - #include "xvasprintf.h" -+#include "statx.h" - - #if HAVE_STATX && defined STATX_INO - # define USE_STATX 1 -@@ -1243,37 +1244,6 @@ static bool dont_sync; - static bool force_sync; - - #if USE_STATX --/* Much of the format printing requires a struct stat or timespec */ --static struct timespec --statx_timestamp_to_timespec (struct statx_timestamp tsx) --{ -- struct timespec ts; -- -- ts.tv_sec = tsx.tv_sec; -- ts.tv_nsec = tsx.tv_nsec; -- return ts; --} -- --static void --statx_to_stat (struct statx *stx, struct stat *stat) --{ -- stat->st_dev = makedev (stx->stx_dev_major, stx->stx_dev_minor); -- stat->st_ino = stx->stx_ino; -- stat->st_mode = stx->stx_mode; -- stat->st_nlink = stx->stx_nlink; -- stat->st_uid = stx->stx_uid; -- stat->st_gid = stx->stx_gid; -- stat->st_rdev = makedev (stx->stx_rdev_major, stx->stx_rdev_minor); -- stat->st_size = stx->stx_size; -- stat->st_blksize = stx->stx_blksize; --/* define to avoid sc_prohibit_stat_st_blocks. */ --# define SC_ST_BLOCKS st_blocks -- stat->SC_ST_BLOCKS = stx->stx_blocks; -- stat->st_atim = statx_timestamp_to_timespec (stx->stx_atime); -- stat->st_mtim = statx_timestamp_to_timespec (stx->stx_mtime); -- stat->st_ctim = statx_timestamp_to_timespec (stx->stx_ctime); --} -- - static unsigned int - fmt_to_mask (char fmt) - { -diff --git a/src/statx.h b/src/statx.h -new file mode 100644 -index 0000000..19f3e18 ---- /dev/null -+++ b/src/statx.h -@@ -0,0 +1,52 @@ -+/* statx -> stat conversion functions for coreutils -+ Copyright (C) 2019 Free Software Foundation, Inc. -+ -+ This program is free software: you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation, either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . */ -+ -+#ifndef COREUTILS_STATX_H -+# define COREUTILS_STATX_H -+ -+# if HAVE_STATX && defined STATX_INO -+/* Much of the format printing requires a struct stat or timespec */ -+static inline struct timespec -+statx_timestamp_to_timespec (struct statx_timestamp tsx) -+{ -+ struct timespec ts; -+ -+ ts.tv_sec = tsx.tv_sec; -+ ts.tv_nsec = tsx.tv_nsec; -+ return ts; -+} -+ -+static inline void -+statx_to_stat (struct statx *stx, struct stat *stat) -+{ -+ stat->st_dev = makedev (stx->stx_dev_major, stx->stx_dev_minor); -+ stat->st_ino = stx->stx_ino; -+ stat->st_mode = stx->stx_mode; -+ stat->st_nlink = stx->stx_nlink; -+ stat->st_uid = stx->stx_uid; -+ stat->st_gid = stx->stx_gid; -+ stat->st_rdev = makedev (stx->stx_rdev_major, stx->stx_rdev_minor); -+ stat->st_size = stx->stx_size; -+ stat->st_blksize = stx->stx_blksize; -+/* define to avoid sc_prohibit_stat_st_blocks. */ -+# define SC_ST_BLOCKS st_blocks -+ stat->SC_ST_BLOCKS = stx->stx_blocks; -+ stat->st_atim = statx_timestamp_to_timespec (stx->stx_atime); -+ stat->st_mtim = statx_timestamp_to_timespec (stx->stx_mtime); -+ stat->st_ctim = statx_timestamp_to_timespec (stx->stx_ctime); -+} -+# endif /* HAVE_STATX && defined STATX_INO */ -+#endif /* COREUTILS_STATX_H */ --- -2.20.1 - diff --git a/SOURCES/coreutils-8.30-tail-use-poll.patch b/SOURCES/coreutils-8.30-tail-use-poll.patch deleted file mode 100644 index 804d567..0000000 --- a/SOURCES/coreutils-8.30-tail-use-poll.patch +++ /dev/null @@ -1,469 +0,0 @@ -From 95f427178720d047316e95f44777cfdf2ecf2b46 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?P=C3=A1draig=20Brady?= -Date: Fri, 4 Jan 2019 09:29:13 -0800 -Subject: [PATCH 1/4] tail: don't exit immediately with filters on AIX - -* src/tail.c: Fix the check_output_available check on AIX. -Note we don't use poll for all systems as the overhead -of adding the gnulib poll module wouldn't be worth it -just for this single use. -* tests/tail-2/pipe-f.sh: Fix the test which always passed -due to only the exit code of sleep being checked. -* NEWS: Mention the bug fix and rearrange alphabetically. -Fixes http://bugs.gnu.org/33946 - -Upstream-commit: d5ab4cbe424e3e95140eec22ef828f50b2fb3067 -Signed-off-by: Kamil Dudka ---- - src/tail.c | 13 +++++++++++++ - tests/tail-2/pipe-f.sh | 5 ++++- - 2 files changed, 17 insertions(+), 1 deletion(-) - -diff --git a/src/tail.c b/src/tail.c -index ac001d7..d63aacc 100644 ---- a/src/tail.c -+++ b/src/tail.c -@@ -30,6 +30,9 @@ - #include - #include - #include -+#ifdef _AIX -+# include -+#endif - - #include "system.h" - #include "argmatch.h" -@@ -335,6 +338,16 @@ named file in a way that accommodates renaming, removal and creation.\n\ - static void - check_output_alive (void) - { -+#ifdef _AIX -+ /* select on AIX was seen to give a readable event immediately. */ -+ struct pollfd pfd; -+ pfd.fd = STDOUT_FILENO; -+ pfd.events = POLLERR; -+ -+ if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR)) -+ raise (SIGPIPE); -+#endif -+ - if (! monitor_output) - return; - -diff --git a/tests/tail-2/pipe-f.sh b/tests/tail-2/pipe-f.sh -index 76b0d90..1126c93 100755 ---- a/tests/tail-2/pipe-f.sh -+++ b/tests/tail-2/pipe-f.sh -@@ -37,7 +37,10 @@ compare exp out || fail=1 - - # This would wait indefinitely before v8.28 due to no EPIPE being - # generated due to no data written after the first small amount --timeout 10 tail -f $mode $fastpoll out | sleep .1 || fail=1 -+(returns_ 124 timeout 10 tail -n2 -f $mode $fastpoll out && touch timed_out) | -+ sed 2q > out2 -+test -e timed_out && fail=1 -+compare exp out2 || fail=1 - - # This would wait indefinitely before v8.28 (until first write) - (returns_ 1 timeout 10 tail -f $mode $fastpoll /dev/null >&-) || fail=1 --- -2.31.1 - - -From 125bb79d3e9f414533b1c29237ee3f647053d0d6 Mon Sep 17 00:00:00 2001 -From: Ayappan -Date: Sun, 20 Jan 2019 00:17:33 -0800 -Subject: [PATCH 2/4] tail: fix recent ineffective AIX change - -* src/tail.c: Fix commit v8.30-40-gd5ab4cb which was ineffective. -Fixes http://bugs.gnu.org/33946 - -Upstream-commit: 17983b2cb3bccbb4fa69691178caddd99269bda9 -Signed-off-by: Kamil Dudka ---- - src/tail.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/tail.c b/src/tail.c -index d63aacc..9ed6d48 100644 ---- a/src/tail.c -+++ b/src/tail.c -@@ -338,6 +338,9 @@ named file in a way that accommodates renaming, removal and creation.\n\ - static void - check_output_alive (void) - { -+ if (! monitor_output) -+ return; -+ - #ifdef _AIX - /* select on AIX was seen to give a readable event immediately. */ - struct pollfd pfd; -@@ -346,11 +349,7 @@ check_output_alive (void) - - if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR)) - raise (SIGPIPE); --#endif -- -- if (! monitor_output) -- return; -- -+#else - struct timeval delay; - delay.tv_sec = delay.tv_usec = 0; - -@@ -362,6 +361,7 @@ check_output_alive (void) - and implies an error condition on output like broken pipe. */ - if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1) - raise (SIGPIPE); -+#endif - } - - static bool --- -2.31.1 - - -From 7741989c3e633aa44f01d8f91332cb65a9280ba3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?P=C3=A1draig=20Brady?= -Date: Sun, 20 Jan 2019 00:13:15 -0800 -Subject: [PATCH 3/4] tail: fix handling of broken pipes with SIGPIPE ignored - -* init.cfg (trap_sigpipe_or_skip_): A new function refactored from... -* tests/misc/printf-surprise.sh: ...here. -* tests/misc/seq-epipe.sh. Likewise. -* src/tail.c (die_pipe): Ensure we exit upon sending SIGPIPE. -* tests/tail-2/pipe-f.sh: Ensure we exit even if SIGPIPE is ignored. -* NEWS: Mention the bug fix. - -Upstream-commit: fa50623394f491b975dbd7ad73193519dd721771 -Signed-off-by: Kamil Dudka ---- - init.cfg | 6 ++++++ - src/tail.c | 14 +++++++++++--- - tests/misc/printf-surprise.sh | 4 +--- - tests/misc/seq-epipe.sh | 4 +--- - tests/tail-2/pipe-f.sh | 19 ++++++++++++++----- - 5 files changed, 33 insertions(+), 14 deletions(-) - -diff --git a/init.cfg b/init.cfg -index b6c81ab..985c8d3 100644 ---- a/init.cfg -+++ b/init.cfg -@@ -613,6 +613,12 @@ mkfifo_or_skip_() - fi - } - -+trap_sigpipe_or_skip_() -+{ -+ (trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' || -+ skip_ 'trapping SIGPIPE is not supported' -+} -+ - # Disable the current test if the working directory seems to have - # the setgid bit set. - skip_if_setgid_() -diff --git a/src/tail.c b/src/tail.c -index 9ed6d48..16e0d73 100644 ---- a/src/tail.c -+++ b/src/tail.c -@@ -333,6 +333,14 @@ named file in a way that accommodates renaming, removal and creation.\n\ - exit (status); - } - -+/* Ensure exit, either with SIGPIPE or EXIT_FAILURE status. */ -+static void ATTRIBUTE_NORETURN -+die_pipe (void) -+{ -+ raise (SIGPIPE); -+ exit (EXIT_FAILURE); -+} -+ - /* If the output has gone away, then terminate - as we would if we had written to this output. */ - static void -@@ -348,7 +356,7 @@ check_output_alive (void) - pfd.events = POLLERR; - - if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR)) -- raise (SIGPIPE); -+ die_pipe (); - #else - struct timeval delay; - delay.tv_sec = delay.tv_usec = 0; -@@ -360,7 +368,7 @@ check_output_alive (void) - /* readable event on STDOUT is equivalent to POLLERR, - and implies an error condition on output like broken pipe. */ - if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1) -- raise (SIGPIPE); -+ die_pipe (); - #endif - } - -@@ -1658,7 +1666,7 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files, - { - /* readable event on STDOUT is equivalent to POLLERR, - and implies an error on output like broken pipe. */ -- raise (SIGPIPE); -+ die_pipe (); - } - else - break; -diff --git a/tests/misc/printf-surprise.sh b/tests/misc/printf-surprise.sh -index fd88133..acac0b1 100755 ---- a/tests/misc/printf-surprise.sh -+++ b/tests/misc/printf-surprise.sh -@@ -49,9 +49,7 @@ vm=$(get_min_ulimit_v_ env $prog %20f 0) \ - # triggering the printf(3) misbehavior -- which, btw, is required by ISO C99. - - mkfifo_or_skip_ fifo -- --(trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' || -- skip_ 'trapping SIGPIPE is not supported' -+trap_sigpipe_or_skip_ - - # Disable MALLOC_PERTURB_, to avoid triggering this bug - # https://bugs.debian.org/481543#77 -diff --git a/tests/misc/seq-epipe.sh b/tests/misc/seq-epipe.sh -index 3e89158..127d61c 100755 ---- a/tests/misc/seq-epipe.sh -+++ b/tests/misc/seq-epipe.sh -@@ -18,9 +18,7 @@ - - . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src - print_ver_ seq -- --(trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' || -- skip_ 'trapping SIGPIPE is not supported' -+trap_sigpipe_or_skip_ - - # upon EPIPE with signals ignored, 'seq' should exit with an error. - timeout 10 sh -c \ -diff --git a/tests/tail-2/pipe-f.sh b/tests/tail-2/pipe-f.sh -index 1126c93..f734a61 100755 ---- a/tests/tail-2/pipe-f.sh -+++ b/tests/tail-2/pipe-f.sh -@@ -18,6 +18,7 @@ - - . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src - print_ver_ tail -+trap_sigpipe_or_skip_ - - # Speedup the non inotify case - fastpoll='-s.1 --max-unchanged-stats=1' -@@ -36,11 +37,19 @@ echo bar | returns_ 1 \ - compare exp out || fail=1 - - # This would wait indefinitely before v8.28 due to no EPIPE being --# generated due to no data written after the first small amount --(returns_ 124 timeout 10 tail -n2 -f $mode $fastpoll out && touch timed_out) | -- sed 2q > out2 --test -e timed_out && fail=1 --compare exp out2 || fail=1 -+# generated due to no data written after the first small amount. -+# Also check tail exits if SIGPIPE is being ignored. -+# Note 'trap - SIGPIPE' is ineffective if the initiating shell -+# has ignored SIGPIPE, but that's not the normal case. -+for disposition in '' '-'; do -+ (trap "$disposition" PIPE; -+ returns_ 124 timeout 10 \ -+ tail -n2 -f $mode $fastpoll out && touch timed_out) | -+ sed 2q > out2 -+ test -e timed_out && fail=1 -+ compare exp out2 || fail=1 -+ rm -f timed_out -+done - - # This would wait indefinitely before v8.28 (until first write) - (returns_ 1 timeout 10 tail -f $mode $fastpoll /dev/null >&-) || fail=1 --- -2.31.1 - - -From 0f5760466d167e955d28a1250ffd0af347d48dc9 Mon Sep 17 00:00:00 2001 -From: Paul Eggert -Date: Sat, 26 Jun 2021 18:23:52 -0700 -Subject: [PATCH 4/4] tail: use poll, not select -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This fixes an unlikely stack out-of-bounds write reported by -Stepan Broz via Kamil Dudka (Bug#49209). -* src/tail.c: Do not include . -[!_AIX]: Include poll.h. -(check_output_alive) [!_AIX]: Use poll instead of select. -(tail_forever_inotify): Likewise. Simplify logic, as there is no -need for a ‘while (len <= evbuf_off)’ loop. - -Upstream-commit: da0d448bca62c6305fc432f67e2c5ccc2da75346 -Signed-off-by: Kamil Dudka ---- - src/tail.c | 101 +++++++++++++++++++++-------------------------------- - 1 file changed, 39 insertions(+), 62 deletions(-) - -diff --git a/src/tail.c b/src/tail.c -index 16e0d73..d77c660 100644 ---- a/src/tail.c -+++ b/src/tail.c -@@ -29,10 +29,8 @@ - #include - #include - #include -+#include - #include --#ifdef _AIX --# include --#endif - - #include "system.h" - #include "argmatch.h" -@@ -55,8 +53,6 @@ - #if HAVE_INOTIFY - # include "hash.h" - # include --/* 'select' is used by tail_forever_inotify. */ --# include - - /* inotify needs to know if a file is local. */ - # include "fs.h" -@@ -349,27 +345,12 @@ check_output_alive (void) - if (! monitor_output) - return; - --#ifdef _AIX -- /* select on AIX was seen to give a readable event immediately. */ - struct pollfd pfd; - pfd.fd = STDOUT_FILENO; - pfd.events = POLLERR; - - if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR)) - die_pipe (); --#else -- struct timeval delay; -- delay.tv_sec = delay.tv_usec = 0; -- -- fd_set rfd; -- FD_ZERO (&rfd); -- FD_SET (STDOUT_FILENO, &rfd); -- -- /* readable event on STDOUT is equivalent to POLLERR, -- and implies an error condition on output like broken pipe. */ -- if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1) -- die_pipe (); --#endif - } - - static bool -@@ -1609,7 +1590,7 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files, - /* Wait for inotify events and handle them. Events on directories - ensure that watched files can be re-added when following by name. - This loop blocks on the 'safe_read' call until a new event is notified. -- But when --pid=P is specified, tail usually waits via the select. */ -+ But when --pid=P is specified, tail usually waits via poll. */ - while (1) - { - struct File_spec *fspec; -@@ -1626,54 +1607,51 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files, - return false; - } - -- /* When watching a PID, ensure that a read from WD will not block -- indefinitely. */ -- while (len <= evbuf_off) -+ if (len <= evbuf_off) - { -- struct timeval delay; /* how long to wait for file changes. */ -+ /* Poll for inotify events. When watching a PID, ensure -+ that a read from WD will not block indefinitely. -+ If MONITOR_OUTPUT, also poll for a broken output pipe. */ - -- if (pid) -+ int file_change; -+ struct pollfd pfd[2]; -+ do - { -- if (writer_is_dead) -- exit (EXIT_SUCCESS); -+ /* How many ms to wait for changes. -1 means wait forever. */ -+ int delay = -1; - -- writer_is_dead = (kill (pid, 0) != 0 && errno != EPERM); -- -- if (writer_is_dead) -- delay.tv_sec = delay.tv_usec = 0; -- else -+ if (pid) - { -- delay.tv_sec = (time_t) sleep_interval; -- delay.tv_usec = 1000000 * (sleep_interval - delay.tv_sec); -+ if (writer_is_dead) -+ exit (EXIT_SUCCESS); -+ -+ writer_is_dead = (kill (pid, 0) != 0 && errno != EPERM); -+ -+ if (writer_is_dead || sleep_interval <= 0) -+ delay = 0; -+ else if (sleep_interval < INT_MAX / 1000 - 1) -+ { -+ /* delay = ceil (sleep_interval * 1000), sans libm. */ -+ double ddelay = sleep_interval * 1000; -+ delay = ddelay; -+ delay += delay < ddelay; -+ } - } -+ -+ pfd[0].fd = wd; -+ pfd[0].events = POLLIN; -+ pfd[1].fd = STDOUT_FILENO; -+ pfd[1].events = pfd[1].revents = 0; -+ file_change = poll (pfd, monitor_output + 1, delay); - } -+ while (file_change == 0); - -- fd_set rfd; -- FD_ZERO (&rfd); -- FD_SET (wd, &rfd); -- if (monitor_output) -- FD_SET (STDOUT_FILENO, &rfd); -- -- int file_change = select (MAX (wd, STDOUT_FILENO) + 1, -- &rfd, NULL, NULL, pid ? &delay: NULL); -- -- if (file_change == 0) -- continue; -- else if (file_change == -1) -- die (EXIT_FAILURE, errno, -- _("error waiting for inotify and output events")); -- else if (FD_ISSET (STDOUT_FILENO, &rfd)) -- { -- /* readable event on STDOUT is equivalent to POLLERR, -- and implies an error on output like broken pipe. */ -- die_pipe (); -- } -- else -- break; -- } -+ if (file_change < 0) -+ die (EXIT_FAILURE, errno, -+ _("error waiting for inotify and output events")); -+ if (pfd[1].revents) -+ die_pipe (); - -- if (len <= evbuf_off) -- { - len = safe_read (wd, evbuf, evlen); - evbuf_off = 0; - -@@ -2434,8 +2412,7 @@ main (int argc, char **argv) - if (forever && ignore_fifo_and_pipe (F, n_files)) - { - /* If stdout is a fifo or pipe, then monitor it -- so that we exit if the reader goes away. -- Note select() on a regular file is always readable. */ -+ so that we exit if the reader goes away. */ - struct stat out_stat; - if (fstat (STDOUT_FILENO, &out_stat) < 0) - die (EXIT_FAILURE, errno, _("standard output")); --- -2.31.1 - diff --git a/SOURCES/coreutils-8.31-sums-man-pages.patch b/SOURCES/coreutils-8.31-sums-man-pages.patch deleted file mode 100644 index 094aaaa..0000000 --- a/SOURCES/coreutils-8.31-sums-man-pages.patch +++ /dev/null @@ -1,36 +0,0 @@ -From ef6be60dcaf424bdb21392aff42331bd4dc272e0 Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Thu, 14 Mar 2019 13:48:01 +0100 -Subject: [PATCH] md5sum,b2sum,sha*sum: --help: add note about binary/text mode - -* src/md5sum.c (usage): Make it clear that there is no difference -between binary mode and text mode on GNU systems. - -Bug: https://bugzilla.redhat.com/406981 -Bug: https://bugzilla.redhat.com/1688740 - -Upstream-commit: ae61b1066351bb784b54fbfd7b52caf129ec286c -Signed-off-by: Kamil Dudka ---- - src/md5sum.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/md5sum.c b/src/md5sum.c -index 3532f7b7a..f75b6de02 100644 ---- a/src/md5sum.c -+++ b/src/md5sum.c -@@ -287,7 +287,10 @@ The following five options are useful only when verifying checksums:\n\ - The sums are computed as described in %s. When checking, the input\n\ - should be a former output of this program. The default mode is to print a\n\ - line with checksum, a space, a character indicating input mode ('*' for binary,\ --\n' ' for text or where binary is insignificant), and name for each FILE.\n"), -+\n' ' for text or where binary is insignificant), and name for each FILE.\n\ -+\n\ -+Note: There is no difference between binary mode and text mode on GNU systems.\ -+\n"), - DIGEST_REFERENCE); - emit_ancillary_info (PROGRAM_NAME); - } --- -2.17.2 - diff --git a/SOURCES/coreutils-8.32-df-duplicated-entries.patch b/SOURCES/coreutils-8.32-df-duplicated-entries.patch deleted file mode 100644 index 5d39c1e..0000000 --- a/SOURCES/coreutils-8.32-df-duplicated-entries.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 0f053de4bc3ca0cfd88a42d236881dfdddb10ee9 Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Wed, 30 Jun 2021 17:53:22 +0200 -Subject: [PATCH] df: fix duplicated remote entries due to bind mounts - -As originally reported in , -df invoked without -a printed duplicated entries for NFS mounts -of bind mounts. This is a regression from commit v8.25-54-g1c17f61ef99, -which introduced the use of a hash table. - -The proposed patch makes sure that the devlist entry seen the last time -is used for comparison when eliminating duplicated mount entries. This -way it worked before introducing the hash table. - -Patch co-authored by Roberto Bergantinos. - -* src/ls.c (struct devlist): Introduce the seen_last pointer. -(devlist_for_dev): Return the devlist entry seen the last time if found. -(filter_mount_list): Remember the devlist entry seen the last time for -each hashed item. -Fixes https://bugs.gnu.org/49298 - -Upstream-commit: d6125af095c9553f38cba0696f15158f5abe4ecc -Signed-off-by: Kamil Dudka ---- - src/df.c | 15 +++++++++++++-- - 1 file changed, 13 insertions(+), 2 deletions(-) - -diff --git a/src/df.c b/src/df.c -index 7e01839..3e9247f 100644 ---- a/src/df.c -+++ b/src/df.c -@@ -54,6 +54,7 @@ struct devlist - dev_t dev_num; - struct mount_entry *me; - struct devlist *next; -+ struct devlist *seen_last; /* valid for hashed devlist entries only */ - }; - - /* Filled with device numbers of examined file systems to avoid -@@ -689,7 +690,13 @@ devlist_for_dev (dev_t dev) - return NULL; - struct devlist dev_entry; - dev_entry.dev_num = dev; -- return hash_lookup (devlist_table, &dev_entry); -+ -+ struct devlist *found = hash_lookup (devlist_table, &dev_entry); -+ if (found == NULL) -+ return NULL; -+ -+ /* Return the last devlist entry we have seen with this dev_num */ -+ return found->seen_last; - } - - static void -@@ -807,8 +814,12 @@ filter_mount_list (bool devices_only) - devlist->dev_num = buf.st_dev; - devlist->next = device_list; - device_list = devlist; -- if (hash_insert (devlist_table, devlist) == NULL) -+ -+ struct devlist *hash_entry = hash_insert (devlist_table, devlist); -+ if (hash_entry == NULL) - xalloc_die (); -+ /* Ensure lookups use this latest devlist. */ -+ hash_entry->seen_last = devlist; - - me = me->me_next; - } --- -2.31.1 - diff --git a/SOURCES/coreutils-8.32-fuse-portal.patch b/SOURCES/coreutils-8.32-fuse-portal.patch deleted file mode 100644 index 99e15e2..0000000 --- a/SOURCES/coreutils-8.32-fuse-portal.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 602fb566468d3837b7871c17a0fab1a20228d119 Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Mon, 7 Jun 2021 14:43:03 +0200 -Subject: [PATCH] mountlist: recognize fuse.portal as dummy file system - -This was originally proposed at: - - https://lists.gnu.org/archive/html/bug-gnulib/2021-02/msg00053.html - -As the full review might take some time, would it be possible to apply -at least the part related to fuse.portal file systems? They started to -cause problems recently: - - https://bugs.launchpad.net/ubuntu/+source/xdg-desktop-portal/+bug/1905623 - https://github.com/muesli/duf/issues/35 - https://bugzilla.redhat.com/1913358 - -Upstream-commit: 9a38d499ca16f2f4304992eb1ab0894cd0b478e1 -Signed-off-by: Kamil Dudka ---- - lib/mountlist.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/lib/mountlist.c b/lib/mountlist.c -index e0227b7..e5f6b07 100644 ---- a/lib/mountlist.c -+++ b/lib/mountlist.c -@@ -173,6 +173,7 @@ - || strcmp (Fs_type, "debugfs") == 0 \ - || strcmp (Fs_type, "devpts") == 0 \ - || strcmp (Fs_type, "fusectl") == 0 \ -+ || strcmp (Fs_type, "fuse.portal") == 0 \ - || strcmp (Fs_type, "mqueue") == 0 \ - || strcmp (Fs_type, "rpc_pipefs") == 0 \ - || strcmp (Fs_type, "sysfs") == 0 \ --- -2.31.1 - diff --git a/SOURCES/coreutils-8.32-rm-stray-skip.patch b/SOURCES/coreutils-8.32-rm-stray-skip.patch deleted file mode 100644 index 66a1efc..0000000 --- a/SOURCES/coreutils-8.32-rm-stray-skip.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 11b37b65d08c2a8b6d967fd866ebbdbe7e864949 Mon Sep 17 00:00:00 2001 -From: Nishant Nayan -Date: Thu, 26 Nov 2020 14:35:17 +0000 -Subject: [PATCH] rm: do not skip files upon failure to remove an empty dir - -When removing a directory fails for some reason, and that directory -is empty, the rm_fts code gets the return value of the excise call -confused with the return value of its earlier call to prompt, -causing fts_skip_tree to be called again and the next file -that rm would otherwise have deleted to survive. - -* src/remove.c (rm_fts): Ensure we only skip a single fts entry, -when processing empty dirs. I.e. only skip the entry -having successfully removed it. -* tests/rm/empty-immutable-skip.sh: New root-only test. -* tests/local.mk: Add it. -* NEWS: Mention the bug fix. -Fixes https://bugs.gnu.org/44883 - -Upstream-commit: 6bf108358a6104ec1c694c9530b3cd56b95f4b57 -Signed-off-by: Kamil Dudka ---- - src/remove.c | 3 ++- - tests/local.mk | 1 + - tests/rm/empty-immutable-skip.sh | 46 ++++++++++++++++++++++++++++++++ - 3 files changed, 49 insertions(+), 1 deletion(-) - create mode 100755 tests/rm/empty-immutable-skip.sh - -diff --git a/src/remove.c b/src/remove.c -index 2d40c55..adf9489 100644 ---- a/src/remove.c -+++ b/src/remove.c -@@ -506,7 +506,8 @@ rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x) - /* When we know (from prompt when in interactive mode) - that this is an empty directory, don't prompt twice. */ - s = excise (fts, ent, x, true); -- fts_skip_tree (fts, ent); -+ if (s == RM_OK) -+ fts_skip_tree (fts, ent); - } - - if (s != RM_OK) -diff --git a/tests/local.mk b/tests/local.mk -index 5f7f775..2aeff2b 100644 ---- a/tests/local.mk -+++ b/tests/local.mk -@@ -136,6 +136,7 @@ all_root_tests = \ - tests/rm/no-give-up.sh \ - tests/rm/one-file-system.sh \ - tests/rm/read-only.sh \ -+ tests/rm/empty-immutable-skip.sh \ - tests/tail-2/append-only.sh \ - tests/tail-2/end-of-device.sh \ - tests/touch/now-owned-by-other.sh -diff --git a/tests/rm/empty-immutable-skip.sh b/tests/rm/empty-immutable-skip.sh -new file mode 100755 -index 0000000..c91d8d4 ---- /dev/null -+++ b/tests/rm/empty-immutable-skip.sh -@@ -0,0 +1,46 @@ -+#!/bin/sh -+# Ensure that rm does not skip extra files after hitting an empty immutable dir. -+# Requires root access to do chattr +i, as well as an ext[23] or xfs file system -+ -+# Copyright (C) 2020 Free Software Foundation, Inc. -+ -+# This program is free software: you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation, either version 3 of the License, or -+# (at your option) any later version. -+ -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+ -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src -+print_ver_ rm -+require_root_ -+ -+# These simple one-file operations are expected to work even in the -+# presence of this bug, and we need them to set up the rest of the test. -+chattr_i_works=1 -+touch f -+chattr +i f 2>/dev/null || chattr_i_works=0 -+rm f 2>/dev/null -+test -f f || chattr_i_works=0 -+chattr -i f 2>/dev/null || chattr_i_works=0 -+rm f 2>/dev/null || chattr_i_works=0 -+test -f f && chattr_i_works=0 -+ -+if test $chattr_i_works = 0; then -+ skip_ "chattr +i doesn't work on this file system" -+fi -+ -+mkdir empty || framework_failure_ -+touch x y || framework_failure_ -+chattr +i empty || framework_failure_ -+rm -rf empty x y -+{ test -f x || test -f y; } && fail=1 -+chattr -i empty -+ -+Exit $fail --- -2.26.2 - diff --git a/SOURCES/coreutils-8.32-split-number.patch b/SOURCES/coreutils-8.32-split-number.patch deleted file mode 100644 index 89541bf..0000000 --- a/SOURCES/coreutils-8.32-split-number.patch +++ /dev/null @@ -1,100 +0,0 @@ -From bb0e7fabcaed9a7e71e30f05e638e9f243cdb13e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?P=C3=A1draig=20Brady?= -Date: Mon, 25 Jan 2021 14:12:48 +0000 -Subject: [PATCH] split: fix --number=K/N to output correct part of file - -This functionality regressed with the adjustments -in commit v8.25-4-g62e7af032 - -* src/split.c (bytes_chunk_extract): Account for already read data -when seeking into the file. -* tests/split/b-chunk.sh: Use the hidden ---io-blksize option, -to test this functionality. -Fixes https://bugs.gnu.org/46048 - -Upstream-commit: bb21daa125aeb4e32546309d370918ca47e612db -Signed-off-by: Kamil Dudka ---- - src/split.c | 2 +- - tests/split/b-chunk.sh | 45 ++++++++++++++++++++++++------------------ - 2 files changed, 27 insertions(+), 20 deletions(-) - -diff --git a/src/split.c b/src/split.c -index 09e610b..19248f6 100644 ---- a/src/split.c -+++ b/src/split.c -@@ -1001,7 +1001,7 @@ bytes_chunk_extract (uintmax_t k, uintmax_t n, char *buf, size_t bufsize, - } - else - { -- if (lseek (STDIN_FILENO, start, SEEK_CUR) < 0) -+ if (lseek (STDIN_FILENO, start - initial_read, SEEK_CUR) < 0) - die (EXIT_FAILURE, errno, "%s", quotef (infile)); - initial_read = SIZE_MAX; - } -diff --git a/tests/split/b-chunk.sh b/tests/split/b-chunk.sh -index 864ce55..39a6799 100755 ---- a/tests/split/b-chunk.sh -+++ b/tests/split/b-chunk.sh -@@ -35,32 +35,39 @@ split -e -n 10 /dev/null || fail=1 - returns_ 1 stat x?? 2>/dev/null || fail=1 - - printf '1\n2\n3\n4\n5\n' > input || framework_failure_ -+printf '1\n2' > exp-1 || framework_failure_ -+printf '\n3\n' > exp-2 || framework_failure_ -+printf '4\n5\n' > exp-3 || framework_failure_ - - for file in input /proc/version /sys/kernel/profiling; do - test -f $file || continue - -- split -n 3 $file > out || fail=1 -- split -n 1/3 $file > b1 || fail=1 -- split -n 2/3 $file > b2 || fail=1 -- split -n 3/3 $file > b3 || fail=1 -+ for blksize in 1 2 4096; do -+ if ! test "$file" = 'input'; then -+ # For /proc like files we must be able to read all -+ # into the internal buffer to be able to determine size. -+ test "$blksize" = 4096 || continue -+ fi - -- case $file in -- input) -- printf '1\n2' > exp-1 -- printf '\n3\n' > exp-2 -- printf '4\n5\n' > exp-3 -+ split -n 3 ---io-blksize=$blksize $file > out || fail=1 -+ split -n 1/3 ---io-blksize=$blksize $file > b1 || fail=1 -+ split -n 2/3 ---io-blksize=$blksize $file > b2 || fail=1 -+ split -n 3/3 ---io-blksize=$blksize $file > b3 || fail=1 - -- compare exp-1 xaa || fail=1 -- compare exp-2 xab || fail=1 -- compare exp-3 xac || fail=1 -- ;; -- esac -+ case $file in -+ input) -+ compare exp-1 xaa || fail=1 -+ compare exp-2 xab || fail=1 -+ compare exp-3 xac || fail=1 -+ ;; -+ esac - -- compare xaa b1 || fail=1 -- compare xab b2 || fail=1 -- compare xac b3 || fail=1 -- cat xaa xab xac | compare - $file || fail=1 -- test -f xad && fail=1 -+ compare xaa b1 || fail=1 -+ compare xab b2 || fail=1 -+ compare xac b3 || fail=1 -+ cat xaa xab xac | compare - $file || fail=1 -+ test -f xad && fail=1 -+ done - done - - Exit $fail --- -2.26.2 - diff --git a/SOURCES/coreutils-8.4-mkdir-modenote.patch b/SOURCES/coreutils-8.4-mkdir-modenote.patch deleted file mode 100644 index 51a129e..0000000 --- a/SOURCES/coreutils-8.4-mkdir-modenote.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/doc/coreutils.texi b/doc/coreutils.texi -index 400e135..47e4480 100644 ---- a/doc/coreutils.texi -+++ b/doc/coreutils.texi -@@ -10074,6 +10074,8 @@ incorrect. @xref{Directory Setuid and Setgid}, for how the - set-user-ID and set-group-ID bits of directories are inherited unless - overridden in this way. - -+Note: The @option{--mode},@option{-m} option only applies to the right-most directories listed on the command line. When combined with @option{--parents}, @option{-p} option, any parent directories are created with @samp{u+wx} modified by umask. -+ - @item -p - @itemx --parents - @opindex -p diff --git a/SOURCES/coreutils-9.0-autofs-no-mount.patch b/SOURCES/coreutils-9.0-autofs-no-mount.patch deleted file mode 100644 index 083a9e0..0000000 --- a/SOURCES/coreutils-9.0-autofs-no-mount.patch +++ /dev/null @@ -1,87 +0,0 @@ -From f4422844dbcd839ce486bcbc15b7bd5b72c9198d Mon Sep 17 00:00:00 2001 -From: Rohan Sable -Date: Mon, 7 Mar 2022 14:14:13 +0000 -Subject: [PATCH 1/2] ls: avoid triggering automounts - -statx() has different defaults wrt automounting -compared to stat() or lstat(), so explicitly -set the AT_NO_AUTOMOUNT flag to suppress that behavior, -and avoid unintended operations or potential errors. - -* src/ls.c (do_statx): Pass AT_NO_AUTOMOUNT to avoid this behavior. -Fixes https://bugs.gnu.org/54286 - -Signed-off-by: Rohan Sable - -Upstream-commit: 85c975df2c25bd799370b04bb294e568e001102f -Signed-off-by: Kamil Dudka ---- - src/ls.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/ls.c b/src/ls.c -index 1047801..fe0e9f8 100644 ---- a/src/ls.c -+++ b/src/ls.c -@@ -1126,7 +1126,7 @@ do_statx (int fd, const char *name, struct stat *st, int flags, - unsigned int mask) - { - struct statx stx; -- int ret = statx (fd, name, flags, mask, &stx); -+ int ret = statx (fd, name, flags | AT_NO_AUTOMOUNT, mask, &stx); - if (ret >= 0) - statx_to_stat (&stx, st); - return ret; --- -2.34.1 - - -From 3d227f9e4f3fe806064721e4b9451ee06526bc80 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?P=C3=A1draig=20Brady?= -Date: Mon, 7 Mar 2022 23:29:20 +0000 -Subject: [PATCH 2/2] stat: only automount with --cached=never - -Revert to the default behavior before the introduction of statx(). - -* src/stat.c (do_stat): Set AT_NO_AUTOMOUNT without --cached=never. -* doc/coreutils.texi (stat invocation): Mention the automount -behavior with --cached=never. - -Fixes https://bugs.gnu.org/54287 - -Upstream-commit: 92cb8427c537f37edd43c5cef1909585201372ab -Signed-off-by: Kamil Dudka ---- - doc/coreutils.texi | 1 + - src/stat.c | 3 +++ - 2 files changed, 4 insertions(+) - -diff --git a/doc/coreutils.texi b/doc/coreutils.texi -index 19b535c..0f5c16a 100644 ---- a/doc/coreutils.texi -+++ b/doc/coreutils.texi -@@ -12204,6 +12204,7 @@ Always read the already cached attributes if available. - - @item never - Always sychronize with the latest file system attributes. -+This also mounts automounted files. - - @item default - Leave the caching behavior to the underlying file system. -diff --git a/src/stat.c b/src/stat.c -index 0c34501..803340a 100644 ---- a/src/stat.c -+++ b/src/stat.c -@@ -1343,6 +1343,9 @@ do_stat (char const *filename, char const *format, char const *format2) - else if (force_sync) - flags |= AT_STATX_FORCE_SYNC; - -+ if (! force_sync) -+ flags |= AT_NO_AUTOMOUNT; -+ - fd = statx (fd, pathname, flags, format_to_mask (format), &stx); - if (fd < 0) - { --- -2.34.1 - diff --git a/SOURCES/coreutils-getgrouplist.patch b/SOURCES/coreutils-getgrouplist.patch deleted file mode 100644 index 5349337..0000000 --- a/SOURCES/coreutils-getgrouplist.patch +++ /dev/null @@ -1,94 +0,0 @@ -diff --git a/lib/getugroups.c b/lib/getugroups.c -index 299bae6..8ece29b 100644 ---- a/lib/getugroups.c -+++ b/lib/getugroups.c -@@ -19,6 +19,9 @@ - - #include - -+/* We do not need this code if getgrouplist(3) is available. */ -+#ifndef HAVE_GETGROUPLIST -+ - #include "getugroups.h" - - #include -@@ -126,3 +129,4 @@ getugroups (int maxcount, gid_t *grouplist, char const *username, - } - - #endif /* HAVE_GRP_H */ -+#endif /* have getgrouplist */ -diff --git a/lib/mgetgroups.c b/lib/mgetgroups.c -index 76474c2..0a9d221 100644 ---- a/lib/mgetgroups.c -+++ b/lib/mgetgroups.c -@@ -31,6 +31,7 @@ - #endif - - #include "getugroups.h" -+#include "xalloc.h" - #include "xalloc-oversized.h" - - /* Work around an incompatibility of OS X 10.11: getgrouplist -@@ -121,9 +122,17 @@ mgetgroups (char const *username, gid_t gid, gid_t **groups) - /* else no username, so fall through and use getgroups. */ - #endif - -- max_n_groups = (username -- ? getugroups (0, NULL, username, gid) -- : getgroups (0, NULL)); -+ if (!username) -+ max_n_groups = getgroups(0, NULL); -+ else -+ { -+#ifdef HAVE_GETGROUPLIST -+ max_n_groups = 0; -+ getgrouplist (username, gid, NULL, &max_n_groups); -+#else -+ max_n_groups = getugroups (0, NULL, username, gid); -+#endif -+ } - - /* If we failed to count groups because there is no supplemental - group support, then return an array containing just GID. -@@ -145,10 +154,25 @@ mgetgroups (char const *username, gid_t gid, gid_t **groups) - if (g == NULL) - return -1; - -- ng = (username -- ? getugroups (max_n_groups, g, username, gid) -- : getgroups (max_n_groups - (gid != (gid_t) -1), -- g + (gid != (gid_t) -1))); -+ if (!username) -+ ng = getgroups (max_n_groups - (gid != (gid_t)-1), g + (gid != (gid_t)-1)); -+ else -+ { -+#ifdef HAVE_GETGROUPLIST -+ int e; -+ ng = max_n_groups; -+ while ((e = getgrouplist (username, gid, g, &ng)) == -1 -+ && ng > max_n_groups) -+ { -+ max_n_groups = ng; -+ g = xrealloc (g, max_n_groups * sizeof (GETGROUPS_T)); -+ } -+ if (e == -1) -+ ng = -1; -+#else -+ ng = getugroups (max_n_groups, g, username, gid); -+#endif -+ } - - if (ng < 0) - { -diff --git a/m4/jm-macros.m4 b/m4/jm-macros.m4 -index 62777c7..5180243 100644 ---- a/m4/jm-macros.m4 -+++ b/m4/jm-macros.m4 -@@ -82,6 +82,7 @@ AC_DEFUN([coreutils_MACROS], - fchown - fchmod - ftruncate -+ getgrouplist - iswspace - mkfifo - mbrlen diff --git a/SOURCES/coreutils-i18n-cut-old.patch b/SOURCES/coreutils-i18n-cut-old.patch deleted file mode 100644 index 757ee0f..0000000 --- a/SOURCES/coreutils-i18n-cut-old.patch +++ /dev/null @@ -1,565 +0,0 @@ -diff --git a/src/cut.c b/src/cut.c -index 7ab6be4..022d0ad 100644 ---- a/src/cut.c -+++ b/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 FILE to standard output.\n\ - -f, --fields=LIST select only these fields; also print any line\n\ - that contains no delimiter character, unless\n\ - the -s option is specified\n\ -- -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) diff --git a/SOURCES/coreutils-i18n-expand-unexpand.patch b/SOURCES/coreutils-i18n-expand-unexpand.patch deleted file mode 100644 index 8fc8dff..0000000 --- a/SOURCES/coreutils-i18n-expand-unexpand.patch +++ /dev/null @@ -1,850 +0,0 @@ -From e87ab5b991b08092a7e07af82b3ec822a8604151 Mon Sep 17 00:00:00 2001 -From: Ondrej Oprala -Date: Wed, 5 Aug 2015 09:15:09 +0200 -Subject: [PATCH] expand,unexpand: add multibyte support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -* NEWS: Mention the changes. -* bootstrap.conf: Add mbfile to the list of modules. -* configure.ac: Properly initialize mbfile. -* src/expand.c (expand): Iterate over multibyte characters properly. -* src/unexpand.c (unexpand): Iterate over multibyte characters -properly. -* tests/local.mk: Add new tests. -* tests/{expand,unexpand}/mb.sh: New tests. - -Co-authored-by: Pádraig Brady ---- - bootstrap.conf | 1 + - configure.ac | 2 + - lib/mbfile.c | 3 + - lib/mbfile.h | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++ - m4/mbfile.m4 | 14 +++ - src/expand.c | 43 +++++---- - src/unexpand.c | 54 +++++++---- - tests/expand/mb.sh | 98 ++++++++++++++++++++ - tests/local.mk | 2 + - tests/unexpand/mb.sh | 97 ++++++++++++++++++++ - 10 files changed, 535 insertions(+), 34 deletions(-) - create mode 100644 lib/mbfile.c - create mode 100644 lib/mbfile.h - create mode 100644 m4/mbfile.m4 - create mode 100755 tests/expand/mb.sh - create mode 100755 tests/unexpand/mb.sh - -diff --git a/bootstrap.conf b/bootstrap.conf -index 8a0ff31..a1c78b2 100644 ---- a/bootstrap.conf -+++ b/bootstrap.conf -@@ -152,6 +152,7 @@ gnulib_modules=" - maintainer-makefile - malloc-gnu - manywarnings -+ mbfile - mbrlen - mbrtowc - mbsalign -diff --git a/configure.ac b/configure.ac -index 1e74b36..24c9725 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -427,6 +427,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 && \ -diff --git a/lib/mbfile.c b/lib/mbfile.c -new file mode 100644 -index 0000000..b0a468e ---- /dev/null -+++ b/lib/mbfile.c -@@ -0,0 +1,3 @@ -+#include -+#define MBFILE_INLINE _GL_EXTERN_INLINE -+#include "mbfile.h" -diff --git a/lib/mbfile.h b/lib/mbfile.h -new file mode 100644 -index 0000000..11f1b12 ---- /dev/null -+++ b/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 */ -diff --git a/m4/mbfile.m4 b/m4/mbfile.m4 -new file mode 100644 -index 0000000..8589902 ---- /dev/null -+++ b/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]) -+ : -+]) -diff --git a/src/expand.c b/src/expand.c -index 9fa2e10..380e020 100644 ---- a/src/expand.c -+++ b/src/expand.c -@@ -37,6 +37,9 @@ - #include - #include - #include -+ -+#include -+ - #include "system.h" - #include "die.h" - #include "xstrndup.h" -@@ -100,19 +103,19 @@ expand (void) - { - /* Input stream. */ - FILE *fp = next_file (NULL); -+ mb_file_t mbf; -+ mbf_char_t c; - - if (!fp) - return; - -+ mbf_init (mbf, fp); -+ - while (true) - { -- /* Input character, or EOF. */ -- int c; -- - /* If true, perform translations. */ - bool convert = true; - -- - /* The following variables have valid values only when CONVERT - is true: */ - -@@ -122,17 +125,23 @@ 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; -+ do { -+ mbf_getc (c, mbf); -+ if (mb_iseof (c)) -+ { -+ mbf_init (mbf, fp = next_file (fp)); -+ continue; -+ } -+ } -+ while (false); - - if (convert) - { -- if (c == '\t') -+ if (mb_iseq (c, '\t')) - { - /* Column the next input tab stop is on. */ - uintmax_t next_tab_column; -@@ -151,32 +160,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')); - } - } - -diff --git a/src/unexpand.c b/src/unexpand.c -index 7801274..569a7ee 100644 ---- a/src/unexpand.c -+++ b/src/unexpand.c -@@ -38,6 +38,9 @@ - #include - #include - #include -+ -+#include -+ - #include "system.h" - #include "die.h" - #include "xstrndup.h" -@@ -107,11 +110,12 @@ 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; - - if (!fp) - return; -@@ -119,12 +123,14 @@ unexpand (void) - /* 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)); -+ -+ mbf_init (mbf, fp); - - while (true) - { - /* Input character, or EOF. */ -- int c; -+ mbf_char_t c; - - /* If true, perform translations. */ - bool convert = true; -@@ -158,12 +164,19 @@ unexpand (void) - - do - { -- while ((c = getc (fp)) < 0 && (fp = next_file (fp))) -- continue; -+ do { -+ mbf_getc (c, mbf); -+ if (mb_iseof (c)) -+ { -+ mbf_init (mbf, fp = next_file (fp)); -+ continue; -+ } -+ } -+ while (false); - - if (convert) - { -- bool blank = !! isblank (c); -+ bool blank = mb_isblank (c); - - if (blank) - { -@@ -180,16 +193,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 +210,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 +225,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. */ -@@ -221,16 +235,20 @@ unexpand (void) - } - else - { -- column++; -- if (!column) -+ const uintmax_t orig_column = column; -+ column += mb_width (c); -+ if (column < orig_column) - die (EXIT_FAILURE, 0, _("input line is too long")); - } - - if (pending) - { - if (pending > 1 && one_blank_before_tab_stop) -- pending_blank[0] = '\t'; -- if (fwrite (pending_blank, 1, pending, stdout) != pending) -+ mb_setascii (&pending_blank[0], '\t'); -+ -+ for (int n = 0; n < pending; ++n) -+ mb_putc (pending_blank[n], stdout); -+ if (ferror (stdout)) - die (EXIT_FAILURE, errno, _("write error")); - pending = 0; - one_blank_before_tab_stop = false; -@@ -240,16 +258,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')); - } - } - -diff --git a/tests/expand/mb.sh b/tests/expand/mb.sh -new file mode 100755 -index 0000000..7971e18 ---- /dev/null -+++ b/tests/expand/mb.sh -@@ -0,0 +1,98 @@ -+#!/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 -+ -+#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 -+ -+exit $fail -diff --git a/tests/local.mk b/tests/local.mk -index 192f776..8053397 100644 ---- a/tests/local.mk -+++ b/tests/local.mk -@@ -544,6 +544,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 \ -@@ -684,6 +685,7 @@ all_tests = \ - tests/touch/read-only.sh \ - tests/touch/relative.sh \ - tests/touch/trailing-slash.sh \ -+ tests/unexpand/mb.sh \ - $(all_root_tests) - - # See tests/factor/create-test.sh. -diff --git a/tests/unexpand/mb.sh b/tests/unexpand/mb.sh -new file mode 100755 -index 0000000..60d4c1a ---- /dev/null -+++ b/tests/unexpand/mb.sh -@@ -0,0 +1,97 @@ -+#!/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 -+ -+#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 --- -2.7.4 - diff --git a/SOURCES/coreutils-i18n-fix2-expand-unexpand.patch b/SOURCES/coreutils-i18n-fix2-expand-unexpand.patch deleted file mode 100644 index b34d7b7..0000000 --- a/SOURCES/coreutils-i18n-fix2-expand-unexpand.patch +++ /dev/null @@ -1,108 +0,0 @@ -diff --git a/src/expand.c b/src/expand.c -index 380e020..310b349 100644 ---- a/src/expand.c -+++ b/src/expand.c -@@ -129,15 +129,19 @@ expand (void) - - do - { -- do { -+ while (true) { - mbf_getc (c, mbf); -- if (mb_iseof (c)) -+ if ((mb_iseof (c)) && (fp = next_file (fp))) - { -- mbf_init (mbf, fp = next_file (fp)); -+ mbf_init (mbf, fp); - continue; - } -+ else -+ { -+ break; -+ } - } -- while (false); -+ - - if (convert) - { -diff --git a/src/unexpand.c b/src/unexpand.c -index 3bbbd66..863a90a 100644 ---- a/src/unexpand.c -+++ b/src/unexpand.c -@@ -164,15 +164,19 @@ unexpand (void) - - do - { -- do { -+ while (true) { - mbf_getc (c, mbf); -- if (mb_iseof (c)) -+ if ((mb_iseof (c)) && (fp = next_file (fp))) - { -- mbf_init (mbf, fp = next_file (fp)); -+ mbf_init (mbf, fp); - continue; - } -+ else -+ { -+ break; -+ } - } -- while (false); -+ - - if (convert) - { -diff --git a/tests/expand/mb.sh b/tests/expand/mb.sh -index 7971e18..031be7a 100755 ---- a/tests/expand/mb.sh -+++ b/tests/expand/mb.sh -@@ -44,6 +44,20 @@ 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) -diff --git a/tests/unexpand/mb.sh b/tests/unexpand/mb.sh -index 60d4c1a..8d75652 100755 ---- a/tests/unexpand/mb.sh -+++ b/tests/unexpand/mb.sh -@@ -44,6 +44,22 @@ 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 diff --git a/SOURCES/coreutils-i18n-fold-newline.patch b/SOURCES/coreutils-i18n-fold-newline.patch deleted file mode 100644 index f7286ef..0000000 --- a/SOURCES/coreutils-i18n-fold-newline.patch +++ /dev/null @@ -1,80 +0,0 @@ -From ff424639fe863cbd6963add1a79b97290c1606c6 Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Fri, 3 Feb 2017 12:26:53 +0100 -Subject: [PATCH] fold.c: preserve new-lines in mutlibyte text - ---- - src/fold.c | 49 ++++++++++++++++++++++++------------------------- - 1 file changed, 24 insertions(+), 25 deletions(-) - -diff --git a/src/fold.c b/src/fold.c -index d23edd5..8c232a7 100644 ---- a/src/fold.c -+++ b/src/fold.c -@@ -342,39 +342,38 @@ fold_multibyte_text (FILE *istream, size_t width, int *saved_errno) - } - - rescan: -- if (operating_mode == byte_mode) /* byte mode */ -+ if (convfail) -+ increment = 1; -+ else if (wc == L'\n') -+ { -+ /* preserve newline */ -+ fwrite (line_out, sizeof(char), offset_out, stdout); -+ START_NEW_LINE; -+ continue; -+ } -+ else if (operating_mode == byte_mode) /* byte mode */ - increment = mblength; - else if (operating_mode == character_mode) /* character mode */ - increment = 1; -- else /* column mode */ -+ else /* column mode */ - { -- if (convfail) -- increment = 1; -- else -+ switch (wc) - { -- 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'\b': -- increment = (column > 0) ? -1 : 0; -- break; -+ case L'\r': -+ increment = -1 * column; -+ break; - -- case L'\r': -- increment = -1 * column; -- break; -+ case L'\t': -+ increment = 8 - column % 8; -+ break; - -- case L'\t': -- increment = 8 - column % 8; -- break; -- -- default: -- increment = wcwidth (wc); -- increment = (increment < 0) ? 0 : increment; -- } -+ default: -+ increment = wcwidth (wc); -+ increment = (increment < 0) ? 0 : increment; - } - } - --- -2.7.4 - diff --git a/SOURCES/coreutils-i18n-sort-human.patch b/SOURCES/coreutils-i18n-sort-human.patch deleted file mode 100644 index 6752493..0000000 --- a/SOURCES/coreutils-i18n-sort-human.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 3976ef5a20369d8b490907ab2cba2d617305a5e0 Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Mon, 30 May 2016 16:19:20 +0200 -Subject: [PATCH] sort: do not use static array 'blanks' in human_numcompare() - -... because the array is not initialized with MB locales. Note this is -rather a conservative fix. I plan to do more cleanup of the i18n patch -in Fedora to prevent mistakes like this in future updates of coreutils. ---- - src/sort.c | 8 +++----- - 1 file changed, 3 insertions(+), 5 deletions(-) - -diff --git a/src/sort.c b/src/sort.c -index 9e07ad8..e47b039 100644 ---- a/src/sort.c -+++ b/src/sort.c -@@ -2304,12 +2304,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)); --- -2.5.5 - diff --git a/SOURCES/coreutils-i18n-un-expand-BOM.patch b/SOURCES/coreutils-i18n-un-expand-BOM.patch deleted file mode 100644 index 6210ce7..0000000 --- a/SOURCES/coreutils-i18n-un-expand-BOM.patch +++ /dev/null @@ -1,456 +0,0 @@ -From 7a7c776a4e228d180e74614fd8c8afcad5d4bdf7 Mon Sep 17 00:00:00 2001 -From: Jakub Martisko -Date: Thu, 7 Jul 2016 12:53:26 +0200 -Subject: [PATCH] coreutils-i18n-un-expand-BOM.patch - ---- - src/expand-common.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++ - src/expand-common.h | 12 ++++++ - src/expand.c | 45 +++++++++++++++++++- - src/unexpand.c | 43 ++++++++++++++++++- - tests/expand/mb.sh | 71 ++++++++++++++++++++++++++++++++ - tests/unexpand/mb.sh | 59 ++++++++++++++++++++++++++ - 6 files changed, 342 insertions(+), 2 deletions(-) - -diff --git a/src/expand-common.c b/src/expand-common.c -index 4657e46..97cbb09 100644 ---- a/src/expand-common.c -+++ b/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 -diff --git a/src/expand-common.h b/src/expand-common.h -index 8cb2079..763bfda 100644 ---- a/src/expand-common.h -+++ b/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); -diff --git a/src/expand.c b/src/expand.c -index 310b349..4136824 100644 ---- a/src/expand.c -+++ b/src/expand.c -@@ -103,11 +103,33 @@ expand (void) - 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); -+ -+ 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")); -+ } -+ } -+ -+ -+ if (found_bom == true) -+ { -+ print_bom(); -+ } - - while (true) - { -@@ -132,6 +154,27 @@ expand (void) - 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 -diff --git a/src/unexpand.c b/src/unexpand.c -index 863a90a..5681b58 100644 ---- a/src/unexpand.c -+++ b/src/unexpand.c -@@ -116,16 +116,36 @@ unexpand (void) - include characters other than spaces, so the blanks must be - stored, not merely counted. */ - 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 * sizeof (mbf_char_t)); - -- mbf_init (mbf, fp); -+ if (found_bom == true) -+ { -+ print_bom(); -+ } - - while (true) - { -@@ -169,6 +189,27 @@ unexpand (void) - 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 -diff --git a/tests/expand/mb.sh b/tests/expand/mb.sh -index 031be7a..1621c84 100755 ---- a/tests/expand/mb.sh -+++ b/tests/expand/mb.sh -@@ -109,4 +109,75 @@ env printf '12345678 - expand < in > out || fail=1 - compare exp out > /dev/null 2>&1 || fail=1 - -+ -+ -+#BOM header test 1 -+printf "\xEF\xBB\xBF" > in; cat <<\EOF >> in || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+EOF -+env printf ' äöü\t. öüä. \tä xx\n' >> in || framework_failure_ -+ -+printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+ -+ -+expand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LANG=C expand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LC_ALL=C expand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+ -+printf '\xEF\xBB\xBF' > in1; cat <<\EOF >> in1 || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+EOF -+env printf ' äöü\t. öüä. \tä xx\n' >> in1 || framework_failure_ -+ -+ -+printf '\xEF\xBB\xBF' > exp; cat <<\EOF >> exp || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+ -+expand in1 in1 > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LANG=C expand in1 in1 > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LC_ALL=C expand in1 in1 > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ - exit $fail -diff --git a/tests/unexpand/mb.sh b/tests/unexpand/mb.sh -index 8d75652..9d4ee3e 100755 ---- a/tests/unexpand/mb.sh -+++ b/tests/unexpand/mb.sh -@@ -111,3 +111,62 @@ env printf '12345678 - - unexpand -a < in > out || fail=1 - compare exp out > /dev/null 2>&1 || fail=1 -+ -+#BOM header test 1 -+printf "\xEF\xBB\xBF" > in; cat <<\EOF >> in || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+env printf ' äöü\t. öüä. \tä xx\n' >> in || framework_failure_ -+ -+printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+ -+unexpand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LANG=C unexpand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LC_ALL=C unexpand < in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+ -+printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_ -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+1234567812345678123456781 -+. . . . -+a b c d -+. . . . -+ä ö ü ß -+. . . . -+ äöü . öüä. ä xx -+EOF -+ -+ -+unexpand in in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LANG=C unexpand in in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 -+ -+LC_ALL=C unexpand in in > out || fail=1 -+compare exp out > /dev/null 2>&1 || fail=1 --- -2.9.3 - diff --git a/SOURCES/coreutils-nfsv4-acls.patch b/SOURCES/coreutils-nfsv4-acls.patch deleted file mode 100644 index 040312c..0000000 --- a/SOURCES/coreutils-nfsv4-acls.patch +++ /dev/null @@ -1,625 +0,0 @@ -From 5a6af47c3db45b6303bac4dcd6da186fd5cd178c Mon Sep 17 00:00:00 2001 -From: Ondrej Valousek -Date: Fri, 2 Dec 2022 13:40:19 +0100 -Subject: [PATCH 1/3] file-has-acl: Basic support for checking NFSv4 ACLs in - Linux. - -* lib/acl-internal.h (acl_nfs4_nontrivial): New declaration. -* lib/acl-internal.c (acl_nfs4_nontrivial): New function. -* lib/file-has-acl.c: Include . -(XATTR_NAME_NFSV4_ACL, TRIVIAL_NFS4_ACL_MAX_LENGTH): New macros. -(file_has_acl): Test for NFSv4 ACLs. -* doc/acl-nfsv4.txt: New file. - -Upstream-commit: b0604a8e134dbcc307c0ffdd5ebd3693e9de7081 -Signed-off-by: Kamil Dudka ---- - doc/acl-nfsv4.txt | 17 ++++++++ - lib/acl-internal.c | 100 +++++++++++++++++++++++++++++++++++++++++++++ - lib/acl-internal.h | 3 ++ - lib/file-has-acl.c | 21 ++++++++++ - 4 files changed, 141 insertions(+) - create mode 100644 doc/acl-nfsv4.txt - -diff --git a/doc/acl-nfsv4.txt b/doc/acl-nfsv4.txt -new file mode 100644 -index 0000000..71352f5 ---- /dev/null -+++ b/doc/acl-nfsv4.txt -@@ -0,0 +1,17 @@ -+General introduction: -+ https://linux.die.net/man/5/nfs4_acl -+ -+The NFSv4 acls are defined in RFC7530 and as such, every NFSv4 server supporting ACLs -+will support this kind of ACLs (note the difference from POSIX draft ACLs) -+ -+The ACLs can be obtained via the nfsv4-acl-tools, i.e. -+ -+$ nfs4_getfacl -+ -+# file: -+A::OWNER@:rwaDxtTnNcCy -+A::GROUP@:rwaDxtTnNcy -+A::EVERYONE@:rwaDxtTnNcy -+ -+Gnulib is aiming to only provide a basic support of these, i.e. recognize trivial -+and non-trivial ACLs -diff --git a/lib/acl-internal.c b/lib/acl-internal.c -index be244c6..4c65dff 100644 ---- a/lib/acl-internal.c -+++ b/lib/acl-internal.c -@@ -25,6 +25,9 @@ - - #if USE_ACL && HAVE_ACL_GET_FILE - -+# include -+# include -+ - # if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ - - /* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED. -@@ -122,6 +125,103 @@ acl_default_nontrivial (acl_t acl) - return (acl_entries (acl) > 0); - } - -+# define ACE4_WHO_OWNER "OWNER@" -+# define ACE4_WHO_GROUP "GROUP@" -+# define ACE4_WHO_EVERYONE "EVERYONE@" -+ -+# define ACE4_ACCESS_ALLOWED_ACE_TYPE 0 -+# define ACE4_ACCESS_DENIED_ACE_TYPE 1 -+ -+/* ACE flag values */ -+# define ACE4_IDENTIFIER_GROUP 0x00000040 -+# define ROUNDUP(x, y) (((x) + (y) - 1) & - (y)) -+ -+int -+acl_nfs4_nontrivial (char *xattr, int len) -+{ -+ int bufs = len; -+ uint32_t num_aces = ntohl (*((uint32_t*)(xattr))), /* Grab the number of aces in the acl */ -+ num_a_aces = 0, -+ num_d_aces = 0; -+ char *bufp = xattr; -+ -+ bufp += 4; /* sizeof(uint32_t); */ -+ bufs -= 4; -+ -+ for (uint32_t ace_n = 0; num_aces > ace_n ; ace_n++) -+ { -+ int d_ptr; -+ uint32_t flag, -+ wholen, -+ type; -+ -+ /* Get the acl type */ -+ if (bufs <= 0) -+ return -1; -+ -+ type = ntohl (*((uint32_t*)bufp)); -+ -+ bufp += 4; -+ bufs -= 4; -+ if (bufs <= 0) -+ return -1; -+ -+ flag = ntohl (*((uint32_t*)bufp)); -+ /* As per RFC 7530, the flag should be 0, but we are just generous to Netapp -+ * and also accept the Group flag -+ */ -+ if (flag & ~ACE4_IDENTIFIER_GROUP) -+ return 1; -+ -+ /* we skip mask - -+ * it's too risky to test it and it does not seem to be actually needed */ -+ bufp += 2*4; -+ bufs -= 2*4; -+ -+ if (bufs <= 0) -+ return -1; -+ -+ wholen = ntohl (*((uint32_t*)bufp)); -+ -+ bufp += 4; -+ bufs -= 4; -+ -+ /* Get the who string */ -+ if (bufs <= 0) -+ return -1; -+ -+ /* for trivial ACL, we expect max 5 (typically 3) ACES, 3 Allow, 2 deny */ -+ if (((strncmp (bufp, ACE4_WHO_OWNER, wholen) == 0) -+ || (strncmp (bufp, ACE4_WHO_GROUP, wholen) == 0)) -+ && wholen == 6) -+ { -+ if (type == ACE4_ACCESS_ALLOWED_ACE_TYPE) -+ num_a_aces++; -+ if (type == ACE4_ACCESS_DENIED_ACE_TYPE) -+ num_d_aces++; -+ } -+ else -+ if ((strncmp (bufp, ACE4_WHO_EVERYONE, wholen) == 0) -+ && (type == ACE4_ACCESS_ALLOWED_ACE_TYPE) -+ && (wholen == 9)) -+ num_a_aces++; -+ else -+ return 1; -+ -+ d_ptr = ROUNDUP (wholen, 4); -+ bufp += d_ptr; -+ bufs -= d_ptr; -+ -+ /* Make sure we aren't outside our domain */ -+ if (bufs < 0) -+ return -1; -+ -+ } -+ return !((num_a_aces <= 3) && (num_d_aces <= 2) -+ && (num_a_aces + num_d_aces == num_aces)); -+ -+} -+ - # endif - - #elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ -diff --git a/lib/acl-internal.h b/lib/acl-internal.h -index 9353376..2a249ff 100644 ---- a/lib/acl-internal.h -+++ b/lib/acl-internal.h -@@ -143,6 +143,9 @@ rpl_acl_set_fd (int fd, acl_t acl) - # define acl_entries rpl_acl_entries - extern int acl_entries (acl_t); - # endif -+/* Return 1 if given ACL in XDR format is non-trivial -+ * Return 0 if it is trivial */ -+extern int acl_nfs4_nontrivial (char *, int); - - # if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ - /* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED. -diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c -index e02f062..1710234 100644 ---- a/lib/file-has-acl.c -+++ b/lib/file-has-acl.c -@@ -32,6 +32,11 @@ - #if GETXATTR_WITH_POSIX_ACLS - # include - # include -+# include -+# ifndef XATTR_NAME_NFSV4_ACL -+# define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" -+# endif -+# define TRIVIAL_NFS4_ACL_MAX_LENGTH 128 - #endif - - /* Return 1 if NAME has a nontrivial access control list, -@@ -67,6 +72,22 @@ file_has_acl (char const *name, struct stat const *sb) - return 1; - } - -+ if (ret < 0) -+ { /* we might be on NFS, so try to check NFSv4 ACLs too */ -+ char xattr[TRIVIAL_NFS4_ACL_MAX_LENGTH]; -+ -+ errno = 0; /* we need to reset errno set by the previous getxattr() */ -+ ret = getxattr (name, XATTR_NAME_NFSV4_ACL, xattr, TRIVIAL_NFS4_ACL_MAX_LENGTH); -+ if (ret < 0 && errno == ENODATA) -+ ret = 0; -+ else -+ if (ret < 0 && errno == ERANGE) -+ return 1; /* we won't fit into the buffer, so non-trivial ACL is presented */ -+ else -+ if (ret > 0) -+ /* looks like trivial ACL, but we need to investigate further */ -+ return acl_nfs4_nontrivial (xattr, ret); -+ } - if (ret < 0) - return - acl_errno_valid (errno); - return ret; --- -2.38.1 - - -From c5266d204a446bea619fa18da8520dceb0a54192 Mon Sep 17 00:00:00 2001 -From: Paul Eggert -Date: Fri, 23 Dec 2022 15:18:29 -0800 -Subject: [PATCH 2/3] file-has-acl: improve recent NFSv4 support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This fixes a link failure with emacsclient on GNU/Linux. This -program wants file_has_acl but none of the other ACL primitives, -so it doesn’t link acl-internal.o; this way it doesn’t need to -link with -lacl. While I was at it I reviewed the recent changes, -fixed some unlikely overflow bugs, and adjusted to GNU style. -* doc/acl-nfsv4.txt: Remove. Its contents are now in a -comment in lib/file-has-acl.c. -* lib/acl-internal.c, lib/acl-internal.h: Move recent changes -relating to acl_nfs4_nontrivial to lib/file-has-acl.c, so that -there is no trouble linking programs that need only file_has_acl. -* lib/file-has-acl.c (acl_nfs4_nontrivial): Move here from -lib/acl-internal.c, so that we needn't link -lacl in -programs that want only file_has_acl, such as emacsclient. -Do not assume a char buffer is aligned for uint32_t. -Check more carefully for buffer read overrun. -Allow up to 6 ACEs, since other code does; but check -that they’re distinct. Avoid integer overflow. -Use memcmp rather than strncmp to compare memory blocks. -(file_has_acl): Preserve initial errno instead of setting to 0. -Allocate a bit more room for trivial ACL buffer. -Use EINVAL for botchedk NFSv4 ACLs (which shouldn’t happen). - -Upstream-commit: 35bd46f0c816948dc1a0430c8ba8b10a01167320 -Signed-off-by: Kamil Dudka ---- - doc/acl-nfsv4.txt | 17 ------ - lib/acl-internal.c | 100 ----------------------------------- - lib/acl-internal.h | 3 -- - lib/file-has-acl.c | 129 +++++++++++++++++++++++++++++++++++++++------ - 4 files changed, 113 insertions(+), 136 deletions(-) - delete mode 100644 doc/acl-nfsv4.txt - -diff --git a/doc/acl-nfsv4.txt b/doc/acl-nfsv4.txt -deleted file mode 100644 -index 71352f5..0000000 ---- a/doc/acl-nfsv4.txt -+++ /dev/null -@@ -1,17 +0,0 @@ --General introduction: -- https://linux.die.net/man/5/nfs4_acl -- --The NFSv4 acls are defined in RFC7530 and as such, every NFSv4 server supporting ACLs --will support this kind of ACLs (note the difference from POSIX draft ACLs) -- --The ACLs can be obtained via the nfsv4-acl-tools, i.e. -- --$ nfs4_getfacl -- --# file: --A::OWNER@:rwaDxtTnNcCy --A::GROUP@:rwaDxtTnNcy --A::EVERYONE@:rwaDxtTnNcy -- --Gnulib is aiming to only provide a basic support of these, i.e. recognize trivial --and non-trivial ACLs -diff --git a/lib/acl-internal.c b/lib/acl-internal.c -index 4c65dff..be244c6 100644 ---- a/lib/acl-internal.c -+++ b/lib/acl-internal.c -@@ -25,9 +25,6 @@ - - #if USE_ACL && HAVE_ACL_GET_FILE - --# include --# include -- - # if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ - - /* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED. -@@ -125,103 +122,6 @@ acl_default_nontrivial (acl_t acl) - return (acl_entries (acl) > 0); - } - --# define ACE4_WHO_OWNER "OWNER@" --# define ACE4_WHO_GROUP "GROUP@" --# define ACE4_WHO_EVERYONE "EVERYONE@" -- --# define ACE4_ACCESS_ALLOWED_ACE_TYPE 0 --# define ACE4_ACCESS_DENIED_ACE_TYPE 1 -- --/* ACE flag values */ --# define ACE4_IDENTIFIER_GROUP 0x00000040 --# define ROUNDUP(x, y) (((x) + (y) - 1) & - (y)) -- --int --acl_nfs4_nontrivial (char *xattr, int len) --{ -- int bufs = len; -- uint32_t num_aces = ntohl (*((uint32_t*)(xattr))), /* Grab the number of aces in the acl */ -- num_a_aces = 0, -- num_d_aces = 0; -- char *bufp = xattr; -- -- bufp += 4; /* sizeof(uint32_t); */ -- bufs -= 4; -- -- for (uint32_t ace_n = 0; num_aces > ace_n ; ace_n++) -- { -- int d_ptr; -- uint32_t flag, -- wholen, -- type; -- -- /* Get the acl type */ -- if (bufs <= 0) -- return -1; -- -- type = ntohl (*((uint32_t*)bufp)); -- -- bufp += 4; -- bufs -= 4; -- if (bufs <= 0) -- return -1; -- -- flag = ntohl (*((uint32_t*)bufp)); -- /* As per RFC 7530, the flag should be 0, but we are just generous to Netapp -- * and also accept the Group flag -- */ -- if (flag & ~ACE4_IDENTIFIER_GROUP) -- return 1; -- -- /* we skip mask - -- * it's too risky to test it and it does not seem to be actually needed */ -- bufp += 2*4; -- bufs -= 2*4; -- -- if (bufs <= 0) -- return -1; -- -- wholen = ntohl (*((uint32_t*)bufp)); -- -- bufp += 4; -- bufs -= 4; -- -- /* Get the who string */ -- if (bufs <= 0) -- return -1; -- -- /* for trivial ACL, we expect max 5 (typically 3) ACES, 3 Allow, 2 deny */ -- if (((strncmp (bufp, ACE4_WHO_OWNER, wholen) == 0) -- || (strncmp (bufp, ACE4_WHO_GROUP, wholen) == 0)) -- && wholen == 6) -- { -- if (type == ACE4_ACCESS_ALLOWED_ACE_TYPE) -- num_a_aces++; -- if (type == ACE4_ACCESS_DENIED_ACE_TYPE) -- num_d_aces++; -- } -- else -- if ((strncmp (bufp, ACE4_WHO_EVERYONE, wholen) == 0) -- && (type == ACE4_ACCESS_ALLOWED_ACE_TYPE) -- && (wholen == 9)) -- num_a_aces++; -- else -- return 1; -- -- d_ptr = ROUNDUP (wholen, 4); -- bufp += d_ptr; -- bufs -= d_ptr; -- -- /* Make sure we aren't outside our domain */ -- if (bufs < 0) -- return -1; -- -- } -- return !((num_a_aces <= 3) && (num_d_aces <= 2) -- && (num_a_aces + num_d_aces == num_aces)); -- --} -- - # endif - - #elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ -diff --git a/lib/acl-internal.h b/lib/acl-internal.h -index 2a249ff..9353376 100644 ---- a/lib/acl-internal.h -+++ b/lib/acl-internal.h -@@ -143,9 +143,6 @@ rpl_acl_set_fd (int fd, acl_t acl) - # define acl_entries rpl_acl_entries - extern int acl_entries (acl_t); - # endif --/* Return 1 if given ACL in XDR format is non-trivial -- * Return 0 if it is trivial */ --extern int acl_nfs4_nontrivial (char *, int); - - # if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ - /* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED. -diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c -index 1710234..676523b 100644 ---- a/lib/file-has-acl.c -+++ b/lib/file-has-acl.c -@@ -29,14 +29,97 @@ - - #include "acl-internal.h" - --#if GETXATTR_WITH_POSIX_ACLS -+#if USE_ACL && GETXATTR_WITH_POSIX_ACLS -+# include -+# include - # include - # include --# include - # ifndef XATTR_NAME_NFSV4_ACL - # define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" - # endif --# define TRIVIAL_NFS4_ACL_MAX_LENGTH 128 -+ -+enum { -+ /* ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000, */ -+ ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001, -+ ACE4_IDENTIFIER_GROUP = 0x00000040 -+}; -+ -+/* Return 1 if given ACL in XDR format is non-trivial, 0 if it is trivial. -+ -1 upon failure to determine it. Possibly change errno. Assume that -+ the ACL is valid, except avoid undefined behavior even if invalid. -+ -+ See . The NFSv4 acls are -+ defined in Internet RFC 7530 and as such, every NFSv4 server -+ supporting ACLs should support NFSv4 ACLs (they differ from from -+ POSIX draft ACLs). The ACLs can be obtained via the -+ nfsv4-acl-tools, e.g., the nfs4_getfacl command. Gnulib provides -+ only basic support of NFSv4 ACLs, i.e., recognize trivial vs -+ nontrivial ACLs. */ -+ -+static int -+acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes) -+{ -+ enum { BYTES_PER_NETWORK_UINT = 4}; -+ -+ /* Grab the number of aces in the acl. */ -+ nbytes -= BYTES_PER_NETWORK_UINT; -+ if (nbytes < 0) -+ return -1; -+ uint32_t num_aces = ntohl (*xattr++); -+ if (6 < num_aces) -+ return 1; -+ int ace_found = 0; -+ -+ for (int ace_n = 0; ace_n < num_aces; ace_n++) -+ { -+ /* Get the acl type and flag. Skip the mask; it's too risky to -+ test it and it does not seem to be needed. Get the wholen. */ -+ nbytes -= 4 * BYTES_PER_NETWORK_UINT; -+ if (nbytes < 0) -+ return -1; -+ uint32_t type = ntohl (xattr[0]); -+ uint32_t flag = ntohl (xattr[1]); -+ uint32_t wholen = ntohl (xattr[3]); -+ xattr += 4; -+ int64_t wholen4 = wholen; -+ wholen4 = ((wholen4 + (BYTES_PER_NETWORK_UINT)) -+ & ~ (BYTES_PER_NETWORK_UINT - 1)); -+ -+ /* Trivial ACLs have only ACE4_ACCESS_ALLOWED_ACE_TYPE or -+ ACE4_ACCESS_DENIED_ACE_TYPE. */ -+ if (ACE4_ACCESS_DENIED_ACE_TYPE < type) -+ return 1; -+ -+ /* RFC 7530 says FLAG should be 0, but be generous to NetApp and -+ also accept the group flag. */ -+ if (flag & ~ACE4_IDENTIFIER_GROUP) -+ return 1; -+ -+ /* Get the who string. Check NBYTES - WHOLEN4 before storing -+ into NBYTES, to avoid truncation on conversion. */ -+ if (nbytes - wholen4 < 0) -+ return -1; -+ nbytes -= wholen4; -+ -+ /* For a trivial ACL, max 6 (typically 3) ACEs, 3 allow, 3 deny. -+ Check that there is at most one ACE of each TYPE and WHO. */ -+ int who2 -+ = (wholen == 6 && memcmp (xattr, "OWNER@", 6) == 0 ? 0 -+ : wholen == 6 && memcmp (xattr, "GROUP@", 6) == 0 ? 2 -+ : wholen == 9 && memcmp (xattr, "EVERYONE@", 9) == 0 ? 4 -+ : -1); -+ if (who2 < 0) -+ return 1; -+ int ace_found_bit = 1 << (who2 | type); -+ if (ace_found & ace_found_bit) -+ return 1; -+ ace_found |= ace_found_bit; -+ -+ xattr = (uint32_t *) ((char *) xattr + wholen4); -+ } -+ -+ return 0; -+} - #endif - - /* Return 1 if NAME has a nontrivial access control list, -@@ -56,6 +139,7 @@ file_has_acl (char const *name, struct stat const *sb) - # if GETXATTR_WITH_POSIX_ACLS - - ssize_t ret; -+ int initial_errno = errno; - - ret = getxattr (name, XATTR_NAME_POSIX_ACL_ACCESS, NULL, 0); - if (ret < 0 && errno == ENODATA) -@@ -73,20 +157,33 @@ file_has_acl (char const *name, struct stat const *sb) - } - - if (ret < 0) -- { /* we might be on NFS, so try to check NFSv4 ACLs too */ -- char xattr[TRIVIAL_NFS4_ACL_MAX_LENGTH]; -- -- errno = 0; /* we need to reset errno set by the previous getxattr() */ -- ret = getxattr (name, XATTR_NAME_NFSV4_ACL, xattr, TRIVIAL_NFS4_ACL_MAX_LENGTH); -- if (ret < 0 && errno == ENODATA) -- ret = 0; -+ { -+ /* Check for NFSv4 ACLs. The max length of a trivial -+ ACL is 6 words for owner, 6 for group, 7 for everyone, -+ all times 2 because there are both allow and deny ACEs. -+ There are 6 words for owner because of type, flag, mask, -+ wholen, "OWNER@"+pad and similarly for group; everyone is -+ another word to hold "EVERYONE@". */ -+ uint32_t xattr[2 * (6 + 6 + 7)]; -+ -+ ret = getxattr (name, XATTR_NAME_NFSV4_ACL, xattr, sizeof xattr); -+ if (ret < 0) -+ switch (errno) -+ { -+ case ENODATA: return 0; -+ case ERANGE : return 1; /* ACL must be nontrivial. */ -+ } - else -- if (ret < 0 && errno == ERANGE) -- return 1; /* we won't fit into the buffer, so non-trivial ACL is presented */ -- else -- if (ret > 0) -- /* looks like trivial ACL, but we need to investigate further */ -- return acl_nfs4_nontrivial (xattr, ret); -+ { -+ /* It looks like a trivial ACL, but investigate further. */ -+ ret = acl_nfs4_nontrivial (xattr, ret); -+ if (ret < 0) -+ { -+ errno = EINVAL; -+ return ret; -+ } -+ errno = initial_errno; -+ } - } - if (ret < 0) - return - acl_errno_valid (errno); --- -2.38.1 - - -From faf965110372c82cd99e9f44f0c64f03cdabb2c1 Mon Sep 17 00:00:00 2001 -From: Paul Eggert -Date: Tue, 27 Dec 2022 20:00:58 -0800 -Subject: [PATCH 3/3] file-has-acl: fix recently-introduced NFSv4 bug - -* lib/file-has-acl.c (acl_nfs4_nontrivial): Fix off-by-one -error when rounding WHOLEN up to next multiple of 4. -Pacify GCC 12.2.1 -Wcast-align. - -Upstream-commit: d65e5a8ba77595a598c9ddb8dfa09c4aea732659 -Signed-off-by: Kamil Dudka ---- - lib/file-has-acl.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c -index 676523b..7876edc 100644 ---- a/lib/file-has-acl.c -+++ b/lib/file-has-acl.c -@@ -81,9 +81,10 @@ acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes) - uint32_t flag = ntohl (xattr[1]); - uint32_t wholen = ntohl (xattr[3]); - xattr += 4; -- int64_t wholen4 = wholen; -- wholen4 = ((wholen4 + (BYTES_PER_NETWORK_UINT)) -- & ~ (BYTES_PER_NETWORK_UINT - 1)); -+ int whowords = (wholen / BYTES_PER_NETWORK_UINT -+ + (wholen % BYTES_PER_NETWORK_UINT != 0)); -+ int64_t wholen4 = whowords; -+ wholen4 *= BYTES_PER_NETWORK_UINT; - - /* Trivial ACLs have only ACE4_ACCESS_ALLOWED_ACE_TYPE or - ACE4_ACCESS_DENIED_ACE_TYPE. */ -@@ -115,7 +116,7 @@ acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes) - return 1; - ace_found |= ace_found_bit; - -- xattr = (uint32_t *) ((char *) xattr + wholen4); -+ xattr += whowords; - } - - return 0; --- -2.38.1 - diff --git a/SOURCES/coreutils-provides.inc b/SOURCES/coreutils-provides.inc deleted file mode 100644 index f06a701..0000000 --- a/SOURCES/coreutils-provides.inc +++ /dev/null @@ -1,37 +0,0 @@ -Provides: /bin/basename -Provides: /bin/cat -Provides: /bin/chgrp -Provides: /bin/chmod -Provides: /bin/chown -Provides: /bin/cp -Provides: /bin/cut -Provides: /bin/date -Provides: /bin/dd -Provides: /bin/df -Provides: /bin/echo -Provides: /bin/env -Provides: /bin/false -Provides: /bin/ln -Provides: /bin/ls -Provides: /bin/mkdir -Provides: /bin/mknod -Provides: /bin/mktemp -Provides: /bin/mv -Provides: /bin/nice -Provides: /bin/pwd -Provides: /bin/readlink -Provides: /bin/rm -Provides: /bin/rmdir -Provides: /bin/sleep -Provides: /bin/sort -Provides: /bin/stty -Provides: /bin/sync -Provides: /bin/touch -Provides: /bin/true -Provides: /bin/uname -Provides: bundled(gnulib) -Provides: fileutils = %{version}-%{release} -Provides: mktemp = 4:%{version}-%{release} -Provides: sh-utils = %{version}-%{release} -Provides: stat = %{version}-%{release} -Provides: textutils = %{version}-%{release} diff --git a/SOURCES/coreutils-selinux.patch b/SOURCES/coreutils-selinux.patch deleted file mode 100644 index 8274a23..0000000 --- a/SOURCES/coreutils-selinux.patch +++ /dev/null @@ -1,120 +0,0 @@ -diff --git a/man/chcon.x b/man/chcon.x -index 8c1ff6f..c84fb96 100644 ---- a/man/chcon.x -+++ b/man/chcon.x -@@ -1,4 +1,4 @@ - [NAME] --chcon \- change file security context -+chcon \- change file SELinux security context - [DESCRIPTION] - .\" Add any additional description here -diff --git a/man/runcon.x b/man/runcon.x -index d2df13e..5c5f5d8 100644 ---- a/man/runcon.x -+++ b/man/runcon.x -@@ -1,5 +1,5 @@ - [NAME] --runcon \- run command with specified security context -+runcon \- run command with specified SELinux security context - [DESCRIPTION] - Run COMMAND with completely-specified CONTEXT, or with current or - transitioned security context modified by one or more of LEVEL, -diff --git a/src/cp.c b/src/cp.c -index 1b528c6..25dbb88 100644 ---- a/src/cp.c -+++ b/src/cp.c -@@ -203,6 +203,9 @@ Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\ - all\n\ - "), stdout); - fputs (_("\ -+ -c deprecated, same as --preserve=context\n\ -+"), stdout); -+ fputs (_("\ - --no-preserve=ATTR_LIST don't preserve the specified attributes\n\ - --parents use full source file name under DIRECTORY\n\ - "), stdout); -@@ -929,7 +932,7 @@ main (int argc, char **argv) - selinux_enabled = (0 < is_selinux_enabled ()); - cp_option_init (&x); - -- while ((c = getopt_long (argc, argv, "abdfHilLnprst:uvxPRS:TZ", -+ while ((c = getopt_long (argc, argv, "abcdfHilLnprst:uvxPRS:TZ", - long_opts, NULL)) - != -1) - { -@@ -977,6 +980,17 @@ main (int argc, char **argv) - copy_contents = true; - break; - -+ case 'c': -+ fprintf (stderr, "%s: warning: option '-c' is deprecated, please use '--preserve=context' instead\n", argv[0]); -+ if ( x.set_security_context ) { -+ (void) fprintf(stderr, "%s: cannot force target context and preserve it\n", argv[0]); -+ exit( 1 ); -+ } -+ else if (selinux_enabled) { -+ x.preserve_security_context = true; -+ x.require_preserve_context = true; -+ } -+ break; - case 'd': - x.preserve_links = true; - x.dereference = DEREF_NEVER; -diff --git a/doc/coreutils.texi b/doc/coreutils.texi -index 47e4480..cff2ead 100644 ---- a/doc/coreutils.texi -+++ b/doc/coreutils.texi -@@ -8083,6 +8083,11 @@ done - exit $fail - @end example - -+@item -c -+@cindex SELinux security context information, preserving -+Preserve SELinux security context of the original files if possible. -+Some file systems don't support storing of SELinux security context. -+ - @item --copy-contents - @cindex directories, copying recursively - @cindex copying directories recursively -diff --git a/src/install.c b/src/install.c -index d79d597..437889a 100644 ---- a/src/install.c -+++ b/src/install.c -@@ -673,7 +673,7 @@ In the 4th form, create all components of the given DIRECTORY(ies).\n\ - -v, --verbose print the name of each directory as it is created\n\ - "), stdout); - fputs (_("\ -- --preserve-context preserve SELinux security context\n\ -+ -P, --preserve-context preserve SELinux security context (-P deprecated)\n\ - -Z set SELinux security context of destination\n\ - file and each created directory to default type\n\ - --context[=CTX] like -Z, or if CTX is specified then set the\n\ -@@ -824,7 +824,7 @@ main (int argc, char **argv) - dir_arg = false; - umask (0); - -- while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pt:TvS:Z", long_options, -+ while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pPt:TvS:Z", long_options, - NULL)) != -1) - { - switch (optc) -@@ -885,6 +885,8 @@ main (int argc, char **argv) - no_target_directory = true; - break; - -+ case 'P': -+ fprintf (stderr, "%s: warning: option '-P' is deprecated, please use '--preserve-context' instead\n", argv[0]); - case PRESERVE_CONTEXT_OPTION: - if (! selinux_enabled) - { -@@ -892,6 +894,10 @@ main (int argc, char **argv) - "this kernel is not SELinux-enabled")); - break; - } -+ if ( x.set_security_context ) { -+ (void) fprintf(stderr, "%s: cannot force target context and preserve it\n", argv[0]); -+ exit( 1 ); -+ } - x.preserve_security_context = true; - use_default_selinux_context = false; - break; diff --git a/SOURCES/sh-utils-2.0.11-dateman.patch b/SOURCES/sh-utils-2.0.11-dateman.patch deleted file mode 100644 index 60cdaa6..0000000 --- a/SOURCES/sh-utils-2.0.11-dateman.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -urNp coreutils-5.97-orig/man/date.x coreutils-5.97/man/date.x ---- coreutils-5.97-orig/man/date.x 1999-11-02 15:07:36.000000000 +0100 -+++ coreutils-5.97/man/date.x 2008-10-15 10:13:31.000000000 +0200 -@@ -11,3 +11,8 @@ calendar date, time of day, time zone, day of week, relative time, - relative date, and numbers. An empty string indicates the beginning - of the day. The date string format is more complex than is easily - documented here but is fully described in the info documentation. -+[ENVIRONMENT] -+.TP -+TZ -+Specifies the timezone, unless overridden by command line parameters. -+If neither is specified, the setting from /etc/localtime is used. diff --git a/SOURCES/coreutils-8.26-selinuxenable.patch b/coreutils-8.26-selinuxenable.patch similarity index 100% rename from SOURCES/coreutils-8.26-selinuxenable.patch rename to coreutils-8.26-selinuxenable.patch diff --git a/SOURCES/coreutils-8.26-test-lock.patch b/coreutils-8.26-test-lock.patch similarity index 100% rename from SOURCES/coreutils-8.26-test-lock.patch rename to coreutils-8.26-test-lock.patch diff --git a/coreutils-8.32-DIR_COLORS.patch b/coreutils-8.32-DIR_COLORS.patch new file mode 100644 index 0000000..ee037bf --- /dev/null +++ b/coreutils-8.32-DIR_COLORS.patch @@ -0,0 +1,100 @@ +From c7b13f5e1a7ad012c510a8bdd5a8943ab4b55833 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 17 Jun 2016 16:58:18 +0200 +Subject: [PATCH] downstream changes to default DIR_COLORS + +--- + DIR_COLORS | 9 ++++++++- + DIR_COLORS.lightbgcolor | 21 +++++++++++++++------ + 2 files changed, 23 insertions(+), 7 deletions(-) + +diff --git a/DIR_COLORS b/DIR_COLORS +index b465771..ad42b09 100644 +--- a/DIR_COLORS ++++ b/DIR_COLORS +@@ -1,3 +1,7 @@ ++# This file goes in the /etc directory, and must be world readable. ++# You can override the system defaults by making a copy of this file ++# as ~/.dir_colors ++ + # Configuration file for dircolors, a utility to help you set the + # LS_COLORS environment variable used by GNU ls with the --color option. + +@@ -11,6 +15,9 @@ + + # Global config options can be specified before TERM or COLORTERM entries + ++# For compatibility, the pattern "^COLOR.*none" is recognized as a way to ++# disable colorization. See https://bugzilla.redhat.com/1349579 for details. ++ + # =================================================================== + # Terminal filters + # =================================================================== +@@ -69,7 +76,7 @@ DOOR 01;35 # door + BLK 40;33;01 # block device driver + CHR 40;33;01 # character device driver + ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file ... +-MISSING 00 # ... and the files they point to ++MISSING 01;37;41 # ... and the files they point to + SETUID 37;41 # file that is setuid (u+s) + SETGID 30;43 # file that is setgid (g+s) + CAPABILITY 00 # file with capability (very expensive to lookup) +diff --git a/DIR_COLORS.lightbgcolor b/DIR_COLORS.lightbgcolor +index eab6258..1627b63 100644 +--- a/DIR_COLORS.lightbgcolor ++++ b/DIR_COLORS.lightbgcolor +@@ -1,3 +1,9 @@ ++# Configuration file for the color ls utility - modified for lighter backgrounds ++ ++# This file goes in the /etc directory, and must be world readable. ++# You can override the system defaults by making a copy of this file ++# as ~/.dir_colors ++ + # Configuration file for dircolors, a utility to help you set the + # LS_COLORS environment variable used by GNU ls with the --color option. + +@@ -11,6 +17,9 @@ + + # Global config options can be specified before TERM or COLORTERM entries + ++# For compatibility, the pattern "^COLOR.*none" is recognized as a way to ++# disable colorization. See https://bugzilla.redhat.com/1349579 for details. ++ + # =================================================================== + # Terminal filters + # =================================================================== +@@ -59,17 +68,17 @@ TERM xterm* + #NORMAL 00 # no color code at all + #FILE 00 # regular file: use no color at all + RESET 0 # reset to "normal" color +-DIR 01;34 # directory +-LINK 01;36 # symbolic link. (If you set this to 'target' instead of a ++DIR 00;34 # directory ++LINK 00;36 # symbolic link. (If you set this to 'target' instead of a + # numerical value, the color is as for the file pointed to.) + MULTIHARDLINK 00 # regular file with more than one link + FIFO 40;33 # pipe +-SOCK 01;35 # socket +-DOOR 01;35 # door ++SOCK 00;35 # socket ++DOOR 00;35 # door + BLK 40;33;01 # block device driver + CHR 40;33;01 # character device driver + ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file ... +-MISSING 00 # ... and the files they point to ++MISSING 01;37;41 # ... and the files they point to + SETUID 37;41 # file that is setuid (u+s) + SETGID 30;43 # file that is setgid (g+s) + CAPABILITY 00 # file with capability (very expensive to lookup) +@@ -78,7 +87,7 @@ OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky + STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable + + # This is for files with execute permission: +-EXEC 01;32 ++EXEC 00;32 + + # =================================================================== + # File extension attributes +-- +2.34.1 + diff --git a/coreutils-9.5.tar.xz.sig b/coreutils-9.5.tar.xz.sig new file mode 100644 index 0000000..6014013 --- /dev/null +++ b/coreutils-9.5.tar.xz.sig @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCAAdFiEEbDfcEhIaUAa8HbgE32/ZcTBgN9kFAmYFirgACgkQ32/ZcTBg +N9nZMg//WF6fyy6kxNZJIeUnAzAyMhY5hjlD33hFSaj2ihfmt7IQzRuOu7bhYk94 +5lpDJvfljubJpuAU15MD0g/7xdRVPEf/igkRqdvm79eWips1c8d7HfcorxqJcYKf +40JV0rQyDaMqQbqFl6rPipAaagE3GBSdHz3eNVhiEQ9MII/XKNX7dZ/5MBIUW/wl +VM7G7sA4WBh0k+K0fGNALrlFHSmQDqwVIVhuDlFNcVmY37NIsIcvIT910HlKTFWV +A5okdepRs9a2dOIhGvMVK/U+4D9vbVbS+QlnXH74UlmnczKPQsCQKsusG02bv9L0 +ih+jFj9BVCoUjB1fQlo6/VE4Kvdhpg/NZKZCaKIEH0d4mn1XHqvyTTRN0SVOlJr8 +ZmY7e94A5TDbpkt5MFPxZ6M1Z5dZTtVX2/rkQtb59jIr/p5eYmjId3NsjWtoXICo +XMr+hLtjMt/XIfN/eXnaSOZSoyNxOPurfe59hfjVhaexCeIrEIglZmYWw8HhkfWz +vAxGWOFVwYfWlWlfxggdYkysRvU0vUb1JhO8HIRwmCX05YEhvTwKZMnvo/z/Y++G +CrXyduj9e8jzRkunlU6mqFmHqaYrgt5t7e1PLFYxEgWBX77fvpSbBsLhX5nH2c6I +4uRaQpaZQ+hnYu7U5OHfhy1OwG2qcYjbou4zK4BuI1ktnBHFgbc= +=IhBg +-----END PGP SIGNATURE----- diff --git a/SOURCES/coreutils-colorls.csh b/coreutils-colorls.csh similarity index 91% rename from SOURCES/coreutils-colorls.csh rename to coreutils-colorls.csh index f631762..66ec2fa 100755 --- a/SOURCES/coreutils-colorls.csh +++ b/coreutils-colorls.csh @@ -15,11 +15,6 @@ alias l. 'ls -d .*' set COLORS=/etc/DIR_COLORS if ($?TERM) then - if ( -e "/etc/DIR_COLORS.256color" ) then - if ( "`/usr/bin/tput colors`" == "256" ) then - set COLORS=/etc/DIR_COLORS.256color - endif - endif if ( -e "/etc/DIR_COLORS.$TERM" ) then set COLORS="/etc/DIR_COLORS.$TERM" endif diff --git a/SOURCES/coreutils-colorls.sh b/coreutils-colorls.sh similarity index 89% rename from SOURCES/coreutils-colorls.sh rename to coreutils-colorls.sh index ac92268..5162f1e 100755 --- a/SOURCES/coreutils-colorls.sh +++ b/coreutils-colorls.sh @@ -22,10 +22,6 @@ if [ -z "$USER_LS_COLORS" ]; then [ -z "$COLORS" ] && [ -e "/etc/DIR_COLORS.$TERM" ] && \ COLORS="/etc/DIR_COLORS.$TERM" - [ -z "$COLORS" ] && [ -e "/etc/DIR_COLORS.256color" ] && \ - [ "x`/usr/bin/tty -s && /usr/bin/tput colors 2>/dev/null`" = "x256" ] && \ - COLORS="/etc/DIR_COLORS.256color" - [ -z "$COLORS" ] && [ -e "/etc/DIR_COLORS" ] && \ COLORS="/etc/DIR_COLORS" diff --git a/SOURCES/coreutils-df-direct.patch b/coreutils-df-direct.patch similarity index 81% rename from SOURCES/coreutils-df-direct.patch rename to coreutils-df-direct.patch index 88015a1..f29a065 100644 --- a/SOURCES/coreutils-df-direct.patch +++ b/coreutils-df-direct.patch @@ -1,4 +1,4 @@ -From 6e36198f10a2f63b89c89ebb5d5c185b20fb3a63 Mon Sep 17 00:00:00 2001 +From f072852456c545bd89296bc88cf59ccd63287a68 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Mon, 29 Mar 2010 17:20:34 +0000 Subject: [PATCH] coreutils-df-direct.patch @@ -11,10 +11,10 @@ Subject: [PATCH] coreutils-df-direct.patch create mode 100755 tests/df/direct.sh diff --git a/doc/coreutils.texi b/doc/coreutils.texi -index 5b9a597..6810c15 100644 +index 8f7f43e..230f1f1 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi -@@ -11898,6 +11898,13 @@ some systems (notably SunOS), doing this yields more up to date results, +@@ -12427,6 +12427,13 @@ some systems (notably Solaris), doing this yields more up to date results, but in general this option makes @command{df} much slower, especially when there are many or very busy file systems. @@ -27,12 +27,12 @@ index 5b9a597..6810c15 100644 + @item --total @opindex --total - @cindex grand total of disk size, usage and available space + @cindex grand total of file system size, usage and available space diff --git a/src/df.c b/src/df.c -index 48025b9..c8efa5b 100644 +index 994f0e3..ceee209 100644 --- a/src/df.c +++ b/src/df.c -@@ -125,6 +125,9 @@ static bool print_type; +@@ -121,6 +121,9 @@ static bool print_type; /* If true, print a grand total at the end. */ static bool print_grand_total; @@ -42,7 +42,7 @@ index 48025b9..c8efa5b 100644 /* Grand total data. */ static struct fs_usage grand_fsu; -@@ -252,13 +255,15 @@ enum +@@ -247,13 +250,15 @@ enum NO_SYNC_OPTION = CHAR_MAX + 1, SYNC_OPTION, TOTAL_OPTION, @@ -53,16 +53,16 @@ index 48025b9..c8efa5b 100644 static struct option const long_options[] = { - {"all", no_argument, NULL, 'a'}, - {"block-size", required_argument, NULL, 'B'}, -+ {"direct", no_argument, NULL, DIRECT_OPTION}, - {"inodes", no_argument, NULL, 'i'}, - {"human-readable", no_argument, NULL, 'h'}, - {"si", no_argument, NULL, 'H'}, -@@ -561,7 +566,10 @@ get_header (void) + {"all", no_argument, nullptr, 'a'}, + {"block-size", required_argument, nullptr, 'B'}, ++ {"direct", no_argument, nullptr, DIRECT_OPTION}, + {"inodes", no_argument, nullptr, 'i'}, + {"human-readable", no_argument, nullptr, 'h'}, + {"si", no_argument, nullptr, 'H'}, +@@ -574,7 +579,10 @@ get_header (void) for (col = 0; col < ncolumns; col++) { - char *cell = NULL; + char *cell = nullptr; - char const *header = _(columns[col]->caption); + char const *header = (columns[col]->field == TARGET_FIELD + && direct_statfs)? @@ -71,7 +71,7 @@ index 48025b9..c8efa5b 100644 if (columns[col]->field == SIZE_FIELD && (header_mode == DEFAULT_MODE -@@ -1464,6 +1472,17 @@ get_point (const char *point, const struct stat *statp) +@@ -1471,6 +1479,17 @@ get_point (char const *point, const struct stat *statp) static void get_entry (char const *name, struct stat const *statp) { @@ -79,17 +79,17 @@ index 48025b9..c8efa5b 100644 + { + char *resolved = canonicalize_file_name (name); + if (resolved) -+ { -+ get_dev (NULL, resolved, name, NULL, NULL, false, false, NULL, false); -+ free (resolved); -+ return; -+ } ++ { ++ get_dev (NULL, resolved, name, NULL, NULL, false, false, NULL, false); ++ free (resolved); ++ return; ++ } + } + if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode)) - && get_disk (name)) + && get_device (name)) return; -@@ -1534,6 +1553,7 @@ or all file systems by default.\n\ +@@ -1541,6 +1560,7 @@ or all file systems by default.\n\ -B, --block-size=SIZE scale sizes by SIZE before printing them; e.g.,\n\ '-BM' prints sizes in units of 1,048,576 bytes;\n\ see SIZE format below\n\ @@ -97,7 +97,7 @@ index 48025b9..c8efa5b 100644 -h, --human-readable print sizes in powers of 1024 (e.g., 1023M)\n\ -H, --si print sizes in powers of 1000 (e.g., 1.1G)\n\ "), stdout); -@@ -1624,6 +1644,9 @@ main (int argc, char **argv) +@@ -1631,6 +1651,9 @@ main (int argc, char **argv) xstrtol_fatal (e, oi, c, long_options, optarg); } break; @@ -107,14 +107,14 @@ index 48025b9..c8efa5b 100644 case 'i': if (header_mode == OUTPUT_MODE) { -@@ -1720,6 +1743,13 @@ main (int argc, char **argv) +@@ -1727,6 +1750,13 @@ main (int argc, char **argv) } } + if (direct_statfs && show_local_fs) + { + error (0, 0, _("options --direct and --local (-l) are mutually " -+ "exclusive")); ++ "exclusive")); + usage (EXIT_FAILURE); + } + @@ -183,5 +183,5 @@ index 0000000..8e4cfb8 + +Exit $fail -- -2.31.1 +2.44.0 diff --git a/SOURCES/coreutils-i18n.patch b/coreutils-i18n.patch similarity index 50% rename from SOURCES/coreutils-i18n.patch rename to coreutils-i18n.patch index 429675f..214c2ac 100644 --- a/SOURCES/coreutils-i18n.patch +++ b/coreutils-i18n.patch @@ -1,37 +1,87 @@ -From 29117b2d07af00f4d4b87cf778e4294588ab1a83 Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Thu, 1 Dec 2016 15:10:04 +0100 +From 94cf02dfcb1be23dedf8a39af295f28ee2de6013 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Wed, 30 Aug 2023 17:19:58 +0200 Subject: [PATCH] coreutils-i18n.patch -TODO: merge upstream --- + bootstrap.conf | 2 + + configure.ac | 6 + lib/linebuffer.h | 8 + - src/fold.c | 308 ++++++++++++++++-- - src/join.c | 359 ++++++++++++++++++--- - src/pr.c | 443 ++++++++++++++++++++++--- - src/sort.c | 764 +++++++++++++++++++++++++++++++++++++++++--- - src/uniq.c | 265 ++++++++++++++- + lib/mbchar.c | 23 ++ + lib/mbchar.h | 373 +++++++++++++++++ + lib/mbfile.c | 20 + + lib/mbfile.h | 267 ++++++++++++ + m4/mbchar.m4 | 13 + + m4/mbfile.m4 | 14 + + src/cut.c | 508 +++++++++++++++++++++-- + src/expand-common.c | 114 ++++++ + src/expand-common.h | 12 + + src/expand.c | 90 +++- + src/fold.c | 312 ++++++++++++-- + src/local.mk | 4 +- + src/pr.c | 443 ++++++++++++++++++-- + src/sort.c | 792 +++++++++++++++++++++++++++++++++--- + src/unexpand.c | 102 ++++- + tests/Coreutils.pm | 3 + + tests/expand/mb.sh | 183 +++++++++ tests/i18n/sort.sh | 29 ++ - tests/local.mk | 2 + - tests/misc/expand.pl | 42 +++ + 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/misc/sort-mb-tests.sh | 45 ++ + tests/misc/unexpand.pl | 39 ++ tests/pr/pr-tests.pl | 49 +++ - 17 files changed, 2430 insertions(+), 160 deletions(-) - create mode 100755 tests/i18n/sort.sh - create mode 100755 tests/misc/sort-mb-tests.sh + tests/sort/sort-merge.pl | 42 ++ + tests/sort/sort.pl | 40 +- + tests/unexpand/mb.sh | 172 ++++++++ + 30 files changed, 3605 insertions(+), 196 deletions(-) + create mode 100644 lib/mbchar.c + create mode 100644 lib/mbchar.h + create mode 100644 lib/mbfile.c + create mode 100644 lib/mbfile.h + create mode 100644 m4/mbchar.m4 + create mode 100644 m4/mbfile.m4 + create mode 100644 tests/expand/mb.sh + create mode 100644 tests/i18n/sort.sh + create mode 100644 tests/misc/sort-mb-tests.sh + create mode 100644 tests/unexpand/mb.sh +diff --git a/bootstrap.conf b/bootstrap.conf +index 126e1e8..b4ccebf 100644 +--- a/bootstrap.conf ++++ b/bootstrap.conf +@@ -163,6 +163,8 @@ gnulib_modules=" + maintainer-makefile + malloc-gnu + manywarnings ++ mbchar ++ mbfile + mbrlen + mbrtoc32 + mbrtowc +diff --git a/configure.ac b/configure.ac +index 9cb6ee1..1131ce3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -504,6 +504,12 @@ fi + # I'm leaving it here for now. This whole thing needs to be modernized... + gl_WINSIZE_IN_PTEM + ++gl_MBFILE ++dnl Do not use gl_MODULE_INDICATOR([mbfile]) here: we don't want 'struct mbchar' ++dnl to have a different size in lib/ than in tests/. ++AC_DEFINE([GNULIB_MBFILE], [1], ++ [Define to 1 if the gnulib module 'mbfile' is in use.]) ++ + gl_HEADER_TIOCGWINSZ_IN_TERMIOS_H + + if test $gl_cv_sys_tiocgwinsz_needs_termios_h = no && \ diff --git a/lib/linebuffer.h b/lib/linebuffer.h -index 64181af..9b8fe5a 100644 +index ae0d55d..5bf5350 100644 --- a/lib/linebuffer.h +++ b/lib/linebuffer.h -@@ -21,6 +21,11 @@ - +@@ -22,6 +22,11 @@ + # include "idx.h" # include +/* Get mbstate_t. */ @@ -42,9 +92,9 @@ index 64181af..9b8fe5a 100644 /* A 'struct linebuffer' holds a line of text. */ struct linebuffer -@@ -28,6 +33,9 @@ struct linebuffer - size_t size; /* Allocated. */ - size_t length; /* Used. */ +@@ -29,6 +34,9 @@ struct linebuffer + idx_t size; /* Allocated. */ + idx_t length; /* Used. */ char *buffer; +# if HAVE_WCHAR_H + mbstate_t state; @@ -52,11 +102,1728 @@ index 64181af..9b8fe5a 100644 }; /* Initialize linebuffer LINEBUFFER for use. */ +diff --git a/lib/mbchar.c b/lib/mbchar.c +new file mode 100644 +index 0000000..d94b7c3 +--- /dev/null ++++ b/lib/mbchar.c +@@ -0,0 +1,23 @@ ++/* Copyright (C) 2001, 2006, 2009-2024 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see . */ ++ ++ ++#include ++ ++#define MBCHAR_INLINE _GL_EXTERN_INLINE ++ ++#include ++ ++#include "mbchar.h" +diff --git a/lib/mbchar.h b/lib/mbchar.h +new file mode 100644 +index 0000000..c06ef11 +--- /dev/null ++++ b/lib/mbchar.h +@@ -0,0 +1,373 @@ ++/* Multibyte character data type. ++ Copyright (C) 2001, 2005-2007, 2009-2024 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see . */ ++ ++/* Written by Bruno Haible . */ ++ ++/* A multibyte character is a short subsequence of a char* string, ++ representing a single 32-bit wide character. ++ ++ We use multibyte characters instead of 32-bit wide characters because ++ of the following goals: ++ 1) correct multibyte handling, i.e. operate according to the LC_CTYPE ++ locale, ++ 2) ease of maintenance, i.e. the maintainer needs not know all details ++ of the ISO C 99 standard, ++ 3) don't fail grossly if the input is not in the encoding set by the ++ locale, because often different encodings are in use in the same ++ countries (ISO-8859-1/UTF-8, EUC-JP/Shift_JIS, ...), ++ 4) fast in the case of ASCII characters. ++ ++ Multibyte characters are only accessed through the mb* macros. ++ ++ mb_ptr (mbc) ++ return a pointer to the beginning of the multibyte sequence. ++ ++ mb_len (mbc) ++ returns the number of bytes occupied by the multibyte sequence. ++ Always > 0. ++ ++ mb_iseq (mbc, sc) ++ returns true if mbc is the standard ASCII character sc. ++ ++ mb_isnul (mbc) ++ returns true if mbc is the nul character. ++ ++ mb_cmp (mbc1, mbc2) ++ returns a positive, zero, or negative value depending on whether mbc1 ++ sorts after, same or before mbc2. ++ ++ mb_casecmp (mbc1, mbc2) ++ returns a positive, zero, or negative value depending on whether mbc1 ++ sorts after, same or before mbc2, modulo upper/lowercase conversion. ++ ++ mb_equal (mbc1, mbc2) ++ returns true if mbc1 and mbc2 are equal. ++ ++ mb_caseequal (mbc1, mbc2) ++ returns true if mbc1 and mbc2 are equal modulo upper/lowercase conversion. ++ ++ mb_isalnum (mbc) ++ returns true if mbc is alphanumeric. ++ ++ mb_isalpha (mbc) ++ returns true if mbc is alphabetic. ++ ++ mb_isascii(mbc) ++ returns true if mbc is plain ASCII. ++ ++ mb_isblank (mbc) ++ returns true if mbc is a blank. ++ ++ mb_iscntrl (mbc) ++ returns true if mbc is a control character. ++ ++ mb_isdigit (mbc) ++ returns true if mbc is a decimal digit. ++ ++ mb_isgraph (mbc) ++ returns true if mbc is a graphic character. ++ ++ mb_islower (mbc) ++ returns true if mbc is lowercase. ++ ++ mb_isprint (mbc) ++ returns true if mbc is a printable character. ++ ++ mb_ispunct (mbc) ++ returns true if mbc is a punctuation character. ++ ++ mb_isspace (mbc) ++ returns true if mbc is a space character. ++ ++ mb_isupper (mbc) ++ returns true if mbc is uppercase. ++ ++ mb_isxdigit (mbc) ++ returns true if mbc is a hexadecimal digit. ++ ++ mb_width (mbc) ++ returns the number of columns on the output device occupied by mbc. ++ Always >= 0. ++ ++ mb_putc (mbc, stream) ++ outputs mbc on stream, a byte oriented FILE stream opened for output. ++ ++ mb_setascii (&mbc, sc) ++ assigns the standard ASCII character sc to mbc. ++ (Only available if the 'mbfile' module is in use.) ++ ++ mb_copy (&destmbc, &srcmbc) ++ copies srcmbc to destmbc. ++ ++ Here are the function prototypes of the macros. ++ ++ extern const char * mb_ptr (const mbchar_t mbc); ++ extern size_t mb_len (const mbchar_t mbc); ++ extern bool mb_iseq (const mbchar_t mbc, char sc); ++ extern bool mb_isnul (const mbchar_t mbc); ++ extern int mb_cmp (const mbchar_t mbc1, const mbchar_t mbc2); ++ extern int mb_casecmp (const mbchar_t mbc1, const mbchar_t mbc2); ++ extern bool mb_equal (const mbchar_t mbc1, const mbchar_t mbc2); ++ extern bool mb_caseequal (const mbchar_t mbc1, const mbchar_t mbc2); ++ extern bool mb_isalnum (const mbchar_t mbc); ++ extern bool mb_isalpha (const mbchar_t mbc); ++ extern bool mb_isascii (const mbchar_t mbc); ++ extern bool mb_isblank (const mbchar_t mbc); ++ extern bool mb_iscntrl (const mbchar_t mbc); ++ extern bool mb_isdigit (const mbchar_t mbc); ++ extern bool mb_isgraph (const mbchar_t mbc); ++ extern bool mb_islower (const mbchar_t mbc); ++ extern bool mb_isprint (const mbchar_t mbc); ++ extern bool mb_ispunct (const mbchar_t mbc); ++ extern bool mb_isspace (const mbchar_t mbc); ++ extern bool mb_isupper (const mbchar_t mbc); ++ extern bool mb_isxdigit (const mbchar_t mbc); ++ extern int mb_width (const mbchar_t mbc); ++ extern void mb_putc (const mbchar_t mbc, FILE *stream); ++ extern void mb_setascii (mbchar_t *new, char sc); ++ extern void mb_copy (mbchar_t *new, const mbchar_t *old); ++ */ ++ ++#ifndef _MBCHAR_H ++#define _MBCHAR_H 1 ++ ++/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE. */ ++#if !_GL_CONFIG_H_INCLUDED ++ #error "Please include config.h first." ++#endif ++ ++#include ++#include ++ ++_GL_INLINE_HEADER_BEGIN ++#ifndef MBCHAR_INLINE ++# define MBCHAR_INLINE _GL_INLINE ++#endif ++ ++/* The longest multibyte characters, nowadays, are 4 bytes long. ++ Regardless of the values of MB_CUR_MAX and MB_LEN_MAX. */ ++#define MBCHAR_BUF_SIZE 4 ++ ++struct mbchar ++{ ++ const char *ptr; /* pointer to current character */ ++ size_t bytes; /* number of bytes of current character, > 0 */ ++ bool wc_valid; /* true if wc is a valid 32-bit wide character */ ++ char32_t wc; /* if wc_valid: the current character */ ++#if defined GNULIB_MBFILE ++ char buf[MBCHAR_BUF_SIZE]; /* room for the bytes, used for file input only */ ++#endif ++}; ++ ++/* EOF (not a real character) is represented with bytes = 0 and ++ wc_valid = false. */ ++ ++typedef struct mbchar mbchar_t; ++ ++/* Access the current character. */ ++#define mb_ptr(mbc) ((mbc).ptr) ++#define mb_len(mbc) ((mbc).bytes) ++ ++/* Comparison of characters. */ ++#define mb_iseq(mbc, sc) ((mbc).wc_valid && (mbc).wc == (sc)) ++#define mb_isnul(mbc) ((mbc).wc_valid && (mbc).wc == 0) ++#define mb_cmp(mbc1, mbc2) \ ++ ((mbc1).wc_valid \ ++ ? ((mbc2).wc_valid \ ++ ? _GL_CMP ((mbc1).wc, (mbc2).wc) \ ++ : -1) \ ++ : ((mbc2).wc_valid \ ++ ? 1 \ ++ : (mbc1).bytes == (mbc2).bytes \ ++ ? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \ ++ : (mbc1).bytes < (mbc2).bytes \ ++ ? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \ ++ : (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1))) ++#define mb_casecmp(mbc1, mbc2) \ ++ ((mbc1).wc_valid \ ++ ? ((mbc2).wc_valid \ ++ ? _GL_CMP (c32tolower ((mbc1).wc), c32tolower ((mbc2).wc)) \ ++ : -1) \ ++ : ((mbc2).wc_valid \ ++ ? 1 \ ++ : (mbc1).bytes == (mbc2).bytes \ ++ ? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \ ++ : (mbc1).bytes < (mbc2).bytes \ ++ ? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \ ++ : (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1))) ++#define mb_equal(mbc1, mbc2) \ ++ ((mbc1).wc_valid && (mbc2).wc_valid \ ++ ? (mbc1).wc == (mbc2).wc \ ++ : (mbc1).bytes == (mbc2).bytes \ ++ && memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0) ++#define mb_caseequal(mbc1, mbc2) \ ++ ((mbc1).wc_valid && (mbc2).wc_valid \ ++ ? c32tolower ((mbc1).wc) == c32tolower ((mbc2).wc) \ ++ : (mbc1).bytes == (mbc2).bytes \ ++ && memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0) ++ ++/* , classification. */ ++#define mb_isascii(mbc) \ ++ ((mbc).wc_valid && (mbc).wc >= 0 && (mbc).wc <= 127) ++#define mb_isalnum(mbc) ((mbc).wc_valid && c32isalnum ((mbc).wc)) ++#define mb_isalpha(mbc) ((mbc).wc_valid && c32isalpha ((mbc).wc)) ++#define mb_isblank(mbc) ((mbc).wc_valid && c32isblank ((mbc).wc)) ++#define mb_iscntrl(mbc) ((mbc).wc_valid && c32iscntrl ((mbc).wc)) ++#define mb_isdigit(mbc) ((mbc).wc_valid && c32isdigit ((mbc).wc)) ++#define mb_isgraph(mbc) ((mbc).wc_valid && c32isgraph ((mbc).wc)) ++#define mb_islower(mbc) ((mbc).wc_valid && c32islower ((mbc).wc)) ++#define mb_isprint(mbc) ((mbc).wc_valid && c32isprint ((mbc).wc)) ++#define mb_ispunct(mbc) ((mbc).wc_valid && c32ispunct ((mbc).wc)) ++#define mb_isspace(mbc) ((mbc).wc_valid && c32isspace ((mbc).wc)) ++#define mb_isupper(mbc) ((mbc).wc_valid && c32isupper ((mbc).wc)) ++#define mb_isxdigit(mbc) ((mbc).wc_valid && c32isxdigit ((mbc).wc)) ++ ++/* Extra function. */ ++ ++/* Unprintable characters appear as a small box of width 1. */ ++#define MB_UNPRINTABLE_WIDTH 1 ++ ++MBCHAR_INLINE int ++mb_width_aux (char32_t wc) ++{ ++ int w = c32width (wc); ++ /* For unprintable characters, arbitrarily return 0 for control characters ++ and MB_UNPRINTABLE_WIDTH otherwise. */ ++ return (w >= 0 ? w : c32iscntrl (wc) ? 0 : MB_UNPRINTABLE_WIDTH); ++} ++ ++#define mb_width(mbc) \ ++ ((mbc).wc_valid ? mb_width_aux ((mbc).wc) : MB_UNPRINTABLE_WIDTH) ++ ++/* Output. */ ++#define mb_putc(mbc, stream) fwrite ((mbc).ptr, 1, (mbc).bytes, (stream)) ++ ++#if defined GNULIB_MBFILE ++/* Assignment. */ ++# define mb_setascii(mbc, sc) \ ++ ((mbc)->ptr = (mbc)->buf, (mbc)->bytes = 1, (mbc)->wc_valid = 1, \ ++ (mbc)->wc = (mbc)->buf[0] = (sc)) ++#endif ++ ++/* Copying a character. */ ++MBCHAR_INLINE void ++mb_copy (mbchar_t *new_mbc, const mbchar_t *old_mbc) ++{ ++#if defined GNULIB_MBFILE ++ if (old_mbc->ptr == &old_mbc->buf[0]) ++ { ++ memcpy (&new_mbc->buf[0], &old_mbc->buf[0], old_mbc->bytes); ++ new_mbc->ptr = &new_mbc->buf[0]; ++ } ++ else ++#endif ++ new_mbc->ptr = old_mbc->ptr; ++ new_mbc->bytes = old_mbc->bytes; ++ if ((new_mbc->wc_valid = old_mbc->wc_valid)) ++ new_mbc->wc = old_mbc->wc; ++} ++ ++ ++/* is_basic(c) tests whether the single-byte character c is ++ - in the ISO C "basic character set" or is one of '@', '$', and '`' ++ which ISO C 23 § 5.2.1.1.(1) guarantees to be single-byte and in ++ practice are safe to treat as basic in the execution character set, ++ or ++ - in the POSIX "portable character set", which ++ ++ equally guarantees to be single-byte. ++ This is a convenience function, and is in this file only to share code ++ between mbiter.h, mbuiter.h, and mbfile.h. */ ++#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ ++ && ('$' == 36) && ('%' == 37) && ('&' == 38) && ('\'' == 39) \ ++ && ('(' == 40) && (')' == 41) && ('*' == 42) && ('+' == 43) \ ++ && (',' == 44) && ('-' == 45) && ('.' == 46) && ('/' == 47) \ ++ && ('0' == 48) && ('1' == 49) && ('2' == 50) && ('3' == 51) \ ++ && ('4' == 52) && ('5' == 53) && ('6' == 54) && ('7' == 55) \ ++ && ('8' == 56) && ('9' == 57) && (':' == 58) && (';' == 59) \ ++ && ('<' == 60) && ('=' == 61) && ('>' == 62) && ('?' == 63) \ ++ && ('@' == 64) && ('A' == 65) && ('B' == 66) && ('C' == 67) \ ++ && ('D' == 68) && ('E' == 69) && ('F' == 70) && ('G' == 71) \ ++ && ('H' == 72) && ('I' == 73) && ('J' == 74) && ('K' == 75) \ ++ && ('L' == 76) && ('M' == 77) && ('N' == 78) && ('O' == 79) \ ++ && ('P' == 80) && ('Q' == 81) && ('R' == 82) && ('S' == 83) \ ++ && ('T' == 84) && ('U' == 85) && ('V' == 86) && ('W' == 87) \ ++ && ('X' == 88) && ('Y' == 89) && ('Z' == 90) && ('[' == 91) \ ++ && ('\\' == 92) && (']' == 93) && ('^' == 94) && ('_' == 95) \ ++ && ('`' == 96) && ('a' == 97) && ('b' == 98) && ('c' == 99) \ ++ && ('d' == 100) && ('e' == 101) && ('f' == 102) && ('g' == 103) \ ++ && ('h' == 104) && ('i' == 105) && ('j' == 106) && ('k' == 107) \ ++ && ('l' == 108) && ('m' == 109) && ('n' == 110) && ('o' == 111) \ ++ && ('p' == 112) && ('q' == 113) && ('r' == 114) && ('s' == 115) \ ++ && ('t' == 116) && ('u' == 117) && ('v' == 118) && ('w' == 119) \ ++ && ('x' == 120) && ('y' == 121) && ('z' == 122) && ('{' == 123) \ ++ && ('|' == 124) && ('}' == 125) && ('~' == 126) ++/* The character set is ISO-646, not EBCDIC. */ ++# define IS_BASIC_ASCII 1 ++ ++/* All locale encodings (see localcharset.h) map the characters 0x00..0x7F ++ to U+0000..U+007F, like ASCII, except for ++ CP864 different mapping of '%' ++ SHIFT_JIS different mappings of 0x5C, 0x7E ++ JOHAB different mapping of 0x5C ++ However, these characters in the range 0x20..0x7E are in the ISO C ++ "basic character set" and in the POSIX "portable character set", which ++ ISO C and POSIX guarantee to be single-byte. Thus, locales with these ++ encodings are not POSIX compliant. And they are most likely not in use ++ any more (as of 2023). */ ++# define is_basic(c) ((unsigned char) (c) < 0x80) ++ ++#else ++ ++MBCHAR_INLINE bool ++is_basic (char c) ++{ ++ switch (c) ++ { ++ case '\0': ++ case '\007': case '\010': ++ case '\t': case '\n': case '\v': case '\f': case '\r': ++ case ' ': case '!': case '"': case '#': case '$': case '%': ++ case '&': case '\'': case '(': case ')': case '*': ++ case '+': case ',': case '-': case '.': case '/': ++ case '0': case '1': case '2': case '3': case '4': ++ case '5': case '6': case '7': case '8': case '9': ++ case ':': case ';': case '<': case '=': case '>': ++ case '?': case '@': ++ case 'A': case 'B': case 'C': case 'D': case 'E': ++ case 'F': case 'G': case 'H': case 'I': case 'J': ++ case 'K': case 'L': case 'M': case 'N': case 'O': ++ case 'P': case 'Q': case 'R': case 'S': case 'T': ++ case 'U': case 'V': case 'W': case 'X': case 'Y': ++ case 'Z': ++ case '[': case '\\': case ']': case '^': case '_': case '`': ++ case 'a': case 'b': case 'c': case 'd': case 'e': ++ case 'f': case 'g': case 'h': case 'i': case 'j': ++ case 'k': case 'l': case 'm': case 'n': case 'o': ++ case 'p': case 'q': case 'r': case 's': case 't': ++ case 'u': case 'v': case 'w': case 'x': case 'y': ++ case 'z': case '{': case '|': case '}': case '~': ++ return 1; ++ default: ++ return 0; ++ } ++} ++ ++#endif ++ ++_GL_INLINE_HEADER_END ++ ++#endif /* _MBCHAR_H */ +diff --git a/lib/mbfile.c b/lib/mbfile.c +new file mode 100644 +index 0000000..8d2957b +--- /dev/null ++++ b/lib/mbfile.c +@@ -0,0 +1,20 @@ ++/* Multibyte character I/O: macros for multi-byte encodings. ++ Copyright (C) 2012-2023 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation, either version 3 of the ++ License, or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see . */ ++ ++#include ++ ++#define MBFILE_INLINE _GL_EXTERN_INLINE ++#include "mbfile.h" +diff --git a/lib/mbfile.h b/lib/mbfile.h +new file mode 100644 +index 0000000..ad61c19 +--- /dev/null ++++ b/lib/mbfile.h +@@ -0,0 +1,267 @@ ++/* Multibyte character I/O: macros for multi-byte encodings. ++ Copyright (C) 2001, 2005, 2009-2023 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation, either version 3 of the ++ License, or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see . */ ++ ++/* Written by Mitsuru Chinen ++ and Bruno Haible . */ ++ ++/* The macros in this file implement multi-byte character input from a ++ stream. ++ ++ mb_file_t ++ is the type for multibyte character input stream, usable for variable ++ declarations. ++ ++ mbf_char_t ++ is the type for multibyte character or EOF, usable for variable ++ declarations. ++ ++ mbf_init (mbf, stream) ++ initializes the MB_FILE for reading from stream. ++ ++ mbf_getc (mbc, mbf) ++ reads the next multibyte character from mbf and stores it in mbc. ++ ++ mb_iseof (mbc) ++ returns true if mbc represents the EOF value. ++ ++ Here are the function prototypes of the macros. ++ ++ extern void mbf_init (mb_file_t mbf, FILE *stream); ++ extern void mbf_getc (mbf_char_t mbc, mb_file_t mbf); ++ extern bool mb_iseof (const mbf_char_t mbc); ++ */ ++ ++#ifndef _MBFILE_H ++#define _MBFILE_H 1 ++ ++/* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE. */ ++#if !_GL_CONFIG_H_INCLUDED ++ #error "Please include config.h first." ++#endif ++ ++#include ++#include ++#include ++#include ++ ++#include "mbchar.h" ++ ++_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) ++{ ++ unsigned int new_bufcount; ++ 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; ++ } ++ ++ new_bufcount = mbf->bufcount; ++ ++ /* If mbf->state is not in an initial state, some more 32-bit wide character ++ may be hiding in the state. We need to call mbrtoc32 again. */ ++ #if GNULIB_MBRTOC32_REGULAR ++ assert (mbsinit (&mbf->state)); ++ #else ++ if (mbsinit (&mbf->state)) ++ #endif ++ { ++ /* Before using mbrtoc32, we need at least one byte. */ ++ if (new_bufcount == 0) ++ { ++ int c = getc (mbf->fp); ++ if (c == EOF) ++ { ++ mbf->eof_seen = true; ++ goto eof; ++ } ++ mbf->buf[0] = (unsigned char) c; ++ new_bufcount++; ++ } ++ ++ /* Handle most ASCII characters quickly, without calling mbrtoc32(). */ ++ if (new_bufcount == 1 && is_basic (mbf->buf[0])) ++ { ++ /* These characters are part of the POSIX portable character set. ++ For most of them, namely those in the ISO C basic character set, ++ ISO C 99 guarantees that their wide character code is identical to ++ their char code. For the few other ones, this is the case as well, ++ in all locale encodings that are in use. The 32-bit wide character ++ code is the same as well. */ ++ mbc->wc = mbc->buf[0] = mbf->buf[0]; ++ mbc->wc_valid = true; ++ mbc->ptr = &mbc->buf[0]; ++ mbc->bytes = 1; ++ mbf->bufcount = 0; ++ return; ++ } ++ } ++ ++ /* Use mbrtoc32 on an increasing number of bytes. Read only as many bytes ++ from mbf->fp as needed. This is needed to give reasonable interactive ++ behaviour when mbf->fp is connected to an interactive tty. */ ++ for (;;) ++ { ++ /* Feed the bytes one by one into mbrtoc32. */ ++ bytes = mbrtoc32 (&mbc->wc, &mbf->buf[mbf->bufcount], new_bufcount - mbf->bufcount, &mbf->state); ++ ++ if (bytes == (size_t) -1) ++ { ++ /* An invalid multibyte sequence was encountered. */ ++ mbf->bufcount = new_bufcount; ++ /* Return a single byte. */ ++ bytes = 1; ++ mbc->wc_valid = false; ++ /* Allow the next invocation to continue from a sane state. */ ++ mbszero (&mbf->state); ++ break; ++ } ++ else if (bytes == (size_t) -2) ++ { ++ /* An incomplete multibyte character. */ ++ mbf->bufcount = new_bufcount; ++ if (mbf->bufcount == MBCHAR_BUF_SIZE) ++ { ++ /* An overlong incomplete multibyte sequence was encountered. */ ++ /* Return a single byte. */ ++ bytes = 1; ++ mbc->wc_valid = false; ++ break; ++ } ++ else ++ { ++ /* Read one more byte and retry mbrtoc32. */ ++ int c = getc (mbf->fp); ++ if (c == EOF) ++ { ++ /* An incomplete multibyte character at the end. */ ++ mbf->eof_seen = true; ++ bytes = new_bufcount; ++ mbc->wc_valid = false; ++ break; ++ } ++ mbf->buf[new_bufcount] = (unsigned char) c; ++ new_bufcount++; ++ } ++ } ++ else ++ { ++ #if !GNULIB_MBRTOC32_REGULAR ++ if (bytes == (size_t) -3) ++ { ++ /* The previous multibyte sequence produced an additional 32-bit ++ wide character. */ ++ mbf->bufcount = new_bufcount; ++ bytes = 0; ++ } ++ else ++ #endif ++ { ++ bytes = mbf->bufcount + bytes; ++ mbf->bufcount = new_bufcount; ++ if (bytes == 0) ++ { ++ /* A null 32-bit wide character was encountered. */ ++ bytes = 1; ++ assert (mbf->buf[0] == '\0'); ++ assert (mbc->wc == 0); ++ } ++ } ++ mbc->wc_valid = true; ++ break; ++ } ++ } ++ ++ /* Return the multibyte sequence mbf->buf[0..bytes-1]. */ ++ mbc->ptr = &mbc->buf[0]; ++ memcpy (&mbc->buf[0], &mbf->buf[0], bytes); ++ mbc->bytes = bytes; ++ ++ mbf->bufcount -= bytes; ++ if (mbf->bufcount > 0) ++ { ++ /* It's not worth calling memmove() for so few bytes. */ ++ unsigned int count = mbf->bufcount; ++ char *p = &mbf->buf[0]; ++ ++ do ++ { ++ *p = *(p + bytes); ++ p++; ++ } ++ while (--count > 0); ++ } ++ return; ++ ++eof: ++ /* An mbchar_t with bytes == 0 is used to indicate EOF. */ ++ mbc->ptr = NULL; ++ mbc->bytes = 0; ++ mbc->wc_valid = false; ++ return; ++} ++ ++MBFILE_INLINE void ++mbfile_multi_ungetc (const struct mbchar *mbc, struct mbfile_multi *mbf) ++{ ++ 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, \ ++ mbszero (&(mbf).state), \ ++ (mbf).bufcount = 0) ++ ++#define mbf_getc(mbc, mbf) mbfile_multi_getc (&(mbc), &(mbf)) ++ ++#define mbf_ungetc(mbc, mbf) mbfile_multi_ungetc (&(mbc), &(mbf)) ++ ++#define mb_iseof(mbc) ((mbc).bytes == 0) ++ ++_GL_INLINE_HEADER_END ++ ++#endif /* _MBFILE_H */ +diff --git a/m4/mbchar.m4 b/m4/mbchar.m4 +new file mode 100644 +index 0000000..471e8c4 +--- /dev/null ++++ b/m4/mbchar.m4 +@@ -0,0 +1,13 @@ ++# mbchar.m4 serial 9 ++dnl Copyright (C) 2005-2007, 2009-2024 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 mbchar.m4 ++dnl From Bruno Haible. ++ ++AC_DEFUN([gl_MBCHAR], ++[ ++ AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) ++]) +diff --git a/m4/mbfile.m4 b/m4/mbfile.m4 +new file mode 100644 +index 0000000..83068a9 +--- /dev/null ++++ b/m4/mbfile.m4 +@@ -0,0 +1,14 @@ ++# mbfile.m4 serial 7 ++dnl Copyright (C) 2005, 2008-2023 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]) ++ : ++]) +diff --git a/src/cut.c b/src/cut.c +index 061e09c..6d10425 100644 +--- a/src/cut.c ++++ b/src/cut.c +@@ -27,6 +27,11 @@ + #include + #include + #include ++ ++/* Get mbstate_t, mbrtowc(). */ ++#if HAVE_WCHAR_H ++# include ++#endif + #include "system.h" + + #include "assure.h" +@@ -35,6 +40,18 @@ + + #include "set-fields.h" + ++/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC ++ installation; work around this configuration error. */ ++#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" + +@@ -51,6 +68,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 +@@ -58,6 +121,9 @@ + CURRENT_RP.HI then we make CURRENT_RP to point to the next range pair. */ + static struct field_range_pair *current_rp; + ++/* Length of the delimiter given as argument to -d. */ ++size_t delimlen; ++ + /* This buffer is used to support the semantics of the -s option + (or lack of same) when the specified field list includes (does + not include) the first field. In both of those cases, the entire +@@ -70,6 +136,29 @@ static char *field_1_buffer; + /* The number of bytes allocated for FIELD_1_BUFFER. */ + static size_t field_1_bufsize; + ++enum operating_mode ++ { ++ undefined_mode, ++ ++ /* 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. */ +@@ -81,10 +170,16 @@ 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'; + ++/* True if the --output-delimiter=STRING option was specified. */ ++static bool output_delimiter_specified; ++ + /* The length of output_delimiter_string. */ + static size_t output_delimiter_length; + +@@ -92,9 +187,6 @@ static size_t output_delimiter_length; + string consisting of the input delimiter. */ + static char *output_delimiter_string; + +-/* The output delimiter string contents, if the default. */ +-static char output_delimiter_default[1]; +- + /* True if we have ever read standard input. */ + static bool have_read_stdin; + +@@ -148,7 +240,7 @@ Print selected parts of lines from each FILE to standard output.\n\ + -f, --fields=LIST select only these fields; also print any line\n\ + that contains no delimiter character, unless\n\ + the -s option is specified\n\ +- -n (ignored)\n\ ++ -n with -b: don't split multibyte characters\n\ + "), stdout); + fputs (_("\ + --complement complement the set of selected bytes, characters\n\ +@@ -252,7 +344,7 @@ cut_bytes (FILE *stream) + next_item (&byte_idx); + if (print_kth (byte_idx)) + { +- if (output_delimiter_string != output_delimiter_default) ++ if (output_delimiter_specified) + { + if (print_delimiter && is_range_start_index (byte_idx)) + { +@@ -271,6 +363,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 +@@ -433,11 +601,218 @@ cut_fields (FILE *stream) + } + } + +-/* Process file FILE to standard output, using CUT_STREAM. ++#if HAVE_MBRTOWC ++static void ++cut_fields_mb (FILE *stream) ++{ ++ int c; ++ 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 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 ++#endif ++ { ++ if (operating_mode == field_mode) ++ cut_fields (stream); ++ else ++ cut_bytes (stream); ++ } ++} ++ ++/* Process file FILE to standard output. + Return true if successful. */ + + static bool +-cut_file (char const *file, void (*cut_stream) (FILE *)) ++cut_file (char const *file) + { + FILE *stream; + +@@ -482,8 +857,8 @@ main (int argc, char **argv) + int optc; + bool ok; + bool delim_specified = false; +- bool byte_mode = false; +- char *spec_list_string = nullptr; ++ char *spec_list_string IF_LINT ( = nullptr); ++ char mbdelim[MB_LEN_MAX + 1]; + + initialize_main (&argc, &argv); + set_program_name (argv[0]); +@@ -493,6 +868,8 @@ main (int argc, char **argv) + + atexit (close_stdout); + ++ operating_mode = undefined_mode; ++ + /* By default, all non-delimited lines are printed. */ + suppress_non_delimited = false; + +@@ -505,35 +882,77 @@ main (int argc, char **argv) + switch (optc) + { + case 'b': +- case 'c': + /* Build the byte list. */ +- byte_mode = true; +- FALLTHROUGH; ++ if (operating_mode != undefined_mode) ++ FATAL_ERROR (_("only one type of list may be specified")); ++ operating_mode = byte_mode; ++ spec_list_string = optarg; ++ break; ++ ++ 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 (spec_list_string) +- FATAL_ERROR (_("only one list may be specified")); ++ if (operating_mode != undefined_mode) ++ FATAL_ERROR (_("only one type of list may be specified")); ++ operating_mode = field_mode; + spec_list_string = optarg; + break; + + case 'd': + /* New delimiter. */ + /* 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: ++ output_delimiter_specified = true; + /* Interpret --output-delimiter='' to mean + 'use the NUL byte as the delimiter.' */ + output_delimiter_length = (optarg[0] == '\0' + ? 1 : strlen (optarg)); +- output_delimiter_string = optarg; ++ output_delimiter_string = xstrdup (optarg); + break; + + case 'n': ++ byte_mode_character_aware = 1; + break; + + case 's': +@@ -555,40 +974,57 @@ main (int argc, char **argv) + } + } + +- if (!spec_list_string) ++ if (operating_mode == undefined_mode) + FATAL_ERROR (_("you must specify a list of bytes, characters, or fields")); + +- if (byte_mode) +- { +- if (delim_specified) +- FATAL_ERROR (_("an input delimiter may be specified only\ ++ if (delim_specified && operating_mode != field_mode) ++ FATAL_ERROR (_("an input delimiter may be specified only\ + when operating on fields")); + +- if (suppress_non_delimited) +- FATAL_ERROR (_("suppressing non-delimited lines makes sense\n\ ++ if (suppress_non_delimited && operating_mode != field_mode) ++ FATAL_ERROR (_("suppressing non-delimited lines makes sense\n\ + \tonly when operating on fields")); +- } + + set_fields (spec_list_string, +- ((byte_mode ? SETFLD_ERRMSG_USE_POS : 0) +- | (complement ? SETFLD_COMPLEMENT : 0))); ++ ( (operating_mode == field_mode) ? 0 : SETFLD_ERRMSG_USE_POS) ++ | (complement ? SETFLD_COMPLEMENT : 0) ); + + 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 == nullptr) + { +- output_delimiter_default[0] = delim; +- output_delimiter_string = output_delimiter_default; +- output_delimiter_length = 1; ++#ifdef HAVE_MBRTOWC ++ if (MB_CUR_MAX > 1 && !force_singlebyte_mode) ++ { ++ 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; ++ } + } + +- void (*cut_stream) (FILE *) = byte_mode ? cut_bytes : cut_fields; + if (optind == argc) +- ok = cut_file ("-", cut_stream); ++ ok = cut_file ("-"); + else + for (ok = true; optind < argc; optind++) +- ok &= cut_file (argv[optind], cut_stream); ++ ok &= cut_file (argv[optind]); + + + if (have_read_stdin && fclose (stdin) == EOF) +diff --git a/src/expand-common.c b/src/expand-common.c +index c95998d..d4386fe 100644 +--- a/src/expand-common.c ++++ b/src/expand-common.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include "system.h" + #include "fadvise.h" + #include "quote.h" +@@ -123,6 +124,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 +diff --git a/src/expand-common.h b/src/expand-common.h +index 1a57108..6025652 100644 +--- a/src/expand-common.h ++++ b/src/expand-common.h +@@ -25,6 +25,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); +diff --git a/src/expand.c b/src/expand.c +index a6176a9..60b1b8e 100644 +--- a/src/expand.c ++++ b/src/expand.c +@@ -38,6 +38,9 @@ + #include + #include + #include ++ ++#include ++ + #include "system.h" + #include "expand-common.h" + +@@ -96,19 +99,41 @@ expand (void) + { + /* Input stream. */ + FILE *fp = next_file (nullptr); ++ mb_file_t mbf; ++ mbf_char_t c; ++ /* True if the starting locale is utf8. */ ++ bool using_utf_locale; ++ ++ /* 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: */ + +@@ -118,17 +143,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; +@@ -147,32 +203,34 @@ expand (void) + if (putchar (' ') < 0) + write_error (); + +- c = ' '; ++ mb_setascii (&c, ' '); + } +- else if (c == '\b') ++ else if (mb_iseq (c, '\b')) + { + /* Go back one column, and force recalculation of the + next tab stop. */ + column -= !!column; + tab_index -= !!tab_index; + } +- else ++ /* A leading control character could make us trip over. */ ++ else if (!mb_iscntrl (c)) + { +- column++; ++ column += mb_width (c); + if (!column) + error (EXIT_FAILURE, 0, _("input line is too long")); + } + +- convert &= convert_entire_line || !! isblank (c); ++ convert &= convert_entire_line || mb_isblank (c); + } + +- if (c < 0) ++ if (mb_iseof (c)) + return; + +- if (putchar (c) < 0) ++ mb_putc (c, stdout); ++ if (ferror (stdout)) + write_error (); + } +- while (c != '\n'); ++ while (!mb_iseq (c, '\n')); + } + } + diff --git a/src/fold.c b/src/fold.c -index 8cd0d6b..d23edd5 100644 +index 941ad11..cf1e747 100644 --- a/src/fold.c +++ b/src/fold.c -@@ -22,12 +22,34 @@ +@@ -23,10 +23,32 @@ #include #include @@ -71,8 +1838,6 @@ index 8cd0d6b..d23edd5 100644 +#endif + #include "system.h" - #include "die.h" - #include "error.h" #include "fadvise.h" #include "xdectoint.h" @@ -91,7 +1856,7 @@ index 8cd0d6b..d23edd5 100644 #define TAB_WIDTH 8 /* The official name of this program (e.g., no 'g' prefix). */ -@@ -35,20 +57,41 @@ +@@ -34,20 +56,41 @@ #define AUTHORS proper_name ("David MacKenzie") @@ -132,12 +1897,12 @@ index 8cd0d6b..d23edd5 100644 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'}, + {"bytes", no_argument, nullptr, 'b'}, ++ {"characters", no_argument, nullptr, 'c'}, + {"spaces", no_argument, nullptr, 's'}, + {"width", required_argument, nullptr, 'w'}, {GETOPT_HELP_OPTION_DECL}, -@@ -76,6 +119,7 @@ Wrap input lines in each FILE, writing to standard output.\n\ +@@ -75,6 +118,7 @@ Wrap input lines in each FILE, writing to standard output.\n\ fputs (_("\ -b, --bytes count bytes rather than columns\n\ @@ -145,7 +1910,7 @@ index 8cd0d6b..d23edd5 100644 -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 to standard output.\n\ +@@ -92,7 +136,7 @@ Wrap input lines in each FILE, writing to standard output.\n\ static size_t adjust_column (size_t column, char c) { @@ -154,7 +1919,7 @@ index 8cd0d6b..d23edd5 100644 { if (c == '\b') { -@@ -116,30 +160,14 @@ adjust_column (size_t column, char c) +@@ -115,30 +159,14 @@ adjust_column (size_t column, char c) to stdout, with maximum line length WIDTH. Return true if successful. */ @@ -167,7 +1932,7 @@ index 8cd0d6b..d23edd5 100644 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 char *line_out = nullptr; static size_t allocated_out = 0; - int saved_errno; - @@ -179,7 +1944,7 @@ index 8cd0d6b..d23edd5 100644 - else - istream = fopen (filename, "r"); - -- if (istream == NULL) +- if (istream == nullptr) - { - error (0, errno, "%s", quotef (filename)); - return false; @@ -187,7 +1952,7 @@ index 8cd0d6b..d23edd5 100644 fadvise (istream, FADVISE_SEQUENTIAL); -@@ -169,6 +197,15 @@ fold_file (char const *filename, size_t width) +@@ -168,6 +196,15 @@ fold_file (char const *filename, size_t width) bool found_blank = false; size_t logical_end = offset_out; @@ -203,12 +1968,15 @@ index 8cd0d6b..d23edd5 100644 /* Look for the last blank. */ while (logical_end) { -@@ -215,11 +252,221 @@ fold_file (char const *filename, size_t width) +@@ -214,13 +251,225 @@ fold_file (char const *filename, size_t width) line_out[offset_out++] = c; } - saved_errno = errno; + *saved_errno = errno; + if (!ferror (istream)) +- saved_errno = 0; ++ *saved_errno = 0; if (offset_out) fwrite (line_out, sizeof (char), (size_t) offset_out, stdout); @@ -384,6 +2152,8 @@ index 8cd0d6b..d23edd5 100644 + } + + *saved_errno = errno; ++ if (!ferror (istream)) ++ *saved_errno = 0; + + if (offset_out) + fwrite (line_out, sizeof (char), (size_t) offset_out, stdout); @@ -412,7 +2182,7 @@ index 8cd0d6b..d23edd5 100644 + if (istream == NULL) + { + error (0, errno, "%s", filename); -+ return 1; ++ return false; + } + + /* Define how ISTREAM is being folded. */ @@ -423,10 +2193,10 @@ index 8cd0d6b..d23edd5 100644 +#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) + if (STREQ (filename, "-")) + clearerr (istream); + else if (fclose (istream) != 0 && !saved_errno) +@@ -251,7 +500,8 @@ main (int argc, char **argv) atexit (close_stdout); @@ -434,9 +2204,9 @@ index 8cd0d6b..d23edd5 100644 + operating_mode = column_mode; + break_spaces = have_read_stdin = false; - while ((optc = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1) + while ((optc = getopt_long (argc, argv, shortopts, longopts, nullptr)) != -1) { -@@ -261,7 +509,15 @@ main (int argc, char **argv) +@@ -260,7 +510,15 @@ main (int argc, char **argv) switch (optc) { case 'b': /* Count bytes rather than columns. */ @@ -453,505 +2223,27 @@ index 8cd0d6b..d23edd5 100644 break; case 's': /* Break at word boundaries. */ -diff --git a/src/join.c b/src/join.c -index 98b461c..9990f38 100644 ---- a/src/join.c -+++ b/src/join.c -@@ -22,19 +22,33 @@ - #include - #include +diff --git a/src/local.mk b/src/local.mk +index 96ee941..8fdb8fc 100644 +--- a/src/local.mk ++++ b/src/local.mk +@@ -450,8 +450,8 @@ src_base32_CPPFLAGS = -DBASE_TYPE=32 $(AM_CPPFLAGS) + src_basenc_SOURCES = src/basenc.c + src_basenc_CPPFLAGS = -DBASE_TYPE=42 $(AM_CPPFLAGS) -+/* 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 line const *line2, - 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, int which) - } - ++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 *line) - - /* 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 line const *line2) - o = o->next; - if (o == NULL) - break; -- putchar (output_separator); -+ PUT_TAB_CHAR; - } - putchar (eolchar); - } -@@ -1099,20 +1345,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; +-src_expand_SOURCES = src/expand.c src/expand-common.c +-src_unexpand_SOURCES = src/unexpand.c src/expand-common.c ++src_expand_SOURCES = src/expand.c src/expand-common.c lib/mbfile.c lib/mbchar.c ++src_unexpand_SOURCES = src/unexpand.c src/expand-common.c lib/mbfile.c lib/mbchar.c + src_wc_SOURCES = src/wc.c + if USE_AVX2_WC_LINECOUNT diff --git a/src/pr.c b/src/pr.c -index 26f221f..633f50e 100644 +index 09c6fa8..7552b62 100644 --- a/src/pr.c +++ b/src/pr.c -@@ -311,6 +311,24 @@ - +@@ -312,6 +312,24 @@ + #include #include #include + @@ -973,10 +2265,10 @@ index 26f221f..633f50e 100644 +#endif + #include "system.h" - #include "die.h" - #include "error.h" + #include "fadvise.h" + #include "hard-locale.h" @@ -324,6 +342,18 @@ - #include "xstrtol.h" + #include "xstrtol-error.h" #include "xdectoint.h" +/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ @@ -1017,8 +2309,8 @@ index 26f221f..633f50e 100644 static bool print_page (void); static bool print_stored (COLUMN *p); @@ -428,6 +471,7 @@ static void add_line_number (COLUMN *p); - static void getoptnum (const char *n_str, int min, int *num, - const char *errfmt); + static void getoptnum (char const *n_str, int min, int *num, + char const *errfmt); static void getoptarg (char *arg, char switch_char, char *character, + int *character_length, int *character_width, int *number); @@ -1031,7 +2323,7 @@ index 26f221f..633f50e 100644 -static void print_char (char c); static void cleanup (void); static void print_sep_string (void); - static void separator_string (const char *optarg_S); + static void separator_string (char const *optarg_S); @@ -453,7 +496,7 @@ static COLUMN *column_vector; we store the leftmost columns contiguously in buff. To print a line from buff, get the index of the first character @@ -1085,7 +2377,7 @@ index 26f221f..633f50e 100644 static char *column_separator = (char *) " "; static char *line_separator = (char *) "\t"; -@@ -851,6 +904,13 @@ separator_string (const char *optarg_S) +@@ -852,6 +905,13 @@ separator_string (char const *optarg_S) integer_overflow (); col_sep_length = len; col_sep_string = optarg_S; @@ -1099,7 +2391,7 @@ index 26f221f..633f50e 100644 } int -@@ -875,6 +935,21 @@ main (int argc, char **argv) +@@ -876,6 +936,21 @@ main (int argc, char **argv) atexit (close_stdout); @@ -1121,7 +2413,7 @@ index 26f221f..633f50e 100644 n_files = 0; file_names = (argc > 1 ? xnmalloc (argc - 1, sizeof (char *)) -@@ -951,8 +1026,12 @@ main (int argc, char **argv) +@@ -952,8 +1027,12 @@ main (int argc, char **argv) break; case 'e': if (optarg) @@ -1136,7 +2428,7 @@ index 26f221f..633f50e 100644 /* Could check tab width > 0. */ untabify_input = true; break; -@@ -965,8 +1044,12 @@ main (int argc, char **argv) +@@ -966,8 +1045,12 @@ main (int argc, char **argv) break; case 'i': if (optarg) @@ -1151,7 +2443,7 @@ index 26f221f..633f50e 100644 /* Could check tab width > 0. */ tabify_output = true; break; -@@ -984,8 +1067,8 @@ main (int argc, char **argv) +@@ -985,8 +1068,8 @@ main (int argc, char **argv) case 'n': numbered_lines = true; if (optarg) @@ -1162,7 +2454,7 @@ index 26f221f..633f50e 100644 break; case 'N': skip_count = false; -@@ -1010,6 +1093,7 @@ main (int argc, char **argv) +@@ -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; @@ -1170,7 +2462,7 @@ index 26f221f..633f50e 100644 use_col_separator = true; if (optarg) separator_string (optarg); -@@ -1165,10 +1249,45 @@ getoptnum (const char *n_str, int min, int *num, const char *err) +@@ -1165,7 +1249,8 @@ getoptnum (char const *n_str, int min, int *num, char const *err) a number. */ static void @@ -1178,6 +2470,11 @@ index 26f221f..633f50e 100644 +getoptarg (char *arg, char switch_char, char *character, int *character_length, + int *character_width, int *number) { + if (!*arg) + { +@@ -1174,7 +1259,41 @@ getoptarg (char *arg, char switch_char, char *character, int *number) + } + if (!ISDIGIT (*arg)) - *character = *arg++; + { @@ -1218,7 +2515,7 @@ index 26f221f..633f50e 100644 if (*arg) { long int tmp_long; -@@ -1190,6 +1309,11 @@ static void +@@ -1203,6 +1322,11 @@ static void init_parameters (int number_of_files) { int chars_used_by_number = 0; @@ -1230,7 +2527,7 @@ index 26f221f..633f50e 100644 lines_per_body = lines_per_page - lines_per_header - lines_per_footer; if (lines_per_body <= 0) -@@ -1227,7 +1351,7 @@ init_parameters (int number_of_files) +@@ -1240,7 +1364,7 @@ init_parameters (int number_of_files) else col_sep_string = column_separator; @@ -1239,7 +2536,7 @@ index 26f221f..633f50e 100644 use_col_separator = true; } /* It's rather pointless to define a TAB separator with column -@@ -1257,11 +1381,11 @@ init_parameters (int number_of_files) +@@ -1272,11 +1396,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. */ @@ -1253,16 +2550,16 @@ index 26f221f..633f50e 100644 /* The number is part of the column width unless we are printing files in parallel. */ -@@ -1270,7 +1394,7 @@ init_parameters (int number_of_files) +@@ -1285,7 +1409,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)) +- if (ckd_mul (&sep_chars, columns - 1, col_sep_length)) ++ if (ckd_mul (&sep_chars, columns - 1, col_sep_width)) sep_chars = INT_MAX; - if (INT_SUBTRACT_WRAPV (chars_per_line - chars_used_by_number, sep_chars, - &useful_chars)) -@@ -1293,7 +1417,7 @@ init_parameters (int number_of_files) + if (ckd_sub (&useful_chars, chars_per_line - chars_used_by_number, + sep_chars)) +@@ -1308,7 +1432,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); @@ -1271,7 +2568,7 @@ index 26f221f..633f50e 100644 } /* Open the necessary files, -@@ -1399,7 +1523,7 @@ init_funcs (void) +@@ -1414,7 +1538,7 @@ init_funcs (void) /* Enlarge p->start_position of first column to use the same form of padding_not_printed with all columns. */ @@ -1280,7 +2577,7 @@ index 26f221f..633f50e 100644 /* This loop takes care of all but the rightmost column. */ -@@ -1433,7 +1557,7 @@ init_funcs (void) +@@ -1448,7 +1572,7 @@ init_funcs (void) } else { @@ -1289,7 +2586,7 @@ index 26f221f..633f50e 100644 h_next = h + chars_per_column; } } -@@ -1724,9 +1848,9 @@ static void +@@ -1745,9 +1869,9 @@ static void align_column (COLUMN *p) { padding_not_printed = p->start_position; @@ -1301,7 +2598,7 @@ index 26f221f..633f50e 100644 padding_not_printed = ANYWHERE; } -@@ -2001,13 +2125,13 @@ store_char (char c) +@@ -2021,13 +2145,13 @@ store_char (char c) /* May be too generous. */ buff = X2REALLOC (buff, &buff_allocated); } @@ -1317,7 +2614,7 @@ index 26f221f..633f50e 100644 char *s; int num_width; -@@ -2024,22 +2148,24 @@ add_line_number (COLUMN *p) +@@ -2044,22 +2168,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. */ @@ -1346,7 +2643,7 @@ index 26f221f..633f50e 100644 output_position = POS_AFTER_TAB (chars_per_output_tab, output_position); } -@@ -2198,7 +2324,7 @@ print_white_space (void) +@@ -2218,7 +2344,7 @@ print_white_space (void) while (goal - h_old > 1 && (h_new = POS_AFTER_TAB (chars_per_output_tab, h_old)) <= goal) { @@ -1355,7 +2652,7 @@ index 26f221f..633f50e 100644 h_old = h_new; } while (++h_old <= goal) -@@ -2218,6 +2344,7 @@ print_sep_string (void) +@@ -2238,6 +2364,7 @@ print_sep_string (void) { char const *s = col_sep_string; int l = col_sep_length; @@ -1363,7 +2660,7 @@ index 26f221f..633f50e 100644 if (separators_not_printed <= 0) { -@@ -2229,6 +2356,7 @@ print_sep_string (void) +@@ -2249,6 +2376,7 @@ print_sep_string (void) { for (; separators_not_printed > 0; --separators_not_printed) { @@ -1371,7 +2668,7 @@ index 26f221f..633f50e 100644 while (l-- > 0) { /* 3 types of sep_strings: spaces only, spaces and chars, -@@ -2242,12 +2370,15 @@ print_sep_string (void) +@@ -2262,12 +2390,15 @@ print_sep_string (void) } else { @@ -1388,7 +2685,7 @@ index 26f221f..633f50e 100644 /* sep_string ends with some spaces */ if (spaces_not_printed > 0) print_white_space (); -@@ -2275,7 +2406,7 @@ print_clump (COLUMN *p, int n, char *clump) +@@ -2295,7 +2426,7 @@ print_clump (COLUMN *p, int n, char *clump) required number of tabs and spaces. */ static void @@ -1397,7 +2694,7 @@ index 26f221f..633f50e 100644 { if (tabify_output) { -@@ -2299,6 +2430,74 @@ print_char (char c) +@@ -2319,6 +2450,74 @@ print_char (char c) putchar (c); } @@ -1472,7 +2769,7 @@ index 26f221f..633f50e 100644 /* Skip to page PAGE before printing. PAGE may be larger than total number of pages. */ -@@ -2476,9 +2675,9 @@ read_line (COLUMN *p) +@@ -2495,9 +2694,9 @@ read_line (COLUMN *p) align_empty_cols = false; } @@ -1484,7 +2781,7 @@ index 26f221f..633f50e 100644 padding_not_printed = ANYWHERE; } -@@ -2547,7 +2746,7 @@ print_stored (COLUMN *p) +@@ -2566,7 +2765,7 @@ print_stored (COLUMN *p) COLUMN *q; int line = p->current_line++; @@ -1493,7 +2790,7 @@ index 26f221f..633f50e 100644 /* FIXME UMR: Uninitialized memory read: * This is occurring while in: -@@ -2559,7 +2758,7 @@ print_stored (COLUMN *p) +@@ -2578,7 +2777,7 @@ print_stored (COLUMN *p) xmalloc [xmalloc.c:94] init_store_cols [pr.c:1648] */ @@ -1502,7 +2799,7 @@ index 26f221f..633f50e 100644 pad_vertically = true; -@@ -2579,9 +2778,9 @@ print_stored (COLUMN *p) +@@ -2598,9 +2797,9 @@ print_stored (COLUMN *p) } } @@ -1514,7 +2811,7 @@ index 26f221f..633f50e 100644 padding_not_printed = ANYWHERE; } -@@ -2594,8 +2793,8 @@ print_stored (COLUMN *p) +@@ -2613,8 +2812,8 @@ print_stored (COLUMN *p) if (spaces_not_printed == 0) { output_position = p->start_position + end_vector[line]; @@ -1525,7 +2822,7 @@ index 26f221f..633f50e 100644 } return true; -@@ -2614,7 +2813,7 @@ print_stored (COLUMN *p) +@@ -2633,7 +2832,7 @@ print_stored (COLUMN *p) number of characters is 1.) */ static int @@ -1534,7 +2831,7 @@ index 26f221f..633f50e 100644 { unsigned char uc = c; char *s = clump_buff; -@@ -2624,10 +2823,10 @@ char_to_clump (char c) +@@ -2643,10 +2842,10 @@ char_to_clump (char c) int chars; int chars_per_c = 8; @@ -1547,7 +2844,7 @@ index 26f221f..633f50e 100644 { width = TAB_WIDTH (chars_per_c, input_position); -@@ -2708,6 +2907,164 @@ char_to_clump (char c) +@@ -2727,6 +2926,164 @@ char_to_clump (char c) return chars; } @@ -1713,13 +3010,13 @@ index 26f221f..633f50e 100644 looking for more options and printing the next batch of files. diff --git a/src/sort.c b/src/sort.c -index 6d2eec5..f189a0d 100644 +index 2d8324c..46331b8 100644 --- a/src/sort.c +++ b/src/sort.c @@ -29,6 +29,14 @@ + #include #include #include - #include +#if HAVE_WCHAR_H +# include +#endif @@ -1730,10 +3027,10 @@ index 6d2eec5..f189a0d 100644 + #include "system.h" #include "argmatch.h" - #include "die.h" -@@ -169,14 +177,39 @@ static int decimal_point; - /* Thousands separator; if -1, then there isn't one. */ - static int thousands_sep; + #include "assure.h" +@@ -157,14 +165,39 @@ static int thousands_sep; + /* We currently ignore multi-byte grouping chars. */ + static bool thousands_sep_ignored; +/* True if -f is specified. */ +static bool folding; @@ -1772,9 +3069,9 @@ index 6d2eec5..f189a0d 100644 /* The kind of blanks for '-b' to skip in various options. */ enum blanktype { bl_start, bl_end, bl_both }; -@@ -350,13 +383,11 @@ static bool reverse; - they were read if all keys compare equal. */ - static bool stable; +@@ -341,13 +374,11 @@ static bool stable; + /* An int value outside char range. */ + enum { NON_CHAR = CHAR_MAX + 1 }; -/* If TAB has this value, blanks separate fields. */ -enum { TAB_DEFAULT = CHAR_MAX + 1 }; @@ -1789,7 +3086,7 @@ index 6d2eec5..f189a0d 100644 /* Flag to remove consecutive duplicate lines from the output. Only the last of a sequence of equal lines will be output. */ -@@ -814,6 +845,46 @@ reap_all (void) +@@ -804,6 +835,46 @@ reap_all (void) reap (-1); } @@ -1836,7 +3133,7 @@ index 6d2eec5..f189a0d 100644 /* Clean up any remaining temporary files. */ static void -@@ -1264,7 +1335,7 @@ zaptemp (char const *name) +@@ -1271,7 +1342,7 @@ zaptemp (char const *name) free (node); } @@ -1845,7 +3142,7 @@ index 6d2eec5..f189a0d 100644 static int struct_month_cmp (void const *m1, void const *m2) -@@ -1279,7 +1350,7 @@ struct_month_cmp (void const *m1, void const *m2) +@@ -1286,7 +1357,7 @@ struct_month_cmp (void const *m1, void const *m2) /* Initialize the character class tables. */ static void @@ -1854,7 +3151,7 @@ index 6d2eec5..f189a0d 100644 { size_t i; -@@ -1291,7 +1362,7 @@ inittables (void) +@@ -1298,7 +1369,7 @@ inittables (void) fold_toupper[i] = toupper (i); } @@ -1863,7 +3160,7 @@ index 6d2eec5..f189a0d 100644 /* If we're not in the "C" locale, read different names for months. */ if (hard_LC_TIME) { -@@ -1373,6 +1444,84 @@ specify_nmerge (int oi, char c, char const *s) +@@ -1380,6 +1451,84 @@ specify_nmerge (int oi, char c, char const *s) xstrtol_fatal (e, oi, c, long_options, s); } @@ -1948,7 +3245,7 @@ index 6d2eec5..f189a0d 100644 /* Specify the amount of main memory to use when sorting. */ static void specify_sort_size (int oi, char c, char const *s) -@@ -1604,7 +1753,7 @@ buffer_linelim (struct buffer const *buf) +@@ -1611,7 +1760,7 @@ buffer_linelim (struct buffer const *buf) by KEY in LINE. */ static char * @@ -1957,7 +3254,7 @@ index 6d2eec5..f189a0d 100644 { char *ptr = line->text, *lim = ptr + line->length - 1; size_t sword = key->sword; -@@ -1613,10 +1762,10 @@ begfield (struct line const *line, struct keyfield const *key) +@@ -1620,10 +1769,10 @@ begfield (struct line const *line, struct keyfield const *key) /* The leading field separator itself is included in a field when -t is absent. */ @@ -1970,7 +3267,7 @@ index 6d2eec5..f189a0d 100644 ++ptr; if (ptr < lim) ++ptr; -@@ -1642,11 +1791,70 @@ begfield (struct line const *line, struct keyfield const *key) +@@ -1649,12 +1798,71 @@ begfield (struct line const *line, struct keyfield const *key) return ptr; } @@ -2036,13 +3333,14 @@ index 6d2eec5..f189a0d 100644 /* Return the limit of (a pointer to the first character after) the field in LINE specified by KEY. */ + ATTRIBUTE_PURE static char * -limfield (struct line const *line, struct keyfield const *key) -+limfield_uni (const struct line *line, const struct keyfield *key) ++limfield_uni (struct line const *line, struct keyfield const *key) { char *ptr = line->text, *lim = ptr + line->length - 1; size_t eword = key->eword, echar = key->echar; -@@ -1661,10 +1869,10 @@ limfield (struct line const *line, struct keyfield const *key) +@@ -1669,10 +1877,10 @@ limfield (struct line const *line, struct keyfield const *key) 'beginning' is the first character following the delimiting TAB. Otherwise, leave PTR pointing at the first 'blank' character after the preceding field. */ @@ -2055,7 +3353,7 @@ index 6d2eec5..f189a0d 100644 ++ptr; if (ptr < lim && (eword || echar)) ++ptr; -@@ -1710,10 +1918,10 @@ limfield (struct line const *line, struct keyfield const *key) +@@ -1718,10 +1926,10 @@ limfield (struct line const *line, struct keyfield const *key) */ /* Make LIM point to the end of (one byte past) the current field. */ @@ -2068,12 +3366,12 @@ index 6d2eec5..f189a0d 100644 if (newlim) lim = newlim; } -@@ -1744,6 +1952,130 @@ limfield (struct line const *line, struct keyfield const *key) +@@ -1752,6 +1960,130 @@ limfield (struct line const *line, struct keyfield const *key) return ptr; } +#if HAVE_MBRTOWC -+static char * ++static char * _GL_ATTRIBUTE_PURE +limfield_mb (const struct line *line, const struct keyfield *key) +{ + char *ptr = line->text, *lim = ptr + line->length - 1; @@ -2199,7 +3497,7 @@ index 6d2eec5..f189a0d 100644 /* Fill BUF reading from FP, moving buf->left bytes from the end of buf->buf to the beginning first. If EOF is reached and the file wasn't terminated by a newline, supply one. Set up BUF's line -@@ -1830,8 +2162,22 @@ fillbuf (struct buffer *buf, FILE *fp, char const *file) +@@ -1838,8 +2170,22 @@ fillbuf (struct buffer *buf, FILE *fp, char const *file) else { if (key->skipsblanks) @@ -2224,16 +3522,32 @@ index 6d2eec5..f189a0d 100644 line->keybeg = line_start; } } -@@ -1981,7 +2327,7 @@ human_numcompare (char const *a, char const *b) - hideously fast. */ +@@ -1977,12 +2323,10 @@ find_unit_order (char const *number) + ATTRIBUTE_PURE + static int +-human_numcompare (char const *a, char const *b) ++human_numcompare (char *a, char *b) + { +- while (blanks[to_uchar (*a)]) +- a++; +- while (blanks[to_uchar (*b)]) +- b++; ++ skipblanks(&a, a + strlen(a)); ++ skipblanks(&b, b + strlen(b)); + + int diff = find_unit_order (a) - find_unit_order (b); + return (diff ? diff : strnumcmp (a, b, decimal_point, thousands_sep)); +@@ -1994,7 +2338,7 @@ human_numcompare (char const *a, char const *b) + + ATTRIBUTE_PURE static int -numcompare (char const *a, char const *b) +numcompare_uni (const char *a, const char *b) { while (blanks[to_uchar (*a)]) a++; -@@ -1991,6 +2337,25 @@ numcompare (char const *a, char const *b) +@@ -2004,6 +2348,25 @@ numcompare (char const *a, char const *b) return strnumcmp (a, b, decimal_point, thousands_sep); } @@ -2256,10 +3570,10 @@ index 6d2eec5..f189a0d 100644 +} +#endif /* HAV_EMBRTOWC */ + - /* Work around a problem whereby the long double value returned by glibc's - strtold ("NaN", ...) contains uninitialized bits: clear all bytes of - A and B before calling strtold. FIXME: remove this function once -@@ -2041,7 +2406,7 @@ general_numcompare (char const *sa, char const *sb) + static int + nan_compare (long double a, long double b) + { +@@ -2045,7 +2408,7 @@ general_numcompare (char const *sa, char const *sb) Return 0 if the name in S is not recognized. */ static int @@ -2268,7 +3582,7 @@ index 6d2eec5..f189a0d 100644 { size_t lo = 0; size_t hi = MONTHS_PER_YEAR; -@@ -2317,15 +2682,14 @@ debug_key (struct line const *line, struct keyfield const *key) +@@ -2372,15 +2735,14 @@ debug_key (struct line const *line, struct keyfield const *key) char saved = *lim; *lim = '\0'; @@ -2286,7 +3600,7 @@ index 6d2eec5..f189a0d 100644 else if (key->general_numeric) ignore_value (strtold (beg, &tighter_lim)); else if (key->numeric || key->human_numeric) -@@ -2459,7 +2823,7 @@ key_warnings (struct keyfield const *gkey, bool gkey_only) +@@ -2526,7 +2888,7 @@ key_warnings (struct keyfield const *gkey, bool gkey_only) /* Warn about significant leading blanks. */ bool implicit_skip = key_numeric (key) || key->month; bool line_offset = key->eword == 0 && key->echar != 0; /* -k1.x,1.y */ @@ -2295,8 +3609,67 @@ index 6d2eec5..f189a0d 100644 && ((!key->skipsblanks && !implicit_skip) || (!key->skipsblanks && key->schar) || (!key->skipeblanks && key->echar))) -@@ -2517,11 +2881,87 @@ key_warnings (struct keyfield const *gkey, bool gkey_only) - error (0, 0, _("option '-r' only applies to last-resort comparison")); +@@ -2574,9 +2936,9 @@ key_warnings (struct keyfield const *gkey, bool gkey_only) + bool number_locale_warned = false; + if (basic_numeric_field_span) + { +- if (tab == TAB_DEFAULT +- ? thousands_sep != NON_CHAR && (isblank (to_uchar (thousands_sep))) +- : tab == thousands_sep) ++ if (tab_length ++ ? tab[0] == thousands_sep ++ : thousands_sep != NON_CHAR && (isblank (to_uchar (thousands_sep)))) + { + error (0, 0, + _("field separator %s is treated as a " +@@ -2587,9 +2949,9 @@ key_warnings (struct keyfield const *gkey, bool gkey_only) + } + if (basic_numeric_field_span || general_numeric_field_span) + { +- if (tab == TAB_DEFAULT +- ? thousands_sep != NON_CHAR && (isblank (to_uchar (decimal_point))) +- : tab == decimal_point) ++ if (tab_length ++ ? tab[0] == decimal_point ++ : thousands_sep != NON_CHAR && (isblank (to_uchar (decimal_point)))) + { + error (0, 0, + _("field separator %s is treated as a " +@@ -2597,19 +2959,19 @@ key_warnings (struct keyfield const *gkey, bool gkey_only) + quote (((char []) {decimal_point, 0}))); + number_locale_warned = true; + } +- else if (tab == '-') ++ else if (tab_length && tab[0] == '-') + { + error (0, 0, + _("field separator %s is treated as a " + "minus sign in numbers"), +- quote (((char []) {tab, 0}))); ++ quote (((char []) {tab[0], 0}))); + } +- else if (general_numeric_field_span && tab == '+') ++ else if (general_numeric_field_span && tab_length && tab[0] == '+') + { + error (0, 0, + _("field separator %s is treated as a " + "plus sign in numbers"), +- quote (((char []) {tab, 0}))); ++ quote (((char []) {tab[0], 0}))); + } + } + +@@ -2620,7 +2982,7 @@ key_warnings (struct keyfield const *gkey, bool gkey_only) + { + error (0, 0, + _("%snumbers use %s as a decimal point in this locale"), +- tab == decimal_point ? "" : _("note "), ++ (tab_length && tab[0] == decimal_point) ? "" : _("note "), + quote (((char []) {decimal_point, 0}))); + + } +@@ -2662,11 +3024,87 @@ diff_reversed (int diff, bool reversed) + return reversed ? (diff < 0) - (diff > 0) : diff; } +#if HAVE_MBRTOWC @@ -2384,17 +3757,17 @@ index 6d2eec5..f189a0d 100644 { struct keyfield *key = keylist; -@@ -2606,7 +3046,7 @@ keycompare (struct line const *a, struct line const *b) +@@ -2747,7 +3185,7 @@ keycompare (struct line const *a, struct line const *b) else if (key->human_numeric) diff = human_numcompare (ta, tb); else if (key->month) -- diff = getmonth (ta, NULL) - getmonth (tb, NULL); -+ diff = getmonth (ta, tlena, NULL) - getmonth (tb, tlenb, NULL); +- diff = getmonth (ta, nullptr) - getmonth (tb, nullptr); ++ diff = getmonth (ta, tlena, nullptr) - getmonth (tb, tlenb, nullptr); else if (key->random) diff = compare_random (ta, tlena, tb, tlenb); else if (key->version) -@@ -2722,6 +3162,211 @@ keycompare (struct line const *a, struct line const *b) - return key->reverse ? -diff : diff; +@@ -2857,6 +3295,211 @@ keycompare (struct line const *a, struct line const *b) + return diff_reversed (diff, key->reverse); } +#if HAVE_MBRTOWC @@ -2605,7 +3978,7 @@ index 6d2eec5..f189a0d 100644 /* Compare two lines A and B, returning negative, zero, or positive depending on whether A compares less than, equal to, or greater than B. */ -@@ -2749,7 +3394,7 @@ compare (struct line const *a, struct line const *b) +@@ -2884,7 +3527,7 @@ compare (struct line const *a, struct line const *b) diff = - NONZERO (blen); else if (blen == 0) diff = 1; @@ -2614,7 +3987,7 @@ index 6d2eec5..f189a0d 100644 { /* xmemcoll0 is a performance enhancement as it will not unconditionally write '\0' after the -@@ -4144,6 +4789,7 @@ set_ordering (char const *s, struct keyfield *key, enum blanktype blanktype) +@@ -4272,6 +4915,7 @@ set_ordering (char const *s, struct keyfield *key, enum blanktype blanktype) break; case 'f': key->translate = fold_toupper; @@ -2622,7 +3995,7 @@ index 6d2eec5..f189a0d 100644 break; case 'g': key->general_numeric = true; -@@ -4223,7 +4869,7 @@ main (int argc, char **argv) +@@ -4351,7 +4995,7 @@ main (int argc, char **argv) initialize_exit_failure (SORT_FAILURE); hard_LC_COLLATE = hard_locale (LC_COLLATE); @@ -2631,8 +4004,8 @@ index 6d2eec5..f189a0d 100644 hard_LC_TIME = hard_locale (LC_TIME); #endif -@@ -4244,6 +4890,29 @@ main (int argc, char **argv) - thousands_sep = -1; +@@ -4374,6 +5018,29 @@ main (int argc, char **argv) + thousands_sep = NON_CHAR; } +#if HAVE_MBRTOWC @@ -2661,7 +4034,7 @@ index 6d2eec5..f189a0d 100644 have_read_stdin = false; inittables (); -@@ -4518,13 +5187,34 @@ main (int argc, char **argv) +@@ -4644,13 +5311,34 @@ main (int argc, char **argv) case 't': { @@ -2671,7 +4044,7 @@ index 6d2eec5..f189a0d 100644 + size_t newtab_length = 1; + strncpy (newtab, optarg, MB_LEN_MAX); + if (! newtab[0]) - die (SORT_FAILURE, 0, _("empty tab")); + error (SORT_FAILURE, 0, _("empty tab")); - if (optarg[1]) +#if HAVE_MBRTOWC + if (MB_CUR_MAX > 1) @@ -2700,425 +4073,430 @@ index 6d2eec5..f189a0d 100644 else { /* Provoke with 'sort -txx'. Complain about -@@ -4535,9 +5225,11 @@ main (int argc, char **argv) - quote (optarg)); +@@ -4661,9 +5349,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")); + error (SORT_FAILURE, 0, _("incompatible tabs")); - tab = newtab; + memcpy (tab, newtab, newtab_length); + tab_length = newtab_length; } break; -@@ -4765,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"), "-"); -diff --git a/src/uniq.c b/src/uniq.c -index 87a0c93..9f755d9 100644 ---- a/src/uniq.c -+++ b/src/uniq.c -@@ -21,6 +21,17 @@ +diff --git a/src/unexpand.c b/src/unexpand.c +index aca67dd..f79c808 100644 +--- a/src/unexpand.c ++++ b/src/unexpand.c +@@ -39,6 +39,9 @@ + #include #include #include - -+/* Get mbstate_t, mbrtowc(). */ -+#if HAVE_WCHAR_H -+# include -+#endif + -+/* Get isw* functions. */ -+#if HAVE_WCTYPE_H -+# include -+#endif -+#include ++#include + #include "system.h" - #include "argmatch.h" - #include "linebuffer.h" -@@ -32,9 +43,21 @@ - #include "stdio--.h" - #include "xmemcoll.h" - #include "xstrtol.h" --#include "memcasecmp.h" -+#include "xmemcoll.h" - #include "quote.h" + #include "expand-common.h" -+/* MB_LEN_MAX is incorrectly defined to be 1 in at least one GCC -+ installation; work around this configuration error. */ -+#if !defined MB_LEN_MAX || MB_LEN_MAX < 2 -+# define MB_LEN_MAX 16 -+#endif -+ -+/* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */ -+#if HAVE_MBRTOWC && defined mbstate_t -+# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0) -+#endif -+ -+ - /* The official name of this program (e.g., no 'g' prefix). */ - #define PROGRAM_NAME "uniq" - -@@ -144,6 +167,10 @@ enum - GROUP_OPTION = CHAR_MAX + 1 - }; - -+/* Function pointers. */ -+static char * -+(*find_field) (struct linebuffer *line); -+ - static struct option const longopts[] = +@@ -105,24 +108,47 @@ unexpand (void) { - {"count", no_argument, NULL, 'c'}, -@@ -260,7 +287,7 @@ size_opt (char const *opt, char const *msgid) - return a pointer to the beginning of the line's field to be compared. */ + /* Input stream. */ + FILE *fp = next_file (nullptr); ++ mb_file_t mbf; - 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; -@@ -280,6 +307,83 @@ find_field (struct linebuffer const *line) - return line->buffer + i; - } + /* 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 HAVE_MBRTOWC + if (!fp) + return; ++ mbf_init (mbf, fp); ++ found_bom=check_bom(fp,&mbf); + -+# 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++) ++ if (using_utf_locale == false && found_bom == true) ++ { ++ /*try using some predefined locale */ + ++ if (set_utf_locale () != 0) + { -+ 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; -+ } ++ 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)); + -+ /* 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. -@@ -288,6 +392,8 @@ find_field (struct linebuffer const *line) - static bool - different (char *old, char *new, size_t oldlen, size_t newlen) - { -+ char *copy_old, *copy_new; -+ - if (check_chars < oldlen) - oldlen = check_chars; - if (check_chars < newlen) -@@ -295,15 +401,104 @@ different (char *old, char *new, size_t oldlen, size_t newlen) ++ if (found_bom == true) ++ { ++ print_bom(); ++ } - if (ignore_case) + while (true) { -- /* FIXME: This should invoke strcoll somehow. */ -- return oldlen != newlen || memcasecmp (old, new, oldlen); -+ size_t i; + /* Input character, or EOF. */ +- int c; ++ mbf_char_t c; + + /* If true, perform translations. */ + bool convert = true; +@@ -156,12 +182,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; ++ } ++ } + -+ copy_old = xmalloc (oldlen + 1); -+ copy_new = xmalloc (oldlen + 1); + + if (convert) + { +- bool blank = !! isblank (c); ++ bool blank = mb_isblank (c); + + if (blank) + { +@@ -178,16 +236,16 @@ unexpand (void) + if (next_tab_column < column) + error (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)) + { +@@ -195,13 +253,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 +@@ -209,7 +268,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,16 +278,20 @@ unexpand (void) + } + else + { +- column++; +- if (!column) ++ const uintmax_t orig_column = column; ++ column += mb_width (c); ++ if (column < orig_column) + error (EXIT_FAILURE, 0, _("input line is too long")); + } + + if (pending) + { + if (pending > 1 && one_blank_before_tab_stop) +- pending_blank[0] = '\t'; +- if (fwrite (pending_blank, 1, pending, stdout) != pending) ++ mb_setascii (&pending_blank[0], '\t'); + -+ for (i = 0; i < oldlen; i++) -+ { -+ copy_old[i] = toupper (old[i]); -+ copy_new[i] = toupper (new[i]); -+ } -+ bool rc = xmemcoll (copy_old, oldlen, copy_new, newlen); -+ free (copy_old); -+ free (copy_new); -+ return rc; ++ for (int n = 0; n < pending; ++n) ++ mb_putc (pending_blank[n], stdout); ++ if (ferror (stdout)) + write_error (); + pending = 0; + one_blank_before_tab_stop = false; +@@ -238,16 +301,17 @@ unexpand (void) + convert &= convert_entire_line || blank; + } + +- if (c < 0) ++ if (mb_iseof (c)) + { + free (pending_blank); + return; + } + +- if (putchar (c) < 0) ++ mb_putc (c, stdout); ++ if (ferror (stdout)) + write_error (); + } +- while (c != '\n'); ++ while (!mb_iseq (c, '\n')); } -- else if (hard_LC_COLLATE) -- return xmemcoll (old, oldlen, new, newlen) != 0; - else -- return oldlen != newlen || memcmp (old, new, oldlen); -+ { -+ copy_old = (char *)old; -+ copy_new = (char *)new; -+ } -+ -+ return xmemcoll (copy_old, oldlen, copy_new, newlen); -+ } -+#if HAVE_MBRTOWC -+static int -+different_multi (const char *old, const char *new, size_t oldlen, size_t newlen, mbstate_t oldstate, mbstate_t newstate) -+{ -+ size_t i, j, chars; -+ const char *str[2]; -+ char *copy[2]; -+ size_t len[2]; -+ mbstate_t state[2]; -+ size_t mblength; -+ wchar_t wc, uwc; -+ mbstate_t state_bak; -+ -+ str[0] = old; -+ str[1] = new; -+ len[0] = oldlen; -+ len[1] = newlen; -+ state[0] = oldstate; -+ state[1] = newstate; -+ -+ for (i = 0; i < 2; i++) -+ { -+ copy[i] = xmalloc (len[i] + 1); -+ memset (copy[i], '\0', 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; -+ 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, str[i] + j, mblength); -+ } -+ else -+ memcpy (copy[i] + j, str[i] + j, mblength); -+ } -+ j += mblength; -+ } -+ copy[i][j] = '\0'; -+ len[i] = j; -+ } -+ int rc = xmemcoll (copy[0], len[0], copy[1], len[1]); -+ free (copy[0]); -+ free (copy[1]); -+ return rc; -+ -+} -+#endif -+ - /* 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. -@@ -367,19 +562,38 @@ check_file (const char *infile, const char *outfile, char delimiter) - char *prevfield IF_LINT ( = NULL); - size_t prevlen IF_LINT ( = 0); - bool first_group_printed = false; -+#if HAVE_MBRTOWC -+ mbstate_t prevstate; -+ -+ memset (&prevstate, '\0', sizeof (mbstate_t)); -+#endif - - while (!feof (stdin)) +diff --git a/tests/Coreutils.pm b/tests/Coreutils.pm +index 18e7bea..24a141b 100644 +--- a/tests/Coreutils.pm ++++ b/tests/Coreutils.pm +@@ -269,6 +269,9 @@ sub run_tests ($$$$$) + # Yes, this is an arbitrary limit. If it causes trouble, + # consider removing it. + my $max = 30; ++ # The downstream i18n multi-byte tests have a "-mb" suffix. ++ # Therefore add 3 to the maximum test name length. ++ $max += 3; + if ($max < length $test_name) { - char *thisfield; - size_t thislen; - bool new_group; -+#if HAVE_MBRTOWC -+ mbstate_t thisstate; -+#endif - - if (readlinebuffer_delim (thisline, stdin, delimiter) == 0) - break; - - thisfield = find_field (thisline); - thislen = thisline->length - 1 - (thisfield - thisline->buffer); -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ { -+ thisstate = thisline->state; - -+ new_group = (prevline->length == 0 -+ || different_multi (thisfield, prevfield, -+ thislen, prevlen, -+ thisstate, prevstate)); -+ } -+ else -+#endif - new_group = (prevline->length == 0 - || different (thisfield, prevfield, thislen, prevlen)); - -@@ -397,6 +611,10 @@ check_file (const char *infile, const char *outfile, char delimiter) - SWAP_LINES (prevline, thisline); - prevfield = thisfield; - prevlen = thislen; -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ prevstate = thisstate; -+#endif - first_group_printed = true; - } - } -@@ -409,17 +627,26 @@ check_file (const char *infile, const char *outfile, char delimiter) - size_t prevlen; - uintmax_t match_count = 0; - bool first_delimiter = true; -+#if HAVE_MBRTOWC -+ mbstate_t prevstate; -+#endif - - if (readlinebuffer_delim (prevline, stdin, delimiter) == 0) - goto closefiles; - prevfield = find_field (prevline); - prevlen = prevline->length - 1 - (prevfield - prevline->buffer); -+#if HAVE_MBRTOWC -+ prevstate = prevline->state; -+#endif - - while (!feof (stdin)) - { - bool match; - char *thisfield; - size_t thislen; -+#if HAVE_MBRTOWC -+ mbstate_t thisstate = thisline->state; -+#endif - if (readlinebuffer_delim (thisline, stdin, delimiter) == 0) - { - if (ferror (stdin)) -@@ -428,6 +655,14 @@ check_file (const char *infile, const char *outfile, char delimiter) - } - thisfield = find_field (thisline); - thislen = thisline->length - 1 - (thisfield - thisline->buffer); -+#if HAVE_MBRTOWC -+ if (MB_CUR_MAX > 1) -+ { -+ match = !different_multi (thisfield, prevfield, -+ thislen, prevlen, thisstate, prevstate); -+ } -+ else -+#endif - match = !different (thisfield, prevfield, thislen, prevlen); - match_count += match; - -@@ -460,6 +695,9 @@ check_file (const char *infile, const char *outfile, char delimiter) - SWAP_LINES (prevline, thisline); - prevfield = thisfield; - prevlen = thislen; -+#if HAVE_MBRTOWC -+ prevstate = thisstate; -+#endif - if (!match) - match_count = 0; - } -@@ -506,6 +744,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; -+ } + warn "$program_name: $test_name: test name is too long (> $max)\n"; +diff --git a/tests/expand/mb.sh b/tests/expand/mb.sh +new file mode 100644 +index 0000000..dd6007c +--- /dev/null ++++ b/tests/expand/mb.sh +@@ -0,0 +1,183 @@ ++#!/bin/sh ++ ++# Copyright (C) 2012-2015 Free Software Foundation, Inc. ++ ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++ ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src ++print_ver_ expand ++ ++export LC_ALL=en_US.UTF-8 ++ ++#input containing multibyte characters ++cat <<\EOF > in || framework_failure_ ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++EOF ++env printf ' äöü\t. öüä. \tä xx\n' >> in || framework_failure_ ++ ++cat <<\EOF > exp || framework_failure_ ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++EOF ++ ++expand < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++#multiple files as an input ++cat <<\EOF >> exp || framework_failure_ ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++EOF ++ ++expand ./in ./in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++#test characters with display widths != 1 ++env printf '12345678 ++e\t|ascii(1) ++\u00E9\t|composed(1) ++e\u0301\t|decomposed(1) ++\u3000\t|ideo-space(2) ++\uFF0D\t|full-hypen(2) ++' > in || framework_failure_ ++ ++env printf '12345678 ++e |ascii(1) ++\u00E9 |composed(1) ++e\u0301 |decomposed(1) ++\u3000 |ideo-space(2) ++\uFF0D |full-hypen(2) ++' > exp || framework_failure_ ++ ++expand < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++#shouldn't fail with "input line too long" ++#when a line starts with a control character ++env printf '\n' > in || framework_failure_ ++ ++expand < in > out || fail=1 ++compare in out > /dev/null 2>&1 || fail=1 ++ ++#non-Unicode characters interspersed between Unicode ones ++env printf '12345678 ++\t\xFF| ++\xFF\t| ++\t\xFFä| ++ä\xFF\t| ++\tä\xFF| ++\xFF\tä| ++äbcdef\xFF\t| ++' > in || framework_failure_ ++ ++env printf '12345678 ++ \xFF| ++\xFF | ++ \xFFä| ++ä\xFF | ++ ä\xFF| ++\xFF ä| ++äbcdef\xFF | ++' > exp || framework_failure_ ++ ++expand < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 + + + - skip_chars = 0; - skip_fields = 0; - check_chars = SIZE_MAX; ++#BOM header test 1 ++printf "\xEF\xBB\xBF" > in; cat <<\EOF >> in || framework_failure_ ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++EOF ++env printf ' äöü\t. öüä. \tä xx\n' >> in || framework_failure_ ++ ++printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_ ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++EOF ++ ++ ++expand < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++LANG=C expand < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++LC_ALL=C expand < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++ ++printf '\xEF\xBB\xBF' > in1; cat <<\EOF >> in1 || framework_failure_ ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++EOF ++env printf ' äöü\t. öüä. \tä xx\n' >> in1 || framework_failure_ ++ ++ ++printf '\xEF\xBB\xBF' > exp; cat <<\EOF >> exp || framework_failure_ ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++EOF ++ ++expand in1 in1 > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++LANG=C expand in1 in1 > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++LC_ALL=C expand in1 in1 > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++exit $fail diff --git a/tests/i18n/sort.sh b/tests/i18n/sort.sh -new file mode 100755 +new file mode 100644 index 0000000..26c95de --- /dev/null +++ b/tests/i18n/sort.sh @@ -3153,20 +4531,36 @@ index 0000000..26c95de + +Exit $fail diff --git a/tests/local.mk b/tests/local.mk -index 568944e..192f776 100644 +index fdbf369..a6ce49c 100644 --- a/tests/local.mk +++ b/tests/local.mk -@@ -362,6 +362,8 @@ all_tests = \ - tests/misc/sort-discrim.sh \ - tests/misc/sort-files0-from.pl \ - tests/misc/sort-float.sh \ +@@ -387,6 +387,8 @@ all_tests = \ + tests/sort/sort-discrim.sh \ + tests/sort/sort-files0-from.pl \ + tests/sort/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 \ + tests/sort/sort-h-thousands-sep.sh \ + tests/sort/sort-merge.pl \ + tests/sort/sort-merge-fdlimit.sh \ +@@ -590,6 +592,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 \ +@@ -746,6 +749,7 @@ all_tests = \ + tests/touch/read-only.sh \ + tests/touch/relative.sh \ + tests/touch/trailing-slash.sh \ ++ tests/unexpand/mb.sh \ + $(all_root_tests) + + # See tests/factor/create-test.sh. diff --git a/tests/misc/expand.pl b/tests/misc/expand.pl -index 8a9cad1..9293e39 100755 +index 11f3fc4..d609a2c 100755 --- a/tests/misc/expand.pl +++ b/tests/misc/expand.pl @@ -27,6 +27,15 @@ my $prog = 'expand'; @@ -3233,7 +4627,7 @@ index 8a9cad1..9293e39 100755 my $verbose = $ENV{VERBOSE}; diff --git a/tests/misc/fold.pl b/tests/misc/fold.pl -index 7b192b4..76f073f 100755 +index 00b4362..7d51bea 100755 --- a/tests/misc/fold.pl +++ b/tests/misc/fold.pl @@ -20,9 +20,18 @@ use strict; @@ -3305,78 +4699,8 @@ index 7b192b4..76f073f 100755 -my $prog = 'fold'; my $fail = run_tests ($program_name, $prog, \@Tests, $save_temps, $verbose); exit $fail; -diff --git a/tests/misc/join.pl b/tests/misc/join.pl -index 4d399d8..07f2823 100755 ---- a/tests/misc/join.pl -+++ b/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 ($) - { -@@ -329,8 +338,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}; - diff --git a/tests/misc/sort-mb-tests.sh b/tests/misc/sort-mb-tests.sh -new file mode 100755 +new file mode 100644 index 0000000..11836ba --- /dev/null +++ b/tests/misc/sort-mb-tests.sh @@ -3426,10 +4750,136 @@ index 0000000..11836ba +compare exp out || { fail=1; cat out; } + +Exit $fail -diff --git a/tests/misc/sort-merge.pl b/tests/misc/sort-merge.pl -index 23f6ed2..402a987 100755 ---- a/tests/misc/sort-merge.pl -+++ b/tests/misc/sort-merge.pl +diff --git a/tests/misc/unexpand.pl b/tests/misc/unexpand.pl +index 76bcbd4..59eb819 100755 +--- a/tests/misc/unexpand.pl ++++ b/tests/misc/unexpand.pl +@@ -27,6 +27,14 @@ my $limits = getlimits (); + + my $prog = 'unexpand'; + ++# comment out next line to disable multibyte tests ++my $mb_locale = $ENV{LOCALE_FR_UTF8}; ++! defined $mb_locale || $mb_locale eq 'none' ++ and $mb_locale = 'C'; ++ ++my $try = "Try \`$prog --help' for more information.\n"; ++my $inval = "$prog: invalid byte, character or field list\n$try"; ++ + my @Tests = + ( + ['a1', {IN=> ' 'x 1 ."y\n"}, {OUT=> ' 'x 1 ."y\n"}], +@@ -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}; + +diff --git a/tests/pr/pr-tests.pl b/tests/pr/pr-tests.pl +index 6b34e0b..34b4aeb 100755 +--- a/tests/pr/pr-tests.pl ++++ b/tests/pr/pr-tests.pl +@@ -24,6 +24,15 @@ use strict; + my $prog = 'pr'; + my $normalize_strerror = "s/': .*/'/"; + ++my $mb_locale; ++#Uncomment the following line to enable multibyte tests ++$mb_locale = $ENV{LOCALE_FR_UTF8}; ++! defined $mb_locale || $mb_locale eq 'none' ++ and $mb_locale = 'C'; ++ ++my $try = "Try \`$prog --help' for more information.\n"; ++my $inval = "$prog: invalid byte, character or field list\n$try"; ++ + my @tv = ( + + # -b option is no longer an official option. But it's still working to +@@ -515,8 +524,48 @@ push @Tests, + {IN=>"x\tx\tx\tx\tx\nx\tx\tx\tx\tx\n"}, + {OUT=>"x\tx\tx\tx\tx\tx\tx\tx\tx\tx\n"} ]; + ++# Add _POSIX2_VERSION=199209 to the environment of each test ++# that uses an old-style option like +1. ++if ($mb_locale ne 'C') ++ { ++ # Duplicate each test vector, appending "-mb" to the test name and ++ # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we ++ # provide coverage for the distro-added multi-byte code paths. ++ my @new; ++ foreach my $t (@Tests) ++ { ++ my @new_t = @$t; ++ my $test_name = shift @new_t; ++ ++ # Depending on whether pr is multi-byte-patched, ++ # it emits different diagnostics: ++ # non-MB: invalid byte or field list ++ # MB: invalid byte, character or field list ++ # Adjust the expected error output accordingly. ++ if (grep {ref $_ eq 'HASH' && exists $_->{ERR} && $_->{ERR} eq $inval} ++ (@new_t)) ++ { ++ my $sub = {ERR_SUBST => 's/, character//'}; ++ push @new_t, $sub; ++ push @$t, $sub; ++ } ++ #temporarily skip some failing tests ++ next if ($test_name =~ "col-0" or $test_name =~ "col-inval" or $test_name =~ "asan1"); ++ push @new, ["$test_name-mb", @new_t, {ENV => "LC_ALL=$mb_locale"}]; ++ } ++ push @Tests, @new; ++ } ++ + @Tests = triple_test \@Tests; + ++# Remember that triple_test creates from each test with exactly one "IN" ++# file two more tests (.p and .r suffix on name) corresponding to reading ++# input from a file and from a pipe. The pipe-reading test would fail ++# due to a race condition about 1 in 20 times. ++# Remove the IN_PIPE version of the "output-is-input" test above. ++# The others aren't susceptible because they have three inputs each. ++@Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests; ++ + my $save_temps = $ENV{DEBUG}; + my $verbose = $ENV{VERBOSE}; + +diff --git a/tests/sort/sort-merge.pl b/tests/sort/sort-merge.pl +index 89eed0c..b855d73 100755 +--- a/tests/sort/sort-merge.pl ++++ b/tests/sort/sort-merge.pl @@ -26,6 +26,15 @@ my $prog = 'sort'; # Turn off localization of executable's output. @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; @@ -3486,10 +4936,10 @@ index 23f6ed2..402a987 100755 my $save_temps = $ENV{DEBUG}; my $verbose = $ENV{VERBOSE}; -diff --git a/tests/misc/sort.pl b/tests/misc/sort.pl -index c3e7f8e..6ecd3ff 100755 ---- a/tests/misc/sort.pl -+++ b/tests/misc/sort.pl +diff --git a/tests/sort/sort.pl b/tests/sort/sort.pl +index d49f65f..ebba925 100755 +--- a/tests/sort/sort.pl ++++ b/tests/sort/sort.pl @@ -24,10 +24,15 @@ my $prog = 'sort'; # Turn off localization of executable's output. @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3; @@ -3554,208 +5004,184 @@ index c3e7f8e..6ecd3ff 100755 my $save_temps = $ENV{DEBUG}; my $verbose = $ENV{VERBOSE}; -diff --git a/tests/misc/unexpand.pl b/tests/misc/unexpand.pl -index 6ba6d40..de86723 100755 ---- a/tests/misc/unexpand.pl -+++ b/tests/misc/unexpand.pl -@@ -27,6 +27,14 @@ my $limits = getlimits (); - - my $prog = 'unexpand'; - -+# comment out next line to disable multibyte tests -+my $mb_locale = $ENV{LOCALE_FR_UTF8}; -+! defined $mb_locale || $mb_locale eq 'none' -+ and $mb_locale = 'C'; +diff --git a/tests/unexpand/mb.sh b/tests/unexpand/mb.sh +new file mode 100644 +index 0000000..8a82d74 +--- /dev/null ++++ b/tests/unexpand/mb.sh +@@ -0,0 +1,172 @@ ++#!/bin/sh + -+my $try = "Try \`$prog --help' for more information.\n"; -+my $inval = "$prog: invalid byte, character or field list\n$try"; ++# Copyright (C) 2012-2015 Free Software Foundation, Inc. + - 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; ++# 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. + -+ # 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; -+ } ++# 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. + -+@Tests = triple_test \@Tests; ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . + - my $save_temps = $ENV{DEBUG}; - my $verbose = $ENV{VERBOSE}; - -diff --git a/tests/misc/uniq.pl b/tests/misc/uniq.pl -index f028036..8eaf59a 100755 ---- a/tests/misc/uniq.pl -+++ b/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"; ++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src ++print_ver_ unexpand + - # 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'; ++export LC_ALL=en_US.UTF-8 + - # 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; ++#input containing multibyte characters ++cat > in <<\EOF ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++EOF + -+ # 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; -+ } ++cat > exp <<\EOF ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++EOF + -+# 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. ++unexpand -a < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 + -+@Tests = grep {$_->[0] ne 'output-is-input.p'} @Tests; + - @Tests = add_z_variants \@Tests; - @Tests = triple_test \@Tests; - -diff --git a/tests/pr/pr-tests.pl b/tests/pr/pr-tests.pl -index ec3980a..136657d 100755 ---- a/tests/pr/pr-tests.pl -+++ b/tests/pr/pr-tests.pl -@@ -24,6 +24,15 @@ use strict; - my $prog = 'pr'; - my $normalize_strerror = "s/': .*/'/"; - -+my $mb_locale; -+#Uncomment the following line to enable multibyte tests -+$mb_locale = $ENV{LOCALE_FR_UTF8}; -+! defined $mb_locale || $mb_locale eq 'none' -+ and $mb_locale = 'C'; ++#multiple files as an input ++cat >> exp <<\EOF ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++EOF + -+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; ++unexpand -a ./in ./in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 + -+ # 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; -+ } ++#test characters with a display width larger than 1 + - @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; ++env printf '12345678 ++e |ascii(1) ++\u00E9 |composed(1) ++e\u0301 |decomposed(1) ++\u3000 |ideo-space(2) ++\uFF0D |full-hypen(2) ++' > in || framework_failure_ + - my $save_temps = $ENV{DEBUG}; - my $verbose = $ENV{VERBOSE}; - ++env printf '12345678 ++e\t|ascii(1) ++\u00E9\t|composed(1) ++e\u0301\t|decomposed(1) ++\u3000\t|ideo-space(2) ++\uFF0D\t|full-hypen(2) ++' > exp || framework_failure_ ++ ++unexpand -a < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++#test input where a blank of width > 1 is not being substituted ++in="$(LC_ALL=en_US.UTF-8 printf ' \u3000 ö ü ß')" ++exp='   ö ü ß' ++ ++unexpand -a < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++#non-Unicode characters interspersed between Unicode ones ++env printf '12345678 ++ \xFF| ++\xFF | ++ \xFFä| ++ä\xFF | ++ ä\xFF| ++\xFF ä| ++äbcdef\xFF | ++' > in || framework_failure_ ++ ++env printf '12345678 ++\t\xFF| ++\xFF\t| ++\t\xFFä| ++ä\xFF\t| ++\tä\xFF| ++\xFF\tä| ++äbcdef\xFF\t| ++' > exp || framework_failure_ ++ ++unexpand -a < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++#BOM header test 1 ++printf "\xEF\xBB\xBF" > in; cat <<\EOF >> in || framework_failure_ ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++EOF ++env printf ' äöü\t. öüä. \tä xx\n' >> in || framework_failure_ ++ ++printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_ ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++EOF ++ ++unexpand < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++LANG=C unexpand < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++LC_ALL=C unexpand < in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++ ++printf "\xEF\xBB\xBF" > exp; cat <<\EOF >> exp || framework_failure_ ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++1234567812345678123456781 ++. . . . ++a b c d ++. . . . ++ä ö ü ß ++. . . . ++ äöü . öüä. ä xx ++EOF ++ ++ ++unexpand in in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++LANG=C unexpand in in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 ++ ++LC_ALL=C unexpand in in > out || fail=1 ++compare exp out > /dev/null 2>&1 || fail=1 -- -2.7.4 +2.44.0 diff --git a/coreutils-keyring.gpg b/coreutils-keyring.gpg new file mode 100644 index 0000000..003a885 --- /dev/null +++ b/coreutils-keyring.gpg @@ -0,0 +1,312 @@ +Release GPG keyring of coreutils group. + +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +ELphkzjc6eM3CaOZ73u4GVXotheeUabUHQ== +=drvb +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/coreutils-python3.patch b/coreutils-python3.patch new file mode 100644 index 0000000..98fc642 --- /dev/null +++ b/coreutils-python3.patch @@ -0,0 +1,65 @@ +From cef9cccce395cd80cd5ac42a4fe6c3909be1c0b5 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Tue, 2 Apr 2024 14:11:26 +0100 +Subject: [PATCH] coreutils-python3.patch + +--- + init.cfg | 4 ++-- + tests/d_type-check | 2 +- + tests/du/move-dir-while-traversing.sh | 6 +++--- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/init.cfg b/init.cfg +index b06965a..08413ee 100644 +--- a/init.cfg ++++ b/init.cfg +@@ -581,10 +581,10 @@ seek_data_capable_() + # Skip the current test if "." lacks d_type support. + require_dirent_d_type_() + { +- python < /dev/null \ ++ python3 < /dev/null \ + || skip_ python missing: assuming no d_type support + +- python "$abs_srcdir"/tests/d_type-check \ ++ python3 "$abs_srcdir"/tests/d_type-check \ + || skip_ requires d_type support + } + +diff --git a/tests/d_type-check b/tests/d_type-check +index 1a2f76f..42d3924 100644 +--- a/tests/d_type-check ++++ b/tests/d_type-check +@@ -1,4 +1,4 @@ +-#!/usr/bin/python ++#!/usr/bin/python3 + # Exit 0 if "." and "./tempfile" have useful d_type information, else 1. + # Intended to exit 0 only on Linux/GNU systems. + import os +diff --git a/tests/du/move-dir-while-traversing.sh b/tests/du/move-dir-while-traversing.sh +index 830a69e..7344ddf 100755 +--- a/tests/du/move-dir-while-traversing.sh ++++ b/tests/du/move-dir-while-traversing.sh +@@ -21,8 +21,8 @@ print_ver_ du + require_trap_signame_ + + # We use a python-inotify script, so... +-python -m pyinotify -h > /dev/null \ +- || skip_ 'python inotify package not installed' ++python3 -m pyinotify -h > /dev/null \ ++ || skip_ 'python3 inotify package not installed' + + # Move a directory "up" while du is processing its sub-directories. + # While du is processing a hierarchy .../B/C/D/... this script +@@ -33,7 +33,7 @@ python -m pyinotify -h > /dev/null \ + # rename syscall before du finishes processing the subtree under D/. + + cat <<'EOF' > inotify-watch-for-dir-access.py +-#!/usr/bin/env python ++#!/usr/bin/env python3 + import pyinotify as pn + import os,sys + +-- +2.44.0 + diff --git a/coreutils-selinux.patch b/coreutils-selinux.patch new file mode 100644 index 0000000..a31c3af --- /dev/null +++ b/coreutils-selinux.patch @@ -0,0 +1,87 @@ +From 78970c915b8556fcec4622e948a37dd8e34efe6d Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Wed, 30 Aug 2023 17:19:58 +0200 +Subject: [PATCH] coreutils-selinux.patch + +--- + src/cp.c | 19 ++++++++++++++++++- + src/install.c | 12 +++++++++++- + 2 files changed, 29 insertions(+), 2 deletions(-) + +diff --git a/src/cp.c b/src/cp.c +index 28b0217..897379f 100644 +--- a/src/cp.c ++++ b/src/cp.c +@@ -997,7 +997,7 @@ main (int argc, char **argv) + selinux_enabled = (0 < is_selinux_enabled ()); + cp_option_init (&x); + +- while ((c = getopt_long (argc, argv, "abdfHilLnprst:uvxPRS:TZ", ++ while ((c = getopt_long (argc, argv, "abcdfHilLnprst:uvxPRS:TZ", + long_opts, nullptr)) + != -1) + { +@@ -1049,6 +1049,23 @@ main (int argc, char **argv) + copy_contents = true; + break; + ++ case 'c': ++ fprintf (stderr, "%s: warning: option '-c' is deprecated," ++ " please use '--preserve=context' instead\n", argv[0]); ++ if (x.set_security_context) ++ { ++ fprintf (stderr, ++ "%s: cannot force target context and preserve it\n", ++ argv[0]); ++ exit (1); ++ } ++ else if (selinux_enabled) ++ { ++ x.preserve_security_context = true; ++ x.require_preserve_context = true; ++ } ++ break; ++ + case 'd': + x.preserve_links = true; + x.dereference = DEREF_NEVER; +diff --git a/src/install.c b/src/install.c +index accd0fd..b686fe9 100644 +--- a/src/install.c ++++ b/src/install.c +@@ -807,7 +807,7 @@ main (int argc, char **argv) + dir_arg = false; + umask (0); + +- while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pt:TvS:Z", long_options, ++ while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pPt:TvS:Z", long_options, + nullptr)) + != -1) + { +@@ -872,6 +872,9 @@ main (int argc, char **argv) + no_target_directory = true; + break; + ++ case 'P': ++ fprintf (stderr, "%s: warning: option '-P' is deprecated," ++ " please use '--preserve-context' instead\n", argv[0]); + case PRESERVE_CONTEXT_OPTION: + if (! selinux_enabled) + { +@@ -879,6 +882,13 @@ main (int argc, char **argv) + "this kernel is not SELinux-enabled")); + break; + } ++ if (x.set_security_context) ++ { ++ fprintf (stderr, ++ "%s: cannot force target context and preserve it\n", ++ argv[0]); ++ exit (1); ++ } + x.preserve_security_context = true; + use_default_selinux_context = false; + break; +-- +2.44.0 + diff --git a/SPECS/coreutils.spec b/coreutils.spec similarity index 85% rename from SPECS/coreutils.spec rename to coreutils.spec index 8f8cbc5..5517ee9 100644 --- a/SPECS/coreutils.spec +++ b/coreutils.spec @@ -1,67 +1,22 @@ Summary: A set of basic GNU tools commonly used in shell scripts Name: coreutils -Version: 8.30 -Release: 15%{?dist} -License: GPLv3+ -Group: System Environment/Base +Version: 9.5 +Release: 2%{?dist} +# some used parts of gnulib are under various variants of LGPL +License: GPL-3.0-or-later AND GFDL-1.3-no-invariants-or-later AND LGPL-2.1-or-later AND LGPL-3.0-or-later Url: https://www.gnu.org/software/coreutils/ Source0: https://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.xz +Source1: https://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.xz.sig +# From https://savannah.gnu.org/project/release-gpgkeys.php?group=coreutils&download=1 +# which is linked as project keyring on https://savannah.gnu.org/projects/coreutils +Source2: coreutils-keyring.gpg Source50: supported_utils -Source51: coreutils-provides.inc Source105: coreutils-colorls.sh Source106: coreutils-colorls.csh # do not make coreutils-single depend on /usr/bin/coreutils %global __requires_exclude ^%{_bindir}/coreutils$ -# rename gnulib's renameat2 to renameatu to avoid clash with glibc (#1598518) -Patch1: coreutils-8.30-renameatu.patch - -# fix heap-based buffer overflow in vasnprintf() (CVE-2018-17942) -Patch2: coreutils-8.30-CVE-2018-17942.patch - -# sync: fix open() fallback bug (#1602463) -Patch3: coreutils-8.30-fsync-fallback.patch - -# cp --preserve=xattr: preserve NFSv4 ACL extended attributes (#1646985) -Patch4: coreutils-8.30-cp-preserve-xattr-NFSv4-ACL.patch - -# chcon: do not validate security context if SELinux is disabled (#1777831) -Patch5: coreutils-8.30-chcon-invalid-context.patch - -# md5sum,b2sum,sha*sum: --help: add note about binary/text mode -Patch6: coreutils-8.31-sums-man-pages.patch - -# df --local: recognize afs, auristorfs, and smb3 as remote fs (#1798030) -Patch7: coreutils-8.30-df-local-fs.patch - -# use statx instead of stat when available (#1760300) -Patch8: coreutils-8.30-statx.patch - -# rm: do not skip files upon failure to remove an empty dir (#1905481) -Patch9: coreutils-8.32-rm-stray-skip.patch - -# split: fix --number=K/N to output correct part of file (#1921246) -Patch10: coreutils-8.32-split-number.patch - -# mountlist: recognize fuse.portal as dummy file system (#1952714) -Patch11: coreutils-8.32-fuse-portal.patch - -# tail: fix stack out-of-bounds write with --follow (#1974784) -Patch12: coreutils-8.30-tail-use-poll.patch - -# doc: improve description of the --kibibytes option of ls (#1527391) -Patch13: coreutils-8.22-doc-ls-kibibytes.patch - -# df: fix duplicated remote entries due to bind mounts (#1962515) -Patch17: coreutils-8.32-df-duplicated-entries.patch - -# ls, stat: avoid triggering automounts (#2044981) -Patch18: coreutils-9.0-autofs-no-mount.patch - -# basic support for checking NFSv4 ACLs (#2158747) -Patch19: coreutils-nfsv4-acls.patch - # disable the test-lock gnulib test prone to deadlock Patch100: coreutils-8.26-test-lock.patch @@ -69,42 +24,22 @@ Patch100: coreutils-8.26-test-lock.patch Patch101: coreutils-8.26-selinuxenable.patch # downstream changes to default DIR_COLORS -Patch102: coreutils-8.25-DIR_COLORS.patch -#do display processor type for uname -p/-i based on uname(2) syscall -Patch103: coreutils-8.2-uname-processortype.patch -#df --direct -Patch104: coreutils-df-direct.patch -#add note about mkdir --mode behaviour into info documentation(#610559) -Patch107: coreutils-8.4-mkdir-modenote.patch +Patch102: coreutils-8.32-DIR_COLORS.patch -# sh-utils -#add info about TZ envvar to date manpage -Patch703: sh-utils-2.0.11-dateman.patch -Patch713: coreutils-4.5.3-langinfo.patch +# use python3 in tests +Patch103: coreutils-python3.patch + +# df --direct +Patch104: coreutils-df-direct.patch # (sb) lin18nux/lsb compliance - multibyte functionality patch Patch800: coreutils-i18n.patch -# (sb) lin18nux/lsb compliance - expand/unexpand -Patch801: coreutils-i18n-expand-unexpand.patch -# i18n patch for cut - old version - used -Patch804: coreutils-i18n-cut-old.patch -#(un)expand - allow multiple files on input - broken by patch 801 -Patch805: coreutils-i18n-fix2-expand-unexpand.patch -#(un)expand - test BOM headers -Patch806: coreutils-i18n-un-expand-BOM.patch -# make 'sort -h' work for arbitrary column even when using UTF-8 locales -Patch807: coreutils-i18n-sort-human.patch -# fold: preserve new-lines in mutlibyte text (#1418505) -Patch808: coreutils-i18n-fold-newline.patch -#getgrouplist() patch from Ulrich Drepper. -Patch908: coreutils-getgrouplist.patch - -#SELINUX Patch - implements Redhat changes -#(upstream did some SELinux implementation unlike with RedHat patch) +# downstream SELinux options deprecated since 2009 Patch950: coreutils-selinux.patch Conflicts: filesystem < 3 + # To avoid clobbering installs Conflicts: coreutils-single @@ -120,20 +55,42 @@ BuildRequires: libattr-devel BuildRequires: libcap-devel BuildRequires: libselinux-devel BuildRequires: libselinux-utils +BuildRequires: make BuildRequires: openssl-devel BuildRequires: strace BuildRequires: texinfo +# For gpg verification of source tarball +BuildRequires: gnupg2 + +# test-only dependencies +BuildRequires: acl +BuildRequires: gdb +BuildRequires: perl-interpreter +BuildRequires: perl(FileHandle) +BuildRequires: python3 +BuildRequires: tzdata +%ifarch %valgrind_arches +BuildRequires: valgrind +%endif + +%if 0%{?fedora} +BuildRequires: perl(Expect) +BuildRequires: python3-inotify +%endif + %if 23 < 0%{?fedora} || 7 < 0%{?rhel} # needed by i18n test-cases BuildRequires: glibc-langpack-en +BuildRequires: glibc-langpack-fr +BuildRequires: glibc-langpack-ko +BuildRequires: glibc-langpack-sv %endif Requires: %{name}-common = %{version}-%{release} -Requires: ncurses Provides: coreutils-full = %{version}-%{release} -%include %{SOURCE51} +Provides: bundled(gnulib) Obsoletes: %{name} < 8.24-100 %description @@ -145,7 +102,7 @@ Summary: coreutils multicall binary Suggests: coreutils-common Provides: coreutils = %{version}-%{release} Provides: coreutils%{?_isa} = %{version}-%{release} -%include %{SOURCE51} +Provides: bundled(gnulib) # To avoid clobbering installs Conflicts: coreutils < 8.24-100 # Note RPM doesn't support separate buildroots for %files @@ -161,19 +118,32 @@ packaged as a single multicall binary. # yum obsoleting rules explained at: # https://bugzilla.redhat.com/show_bug.cgi?id=1107973#c7 Obsoletes: %{name} < 8.24-100 -Requires(preun): /sbin/install-info -Requires(post): /sbin/install-info + +# info doc refers to "Specifying the Time Zone" from glibc-doc (#959597) +Suggests: glibc-doc + Summary: coreutils common optional components %description common Optional though recommended components, including documentation and translations. %prep +%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' %autosetup -N -# will be modified by coreutils-8.25-DIR_COLORS.patch -tee DIR_COLORS{,.256color,.lightbgcolor} /dev/null -# git add DIR_COLORS{,.256color,.lightbgcolor} +# will be regenerated in the build directories +rm -f src/fs.h + +# will be further modified by coreutils-8.32-DIR_COLORS.patch +sed src/dircolors.hin \ + -e 's| 00;36$| 01;36|' \ + > DIR_COLORS +sed src/dircolors.hin \ + -e 's| 01;31$| 00;31|' \ + -e 's| 01;35$| 00;35|' \ + > DIR_COLORS.lightbgcolor + +# git add DIR_COLORS{,.lightbgcolor} # git commit -m "clone DIR_COLORS before patching" # apply all patches @@ -187,14 +157,28 @@ autoreconf -fiv %build export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing -fpic" + +# Upstream suggests to build with -Dlint for static analyzers: +# https://lists.gnu.org/archive/html/coreutils/2018-06/msg00110.html +# ... and even for production binary RPMs: +# https://lists.gnu.org/archive/html/bug-gnulib/2020-05/msg00130.html +# There is currently no measurable performance drop or other known downside. +CFLAGS="$CFLAGS -Dlint" + +# make mknod work again in chroot without /proc being mounted (#1811038) +export ac_cv_func_lchmod="no" + +# needed for out-of-tree build +%global _configure ../configure + %{expand:%%global optflags %{optflags} -D_GNU_SOURCE=1} for type in separate single; do - mkdir $type && \ - (cd $type && ln -s ../configure || exit 1 + mkdir -p $type && \ + (cd $type || exit $? if test $type = 'single'; then config_single='--enable-single-binary' config_single="$config_single --without-openssl" # smaller/slower sha*sum - config_single="$config_single --without-gmp" # expr/factor machine ints + config_single="$config_single --without-libgmp" # expr/factor machine ints else config_single='--with-openssl' # faster sha*sum fi @@ -202,12 +186,13 @@ for type in separate single; do --cache-file=../config.cache \ --enable-install-program=arch \ --enable-no-install-program=kill,uptime \ + --enable-systemd \ --with-tty-group \ DEFAULT_POSIX2_VERSION=200112 alternative=199209 || : - make all %{?_smp_mflags} + %make_build all V=1 # make sure that parse-datetime.{c,y} ends up in debuginfo (#1555079) - ln -v ../lib/parse-datetime.{c,y} . + ln -fv ../lib/parse-datetime.{c,y} . ) done @@ -245,8 +230,7 @@ for type in separate single; do done mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/profile.d -install -p -c -m644 DIR_COLORS{,.256color,.lightbgcolor} \ - $RPM_BUILD_ROOT%{_sysconfdir} +install -p -c -m644 DIR_COLORS{,.lightbgcolor} $RPM_BUILD_ROOT%{_sysconfdir} install -p -c -m644 %SOURCE105 $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/colorls.sh install -p -c -m644 %SOURCE106 $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/colorls.csh @@ -257,18 +241,6 @@ grep LC_TIME %name.lang | cut -d'/' -f1-6 | sed -e 's/) /) %%dir /g' >>%name.lan # (sb) Deal with Installed (but unpackaged) file(s) found rm -f $RPM_BUILD_ROOT%{_infodir}/dir -%preun common -if [ $1 = 0 ]; then - if [ -f %{_infodir}/%{name}.info.gz ]; then - /sbin/install-info --delete %{_infodir}/%{name}.info.gz %{_infodir}/dir || : - fi -fi - -%post common -if [ -f %{_infodir}/%{name}.info.gz ]; then - /sbin/install-info %{_infodir}/%{name}.info.gz %{_infodir}/dir || : -fi - %files -f supported_utils %exclude %{_bindir}/*.single %dir %{_libexecdir}/coreutils @@ -293,48 +265,253 @@ fi %license COPYING %changelog -* Mon Jan 02 2023 Kamil Dudka - 8.30-15 -- basic support for checking NFSv4 ACLs (#2158747) +* Mon Jul 15 2024 Lukáš Zaoral - 9.5-2 +- fix fold exit code for non-existent files (RHEL-46722) -* Mon Aug 01 2022 Kamil Dudka - 8.30-14 +* Thu Jul 04 2024 Lukáš Zaoral - 9.5-1 +- rebase to latest upstream version +- sync i18n patch with SUSE (Kudos to Berny Völker!) +- add some test dependencies to execute additional part of the upstream test-suite +- enable LTO on ppc64le (RHEL-39977) + +* Mon Jun 24 2024 Troy Dawson - 9.4-7 +- Bump release for June 2024 mass rebuild + +* Mon Jan 29 2024 Lukáš Zaoral - 9.4-6 +- fix tail on kernels with 64k page sizes (RHEL-22866) + +* Wed Jan 24 2024 Fedora Release Engineering - 9.4-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Fri Jan 19 2024 Fedora Release Engineering - 9.4-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Thu Jan 18 2024 Lukáš Zaoral - 9.4-3 +- fix compilation on i686 + +* Thu Jan 18 2024 Lukáš Zaoral - 9.4-2 +- fix buffer overflow in split (CVE-2024-0684) + +* Fri Sep 15 2023 Lukáš Zaoral - 9.4-1 +- new upstream release 9.4 (#2235759) +- enable integration with systemd +- fix the license field + +* Wed Jul 19 2023 Fedora Release Engineering - 9.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Tue Apr 18 2023 Kamil Dudka - 9.3-1 +- remove obsolete Provides for absolute paths +- new upstream release 9.3 + +* Tue Apr 11 2023 Lukáš Zaoral - 9.2-4 +- migrate to SPDX license format + +* Fri Mar 24 2023 Kamil Dudka - 9.2-3 +- copy: fix --reflink=auto to fallback in more cases (#2180056) +- cksum: fix reporting of failed checks (#2180056) + +* Wed Mar 22 2023 Kamil Dudka - 9.2-2 +- coreutils-getgrouplist.patch: drop a patch no longer needed + +* Wed Mar 22 2023 Kamil Dudka - 9.2-1 +- new upstream release 9.2 + +* Thu Jan 19 2023 Fedora Release Engineering +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Mon Jan 02 2023 Kamil Dudka - 9.1-10 +- drop obsolete downstream-only extension of date(1) man page +- undocument downstream SELinux options deprecated since 2009 + +* Mon Jan 02 2023 Kamil Dudka - 9.1-9 +- basic support for checking NFSv4 ACLs (#2137866) + +* Mon Sep 19 2022 Kamil Dudka - 9.1-8 +- remove obsolete extension of mkdir(1) info documentation + +* Tue Aug 23 2022 Kamil Dudka - 9.1-7 +- remove non-upstream patch for uname -i/-p (#548834) + +* Mon Aug 08 2022 Kamil Dudka - 9.1-6 +- improve wording of a comment in /etc/DIR_COLORS (#2112593) + +* Mon Aug 08 2022 Kamil Dudka - 9.1-5 +- improve handling of control characters in unexpand (#2112870) + +* Mon Aug 01 2022 Kamil Dudka - 9.1-4 - prevent unexpand from failing on control characters (#2112870) -* Tue Mar 01 2022 Kamil Dudka - 8.30-13 +* Wed Jul 20 2022 Fedora Release Engineering +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Sat Apr 23 2022 Pádraig Brady - 9.1-2 +- make simple backups in correct dir; broken in 9.1 + +* Tue Apr 19 2022 Kamil Dudka - 9.1-1 +- new upstream release 9.1 + +* Mon Mar 21 2022 Kamil Dudka - 9.0-5 - ls, stat: avoid triggering automounts (#2044981) + +* Tue Mar 01 2022 Kamil Dudka - 9.0-4 - make `df --direct` work again (#2058686) -- doc: improve description of the --kibibytes option of ls (#1527391) -* Wed Jul 07 2021 Kamil Dudka - 8.30-12 -- df: fix duplicated remote entries due to bind mounts (#1962515) +* Wed Jan 19 2022 Fedora Release Engineering +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild -* Thu Jul 01 2021 Kamil Dudka - 8.30-11 -- tail: fix stack out-of-bounds write with --follow (#1974784) +* Mon Oct 04 2021 Kamil Dudka - 9.0-2 +- chmod: fix exit status when ignoring symlinks -* Tue Jun 08 2021 Kamil Dudka - 8.30-10 -- mountlist: recognize fuse.portal as dummy file system (#1952714) +* Sun Sep 26 2021 Kamil Dudka - 9.0-1 +- new upstream release 9.0 -* Fri Mar 26 2021 Kamil Dudka - 8.30-9 +* Tue Sep 14 2021 Sahana Prasad +- Rebuilt with OpenSSL 3.0.0 + +* Wed Jul 21 2021 Fedora Release Engineering +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Wed Jul 07 2021 Kamil Dudka - 8.32-30 +- df: fix duplicated remote entries due to bind mounts (#1979814) + +* Thu Jul 01 2021 Kamil Dudka - 8.32-28 +- tail: fix stack out-of-bounds write with --follow + +* Tue Jun 08 2021 Kamil Dudka - 8.32-27 +- mountlist: recognize fuse.portal as dummy file system (#1913358) + +* Mon May 17 2021 Kamil Dudka - 8.32-26 +- cp: pick additional copy_file_range()-related fixes from upstream + +* Mon May 03 2021 Kamil Dudka - 8.32-24 +- copy: ensure we enforce --reflink=never (#1956080) + +* Tue Apr 27 2021 Kamil Dudka - 8.32-23 +- copy: do not refuse to copy a swap file + +* Fri Apr 09 2021 Kamil Dudka - 8.32-22 +- weaken the dependency on glibc-doc to reduce minimal installations +- drop the last use of ncurses no longer needed (#1830318) +- utimens: fix confusing arg type in internal func + +* Fri Mar 26 2021 Kamil Dudka - 8.32-21 +- hostname,ln: fix memory leaks detected by Coverity + +* Wed Mar 24 2021 Kamil Dudka - 8.32-20 +- cp: use copy_file_range if available + +* Thu Feb 18 2021 Kamil Dudka - 8.32-19 +- stat: add support for the exfat file system (#1921427) + +* Wed Feb 03 2021 Kamil Dudka - 8.32-18 +- make coreutils-common recommend glibc-doc for info doc refs (#959597) + +* Tue Feb 02 2021 Kamil Dudka - 8.32-17 +- ls: fix crash printing SELinux context for unstatable files (#1921249) - split: fix --number=K/N to output correct part of file (#1921246) +- expr: fix invalid read with unmatched \(...\) (#1919775) + +* Tue Jan 26 2021 Fedora Release Engineering +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Tue Dec 08 2020 Kamil Dudka - 8.32-15 - rm: do not skip files upon failure to remove an empty dir (#1905481) + +* Tue Nov 03 2020 Kamil Dudka - 8.32-14 +- df,stat,tail: recognize more file system types + +* Wed Oct 14 2020 Kamil Dudka - 8.32-13 +- make the %%build section idempotent + +* Mon Aug 17 2020 Kamil Dudka - 8.32-12 +- do not install /etc/DIR_COLORS.256color (#1830318) + +* Thu Jul 30 2020 Kamil Dudka - 8.32-11 +- cp: default to --reflink=auto (#1861108) + +* Mon Jul 27 2020 Fedora Release Engineering +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Fri Jul 24 2020 Kamil Dudka - 8.32-9 +- disable -flto on ppc64le to make test-float pass (#1789115) + +* Mon Jul 13 2020 Tom Stellard - 8.32-8 +- Use make macros +- https://fedoraproject.org/wiki/Changes/UseMakeBuildInstallMacro + +* Fri Jun 26 2020 James Cassell - 8.32-7 +- move ncurses to -common package since it's needed for colorls.sh +- make ncurses optional + +* Fri May 15 2020 Kamil Dudka - 8.32-6 +- compile with -Dlint to enable optional initialization and cleanup code + +* Thu Apr 23 2020 Kamil Dudka - 8.32-5 +- du: simplify leaf optimization for XFS (#1823247) + +* Fri Apr 17 2020 Tom Stellard - 8.32-4 +- Fix missing inline function definition + +* Wed Mar 11 2020 Kamil Dudka - 8.32-3 +- uniq: remove collation handling as required by newer POSIX + +* Mon Mar 09 2020 Kamil Dudka - 8.32-2 +- make mknod work again in chroot without /proc being mounted (#1811038) +- ls: restore 8.31 behavior on removed directories + +* Thu Mar 05 2020 Kamil Dudka - 8.32-1 +- new upstream release 8.32 + +* Tue Feb 11 2020 Kamil Dudka - 8.31-10 +- make upstream test-suite work with root privileges (#1800597) + +* Wed Feb 05 2020 Kamil Dudka - 8.31-9 +- use upstream fix the cp/proc-short-read test + +* Thu Jan 30 2020 Kamil Dudka - 8.31-8 +- skip a test that relies on /proc/kallsyms having immutable content + +* Tue Jan 28 2020 Fedora Release Engineering +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Oct 17 2019 Kamil Dudka - 8.31-6 +- temporarily disable the use of statx (#1760300) + +* Fri Oct 11 2019 Kamil Dudka - 8.31-5 - use statx instead of stat when available (#1760300) -* Tue Apr 14 2020 Kamil Dudka - 8.30-8 -- df --local: recognize afs, auristorfs, and smb3 as remote fs (#1798030) -- fix formatting of sha512sum(1) man page (#1688744) +* Wed Jul 24 2019 Fedora Release Engineering +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild -* Wed Jan 29 2020 Kamil Dudka - 8.30-7 -- chcon: do not validate security context if SELinux is disabled (#1777831) +* Tue Jul 16 2019 Kamil Dudka - 8.31-3 +- disable flashing in ls colors for broken symbolic links (#1728986) -* Fri Jan 11 2019 Kamil Dudka - 8.30-6 -- cp --preserve=xattr: preserve NFSv4 ACL extended attributes (#1646985) +* Mon Mar 18 2019 Kamil Dudka - 8.31-2 +- fix formatting of sha512sum(1) man page (#1688740) -* Wed Nov 07 2018 Kamil Dudka - 8.30-5 -- sync: fix open() fallback bug (#1602463) -- fix implicit declaration warning in coreutils-getgrouplist.patch (#1602463) +* Mon Mar 11 2019 Kamil Dudka - 8.31-1 +- new upstream release 8.31 -* Thu Oct 11 2018 Kamil Dudka - 8.30-4 +* Thu Jan 31 2019 Fedora Release Engineering +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Wed Nov 07 2018 Kamil Dudka - 8.30-8 +- sync: fix open() fallback bug +- fix implicit declaration warning in coreutils-getgrouplist.patch + +* Sat Nov 03 2018 Kevin Fenzi - 8.30-7 +- Also remove Requires pre/post used by info scriptlets. + +* Sat Nov 03 2018 Kevin Fenzi - 8.30-6 +- Remove no longer needed info scriptlets + +* Thu Oct 11 2018 Kamil Dudka - 8.30-5 - fix heap-based buffer overflow in vasnprintf() (CVE-2018-17942) +* Thu Jul 12 2018 Fedora Release Engineering - 8.30-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + * Tue Jul 10 2018 Kamil Dudka - 8.30-3 - rename gnulib's renameat2 to renameatu to avoid clash with glibc (#1598518) @@ -344,22 +521,31 @@ fi * Mon Jul 02 2018 Kamil Dudka - 8.30-1 - new upstream release 8.30 -* Mon May 28 2018 Kamil Dudka - 8.29-8 +* Wed May 30 2018 Kamil Dudka - 8.29-12 +- add provides to coreutils-single to make it a drop-in replacement + +* Mon May 28 2018 Kamil Dudka - 8.29-11 - ls: increase the allowed abmon width from 5 to 12 (#1577872) - date, ls: pick strftime fixes from glibc to improve locale support (#1577872) -* Fri May 04 2018 Kamil Dudka - 8.29-7 -- add provides to coreutils-single to make it a drop-in replacement (#1572693) -- reintroduce very old Provides (mktemp, sh-utils, textwrap, fileutils, stat) - -* Fri Apr 20 2018 Kamil Dudka - 8.29-6 +* Fri Apr 20 2018 Kamil Dudka - 8.29-10 - fix crash caused by mistakenly enabled leaf optimization (#1558249) -* Wed Mar 21 2018 Kamil Dudka - 8.29-5 +* Fri Mar 23 2018 Kamil Dudka - 8.29-9 +- make it possible to install the latest available Adobe Reader RPM for Linux + +* Mon Mar 19 2018 Kamil Dudka - 8.29-8 - drop BR for bison, which is not used during the build + +* Fri Mar 16 2018 Kamil Dudka - 8.29-7 - make sure that parse-datetime.{c,y} ends up in debuginfo (#1555079) + +* Tue Mar 06 2018 Kamil Dudka - 8.29-6 - fix build failure with glibc-2.28 +* Mon Feb 26 2018 Igor Gnatenko - 8.29-5 +- Remove /bin/* Provides + * Mon Feb 19 2018 Kamil Dudka - 8.29-4 - add explicit BR for the gcc compiler diff --git a/sources b/sources new file mode 100644 index 0000000..8c6fdeb --- /dev/null +++ b/sources @@ -0,0 +1 @@ +SHA512 (coreutils-9.5.tar.xz) = 2ca0deac4dc10a80fd0c6fd131252e99d457fd03b7bd626a6bc74fe5a0529c0a3d48ce1f5da1d3b3a7a150a1ce44f0fbb6b68a6ac543dfd5baa3e71f5d65401c diff --git a/SOURCES/supported_utils b/supported_utils similarity index 98% rename from SOURCES/supported_utils rename to supported_utils index 8105ccf..6db4fb5 100644 --- a/SOURCES/supported_utils +++ b/supported_utils @@ -1,6 +1,7 @@ %{_bindir}/arch %{_bindir}/b2sum %{_bindir}/basename +%{_bindir}/basenc %{_bindir}/cat %{_bindir}/chgrp %{_bindir}/chmod