RHEL 9.0.0 Alpha bootstrap

The content of this branch was automatically imported from Fedora ELN
with the following as its source:
https://src.fedoraproject.org/rpms/coreutils#f4b85e63ba4ad4457596bf9181b39e7831c9e701
This commit is contained in:
Petr Šabata 2020-10-14 23:13:56 +02:00
parent 6e90f9a04f
commit b12d395039
38 changed files with 9622 additions and 0 deletions

1
.gitignore vendored
View File

@ -0,0 +1 @@
/coreutils-[0-9.]*.tar.xz

7
STAGE1-coreutils Normal file
View File

@ -0,0 +1,7 @@
srpm coreutils
mcd $BUILDDIR/$1
(cd $SRC/${1}-*/ ; autoreconf -vif)
$SRC/${1}-*/configure $TCONFIGARGS --disable-pam
notparallel
make $J man1_MANS= V=1
make $J man1_MANS= install DESTDIR=${ROOTFS}

View File

@ -0,0 +1,20 @@
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);
}
}

View File

@ -0,0 +1,49 @@
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)

View File

@ -0,0 +1,26 @@
From 6880c3dc9098b3337612850d1500b474aeb944ca Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Tue, 29 Aug 2017 17:33:51 +0200
Subject: [PATCH] require_selinux_(): use selinuxenabled(8) if available
---
init.cfg | 3 +++
1 file changed, 3 insertions(+)
diff --git a/init.cfg b/init.cfg
index af6b581..f887b3a 100644
--- a/init.cfg
+++ b/init.cfg
@@ -114,6 +114,9 @@ require_selinux_()
grep 'selinuxfs$' /proc/filesystems > /dev/null \
|| skip_ "this system lacks SELinux support"
+ # use the 'selinuxenabled' utility if available
+ selinuxenabled; [ $? = 1 ] && skip_ "SELinux is disabled"
+
# Independent of whether SELinux is enabled system-wide,
# the current file system may lack SELinux support.
# Also the current build may have SELinux support disabled.
--
2.9.5

View File

@ -0,0 +1,29 @@
From 0d04ee8ddedb2bf33d64f148f246a3b7ec4fef21 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Mon, 23 Jan 2017 12:35:41 +0100
Subject: [PATCH] test-lock: disable the rwlock test
It hangs indefinitely if the system rwlock implementation does not
prevent writer starvation (and glibc does not implement it).
Bug: http://www.mail-archive.com/bug-gnulib@gnu.org/msg33017.html
---
gnulib-tests/test-lock.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gnulib-tests/test-lock.c b/gnulib-tests/test-lock.c
index aa6de27..5af0a6c 100644
--- a/gnulib-tests/test-lock.c
+++ b/gnulib-tests/test-lock.c
@@ -42,7 +42,7 @@
Uncomment some of these, to verify that all tests crash if no locking
is enabled. */
#define DO_TEST_LOCK 1
-#define DO_TEST_RWLOCK 1
+#define DO_TEST_RWLOCK 0
#define DO_TEST_RECURSIVE_LOCK 1
#define DO_TEST_ONCE 1
--
2.7.4

View File

@ -0,0 +1,100 @@
From 81e25c8521937ecf7f444bab11fddaaf81cc3efd Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
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 bd5df23..84f2417 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 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 +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
@@ -58,7 +65,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 30;41 # file with capability
diff --git a/DIR_COLORS.lightbgcolor b/DIR_COLORS.lightbgcolor
index 4316832..6402854 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
@@ -48,17 +57,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 30;41 # file with capability
@@ -67,7 +76,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.
--
2.21.1

View File

@ -0,0 +1,119 @@
From 76126e2831580d0df20530f4d6f72189bd4f0b9a Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 18 Jun 2020 22:16:24 -0700
Subject: [PATCH] cp: default to COW
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Likewise for install. Proposed in Bug#24400, and long past due.
* NEWS:
* doc/coreutils.texi (cp invocation):
* src/copy.h (enum Reflink_type): Document this.
* src/cp.c (cp_option_init):
* src/install.c (cp_option_init): Implement this.
Upstream-commit: 25725f9d41735d176d73a757430739fb71c7d043
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
doc/coreutils.texi | 19 ++++++++++++-------
src/copy.h | 4 ++--
src/cp.c | 2 +-
src/install.c | 2 +-
4 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 02e0c1c..2382a16 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -8854,12 +8854,14 @@ The @var{when} value can be one of the following:
@table @samp
@item always
-The default behavior: if the copy-on-write operation is not supported
+If the copy-on-write operation is not supported
then report the failure for each file and exit with a failure status.
+Plain @option{--reflink} is equivalent to @option{--reflink=when}.
@item auto
If the copy-on-write operation is not supported then fall back
to the standard copy behavior.
+This is the default if no @option{--reflink} option is given.
@item never
Disable copy-on-write operation and use the standard copy behavior.
@@ -8868,12 +8870,6 @@ Disable copy-on-write operation and use the standard copy behavior.
This option is overridden by the @option{--link}, @option{--symbolic-link}
and @option{--attributes-only} options, thus allowing it to be used
to configure the default data copying behavior for @command{cp}.
-For example, with the following alias, @command{cp} will use the
-minimum amount of space supported by the file system.
-
-@example
-alias cp='cp --reflink=auto --sparse=always'
-@end example
@item --remove-destination
@opindex --remove-destination
@@ -8918,6 +8914,15 @@ This is useful in creating a file for use with the @command{mkswap} command,
since such a file must not have any holes.
@end table
+For example, with the following alias, @command{cp} will use the
+minimum amount of space supported by the file system.
+(Older versions of @command{cp} can also benefit from
+@option{--reflink=auto} here.)
+
+@example
+alias cp='cp --sparse=always'
+@end example
+
@optStripTrailingSlashes
@item -s
diff --git a/src/copy.h b/src/copy.h
index 874d6f7..a0ad494 100644
--- a/src/copy.h
+++ b/src/copy.h
@@ -46,10 +46,10 @@ enum Sparse_type
/* Control creation of COW files. */
enum Reflink_type
{
- /* Default to a standard copy. */
+ /* Do a standard copy. */
REFLINK_NEVER,
- /* Try a COW copy and fall back to a standard copy. */
+ /* Try a COW copy and fall back to a standard copy; this is the default. */
REFLINK_AUTO,
/* Require a COW copy and fail if not available. */
diff --git a/src/cp.c b/src/cp.c
index 0193df8..9e7ad14 100644
--- a/src/cp.c
+++ b/src/cp.c
@@ -796,7 +796,7 @@ cp_option_init (struct cp_options *x)
x->move_mode = false;
x->install_mode = false;
x->one_file_system = false;
- x->reflink_mode = REFLINK_NEVER;
+ x->reflink_mode = REFLINK_AUTO;
x->preserve_ownership = false;
x->preserve_links = false;
diff --git a/src/install.c b/src/install.c
index 4ab44a6..aef16ca 100644
--- a/src/install.c
+++ b/src/install.c
@@ -264,7 +264,7 @@ cp_option_init (struct cp_options *x)
{
cp_options_default (x);
x->copy_as_regular = true;
- x->reflink_mode = REFLINK_NEVER;
+ x->reflink_mode = REFLINK_AUTO;
x->dereference = DEREF_ALWAYS;
x->unlink_dest_before_opening = true;
x->unlink_dest_after_failed_open = false;
--
2.25.4

View File

@ -0,0 +1,164 @@
From b9f9ed14bda93ecb407129b69e6476813c250046 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 15 Apr 2020 20:50:32 -0700
Subject: [PATCH] fts: remove NOSTAT_LEAF_OPTIMIZATION
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
It caused find and du to dump core, and it was useful
only for obsolescent Linux filesystems anyway. Problem reported in:
https://lists.gnu.org/r/bug-gnulib/2020-04/msg00068.html
Quite possibly there is still a serious underlying fts bug with
tight-loop-check and mutating file systems, but if so this patch
should cause the bug to be triggered less often.
* lib/fts.c (enum leaf_optimization): Remove
NOSTAT_LEAF_OPTIMIZATION, as its problematic.
(S_MAGIC_REISERFS, S_MAGIC_XFS): Remove; no longer needed.
(leaf_optimization): Remove special cases for ReiserFS and XFS.
(fts_read): Remove NOSTAT_LEAF_OPTIMIZATION code.
* lib/fts_.h (struct _ftsent.fts_n_dirs_remaining):
Remove. All uses removed.
Upstream-commit: 47bf2cf3184027c1eb9c1dfeea5c5b8b2d69710d
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/fts.c | 56 ++++++++-------------------------------------------
lib/fts_.h | 5 -----
2 files changed, 8 insertions(+), 53 deletions(-)
diff --git a/lib/fts.c b/lib/fts.c
index 1093ce5..dfe3fef 100644
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -445,7 +445,6 @@ fts_open (char * const *argv,
if ((parent = fts_alloc(sp, "", 0)) == NULL)
goto mem2;
parent->fts_level = FTS_ROOTPARENTLEVEL;
- parent->fts_n_dirs_remaining = -1;
}
/* The classic fts implementation would call fts_stat with
@@ -634,9 +633,8 @@ fts_close (FTS *sp)
}
/* Minimum link count of a traditional Unix directory. When leaf
- optimization is OK and MIN_DIR_NLINK <= st_nlink, then st_nlink is
- an upper bound on the number of subdirectories (counting "." and
- ".."). */
+ optimization is OK and a directory's st_nlink == MIN_DIR_NLINK,
+ then the directory has no subdirectories. */
enum { MIN_DIR_NLINK = 2 };
/* Whether leaf optimization is OK for a directory. */
@@ -645,12 +643,8 @@ enum leaf_optimization
/* st_nlink is not reliable for this directory's subdirectories. */
NO_LEAF_OPTIMIZATION,
- /* Leaf optimization is OK, but is not useful for avoiding stat calls. */
- OK_LEAF_OPTIMIZATION,
-
- /* Leaf optimization is not only OK: it is useful for avoiding
- stat calls, because dirent.d_type does not work. */
- NOSTAT_LEAF_OPTIMIZATION
+ /* st_nlink == 2 means the directory lacks subdirectories. */
+ OK_LEAF_OPTIMIZATION
};
#if (defined __linux__ || defined __ANDROID__) \
@@ -663,9 +657,7 @@ enum leaf_optimization
# define S_MAGIC_CIFS 0xFF534D42
# define S_MAGIC_NFS 0x6969
# define S_MAGIC_PROC 0x9FA0
-# define S_MAGIC_REISERFS 0x52654973
# define S_MAGIC_TMPFS 0x1021994
-# define S_MAGIC_XFS 0x58465342
# ifdef HAVE___FSWORD_T
typedef __fsword_t fsword;
@@ -786,23 +778,15 @@ dirent_inode_sort_may_be_useful (FTSENT const *p, int dir_fd)
}
/* Given an FTS entry P for a directory with descriptor DIR_FD,
- return true if it is both useful and valid to apply leaf optimization.
- The optimization is useful only for file systems that lack usable
- dirent.d_type info. The optimization is valid if an st_nlink value
- of at least MIN_DIR_NLINK is an upper bound on the number of
- subdirectories of D, counting "." and ".." as subdirectories.
+ return whether it is valid to apply leaf optimization.
+ The optimization is valid if a directory's st_nlink value equal
+ to MIN_DIR_NLINK means the directory has no subdirectories.
DIR_FD is negative if unavailable. */
static enum leaf_optimization
leaf_optimization (FTSENT const *p, int dir_fd)
{
switch (filesystem_type (p, dir_fd))
{
- /* List here the file system types that may lack usable dirent.d_type
- info, yet for which the optimization does apply. */
- case S_MAGIC_REISERFS:
- case S_MAGIC_XFS: /* XFS lacked it until 2013-08-22 commit. */
- return NOSTAT_LEAF_OPTIMIZATION;
-
case 0:
/* Leaf optimization is unsafe if the file system type is unknown. */
FALLTHROUGH;
@@ -1027,26 +1011,7 @@ check_for_dir:
if (p->fts_info == FTS_NSOK)
{
if (p->fts_statp->st_size == FTS_STAT_REQUIRED)
- {
- FTSENT *parent = p->fts_parent;
- if (parent->fts_n_dirs_remaining == 0
- && ISSET(FTS_NOSTAT)
- && ISSET(FTS_PHYSICAL)
- && (leaf_optimization (parent, sp->fts_cwd_fd)
- == NOSTAT_LEAF_OPTIMIZATION))
- {
- /* nothing more needed */
- }
- else
- {
- p->fts_info = fts_stat(sp, p, false);
- if (S_ISDIR(p->fts_statp->st_mode)
- && p->fts_level != FTS_ROOTLEVEL
- && 0 < parent->fts_n_dirs_remaining
- && parent->fts_n_dirs_remaining != (nlink_t) -1)
- parent->fts_n_dirs_remaining--;
- }
- }
+ p->fts_info = fts_stat(sp, p, false);
else
fts_assert (p->fts_statp->st_size == FTS_NO_STAT_REQUIRED);
}
@@ -1830,11 +1795,6 @@ err: memset(sbp, 0, sizeof(struct stat));
}
if (S_ISDIR(sbp->st_mode)) {
- p->fts_n_dirs_remaining
- = ((sbp->st_nlink < MIN_DIR_NLINK
- || p->fts_level <= FTS_ROOTLEVEL)
- ? -1
- : sbp->st_nlink - (ISSET (FTS_SEEDOT) ? 0 : MIN_DIR_NLINK));
if (ISDOT(p->fts_name)) {
/* Command-line "." and ".." are real directories. */
return (p->fts_level == FTS_ROOTLEVEL ? FTS_D : FTS_DOT);
diff --git a/lib/fts_.h b/lib/fts_.h
index d40a116..2e76cc4 100644
--- a/lib/fts_.h
+++ b/lib/fts_.h
@@ -227,11 +227,6 @@ typedef struct _ftsent {
size_t fts_namelen; /* strlen(fts_name) */
- /* If not (nlink_t) -1, an upper bound on the number of
- remaining subdirectories of interest. If this becomes
- zero, some work can be avoided. */
- nlink_t fts_n_dirs_remaining;
-
# define FTS_D 1 /* preorder directory */
# define FTS_DC 2 /* directory that causes cycles */
# define FTS_DEFAULT 3 /* none of the above */
--
2.21.1

View File

@ -0,0 +1,153 @@
From 8c022656320592dbad146f5d3a3ae1875f419446 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 5 Mar 2020 17:25:29 -0800
Subject: [PATCH 1/2] ls: restore 8.31 behavior on removed directories
* NEWS: Mention this.
* src/ls.c: Do not include <sys/sycall.h>
(print_dir): Don't worry about whether the directory is removed.
* tests/ls/removed-directory.sh: Adjust to match new (i.e., old)
behavior.
Upstream-commit: 10fcb97bd728f09d4a027eddf8ad2900f0819b0a
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/ls.c | 22 ----------------------
tests/ls/removed-directory.sh | 10 ++--------
2 files changed, 2 insertions(+), 30 deletions(-)
diff --git a/src/ls.c b/src/ls.c
index 9d25f62..850ecc2 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -49,10 +49,6 @@
# include <sys/ptem.h>
#endif
-#ifdef __linux__
-# include <sys/syscall.h>
-#endif
-
#include <stdio.h>
#include <assert.h>
#include <setjmp.h>
@@ -2896,7 +2892,6 @@ print_dir (char const *name, char const *realname, bool command_line_arg)
struct dirent *next;
uintmax_t total_blocks = 0;
static bool first = true;
- bool found_any_entries = false;
errno = 0;
dirp = opendir (name);
@@ -2972,7 +2967,6 @@ print_dir (char const *name, char const *realname, bool command_line_arg)
next = readdir (dirp);
if (next)
{
- found_any_entries = true;
if (! file_ignored (next->d_name))
{
enum filetype type = unknown;
@@ -3018,22 +3012,6 @@ print_dir (char const *name, char const *realname, bool command_line_arg)
if (errno != EOVERFLOW)
break;
}
-#ifdef __linux__
- else if (! found_any_entries)
- {
- /* If readdir finds no directory entries at all, not even "." or
- "..", then double check that the directory exists. */
- if (syscall (SYS_getdents, dirfd (dirp), NULL, 0) == -1
- && errno != EINVAL)
- {
- /* We exclude EINVAL as that pertains to buffer handling,
- and we've passed NULL as the buffer for simplicity.
- ENOENT is returned if appropriate before buffer handling. */
- file_failure (command_line_arg, _("reading directory %s"), name);
- }
- break;
- }
-#endif
else
break;
diff --git a/tests/ls/removed-directory.sh b/tests/ls/removed-directory.sh
index e8c835d..fe8f929 100755
--- a/tests/ls/removed-directory.sh
+++ b/tests/ls/removed-directory.sh
@@ -26,20 +26,14 @@ case $host_triplet in
*) skip_ 'non linux kernel' ;;
esac
-LS_FAILURE=2
-
-cat <<\EOF >exp-err || framework_failure_
-ls: reading directory '.': No such file or directory
-EOF
-
cwd=$(pwd)
mkdir d || framework_failure_
cd d || framework_failure_
rmdir ../d || framework_failure_
-returns_ $LS_FAILURE ls >../out 2>../err || fail=1
+ls >../out 2>../err || fail=1
cd "$cwd" || framework_failure_
compare /dev/null out || fail=1
-compare exp-err err || fail=1
+compare /dev/null err || fail=1
Exit $fail
--
2.21.1
From 847324a0debd9d12062c79e7a7a9d3d8ce76390d Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sat, 7 Mar 2020 10:29:51 -0800
Subject: [PATCH 2/2] ls: improve removed-directory test
* tests/ls/removed-directory.sh: Remove host_triplet test.
Skip this test if one cannot remove the working directory.
From a suggestion by Bernhard Voelker (Bug#39929).
Upstream-commit: 672819c73f2e94e61386dc0584bddf9da860cc26
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
tests/ls/removed-directory.sh | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/tests/ls/removed-directory.sh b/tests/ls/removed-directory.sh
index fe8f929..63b209d 100755
--- a/tests/ls/removed-directory.sh
+++ b/tests/ls/removed-directory.sh
@@ -1,7 +1,7 @@
#!/bin/sh
-# If ls is asked to list a removed directory (e.g. the parent process's
-# current working directory that has been removed by another process), it
-# emits an error message.
+# If ls is asked to list a removed directory (e.g., the parent process's
+# current working directory has been removed by another process), it
+# should not emit an error message merely because the directory is removed.
# Copyright (C) 2020 Free Software Foundation, Inc.
@@ -21,15 +21,10 @@
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
print_ver_ ls
-case $host_triplet in
- *linux*) ;;
- *) skip_ 'non linux kernel' ;;
-esac
-
cwd=$(pwd)
mkdir d || framework_failure_
cd d || framework_failure_
-rmdir ../d || framework_failure_
+rmdir ../d || skip_ "can't remove working directory on this platform"
ls >../out 2>../err || fail=1
cd "$cwd" || framework_failure_
--
2.21.1

16
coreutils-8.32.tar.xz.sig Normal file
View File

@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEEbDfcEhIaUAa8HbgE32/ZcTBgN9kFAl5hC5MACgkQ32/ZcTBg
N9n92Q//Td2GE1f8AZKkxCNI76Q/TqbxAwhjbkR+KdzvsyMePmgHcMgHG6sO2MNF
g6DIBmHpO3vWGzvUxUZRRhuW5QBOnMxHb/WXZ0p/g45d5MQdn4i0dA0wUJgByOqn
/WVfygNg9mrWFx/uTeCdhrwL11m71C7j/eQVu7Wr5DIb20VJ8+nVC2IWW33ZvxRj
Goa0wwDpeeD9qYe/Y+E5ZyhDYHJGRmNAlS03SXLO3+RfsbZFwdQEtzvr+v1VN6/S
9OsoI/GLdRjY1tByppaoZ63ZybB6iF5zZfJiWDF7Nw4MduJpjZQDSywiNleJ9vOi
fwR1180PjMV6aTXvPwqbqQxZjDl7nqvO36ghlTvErJbqdJVIYxmUGNjeJyjqI85l
Lhckh0GWos9K/kl13Ry9KWsxNQgfjNhtgjXGh+W47ojrho2kCiK5BTwDFeVU0jtU
H/1EePSGAIUF/Sfjz3rmGgLaaBwPiRiyzEIuZMyd4NCJWwfOTqgOshOYw15GCWYq
wGesN/4LWzEja7Au5lHP7imXjP0bp4qE/sYrOb4WzVVLCn+z2hu6SEIzjJzSm+D+
8Wv3Ia1/ypVpR+Z7gUt7VtEvI8zAwlySd/6Jw5U7TL0rzvZsTVWmCvEjPp+o3jCB
Fy/4ybao1gowBFtT1AtPMmxmiJ41KWCxLFrTuGJpFYCGvBH2y8s=
=yHV6
-----END PGP SIGNATURE-----

View File

@ -0,0 +1,13 @@
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

68
coreutils-colorls.csh Executable file
View File

@ -0,0 +1,68 @@
# skip everything for non-interactive shells
if (! $?prompt) exit
# color-ls initialization
if ( $?USER_LS_COLORS ) then
if ( "$USER_LS_COLORS" != "" ) then
#when USER_LS_COLORS defined do not override user
#specified LS_COLORS and use them
goto finish
endif
endif
alias ll 'ls -l'
alias l. 'ls -d .*'
set COLORS=/etc/DIR_COLORS
if ($?TERM) then
if ( -e "/etc/DIR_COLORS.256color" && -e "/usr/bin/tput" ) 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
endif
if ( -f ~/.dircolors ) set COLORS=~/.dircolors
if ( -f ~/.dir_colors ) set COLORS=~/.dir_colors
if ($?TERM) then
if ( -f ~/.dircolors."$TERM" ) set COLORS=~/.dircolors."$TERM"
if ( -f ~/.dir_colors."$TERM" ) set COLORS=~/.dir_colors."$TERM"
endif
set INCLUDE="`/usr/bin/cat "$COLORS" | /usr/bin/grep '^INCLUDE' | /usr/bin/cut -d ' ' -f2-`"
if ( ! -e "$COLORS" ) exit
set _tmp="`/usr/bin/mktemp .colorlsXXX -q --tmpdir=/tmp`"
#if mktemp fails, exit when include was active, otherwise use $COLORS file
if ( "$_tmp" == '' ) then
if ( "$INCLUDE" == '' ) then
eval "`/usr/bin/dircolors -c $COLORS`"
endif
goto cleanup
endif
if ( "$INCLUDE" != '' ) /usr/bin/cat "$INCLUDE" >> $_tmp
/usr/bin/grep -v '^INCLUDE' "$COLORS" >> $_tmp
eval "`/usr/bin/dircolors -c $_tmp`"
/usr/bin/rm -f $_tmp
if ( "$LS_COLORS" == '' ) exit
cleanup:
set color_none=`/usr/bin/sed -n '/^COLOR.*none/Ip' < $COLORS`
if ( "$color_none" != '' ) then
unset color_none
exit
endif
unset color_none
unset _tmp
unset INCLUDE
unset COLORS
finish:
alias ll 'ls -l --color=auto'
alias l. 'ls -d .* --color=auto'
alias ls 'ls --color=auto'

57
coreutils-colorls.sh Executable file
View File

@ -0,0 +1,57 @@
# color-ls initialization
# Skip all for noninteractive shells.
[ ! -t 0 ] && return
#when USER_LS_COLORS defined do not override user LS_COLORS, but use them.
if [ -z "$USER_LS_COLORS" ]; then
alias ll='ls -l' 2>/dev/null
alias l.='ls -d .*' 2>/dev/null
INCLUDE=
COLORS=
for colors in "$HOME/.dir_colors.$TERM" "$HOME/.dircolors.$TERM" \
"$HOME/.dir_colors" "$HOME/.dircolors"; do
[ -e "$colors" ] && COLORS="$colors" && \
INCLUDE="`/usr/bin/cat "$COLORS" | /usr/bin/grep '^INCLUDE' | /usr/bin/cut -d ' ' -f2-`" && \
break
done
[ -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"
# Existence of $COLORS already checked above.
[ -n "$COLORS" ] || return
if [ -e "$INCLUDE" ];
then
TMP="`/usr/bin/mktemp .colorlsXXX -q --tmpdir=/tmp`"
[ -z "$TMP" ] && return
/usr/bin/cat "$INCLUDE" >> $TMP
/usr/bin/grep -v '^INCLUDE' "$COLORS" >> $TMP
eval "`/usr/bin/dircolors --sh $TMP 2>/dev/null`"
/usr/bin/rm -f $TMP
else
eval "`/usr/bin/dircolors --sh $COLORS 2>/dev/null`"
fi
[ -z "$LS_COLORS" ] && return
/usr/bin/grep -qi "^COLOR.*none" $COLORS >/dev/null 2>/dev/null && return
fi
unset TMP COLORS INCLUDE
alias ll='ls -l --color=auto' 2>/dev/null
alias l.='ls -d .* --color=auto' 2>/dev/null
alias ls='ls --color=auto' 2>/dev/null

174
coreutils-df-direct.patch Normal file
View File

@ -0,0 +1,174 @@
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index a507280..400e135 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -11303,6 +11303,13 @@ some systems (notably SunOS), 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.
+@item --direct
+@opindex --direct
+@cindex direct statfs for a file
+Do not resolve mount point and show statistics directly for a file. It can be
+especially useful for NFS mount points if there is a boundary between two
+storage policies behind the mount point.
+
@item --total
@opindex --total
@cindex grand total of disk size, usage and available space
diff --git a/src/df.c b/src/df.c
index 8f760db..a7385fd 100644
--- a/src/df.c
+++ b/src/df.c
@@ -120,6 +120,9 @@ static bool print_type;
/* If true, print a grand total at the end. */
static bool print_grand_total;
+/* If true, show statistics for a file instead of mount point. */
+static bool direct_statfs;
+
/* Grand total data. */
static struct fs_usage grand_fsu;
@@ -247,13 +250,15 @@ enum
NO_SYNC_OPTION = CHAR_MAX + 1,
SYNC_OPTION,
TOTAL_OPTION,
- OUTPUT_OPTION
+ OUTPUT_OPTION,
+ DIRECT_OPTION
};
static struct option const long_options[] =
{
{"all", no_argument, NULL, 'a'},
{"block-size", required_argument, NULL, 'B'},
+ {"direct", no_argument, NULL, DIRECT_OPTION},
{"inodes", no_argument, NULL, 'i'},
{"human-readable", no_argument, NULL, 'h'},
{"si", no_argument, NULL, 'H'},
@@ -509,7 +514,10 @@ get_header (void)
for (col = 0; col < ncolumns; col++)
{
char *cell = NULL;
- char const *header = _(columns[col]->caption);
+ char const *header = (columns[col]->field == TARGET_FIELD
+ && direct_statfs)?
+ _("File") :
+ _(columns[col]->caption);
if (columns[col]->field == SIZE_FIELD
&& (header_mode == DEFAULT_MODE
@@ -1397,6 +1405,19 @@ get_point (const char *point, const struct stat *statp)
static void
get_entry (char const *name, struct stat const *statp)
{
+ if (direct_statfs)
+ {
+ char *resolved = canonicalize_file_name (name);
+ if (resolved)
+ {
+ char *mp = find_mount_point (name, statp);
+ get_dev (NULL, mp, resolved, NULL, NULL, false, false, NULL, false);
+ free(mp);
+ free (resolved);
+ return;
+ }
+ }
+
if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))
&& get_disk (name))
return;
@@ -1467,6 +1488,7 @@ or all file systems by default.\n\
-B, --block-size=SIZE scale sizes by SIZE before printing them; e.g.,\n\
'-BM' prints sizes in units of 1,048,576 bytes;\n\
see SIZE format below\n\
+ --direct show statistics for a file instead of mount point\n\
-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);
@@ -1557,6 +1579,9 @@ main (int argc, char **argv)
xstrtol_fatal (e, oi, c, long_options, optarg);
}
break;
+ case DIRECT_OPTION:
+ direct_statfs = true;
+ break;
case 'i':
if (header_mode == OUTPUT_MODE)
{
@@ -1653,6 +1678,13 @@ main (int argc, char **argv)
}
}
+ if (direct_statfs && show_local_fs)
+ {
+ error (0, 0, _("options --direct and --local (-l) are mutually "
+ "exclusive"));
+ usage (EXIT_FAILURE);
+ }
+
if (human_output_opts == -1)
{
if (posix_format)
diff --git a/tests/df/direct.sh b/tests/df/direct.sh
new file mode 100755
index 0000000..8e4cfb8
--- /dev/null
+++ b/tests/df/direct.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+# Ensure "df --direct" works as documented
+
+# Copyright (C) 2010 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 <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../src
+print_ver_ df
+
+df || skip_ "df fails"
+
+DIR=`pwd` || framework_failure
+FILE="$DIR/file"
+touch "$FILE" || framework_failure
+echo "$FILE" > file_exp || framework_failure
+echo "Mounted on" > header_mounted_exp || framework_failure
+echo "File" > header_file_exp || framework_failure
+
+fail=0
+
+df --portability "$FILE" > df_out || fail=1
+df --portability --direct "$FILE" > df_direct_out || fail=1
+df --portability --direct --local "$FILE" > /dev/null 2>&1 && fail=1
+
+# check df header
+$AWK '{ if (NR==1) print $6 " " $7; }' df_out > header_mounted_out \
+ || framework_failure
+$AWK '{ if (NR==1) print $6; }' df_direct_out > header_file_out \
+ || framework_failure
+compare header_mounted_out header_mounted_exp || fail=1
+compare header_file_out header_file_exp || fail=1
+
+# check df output (without --direct)
+$AWK '{ if (NR==2) print $6; }' df_out > file_out \
+ || framework_failure
+compare file_out file_exp && fail=1
+
+# check df output (with --direct)
+$AWK '{ if (NR==2) print $6; }' df_direct_out > file_out \
+ || framework_failure
+compare file_out file_exp || fail=1
+
+Exit $fail

View File

@ -0,0 +1,94 @@
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 <config.h>
+/* We do not need this code if getgrouplist(3) is available. */
+#ifndef HAVE_GETGROUPLIST
+
#include "getugroups.h"
#include <errno.h>
@@ -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

View File

@ -0,0 +1,565 @@
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 <assert.h>
#include <getopt.h>
#include <sys/types.h>
+
+/* Get mbstate_t, mbrtowc(). */
+#if HAVE_WCHAR_H
+# include <wchar.h>
+#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)

View File

@ -0,0 +1,864 @@
From e87ab5b991b08092a7e07af82b3ec822a8604151 Mon Sep 17 00:00:00 2001
From: Ondrej Oprala <ooprala@redhat.com>
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 <pbrady@redhat.com>
---
bootstrap.conf | 1 +
configure.ac | 2 +
lib/mbfile.c | 3 +
lib/mbfile.h | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++
m4/mbfile.m4 | 14 +++
src/expand.c | 43 +++++----
src/local.mk | 4 +-
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 <config.h>
+#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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Mitsuru Chinen <mchinen@yamato.ibm.com>
+ and Bruno Haible <bruno@clisp.org>. */
+
+/* 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 <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+ <wchar.h>.
+ BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
+ <wchar.h>. */
+#include <stdio.h>
+#include <time.h>
+#include <wchar.h>
+
+#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 <stdio.h>
#include <getopt.h>
#include <sys/types.h>
+
+#include <mbfile.h>
+
#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/local.mk b/src/local.mk
index 72db9c704..ef3bfa469 100644
--- a/src/local.mk
+++ b/src/local.mk
@@ -415,8 +415,8 @@ src_basenc_CPPFLAGS = -DBASE_TYPE=42 $(AM_CPPFLAGS)
src_ginstall_CPPFLAGS = -DENABLE_MATCHPATHCON=1 $(AM_CPPFLAGS)
-src_expand_SOURCES = src/expand.c src/expand-common.c
-src_unexpand_SOURCES = src/unexpand.c src/expand-common.c
+src_expand_SOURCES = src/expand.c src/expand-common.c lib/mbfile.c
+src_unexpand_SOURCES = src/unexpand.c src/expand-common.c lib/mbfile.c
# Ensure we don't link against libcoreutils.a as that lib is
# not compiled with -fPIC which causes issues on 64 bit at least
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 <stdio.h>
#include <getopt.h>
#include <sys/types.h>
+
+#include <mbfile.h>
+
#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,7 +235,7 @@ unexpand (void)
}
else
{
- column++;
+ column += mb_width (c);
if (!column)
die (EXIT_FAILURE, 0, _("input line is too long"));
}
@@ -229,8 +243,11 @@ unexpand (void)
if (pending)
{
if (pending > 1 && one_blank_before_tab_stop)
- pending_blank[0] = '\t';
- if (fwrite (pending_blank, 1, pending, stdout) != pending)
+ mb_setascii (&pending_blank[0], '\t');
+
+ for (int n = 0; n < pending; ++n)
+ mb_putc (pending_blank[n], stdout);
+ if (ferror (stdout))
die (EXIT_FAILURE, errno, _("write error"));
pending = 0;
one_blank_before_tab_stop = false;
@@ -240,16 +257,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 <http://www.gnu.org/licenses/>.
+
+. "${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 <http://www.gnu.org/licenses/>.
+
+. "${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

View File

@ -0,0 +1,28 @@
From 02424bfcd719bbaa695f4e1c3ef17ad91b0d23c0 Mon Sep 17 00:00:00 2001
From: Lubomir Rintel <lkundrak@v3.sk>
Date: Thu, 28 Jan 2016 20:57:22 +0100
Subject: [PATCH] unexpand: fix blank line handling
echo '' |./src/unexpand -a
Really?
---
src/unexpand.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/unexpand.c b/src/unexpand.c
index 569a7ee..3bbbd66 100644
--- a/src/unexpand.c
+++ b/src/unexpand.c
@@ -233,7 +233,7 @@ unexpand (void)
next_tab_column = column;
tab_index -= !!tab_index;
}
- else
+ else if (!mb_iseq (c, '\n'))
{
column += mb_width (c);
if (!column)
--
2.7.4

View File

@ -0,0 +1,108 @@
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

View File

@ -0,0 +1,80 @@
From ff424639fe863cbd6963add1a79b97290c1606c6 Mon Sep 17 00:00:00 2001
From: rpm-build <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

View File

@ -0,0 +1,35 @@
From 3976ef5a20369d8b490907ab2cba2d617305a5e0 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
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)
<none/unknown> < 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

View File

@ -0,0 +1,456 @@
From 7a7c776a4e228d180e74614fd8c8afcad5d4bdf7 Mon Sep 17 00:00:00 2001
From: Jakub Martisko <jamartis@redhat.com>
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 <assert.h>
#include <stdio.h>
#include <sys/types.h>
+#include <mbfile.h>
#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;i<predef_locales_count;i++)
+ {
+ if (setlocale(LC_ALL,predef_locales[i])!=NULL)
+ {
+ break;
+ }
+ else if (i==predef_locales_count-1)
+ {
+ return 1;
+ error (EXIT_FAILURE, errno, _("cannot set UTF-8 locale"));
+ }
+ }
+ return 0;
+}
+
+extern bool
+check_utf_locale(void)
+{
+ char* locale = setlocale (LC_CTYPE , NULL);
+ if (locale == NULL)
+ {
+ return false;
+ }
+ else if (strcasestr(locale, "utf8") == NULL && strcasestr(locale, "utf-8") == NULL)
+ {
+ return false;
+ }
+ return true;
+}
+
+extern bool
+check_bom(FILE* fp, mb_file_t *mbf)
+{
+ int c;
+
+
+ c=fgetc(fp);
+
+ /*test BOM header of the first file */
+ mbf->bufcount=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

3536
coreutils-i18n.patch Normal file

File diff suppressed because it is too large Load Diff

9
coreutils-provides.inc Normal file
View File

@ -0,0 +1,9 @@
Provides: bundled(gnulib)
# make it possible to install the latest available Adobe Reader RPM for Linux
Provides: /bin/cat
Provides: /bin/chmod
Provides: /bin/echo
Provides: /bin/ln
Provides: /bin/rm
Provides: /bin/touch

120
coreutils-selinux.patch Normal file
View File

@ -0,0 +1,120 @@
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;

2263
coreutils.spec Normal file

File diff suppressed because it is too large Load Diff

BIN
rh_i18n_wip.tar.gz Normal file

Binary file not shown.

View File

@ -0,0 +1,12 @@
diff -urNp coreutils-5.97-orig/man/date.x coreutils-5.97/man/date.x
--- coreutils-5.97-orig/man/date.x 1999-11-02 15:07:36.000000000 +0100
+++ coreutils-5.97/man/date.x 2008-10-15 10:13:31.000000000 +0200
@@ -11,3 +11,8 @@ 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.

1
sources Normal file
View File

@ -0,0 +1 @@
SHA512 (coreutils-8.32.tar.xz) = 1c8f3584efd61b4b02e7ac5db8e103b63cfb2063432caaf1e64cb2dcc56d8c657d1133bbf10bd41468d6a1f31142e6caa81d16ae68fa3e6e84075c253613a145

105
supported_utils Normal file
View File

@ -0,0 +1,105 @@
%{_bindir}/arch
%{_bindir}/b2sum
%{_bindir}/basename
%{_bindir}/basenc
%{_bindir}/cat
%{_bindir}/chgrp
%{_bindir}/chmod
%{_bindir}/chown
%{_bindir}/cp
%{_bindir}/cut
%{_bindir}/date
%{_bindir}/dd
%{_bindir}/df
%{_bindir}/echo
%{_bindir}/env
%{_bindir}/false
%{_bindir}/link
%{_bindir}/ln
%{_bindir}/ls
%{_bindir}/mkdir
%{_bindir}/mknod
%{_bindir}/mv
%{_bindir}/nice
%{_bindir}/pwd
%{_bindir}/readlink
%{_bindir}/rm
%{_bindir}/rmdir
%{_bindir}/sleep
%{_bindir}/sort
%{_bindir}/stty
%{_bindir}/sync
%{_bindir}/mktemp
%{_bindir}/touch
%{_bindir}/true
%{_bindir}/uname
%{_bindir}/unlink
%{_bindir}/[
%{_bindir}/base32
%{_bindir}/base64
%{_bindir}/chcon
%{_bindir}/cksum
%{_bindir}/comm
%{_bindir}/csplit
%{_bindir}/dir
%{_bindir}/dircolors
%{_bindir}/dirname
%{_bindir}/du
%{_bindir}/expand
%{_bindir}/expr
%{_bindir}/factor
%{_bindir}/fmt
%{_bindir}/fold
%{_bindir}/groups
%{_bindir}/head
%{_bindir}/hostid
%{_bindir}/id
%{_bindir}/install
%{_bindir}/join
%{_bindir}/logname
%{_bindir}/md5sum
%{_bindir}/mkfifo
%{_bindir}/nl
%{_bindir}/nohup
%{_bindir}/nproc
%{_bindir}/numfmt
%{_bindir}/od
%{_bindir}/paste
%{_bindir}/pathchk
%{_bindir}/pinky
%{_bindir}/pr
%{_bindir}/printenv
%{_bindir}/printf
%{_bindir}/ptx
%{_bindir}/realpath
%{_bindir}/runcon
%{_bindir}/seq
%{_bindir}/sha1sum
%{_bindir}/sha224sum
%{_bindir}/sha256sum
%{_bindir}/sha384sum
%{_bindir}/sha512sum
%{_bindir}/shred
%{_bindir}/shuf
%{_bindir}/split
%{_bindir}/stat
%{_bindir}/stdbuf
%{_bindir}/sum
%{_bindir}/tac
%{_bindir}/tail
%{_bindir}/tee
%{_bindir}/test
%{_bindir}/timeout
%{_bindir}/tr
%{_bindir}/truncate
%{_bindir}/tsort
%{_bindir}/tty
%{_bindir}/unexpand
%{_bindir}/uniq
%{_bindir}/users
%{_bindir}/vdir
%{_bindir}/wc
%{_bindir}/who
%{_bindir}/whoami
%{_bindir}/yes
%{_sbindir}/chroot

View File

@ -0,0 +1,63 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Makefile of /CoreOS/coreutils/readlink-cannot-handle-recursive-symlink s
# Description: Test for readlink cannot handle recursive symlinks
# Author: Jan Scotka <jscotka@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2010 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# This program is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export TEST=/CoreOS/coreutils/readlink-cannot-handle-recursive-symlinks
export TESTVERSION=1.0
BUILT_FILES=
FILES=$(METADATA) runtest.sh Makefile PURPOSE
.PHONY: all install download clean
run: $(FILES) build
./runtest.sh
build: $(BUILT_FILES)
chmod a+x runtest.sh
clean:
rm -f *~ $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@echo "Owner: Jan Scotka <jscotka@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "Description: Test for readlink cannot handle recursive symlinks" >> $(METADATA)
@echo "Type: Sanity" >> $(METADATA)
@echo "TestTime: 5m" >> $(METADATA)
@echo "RunFor: coreutils" >> $(METADATA)
@echo "Requires: coreutils" >> $(METADATA)
@echo "Priority: Normal" >> $(METADATA)
@echo "License: GPLv2" >> $(METADATA)
@echo "Confidential: no" >> $(METADATA)
@echo "Destructive: no" >> $(METADATA)
rhts-lint $(METADATA)

View File

@ -0,0 +1,54 @@
PURPOSE of /CoreOS/coreutils/readlink-cannot-handle-recursive-symlinks
Description: Test for readlink cannot handle recursive symlinks
Author: Jan Scotka <jscotka@redhat.com>
Bug summary: readlink cannot handle recursive symlinks
Description:
Description of problem:
The readlink command fails with an error "Too many levels of symbolic links", even if there are only 2 levels.
The readlink command from RHEL 3 and RHEL 4 and from Fedora 11 all work fine.
Among other changes between RHEL 4 and RHEL 5, RHEL 5's coreutils added calls to cycle_check() in lib/canonicalize.c, but in upstream canonicalize.c (now in gnulib instead of coreutils), we see the comment:
/* Detect loops. We cannot use the cycle-check module here,
since it's actually possible to encounter the same symlink
more than once in a given traversal. However, encountering
the same symlink,NAME pair twice does indicate a loop. */
http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/canonicalize.c;h=4f348398fd69ae516396313d18ac294a4ca3dde3;hb=b653eda3ac4864de205419d9f41eec267cb89eeb#l262
The latest canonicalize.c uses seen_triple() instead of cycle_check().
Version-Release number of selected component (if applicable):
coreutils-5.97-19.el5
How reproducible:
every time
Steps to Reproduce:
1. Create a directory with a symlink to itself
mkdir /tmp/dir
cd /tmp/dir
ln -s ../dir dirlink
2. Run readlink using the 'dirlink' symlink recursively
readlink -v -f dirlink
readlink -v -f dirlink/dirlink
readlink -v -f dirlink/dirlink/dirlink
Actual results:
The first readlink command on just dirlink succeeds, but the 2nd and 3rd commands fail with
readlink: dirlink/dirlink: Too many levels of symbolic links
Expected results:
$ readlink -v -f dirlink
/tmp/dir
$ readlink -v -f dirlink/dirlink
/tmp/dir
$ readlink -v -f dirlink/dirlink/dirlink
/tmp/dir
Additional info:

View File

@ -0,0 +1,60 @@
#!/bin/bash
# vim: dict=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# runtest.sh of /CoreOS/coreutils/readlink-cannot-handle-recursive-symlinks
# Description: Test for readlink cannot handle recursive symlinks
# Author: Jan Scotka <jscotka@redhat.com>
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Copyright (c) 2010 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing
# to use, modify, copy, or redistribute it subject to the terms
# and conditions of the GNU General Public License version 2.
#
# This program is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Include rhts environment
. /usr/bin/rhts-environment.sh
. /usr/lib/beakerlib/beakerlib.sh
PACKAGE="coreutils"
rlJournalStart
rlPhaseStartSetup
rlAssertRpm $PACKAGE
rlRun "TmpDir=\`mktemp -d\`" 0 "Creating tmp directory"
rlRun "pushd $TmpDir"
rlRun "mkdir link" 0 "Creating test directory"
rlRun "cd link" 0 "cd to this dir"
rlRun "ln -s ../link link" 0 "creating symlink to ../link -> link"
rlPhaseEnd
rlPhaseStartTest
rlLog "Test of readlink up to 20 iteration"
export TMPVAR="link"
for foo in `seq 20`
do echo $TMPVAR
rlRun "readlink -v -f $TMPVAR" 0 "readlink of $TMPVAR"
TMPVAR="$TMPVAR/link"
done
rlPhaseEnd
rlPhaseStartCleanup
rlRun "popd"
rlRun "rm -r $TmpDir" 0 "Removing tmp directory"
rlPhaseEnd
rlJournalPrintText
rlJournalEnd

39
tests/test-basics Executable file
View File

@ -0,0 +1,39 @@
#!/bin/sh
# Checks that touch ls rm and foo work
# https://www.mankier.com/1/beakerlib#Examples
. /usr/share/beakerlib/beakerlib.sh
# Set the full test name
TEST="/examples/beakerlib/Sanity/phases"
# Package being tested
PACKAGE="coreutils"
rlJournalStart
# Setup phase: Prepare test directory
rlPhaseStartSetup
rlAssertRpm $PACKAGE
rlRun 'TmpDir=$(mktemp -d)' 0 'Creating tmp directory' # no-reboot
rlRun "pushd $TmpDir"
rlPhaseEnd
# Test phase: Testing touch, ls and rm commands
rlPhaseStartTest
rlRun "touch foo" 0 "Creating the foo test file"
rlAssertExists "foo"
rlRun "ls -l foo" 0 "Listing the foo test file"
rlRun "rm foo" 0 "Removing the foo test file"
rlAssertNotExists "foo"
rlRun "ls -l foo" 2 "Listing foo should now report an error"
rlPhaseEnd
# Cleanup phase: Remove test directory
rlPhaseStartCleanup
rlRun "popd"
rlRun "rm -r $TmpDir" 0 "Removing tmp directory"
rlPhaseEnd
rlJournalEnd
# Print the test report
rlJournalPrintText

9
tests/test_basics.yml Normal file
View File

@ -0,0 +1,9 @@
---
# This first play always runs on the local staging system
- hosts: localhost
tags:
- atomic
- classic
- container
roles:
- { role: standard-test-beakerlib, tests: [ test-basics, readlink-cannot-handle-recursive-symlinks ] }

2
tests/tests.yml Normal file
View File

@ -0,0 +1,2 @@
# Fedora Continuous Integration: https://fedoraproject.org/wiki/CI
- include: test_basics.yml

123
upstream-key.gpg Normal file
View File

@ -0,0 +1,123 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.6 (GNU/Linux)
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
Ke4=
=zRdO
-----END PGP PUBLIC KEY BLOCK-----