Age | Commit message (Collapse) | Author |
|
* src/chroot.c (is_root): A new helper function to
determine if the passed argument is the root directory
based on inode comparison.
(main): Use the new helper rather than comparing strings.
* tests/misc/chroot-fail.sh: Add cases for alternative root paths.
|
|
It's dangerous and confusing to leave root's supplemental
groups in place when specifying other users with --userspec.
In the edge case that that is desired one can explicitly
specify --groups.
Also we implicitly set the system defined supplemental groups
for a user. The existing mechanism where supplemental groups
needed to be explicitly specified is confusing and not general
when the lookup needs to be done within the chroot.
Also we extend the --groups syntax slightly to allow clearing
the set of supplementary groups using --groups=''.
* src/chroot.c (setgroups): On systems without supplemental groups,
clearing then is a noop and so should return success.
(main): Lookup the primary GID with getpwuid() when just a numeric
uid is specified, and also infer the USERNAME from this call,
needed when we're later looking up the supplemental groups for a user.
Support clearing supplemental groups, either implicitly for
unknown users, or explicitly when --groups='' is specified.
* tests/misc/chroot-credentials.sh: Various new test cases
* doc/coreutils.texi (chroot invocation): Adjust for the new behavior.
* NEWS: Mention the change in behavior.
|
|
This allows chroot to be used as a light weight tool
to change user identification for a command,
while not changing the current working directory.
It also makes `chroot / true` consistently succeed on
all platforms for non root users.
* src/chroot.c (main): If the same root is specified. i.e. '/'
then don't change the current working directory, and avoid the
overhead of the other redundant calls.
* tests/misc/chroot-fail.sh: Remove failure guard previously
needed on some systems. Also add an explicit case to ensure
we don't change directory.
* NEWS: Mention the change in behavior.
|
|
Linux with network namespaces contains entries in /proc/mounts like:
proc net:[4026532464] proc rw,nosuid,nodev,noexec,relatime 0 0
resulting in a failure to stat 'net:[...]', inducing a warning
and an exit with failure status.
* src/df.c (get_dev): Ignore all relative mount points.
* tests/df/skip-duplicates.sh: Add an entry to test relative dirs.
|
|
The symlink handling in commit v8.21-172-g33660b4 was incomplete
in the case where there were symlinks in the mount list itself.
For example, in the case where /dev/mapper/fedora-home was in the
mount list and that in turn was a symlink to /dev/dm-2, we have:
before> df --out=source /dev/mapper/fedora-home
devtmpfs
after > df --out=source /dev/mapper/fedora-home
/dev/mapper/fedora-home
* src/df.c (get_disk): Compare canonicalized device names from
the mount list. Note we still display the non canonicalized name,
even if longer, as we assume that is the most representative.
* tests/df/df-symlink.sh: This could theoretically fail on some systems
depending on the content of the mount list, but adjust to fail on any
system where symlinks are present in the mount list for the current dir.
|
|
* src/df.c (filter_mountlist): Remove the constraint that
a '/' needs to be in the device name for a mount entry to
be considered for deduplication. Virtual file systems also
have storage associated with them (like tmpfs for example),
and thus need to be deduplicated since they will be shown
in the default df output and subject to --total processing also.
* test/df/skip-duplicates.sh: Add a test to ensure we deduplicate
all entries, even for virtual file systems. Also avoid possible
length operations on many remote file systems in the initial
check of df operation. Also avoid the assumption that "/root"
is on the same file system as "/".
* NEWS: Mention the change in behavior.
|
|
* tests/ls/stat-vs-dirent.sh: This test lists all parent directories,
and would spuriously fail if any of those had a file name with a
leading space as the first entry. There is only ever a single space
between the right aligned inode number and the file name, so
process accordingly.
|
|
* src/shred.c (main): With the preceding change, shred -s-2 FILE
would write 64KB blocks forever -- or until disk full. This change
makes shred reject a negative size.
* tests/misc/shred-negative.sh: New file.
* tests/local.mk (all_tests): Add it.
|
|
* tests/dd/ascii.sh: Avoid unnecessary subshells. Catch dd's
exit code. Remove testing artifact. In the case of a comparison
failure, show the differences in octal format in addition to
"binary files differ". Simplify the creation of the 'in' file.
|
|
Problem reported by Don Baggett in <http:/bugs.gnu.org/17422>.
* NEWS:
* doc/coreutils.texi (dd invocation): Document this.
* src/dd.c (conversions): conv=ascii implies conv=unblock.
conv=ebcdic and conv=ibm imply conv=block.
(ascii_to_ebcdic, ebcdic_to_ascii): Correct to match
POSIX 1003.1-2013.
* tests/dd/ascii.sh: New file.
* tests/local.mk (all_tests): Add it.
|
|
* tests/chmod/c-option.sh: Use `compare /dev/null ... || fail=1`
rather than `test -s ... && fail=1`, so that the file contents
are output, thus improving diagnostics for failing tests.
* tests/cp/acl.sh: Likewise.
* tests/cp/cp-a-selinux.sh: Likewise.
* tests/cp/cp-mv-enotsup-xattr.sh: Likewise.
* tests/cp/reflink-perm.sh: Likewise.
* tests/dd/misc.sh: Likewise.
* tests/misc/env-null.sh: Likewise.
* tests/misc/env.sh: Likewise.
* tests/misc/nice.sh: Likewise.
* tests/misc/nohup.sh: Likewise.
* tests/misc/printenv.sh: Likewise.
* tests/misc/xattr.sh: Likewise.
* tests/mv/update.sh: Likewise.
* tests/rm/deep-2.sh: Likewise.
* tests/rm/read-only.sh: Likewise.
* tests/split/r-chunk.sh: Likewise.
* tests/tail-2/follow-stdin.sh: Likewise.
* tests/tail-2/inotify-race.sh: Likewise.
* tests/tail-2/wait.sh: Likewise.
* tests/touch/no-dereference.sh: Likewise.
* cfg.mk (sc_prohibit_test_empty:): New syntax-check.
* tests/cp/proc-zero-len.sh: Adjust to avoid false syntax-check failure.
* tests/cp/proc-zero-len.sh: Likewise.
* tests/mv/part-symlink.sh: Likewise.
* tests/tail-2/infloop-1.sh: Likewise.
|
|
* src/copy.c (copy_internal): Include the copy_attr() call for symlinks.
This should not dereference symlinks, since llistxattr() is used
in attr_copy_file() in libattr, and so should copy all but the filtered
extended attributes. Note we don't just move the copy_attr() call
before the set_owner() call, as that would break capabilities
for non symlinks.
* tests/cp/cp-mv-enotsup-xattr.sh: Add a test case.
* NEWS: Mention the bug fix.
Fixes http://bugs.gnu.org/16131
|
|
* init.cfg (require_smack_): New function.
* local.mk: Referenced new tests.
* tests/id/smack.sh: SMACK tests (new file).
* tests/mkdir/smack-no-root.sh: SMACK tests (new file).
* tests/mkdir/smack-root.sh: SMACK tests (new file).
|
|
* src/numfmt.c (setup_padding_buffer): Simplify the code by not
explicitly dealing with heap exhaustion.
(parse_format_string): Likewise. Handle multiple grouping
modifiers as does the standard printf. Handle the new leading
zero --format modifier.
(double_to_human): Use more defensive coding against overwriting
stack buffers. Honor the leading zeros width.
(usage): Mention the leading zero --format modifier.
(main): Allow --padding in combo with a --format (width),
as the number of leading zeros are useful independent of
the main field width.
* doc/coreutils.texi (numfmt invocation): Likewise.
* tests/misc/numfmt.pl: Add new test cases.
* NEWS: Mention the improvement.
|
|
This issue was identified by running the test suite with
http://code.google.com/p/address-sanitizer/
which is included in GCC 4.8 and enabled with -fsanitize=address
This was checked on Fedora 20 with GCC 4.8 as follows:
$ yum install libasan # http://bugzilla.redhat.com/991003
$ rm -f src/ptx.o
$ make check AM_CFLAGS='-fsanitize=address' SUBDIRS=. VERBOSE=yes
$ failure identified in tests/test-suite.log
To see this particular failure triggered with multiple files:
$ src/ptx <(echo a) <(echo a) 2>&1 | asan_symbolize.py -d
=================================================================
==32178==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x60200000e74f at pc 0x435442 bp 0x7fffe8a1b290 sp 0x7fffe8a1b288
READ of size 1 at 0x60200000e74f thread T0
#0 0x435441 in define_all_fields coreutils/src/ptx.c:1425
#1 0x7fa206d31d64 in __libc_start_main ??:?
#2 0x42f77c in _start ??:?
0x60200000e74f is located 1 bytes to the left of 3-byte region
[0x60200000e750,0x60200000e753) allocated by thread T0 here:
#0 0x421809 in realloc ??:?
#1 0x439b4e in fread_file coreutils/lib/read-file.c:97
Shadow bytes around the buggy address:
0x0c047fff9c90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9ca0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9cb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9cc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9cd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fd fd
=>0x0c047fff9ce0: fa fa 03 fa fa fa fd fd fa[fa]03 fa fa fa 00 00
0x0c047fff9cf0: fa fa 04 fa fa fa 04 fa fa fa fd fa fa fa fd fa
0x0c047fff9d00: fa fa 00 fa fa fa fd fa fa fa 00 fa fa fa 00 fa
0x0c047fff9d10: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x0c047fff9d20: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x0c047fff9d30: fa fa fd fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
ASan internal: fe
==32178==ABORTING
The initial report and high level analysis were from Jim Meyering...
"The underlying problem is that swallow_file_in_memory()
is setting the contents of the global text_buffer for the first file,
then updating it (clobbering old value) for the second file.
Yet, some pointers to the initial buffer have been squirreled away
and later, one of them (keyafter) is presumed to point into
the new "text_buffer", which it does not. The subsequent
SKIP_WHITE_BACKWARDS use backs up "cursor" and goes out of bounds."
* src/ptx.c (text_buffers): Maintain references for the limits of each
buffer corresponding to each file, rather than just the last processed.
(struct OCCURS): Add a member to map back to the corresponding file.
Note normally this could be computed from the "reference" member
rather than needing the extra storage, however this is not possible
when in --references mode.
(find_occurs_in_text): Reference the array rather than a single entry.
(define_all_fields): Likewise. Also avoid computing the file index
since this is now stored directly.
(main): Update text_buffers[] array rather than a single text_buffer.
* tests/misc/ptx-overrun.sh: Even though this issue is already triggered
with AddressSanitizer, add a new case to demonstrate the whitespace
trimming issue, and to trigger without AddressSanitizer.
Fixes https://bugs.gnu.org/16171
|
|
Since the recent commit v8.22-68-g08783f1, ls coloring
is now dependent on the COLORTERM environment variable.
* tests/envvar-check: Unset COLORTERM from test environment.
* tests/ls/color-dtype-dir.sh: Ensure coloring is used.
* tests/misc/ls-misc.pl: Likewise.
Prompted by the continuous integration build failure at:
http://hydra.nixos.org/build/10397646
|
|
--colors controls whether to output colors depending on
whether we're connected to a terminal or not, while this
change gives control over which terminals we output colors to.
* NEWS: Mention the change in behavior.
* src/ls.c (known_term_type): A new function to search the static
list from dircolors.h
(parse_ls_colors): Honor the TERM when both LS_COLORS and COLORTERM
are non empty.
* tests/ls/color-term.sh: A new test.
* tests/local.mk: Reference the new test.
Fixes http://bugs.gnu.org/15992
|
|
* tests/dd/sparse.sh: When testing that a hole is created,
use an existing sparse destination file, so that we're
not write extending the file size, and thus avoiding
speculative preallocation which can result in smaller
holes than requested.
Workaround suggested by Brian Foster
|
|
* tests/misc/numfmt.pl: Fix comment misspelling.
* src/cut.c: Likewise.
* src/tsort.c (detect_loop): Replace an fprintf() with error().
|
|
* doc/coreutils.texi (shred invocation): Mention some reasons
why clearing slack space might be useful.
* src/shred.c (do_wipefd): Add initial writes for each pass
for small regular files in case the storage for those is
in the inode, and thus a larger write up to a block size would
bypass that. Move the direct I/O control to...
(dopass): ... here so we can avoid enabling it for these small
initial writes. It's better to retry direct I/O for each pass
anyway to handle the case where direct I/O is disabled for only
the last portion of a file when the size is not a multiple of
the block size. Note we don't avoid the sync for the initial
write as it will be small but more importantly could be on a
different part of the disk and so worth doing independently
to ensure the write is not discarded.
* tests/misc/shred-exact.sh: Check some more direct I/O cases.
* NEWS: Mention the improvements.
The inode storage issue was mentioned by Paul Eggert.
|
|
* src/shred.c (do_wipefd): Don't increase the size written
for an empty file up to a full block. Also increase the size
to OFF_T_MAX in the edge case where we do overflow.
* NEWS: Mention the shred improvements from recent changes.
* tests/misc/shred-passes.sh: Adjust as we no longer
write a BLKSIZE of data for empty files.
|
|
* src/head.c (elide_tail_bytes_file): Fix typo in lseek invocation.
* tests/misc/head-c.sh: Add test for this bug.
* NEWS: Document this.
|
|
* src/copy.c (overwrite_ok): Fix the gettext calls so
that the second string is tagged for translation.
Display the correct "replace ..." prompt when in move_mode.
* tests/mv/i-3.sh: Display the output on failure to ease debugging.
|
|
* src/ptx.c (main): Add a 'break' after the --format handling case.
Otherwise it would fall through into the usage case.
* tests/misc/ptx.pl: Add test cases for --format=tex and --format=roff.
* NEWS (Bug fixes): Mention the fix.
Bug introduced in 1999-04-04 commit, SH-UTILS-1_16f-269-gd815c15.
Spotted by coverity (MISSING_BREAK).
|
|
* src/copy.c (overwrite_prompt): New arg X. All callers changed.
Use X to improve the quality of the prompt (Bug#17087).
* tests/mv/i-2.sh, tests/mv/i-3.sh: Change test to match new prompt.
|
|
For files with "special" bits set, we would stat the relative
file name in the wrong directory, giving an erroneous ENOENT diagnostic.
This issue was introduced with commit v5.92-653-gc1994c1
which changed fts to not change directory on traversal.
* src/chmod.c (mode_changed): Use fts->fts_cwd_fd with fstatat rather
than stat. All callers changed.
* tests/chmod/c-option.sh: Add a test case.
* NEWS: Mention the fix.
Fixes http://bugs.gnu.org/17035
|
|
Prior to this change, "ln -sr '' F" would segfault, attempting
to read path2[1] in relpath.c's path_common_prefix function.
This problem arises whenever canonicalize_filename_mode returns
NULL.
* src/ln.c (convert_abs_rel): Call relpath only when
both canonicalize_filename_mode calls return non-NULL.
* tests/ln/relative.sh: Add a test to trigger this failure.
* THANKS.in: List reporter's name/address.
* NEWS (Bug fixes): Mention it.
Reported by Erik Bernstein in 739752@bugs.debian.org.
Fixes http://bugs.gnu.org/17010.
|
|
- Support arbitrary numbers in --groups, consistent with
what is already done for --userspec
- Avoid look-ups entirely for --groups items with a leading '+'
- Support names that are actually numbers in --groups
- Ignore an empty --groups="" option for consistency with --userspec
- Look up both inside and outside the chroot with inside taking
precedence. The look-up outside may load required libraries
to complete the look-up inside the chroot. This can happen for
example with a 32 bit chroot on a 64 bit system, where the
32 bit NSS plugins within the chroot fail to load.
* src/chroot.c (parse_additional_groups): A new function refactored
from set_addition_groups(), to just do the parsing. The actual
setgroups() call is separated out for calling from the chroot later.
(main): Call parse_user_spec() and parse_additional_groups()
both outside and inside the chroot for the reasons outlined above.
* tests/misc/chroot-credentials.sh: Ensure arbitrary numeric IDs
can be specified without causing look-up errors.
* NEWS: Mention the improvements.
* THANKS.in: Add Norihiro Kamae who initially reported the issue
with a proposed patch.
Also thanks to Dmitry V. Levin for his diagnosis and sample patch.
|
|
On most shells `:>file || framework_failure_` will not evaluate
the framework_failure_ even if there was an error writing the file.
shells which do evaluate the failure are ksh 93u+ and bash 4.2,
while shells wich don't include bash 4.3, solaris, freebsd, dash.
Furthermore this construct is problematic on Solaris 10 sh,
which will try to optimize away a `:' command in a loop
after the first iteration, even if it is redirected.
* tests/cp/link-deref.sh: Remove the leading colon on redirections.
* tests/cp/reflink-perm.sh: Likewise.
* tests/id/zero.sh: Likewise.
* tests/install/install-C.sh: Likewise.
* tests/misc/env.sh: Likewise.
* tests/misc/md5sum-bsd.sh: Likewise.
* tests/misc/runcon-no-reorder.sh: Likewise.
* tests/mv/partition-perm.sh: Likewise.
* tests/rm/r-root.sh: Likewise.
* tests/split/l-chunk.sh: Likewise.
* tests/split/line-bytes.sh: Likewise.
* tests/tail-2/inotify-rotate.sh: Likewise.
* tests/tail-2/retry.sh: Likewise.
* tests/tail-2/symlink.sh: Likewise.
* tests/tail-2/wait.sh: Likewise.
* tests/touch/read-only.sh: Likewise.
+ cfg.mk (sc_prohibit_colon_redirection): A new syntax check
to avoid further instances of this creeping in.
|
|
* tests/misc/nohup.sh: When running tests without a controlling tty,
an exec failure is triggered in a subshell, which causes POSIX
shells to immediately exit the subshell. This was brought
to notice by the newly conforming bash 4.3.
Fixes http:/bugs.gnu.org/16940
|
|
* NEWS: Mention the fix.
* gnulib: Update to incorporate the fix.
This is the only change in this gnulib update.
* tests/misc/date.pl: Add a test for this case.
Fixes http://bugs.gnu.org/16872
|
|
Problem reported by valiant xiao in <http://bugs.gnu.org/16855>.
* NEWS: Document this.
* src/shuf.c (main): With -r, report an error if the input is empty.
* tests/misc/shuf.sh: Test for the bug.
|
|
* src/copy.c (copy_reg): If linkat() is available it doesn't
matter about the gnulib emulation provided, and thus the
LINK_FOLLOWS_SYMLINKS should not have significance here.
This was noticed on FreeBSD and the consequence is that
cp --link will create hardlinks to symlinks there, rather
than emulating with symlinks to symlinks.
* tests/cp/link-deref.sh: Adjust the checks to cater
for all cases where hardlinks to symlinks are supported.
|
|
If we can't output more data, we should immediately
diagnose the issue and exit rather than consuming all
of input (in some cases).
* src/tail.c (xwrite_stdout): Also diagnose the case where
only some data is written. Also clearerr() to avoid the
redundant less specific error from atexit (close_stdout);
* src/head.c (xwrite_stdout): Copy this new function from tail,
and use it to write all output.
* tests/misc/head-write-error.sh: A new test to ensure we
exit immediately on write error.
* tests/local.mk: Reference the new test.
|
|
* src/head.c (elide_tail_lines_pipe): Just output all input in
this case to avoid the issue and also avoid redundant '\n' processing.
(elide_tail_lines_seekable): Likewise.
* tests/misc/head-elide-tail.pl: Add tests for no '\n' at EOF.
* NEWS: Mention the fix.
Fixes http://bugs.gnu.org/16329
|
|
* src/od.c (main): Handle the new --endian option,
taking "little" and "big" as parameters.
(usage): Describe the new option.
(PRINT_FIELDS): Adjust to swap bytes if required.
* tests/misc/od-endian.sh: A new test to verify
the byte swapping operations for hex (ints) and floats
for all sizes between 1 and 16 inclusive.
* test/local.mk: Reference the new test.
* doc/coreutils.texi (od invocation): Describe the new option.
* NEWS: Mention the new feature.
|
|
* tests/chown/separator.sh: skip test if the user's group has
multiple entries.
Fixes http://bugs.gnu.org/16532
|
|
* src/ln.c (errno_nonexisting): A new function to determine if
the errno implies that a file doesn't or can't (currently) exist.
(target_directory_operand): Use the new function to expand the
set of errors we handle.
* tests/ln/sf-1.sh: Add test cases for the newly handled errors.
* THANKS.in: Mention the reporter.
* NEWS: Mention the bug fix.
|
|
* tests/cp/no-ctx.sh: Since the test diagnoses whether the
intercepted lgetfilecon() calls are actually called or not,
restrict the test to systems where that occurs.
The test cases are minimal on non SELinux systems and should
be well covered by other tests.
Reported-by: Bernhard Voelker
|
|
* src/selinux.c (restorecon_private): On ArchLinux the
`fakeroot cp -a file1 file2` command segfaulted due
to getfscreatecon() returning a NULL context.
So map this to the sometimes ignored ENODATA error,
rather than crashing.
* tests/cp/no-ctx.sh: Add a new test case.
* tests/local.mk: Reference the new test.
* NEWS: Mention the fix.
Fixes http://bugs.gnu.org/16335
|
|
* init.cfg (gcc_shared_): A new function refactored from tests.
(require_gcc_shared_): Adjust to call gcc_shared_() to build the
test library, and remove that library before the function returns.
* tests/cp/nfs-removal-race.sh: Call the new gcc_shared_().
* tests/df/no-mtab-status.sh: Likewise.
* tests/df/skip-duplicates.sh: Likewise.
* tests/ls/getxattr-speedup.sh: Likewise.
* tests/rm/r-root.sh: Likewise.
|
|
* src/copy.c (copy_internal): Use the global process context
to set the context of existing directories before they're populated.
This is more consistent with the new directory case, and fixes
a bug for existing directories where we erroneously set the
context to the last copied descendent, rather than to that of
the source directory itself.
* tests/cp/cp-a-selinux.sh: Add a test for this case.
* NEWS: Mention the fix.
* THANKS.in: Add reporter Michal Trunecka.
|
|
On emulated aarch64 systems like in the qemu-based OpenBuildService
of openSUSE, cp fails to copy /proc/cpuinfo because the inode number
changes between the initial stat() call and copying the file:
$ cp /proc/cpuinfo exp
cp: skipping file '/proc/cpuinfo', as it was \
replaced while being copied
* tests/cp/proc-zero-len.sh: When cp fails, check on the above
error message to skip the test.
|
|
Run "make update-copyright", but then also run this,
perl -pi -e 's/2\d\d\d-//' tests/sample-test
to make that one script use the single most recent year number.
|
|
* gnulib: Update to latest.
* bootstrap: Update from gnulib.
* tests/init.sh: Likewise.
|
|
* test/dd/no-allocate.sh: Use 'wait' to ensure we don't have
multiple writers to the fifo, which was seen to trigger
a very hard to reproduce deadlock with make -j20 on solaris.
Also avoid writing to the fifo with the shell; instead using dd.
(check_dd_seek_alloc): A new function refactored from the various
cases, which are now constructed from function parameters.
|
|
* tests/cp/link-deref.sh: On systems were cp can't determine if
gnulib linkat() emulation might create a symlink instead of a hardlink
to a symlink, copy.c will create a symlink to the symlink so that
it has more control over its metadata. Also even if the system
supports this operation, the particular file system under test may not.
So avoid the hardlinked symlink verification in these cases.
This fixes a false failure on aix, solaris and freebsd.
|
|
* tests/df/total-unprocessed.sh: Skip the test when we can't
determine the file system type as the exclusion filter is not
applied in that case. "lofs" being ignored is effectively
an unknown file system type.
|
|
* tests/cp/sparse-fiemap.sh: Newer versions of filefrag output
more fields, in different orders, so handle that to avoid warnings.
|
|
* tests/readlink/multi.sh: Ensure there is a trailing delimeter
or xargs may (on AIX 7 at least) suppress the last argument.
|