mirror of
https://git.savannah.gnu.org/git/coreutils.git
synced 2025-09-10 07:59:52 +02:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f386722dc0 | ||
|
|
d81094dc7b | ||
|
|
cf91b9d62c | ||
|
|
daa1e4f557 | ||
|
|
854c90ecc0 | ||
|
|
cc95246ee2 | ||
|
|
ae4dace2ec | ||
|
|
09ded7049b | ||
|
|
ffd62ab92c | ||
|
|
6f91c2eac3 | ||
|
|
ce630dfc7e | ||
|
|
f6c21f6d3a | ||
|
|
db28af406f | ||
|
|
5891d28ede | ||
|
|
17c31a73f1 | ||
|
|
5e170ff0b8 | ||
|
|
7ad749886c | ||
|
|
a9bd274616 | ||
|
|
a4525de1ef | ||
|
|
9c5e542fd1 | ||
|
|
6272817de0 | ||
|
|
093a8b4bfa | ||
|
|
55456b95d8 | ||
|
|
76f2fb6271 | ||
|
|
eeabb11eb6 | ||
|
|
bdda9adb38 |
@@ -1 +1 @@
|
||||
9.1
|
||||
9.2
|
||||
|
||||
50
NEWS
50
NEWS
@@ -1,5 +1,55 @@
|
||||
GNU coreutils NEWS -*- outline -*-
|
||||
|
||||
* Noteworthy changes in release 9.3 (2023-04-18) [stable]
|
||||
|
||||
** Bug fixes
|
||||
|
||||
cp --reflink=auto (the default), mv, and install
|
||||
will again fall back to a standard copy in more cases.
|
||||
Previously copies could fail with permission errors on
|
||||
more restricted systems like android or containers etc.
|
||||
[bug introduced in coreutils-9.2]
|
||||
|
||||
cp --recursive --backup will again operate correctly.
|
||||
Previousy it may have issued "File exists" errors when
|
||||
it failed to appropriately rename files being replaced.
|
||||
[bug introduced in coreutils-9.2]
|
||||
|
||||
date --file and dircolors will now diagnose a failure to read a file.
|
||||
Previously they would have silently ignored the failure.
|
||||
[This bug was present in "the beginning".]
|
||||
|
||||
md5sum --check again correctly prints the status of each file checked.
|
||||
Previously the status for files was printed as 'OK' once any file had passed.
|
||||
This also applies to cksum, sha*sum, and b2sum.
|
||||
[bug introduced in coreutils-9.2]
|
||||
|
||||
wc will now diagnose if any total counts have overflowed.
|
||||
[This bug was present in "the beginning".]
|
||||
|
||||
`wc -c` will again correctly update the read offset of inputs.
|
||||
Previously it deduced the size of inputs while leaving the offset unchanged.
|
||||
[bug introduced in coreutils-8.27]
|
||||
|
||||
Coreutils programs no longer fail for timestamps past the year 2038
|
||||
on obsolete configurations with 32-bit signed time_t, because the
|
||||
build procedure now rejects these configurations.
|
||||
[This bug was present in "the beginning".]
|
||||
|
||||
** Changes in behavior
|
||||
|
||||
'cp -n' and 'mv -n' now issue an error diagnostic if skipping a file,
|
||||
to correspond with -n inducing a nonzero exit status as of coreutils 9.2.
|
||||
Similarly 'cp -v' and 'mv -v' will output a message for each file skipped
|
||||
due to -n, -i, or -u.
|
||||
|
||||
** New features
|
||||
|
||||
cp and mv now support --update=none to always skip existing files
|
||||
in the destination, while not affecting the exit status.
|
||||
This is equivalent to the --no-clobber behavior from before v9.2.
|
||||
|
||||
|
||||
* Noteworthy changes in release 9.2 (2023-03-20) [stable]
|
||||
|
||||
** Bug fixes
|
||||
|
||||
@@ -54,13 +54,13 @@ all mention of "[$(EXEEXT)" from src/Makefile.
|
||||
32 bit time_t build failures
|
||||
------------------------
|
||||
|
||||
On systems where it's determined that 64 bit time_t is supported
|
||||
(indicated by touch -t <some time after 2038>), but that coreutils
|
||||
would be built with a narrower time_t, the build will fail.
|
||||
This can be allowed by passing TIME_T_32_BIT_OK=yes to configure,
|
||||
or avoided by enabling 64 bit builds. For example GCC on AIX defaults
|
||||
to 32 bit, and to enable the 64 bit ABI one can use:
|
||||
./configure CFLAGS=-maix64 LDFLAGs=-maix64 AR='ar -X64'
|
||||
Although 32-bit builds fail if that forces time_t to be 32 bits, this
|
||||
can be fixed by using 64-bit builds. For example, on AIX where GCC
|
||||
defaults to 32 bits, one can use "./configure CC='gcc -maix64' AR='ar
|
||||
-X64'"; similarly, on Solaris one can configure with CC='gcc -m64'.
|
||||
If all else fails one can configure with ac_year2038_required=no;
|
||||
however, this will mishandle timestamps after 2038, and please file
|
||||
bug reports for any such situations.
|
||||
|
||||
|
||||
*************************************************
|
||||
|
||||
@@ -318,7 +318,7 @@ gnulib_modules="
|
||||
xstrtol-error
|
||||
xstrtold
|
||||
xstrtoumax
|
||||
year2038
|
||||
year2038-required
|
||||
yesno
|
||||
"
|
||||
|
||||
|
||||
4
cfg.mk
4
cfg.mk
@@ -49,7 +49,7 @@ export VERBOSE = yes
|
||||
# 4914152 9e
|
||||
export XZ_OPT = -8e
|
||||
|
||||
old_NEWS_hash = ffba6793067438bae569f42acb4c5ab9
|
||||
old_NEWS_hash = 72a8f8283d3c9daef72e06be5bb52734
|
||||
|
||||
# Add an exemption for sc_makefile_at_at_check.
|
||||
_makefile_at_at_check_exceptions = ' && !/^cu_install_prog/ && !/dynamic-dep/'
|
||||
@@ -844,7 +844,7 @@ exclude_file_name_regexp--sc_trailing_blank = \
|
||||
exclude_file_name_regexp--sc_system_h_headers = \
|
||||
^src/((die|system|copy|chown-core|find-mount-point)\.h|make-prime-list\.c)$$
|
||||
|
||||
_src = (crctab|false|lbracket|ls-(dir|ls|vdir)|tac-pipe|uname-(arch|uname))
|
||||
_src = (false|lbracket|ls-(dir|ls|vdir)|tac-pipe|uname-(arch|uname))
|
||||
_gl_src = (xdecto.max|cl-strtold)
|
||||
exclude_file_name_regexp--sc_require_config_h_first = \
|
||||
(^lib/buffer-lcm\.c|gl/lib/$(_gl_src)\.c|src/$(_src)\.c)$$
|
||||
|
||||
@@ -9236,9 +9236,9 @@ results in an error message on systems that do not support symbolic links.
|
||||
@optNoTargetDirectory
|
||||
|
||||
@item -u
|
||||
@itemx --update
|
||||
@itemx --update[=@var{which}]
|
||||
@opindex -u
|
||||
@opindex --update
|
||||
@opindex --update[=@var{which}]
|
||||
@cindex newer files, copying only
|
||||
Do not copy a non-directory that has an existing destination with the
|
||||
same or newer modification timestamp; instead, silently skip the file
|
||||
@@ -9254,6 +9254,26 @@ for example), that will take precedence; consequently, depending on the
|
||||
order that files are processed from the source, newer files in the destination
|
||||
may be replaced, to mirror hard links in the source.
|
||||
|
||||
@macro whichUpdate
|
||||
@var{which} gives more control over which existing files in the
|
||||
destination are replaced, and its value can be one of the following:
|
||||
|
||||
@table @samp
|
||||
@item all
|
||||
This is the default operation when an @option{--update} option is not specified,
|
||||
and results in all existing files in the destination being replaced.
|
||||
|
||||
@item none
|
||||
This is similar to the @option{--no-clobber} option, in that no files in the
|
||||
destination are replaced, but also skipping a file does not induce a failure.
|
||||
|
||||
@item older
|
||||
This is the default operation when @option{--update} is specified, and results
|
||||
in files being replaced if they're older than the corresponding source file.
|
||||
@end table
|
||||
@end macro
|
||||
@whichUpdate
|
||||
|
||||
@item -v
|
||||
@itemx --verbose
|
||||
@opindex -v
|
||||
@@ -10165,6 +10185,8 @@ of its permissions, and fail if the response is not affirmative.
|
||||
Do not overwrite an existing file; silently fail instead.
|
||||
@mvOptsIfn
|
||||
This option is mutually exclusive with @option{-b} or @option{--backup} option.
|
||||
See also the @option{--update=none} option which will
|
||||
skip existing files but not fail.
|
||||
|
||||
@item --no-copy
|
||||
@opindex --no-copy
|
||||
@@ -10188,6 +10210,8 @@ same source and destination.
|
||||
This option is ignored if the @option{-n} or @option{--no-clobber}
|
||||
option is also specified.
|
||||
|
||||
@whichUpdate
|
||||
|
||||
@item -v
|
||||
@itemx --verbose
|
||||
@opindex -v
|
||||
|
||||
2
gnulib
2
gnulib
Submodule gnulib updated: f17d397771...4b60490554
@@ -116,8 +116,9 @@ main (void)
|
||||
}
|
||||
}
|
||||
|
||||
printf ("#include <stdint.h>\n\n");
|
||||
printf ("uint_fast32_t const crctab[8][256] = {\n");
|
||||
printf ("#include <config.h>\n");
|
||||
printf ("#include <stdint.h>\n");
|
||||
printf ("\nuint_fast32_t const crctab[8][256] = {\n");
|
||||
for (int y = 0; y < 8; y++)
|
||||
{
|
||||
printf ("{\n 0x%08x", crctab[y][0]);
|
||||
|
||||
106
src/copy.c
106
src/copy.c
@@ -146,6 +146,7 @@ enum copy_debug_val
|
||||
COPY_DEBUG_NO,
|
||||
COPY_DEBUG_YES,
|
||||
COPY_DEBUG_EXTERNAL,
|
||||
COPY_DEBUG_EXTERNAL_INTERNAL,
|
||||
COPY_DEBUG_AVOIDED,
|
||||
COPY_DEBUG_UNSUPPORTED,
|
||||
};
|
||||
@@ -179,6 +180,7 @@ copy_debug_sparse_string (enum copy_debug_val debug_val)
|
||||
case COPY_DEBUG_NO: return "no";
|
||||
case COPY_DEBUG_YES: return "zeros";
|
||||
case COPY_DEBUG_EXTERNAL: return "SEEK_HOLE";
|
||||
case COPY_DEBUG_EXTERNAL_INTERNAL: return "SEEK_HOLE + zeros";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
@@ -278,15 +280,28 @@ create_hole (int fd, char const *name, bool punch_holes, off_t size)
|
||||
}
|
||||
|
||||
|
||||
/* Whether the errno from FICLONE, or copy_file_range
|
||||
indicates operation is not supported for this file or file system. */
|
||||
/* Whether an errno value ERR, set by FICLONE or copy_file_range,
|
||||
indicates that the copying operation has terminally failed, even
|
||||
though it was invoked correctly (so that, e.g, EBADF cannot occur)
|
||||
and even though !is_CLONENOTSUP (ERR). */
|
||||
|
||||
static bool
|
||||
is_terminal_error (int err)
|
||||
{
|
||||
return err == EIO || err == ENOMEM || err == ENOSPC || err == EDQUOT;
|
||||
}
|
||||
|
||||
/* Similarly, whether ERR indicates that the copying operation is not
|
||||
supported or allowed for this file or process, even though the
|
||||
operation was invoked correctly. */
|
||||
|
||||
static bool
|
||||
is_CLONENOTSUP (int err)
|
||||
{
|
||||
return err == ENOSYS || is_ENOTSUP (err)
|
||||
return err == ENOSYS || err == ENOTTY || is_ENOTSUP (err)
|
||||
|| err == EINVAL || err == EBADF
|
||||
|| err == EXDEV || err == ETXTBSY;
|
||||
|| err == EXDEV || err == ETXTBSY
|
||||
|| err == EPERM || err == EACCES;
|
||||
}
|
||||
|
||||
|
||||
@@ -312,6 +327,8 @@ sparse_copy (int src_fd, int dest_fd, char **abuf, size_t buf_size,
|
||||
|
||||
if (copy_debug.sparse_detection == COPY_DEBUG_UNKNOWN)
|
||||
copy_debug.sparse_detection = hole_size ? COPY_DEBUG_YES : COPY_DEBUG_NO;
|
||||
else if (hole_size && copy_debug.sparse_detection == COPY_DEBUG_EXTERNAL)
|
||||
copy_debug.sparse_detection = COPY_DEBUG_EXTERNAL_INTERNAL;
|
||||
|
||||
/* If not looking for holes, use copy_file_range if functional,
|
||||
but don't use if reflink disallowed as that may be implicit. */
|
||||
@@ -339,20 +356,18 @@ sparse_copy (int src_fd, int dest_fd, char **abuf, size_t buf_size,
|
||||
{
|
||||
copy_debug.offload = COPY_DEBUG_UNSUPPORTED;
|
||||
|
||||
if (is_CLONENOTSUP (errno))
|
||||
break;
|
||||
|
||||
/* copy_file_range might not be enabled in seccomp filters,
|
||||
so retry with a standard copy. EPERM can also occur
|
||||
for immutable files, but that would only be in the edge case
|
||||
where the file is made immutable after creating/truncating,
|
||||
/* Consider operation unsupported only if no data copied.
|
||||
For example, EPERM could occur if copy_file_range not enabled
|
||||
in seccomp filters, so retry with a standard copy. EPERM can
|
||||
also occur for immutable files, but that would only be in the
|
||||
edge case where the file is made immutable after creating,
|
||||
in which case the (more accurate) error is still shown. */
|
||||
if (errno == EPERM && *total_n_read == 0)
|
||||
if (*total_n_read == 0 && is_CLONENOTSUP (errno))
|
||||
break;
|
||||
|
||||
/* ENOENT was seen sometimes across CIFS shares, resulting in
|
||||
no data being copied, but subsequent standard copies succeed. */
|
||||
if (errno == ENOENT && *total_n_read == 0)
|
||||
if (*total_n_read == 0 && errno == ENOENT)
|
||||
break;
|
||||
|
||||
if (errno == EINTR)
|
||||
@@ -1168,21 +1183,18 @@ fd_has_acl (int fd)
|
||||
Return FALSE if it's a terminal failure for this file. */
|
||||
|
||||
static bool
|
||||
handle_clone_fail (int dst_dirfd, char const* dst_relname,
|
||||
char const* src_name, char const* dst_name,
|
||||
handle_clone_fail (int dst_dirfd, char const *dst_relname,
|
||||
char const *src_name, char const *dst_name,
|
||||
int dest_desc, bool new_dst, enum Reflink_type reflink_mode)
|
||||
{
|
||||
/* If the clone operation is creating the destination,
|
||||
then don't try and cater for all non transient file system errors,
|
||||
and instead only cater for specific transient errors. */
|
||||
bool transient_failure;
|
||||
if (dest_desc < 0) /* currently for fclonefileat(). */
|
||||
transient_failure = errno == EIO || errno == ENOMEM
|
||||
|| errno == ENOSPC || errno == EDQUOT;
|
||||
else /* currently for FICLONE. */
|
||||
transient_failure = ! is_CLONENOTSUP (errno);
|
||||
/* When the clone operation fails, report failure only with errno values
|
||||
known to mean trouble when the clone is supported and called properly.
|
||||
Do not report failure merely because !is_CLONENOTSUP (errno),
|
||||
as systems may yield oddball errno values here with FICLONE,
|
||||
and is_CLONENOTSUP is not appropriate for fclonefileat. */
|
||||
bool report_failure = is_terminal_error (errno);
|
||||
|
||||
if (reflink_mode == REFLINK_ALWAYS || transient_failure)
|
||||
if (reflink_mode == REFLINK_ALWAYS || report_failure)
|
||||
error (0, errno, _("failed to clone %s from %s"),
|
||||
quoteaf_n (0, dst_name), quoteaf_n (1, src_name));
|
||||
|
||||
@@ -1190,14 +1202,14 @@ handle_clone_fail (int dst_dirfd, char const* dst_relname,
|
||||
but cloned no data. */
|
||||
if (new_dst /* currently not for fclonefileat(). */
|
||||
&& reflink_mode == REFLINK_ALWAYS
|
||||
&& ((! transient_failure) || lseek (dest_desc, 0, SEEK_END) == 0)
|
||||
&& ((! report_failure) || lseek (dest_desc, 0, SEEK_END) == 0)
|
||||
&& unlinkat (dst_dirfd, dst_relname, 0) != 0 && errno != ENOENT)
|
||||
error (0, errno, _("cannot remove %s"), quoteaf (dst_name));
|
||||
|
||||
if (! transient_failure)
|
||||
if (! report_failure)
|
||||
copy_debug.reflink = COPY_DEBUG_UNSUPPORTED;
|
||||
|
||||
if (reflink_mode == REFLINK_ALWAYS || transient_failure)
|
||||
if (reflink_mode == REFLINK_ALWAYS || report_failure)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -2053,6 +2065,7 @@ abandon_move (const struct cp_options *x,
|
||||
{
|
||||
assert (x->move_mode);
|
||||
return (x->interactive == I_ALWAYS_NO
|
||||
|| x->interactive == I_ALWAYS_SKIP
|
||||
|| ((x->interactive == I_ASK_USER
|
||||
|| (x->interactive == I_UNSPECIFIED
|
||||
&& x->stdin_tty
|
||||
@@ -2226,7 +2239,8 @@ copy_internal (char const *src_name, char const *dst_name,
|
||||
|
||||
if (rename_errno == 0
|
||||
? !x->last_file
|
||||
: rename_errno != EEXIST || x->interactive != I_ALWAYS_NO)
|
||||
: rename_errno != EEXIST
|
||||
|| (x->interactive != I_ALWAYS_NO && x->interactive != I_ALWAYS_SKIP))
|
||||
{
|
||||
char const *name = rename_errno == 0 ? dst_name : src_name;
|
||||
int dirfd = rename_errno == 0 ? dst_dirfd : AT_FDCWD;
|
||||
@@ -2280,7 +2294,9 @@ copy_internal (char const *src_name, char const *dst_name,
|
||||
|
||||
if (nonexistent_dst <= 0)
|
||||
{
|
||||
if (! (rename_errno == EEXIST && x->interactive == I_ALWAYS_NO))
|
||||
if (! (rename_errno == EEXIST
|
||||
&& (x->interactive == I_ALWAYS_NO
|
||||
|| x->interactive == I_ALWAYS_SKIP)))
|
||||
{
|
||||
/* Regular files can be created by writing through symbolic
|
||||
links, but other files cannot. So use stat on the
|
||||
@@ -2321,8 +2337,10 @@ copy_internal (char const *src_name, char const *dst_name,
|
||||
if (rename_errno == EEXIST)
|
||||
{
|
||||
bool return_now = false;
|
||||
bool return_val = true;
|
||||
bool skipped = false;
|
||||
|
||||
if (x->interactive != I_ALWAYS_NO
|
||||
if ((x->interactive != I_ALWAYS_NO && x->interactive != I_ALWAYS_SKIP)
|
||||
&& ! same_file_ok (src_name, &src_sb, dst_dirfd, drelname,
|
||||
&dst_sb, x, &return_now))
|
||||
{
|
||||
@@ -2373,7 +2391,8 @@ copy_internal (char const *src_name, char const *dst_name,
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
skipped = true;
|
||||
goto skip;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2392,21 +2411,38 @@ copy_internal (char const *src_name, char const *dst_name,
|
||||
doesn't end up removing the source file. */
|
||||
if (rename_succeeded)
|
||||
*rename_succeeded = true;
|
||||
return false;
|
||||
|
||||
skipped = true;
|
||||
return_val = x->interactive == I_ALWAYS_SKIP;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! S_ISDIR (src_mode)
|
||||
&& (x->interactive == I_ALWAYS_NO
|
||||
|| x->interactive == I_ALWAYS_SKIP
|
||||
|| (x->interactive == I_ASK_USER
|
||||
&& ! overwrite_ok (x, dst_name, dst_dirfd,
|
||||
dst_relname, &dst_sb))))
|
||||
return false;
|
||||
{
|
||||
skipped = true;
|
||||
return_val = x->interactive == I_ALWAYS_SKIP;
|
||||
}
|
||||
}
|
||||
|
||||
skip:
|
||||
if (skipped)
|
||||
{
|
||||
if (x->verbose)
|
||||
printf (_("skipped %s\n"), quoteaf (dst_name));
|
||||
else if (x->interactive == I_ALWAYS_NO)
|
||||
error (0, 0, _("not replacing %s"), quoteaf (dst_name));
|
||||
|
||||
return_now = true;
|
||||
}
|
||||
|
||||
if (return_now)
|
||||
return true;
|
||||
return return_val;
|
||||
|
||||
if (!S_ISDIR (dst_sb.st_mode))
|
||||
{
|
||||
|
||||
16
src/copy.h
16
src/copy.h
@@ -57,11 +57,25 @@ enum Reflink_type
|
||||
REFLINK_ALWAYS
|
||||
};
|
||||
|
||||
/* Control how existing destination files are updated. */
|
||||
enum Update_type
|
||||
{
|
||||
/* Always update.. */
|
||||
UPDATE_ALL,
|
||||
|
||||
/* Update if dest older. */
|
||||
UPDATE_OLDER,
|
||||
|
||||
/* Leave existing files. */
|
||||
UPDATE_NONE,
|
||||
};
|
||||
|
||||
/* This type is used to help mv (via copy.c) distinguish these cases. */
|
||||
enum Interactive
|
||||
{
|
||||
I_ALWAYS_YES = 1,
|
||||
I_ALWAYS_NO,
|
||||
I_ALWAYS_NO, /* Skip and fail. */
|
||||
I_ALWAYS_SKIP, /* Skip and ignore. */
|
||||
I_ASK_USER,
|
||||
I_UNSPECIFIED
|
||||
};
|
||||
|
||||
54
src/cp.c
54
src/cp.c
@@ -102,6 +102,16 @@ static enum Reflink_type const reflink_type[] =
|
||||
};
|
||||
ARGMATCH_VERIFY (reflink_type_string, reflink_type);
|
||||
|
||||
static char const *const update_type_string[] =
|
||||
{
|
||||
"all", "none", "older", NULL
|
||||
};
|
||||
static enum Update_type const update_type[] =
|
||||
{
|
||||
UPDATE_ALL, UPDATE_NONE, UPDATE_OLDER,
|
||||
};
|
||||
ARGMATCH_VERIFY (update_type_string, update_type);
|
||||
|
||||
static struct option const long_opts[] =
|
||||
{
|
||||
{"archive", no_argument, NULL, 'a'},
|
||||
@@ -129,7 +139,7 @@ static struct option const long_opts[] =
|
||||
{"suffix", required_argument, NULL, 'S'},
|
||||
{"symbolic-link", no_argument, NULL, 's'},
|
||||
{"target-directory", required_argument, NULL, 't'},
|
||||
{"update", no_argument, NULL, 'u'},
|
||||
{"update", optional_argument, NULL, 'u'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
{GETOPT_SELINUX_CONTEXT_OPTION_DECL},
|
||||
{GETOPT_HELP_OPTION_DECL},
|
||||
@@ -182,8 +192,10 @@ Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\
|
||||
-L, --dereference always follow symbolic links in SOURCE\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
-n, --no-clobber do not overwrite an existing file (overrides\n\
|
||||
a previous -i option)\n\
|
||||
-n, --no-clobber do not overwrite an existing file (overrides a\n\
|
||||
-u or previous -i option). See also --update\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
-P, --no-dereference never follow symbolic links in SOURCE\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
@@ -212,10 +224,14 @@ Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\
|
||||
-T, --no-target-directory treat DEST as a normal file\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
-u, --update copy only when the SOURCE file is newer\n\
|
||||
than the destination file or when the\n\
|
||||
destination file is missing\n\
|
||||
--update[=UPDATE] control which existing files are updated;\n\
|
||||
UPDATE={all,none,older(default)}. See below\n\
|
||||
-u equivalent to --update[=older]\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
-v, --verbose explain what is being done\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
-x, --one-file-system stay on this file system\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
@@ -242,6 +258,7 @@ selected by --sparse=auto. Specify --sparse=always to create a sparse DEST\n\
|
||||
file whenever the SOURCE file contains a long enough sequence of zero bytes.\n\
|
||||
Use --sparse=never to inhibit creation of sparse files.\n\
|
||||
"), stdout);
|
||||
emit_update_parameters_note ();
|
||||
fputs (_("\
|
||||
\n\
|
||||
When --reflink[=always] is specified, perform a lightweight copy, where the\n\
|
||||
@@ -1103,7 +1120,30 @@ main (int argc, char **argv)
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
x.update = true;
|
||||
if (optarg == NULL)
|
||||
x.update = true;
|
||||
else if (x.interactive != I_ALWAYS_NO) /* -n takes precedence. */
|
||||
{
|
||||
enum Update_type update_opt;
|
||||
update_opt = XARGMATCH ("--update", optarg,
|
||||
update_type_string, update_type);
|
||||
if (update_opt == UPDATE_ALL)
|
||||
{
|
||||
/* Default cp operation. */
|
||||
x.update = false;
|
||||
x.interactive = I_UNSPECIFIED;
|
||||
}
|
||||
else if (update_opt == UPDATE_NONE)
|
||||
{
|
||||
x.update = false;
|
||||
x.interactive = I_ALWAYS_SKIP;
|
||||
}
|
||||
else if (update_opt == UPDATE_OLDER)
|
||||
{
|
||||
x.update = true;
|
||||
x.interactive = I_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <config.h>
|
||||
#include <stdint.h>
|
||||
|
||||
uint_fast32_t const crctab[8][256] = {
|
||||
|
||||
@@ -368,7 +368,9 @@ batch_convert (char const *input_filename, char const *format,
|
||||
ssize_t line_length = getline (&line, &buflen, in_stream);
|
||||
if (line_length < 0)
|
||||
{
|
||||
/* FIXME: detect/handle error here. */
|
||||
if (ferror (in_stream))
|
||||
die (EXIT_FAILURE, errno, _("%s: read error"),
|
||||
quotef (input_filename));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1254,14 +1254,14 @@ digest_check (char const *checkfile_name)
|
||||
|
||||
if (!status_only)
|
||||
{
|
||||
if ( ! matched_checksums || ! quiet)
|
||||
if (! match || ! quiet)
|
||||
{
|
||||
if (needs_escape)
|
||||
putchar ('\\');
|
||||
print_filename (filename, needs_escape);
|
||||
}
|
||||
|
||||
if ( ! matched_checksums)
|
||||
if (! match)
|
||||
printf (": %s\n", _("FAILED"));
|
||||
else if (!quiet)
|
||||
printf (": %s\n", _("OK"));
|
||||
|
||||
@@ -298,6 +298,11 @@ dc_parse_stream (FILE *fp, char const *filename)
|
||||
{
|
||||
if (getline (&input_line, &input_line_size, fp) <= 0)
|
||||
{
|
||||
if (ferror (fp))
|
||||
{
|
||||
error (0, errno, _("%s: read error"), quotef (filename));
|
||||
ok = false;
|
||||
}
|
||||
free (input_line);
|
||||
break;
|
||||
}
|
||||
|
||||
49
src/mv.c
49
src/mv.c
@@ -24,6 +24,7 @@
|
||||
#include <selinux/label.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "argmatch.h"
|
||||
#include "backupfile.h"
|
||||
#include "copy.h"
|
||||
#include "cp-hash.h"
|
||||
@@ -53,6 +54,16 @@ enum
|
||||
STRIP_TRAILING_SLASHES_OPTION
|
||||
};
|
||||
|
||||
static char const *const update_type_string[] =
|
||||
{
|
||||
"all", "none", "older", NULL
|
||||
};
|
||||
static enum Update_type const update_type[] =
|
||||
{
|
||||
UPDATE_ALL, UPDATE_NONE, UPDATE_OLDER,
|
||||
};
|
||||
ARGMATCH_VERIFY (update_type_string, update_type);
|
||||
|
||||
static struct option const long_options[] =
|
||||
{
|
||||
{"backup", optional_argument, NULL, 'b'},
|
||||
@@ -66,7 +77,7 @@ static struct option const long_options[] =
|
||||
{"strip-trailing-slashes", no_argument, NULL, STRIP_TRAILING_SLASHES_OPTION},
|
||||
{"suffix", required_argument, NULL, 'S'},
|
||||
{"target-directory", required_argument, NULL, 't'},
|
||||
{"update", no_argument, NULL, 'u'},
|
||||
{"update", optional_argument, NULL, 'u'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
{GETOPT_HELP_OPTION_DECL},
|
||||
{GETOPT_VERSION_OPTION_DECL},
|
||||
@@ -277,15 +288,20 @@ If you specify more than one of -i, -f, -n, only the final one takes effect.\n\
|
||||
fputs (_("\
|
||||
-t, --target-directory=DIRECTORY move all SOURCE arguments into DIRECTORY\n\
|
||||
-T, --no-target-directory treat DEST as a normal file\n\
|
||||
-u, --update move only when the SOURCE file is newer\n\
|
||||
than the destination file or when the\n\
|
||||
destination file is missing\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
--update[=UPDATE] control which existing files are updated;\n\
|
||||
UPDATE={all,none,older(default)}. See below\n\
|
||||
-u equivalent to --update[=older]\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
-v, --verbose explain what is being done\n\
|
||||
-Z, --context set SELinux security context of destination\n\
|
||||
file to default type\n\
|
||||
"), stdout);
|
||||
fputs (HELP_OPTION_DESCRIPTION, stdout);
|
||||
fputs (VERSION_OPTION_DESCRIPTION, stdout);
|
||||
emit_update_parameters_note ();
|
||||
emit_backup_suffix_note ();
|
||||
emit_ancillary_info (PROGRAM_NAME);
|
||||
}
|
||||
@@ -358,7 +374,30 @@ main (int argc, char **argv)
|
||||
no_target_directory = true;
|
||||
break;
|
||||
case 'u':
|
||||
x.update = true;
|
||||
if (optarg == NULL)
|
||||
x.update = true;
|
||||
else if (x.interactive != I_ALWAYS_NO) /* -n takes precedence. */
|
||||
{
|
||||
enum Update_type update_opt;
|
||||
update_opt = XARGMATCH ("--update", optarg,
|
||||
update_type_string, update_type);
|
||||
if (update_opt == UPDATE_ALL)
|
||||
{
|
||||
/* Default mv operation. */
|
||||
x.update = false;
|
||||
x.interactive = I_UNSPECIFIED;
|
||||
}
|
||||
else if (update_opt == UPDATE_NONE)
|
||||
{
|
||||
x.update = false;
|
||||
x.interactive = I_ALWAYS_SKIP;
|
||||
}
|
||||
else if (update_opt == UPDATE_OLDER)
|
||||
{
|
||||
x.update = true;
|
||||
x.interactive = I_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
x.verbose = true;
|
||||
|
||||
15
src/system.h
15
src/system.h
@@ -608,6 +608,21 @@ Otherwise, units default to 1024 bytes (or 512 if POSIXLY_CORRECT is set).\n\
|
||||
"), program);
|
||||
}
|
||||
|
||||
static inline void
|
||||
emit_update_parameters_note (void)
|
||||
{
|
||||
fputs (_("\
|
||||
\n\
|
||||
UPDATE controls which existing files in the destination are replaced.\n\
|
||||
'all' is the default operation when an --update option is not specified,\n\
|
||||
and results in all existing files in the destination being replaced.\n\
|
||||
'none' is similar to the --no-clobber option, in that no files in the\n\
|
||||
destination are replaced, but also skipped files do not induce a failure.\n\
|
||||
'older' is the default operation when --update is specified, and results\n\
|
||||
in files being replaced if they're older than the corresponding source file.\n\
|
||||
"), stdout);
|
||||
}
|
||||
|
||||
static inline void
|
||||
emit_backup_suffix_note (void)
|
||||
{
|
||||
|
||||
56
src/wc.c
56
src/wc.c
@@ -78,6 +78,10 @@ static uintmax_t total_lines;
|
||||
static uintmax_t total_words;
|
||||
static uintmax_t total_chars;
|
||||
static uintmax_t total_bytes;
|
||||
static uintmax_t total_lines_overflow;
|
||||
static uintmax_t total_words_overflow;
|
||||
static uintmax_t total_chars_overflow;
|
||||
static uintmax_t total_bytes_overflow;
|
||||
static uintmax_t max_line_length;
|
||||
|
||||
/* Which counts to print. */
|
||||
@@ -446,7 +450,10 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, off_t current_pos)
|
||||
beyond the end of the file. As in the example above. */
|
||||
|
||||
bytes = end_pos < current_pos ? 0 : end_pos - current_pos;
|
||||
skip_read = true;
|
||||
if (bytes && 0 <= lseek (fd, bytes, SEEK_CUR))
|
||||
skip_read = true;
|
||||
else
|
||||
bytes = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -703,10 +710,16 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, off_t current_pos)
|
||||
|
||||
if (total_mode != total_only)
|
||||
write_counts (lines, words, chars, bytes, linelength, file_x);
|
||||
total_lines += lines;
|
||||
total_words += words;
|
||||
total_chars += chars;
|
||||
total_bytes += bytes;
|
||||
|
||||
if (INT_ADD_WRAPV (total_lines, lines, &total_lines))
|
||||
total_lines_overflow = true;
|
||||
if (INT_ADD_WRAPV (total_words, words, &total_words))
|
||||
total_words_overflow = true;
|
||||
if (INT_ADD_WRAPV (total_chars, chars, &total_chars))
|
||||
total_chars_overflow = true;
|
||||
if (INT_ADD_WRAPV (total_bytes, bytes, &total_bytes))
|
||||
total_bytes_overflow = true;
|
||||
|
||||
if (linelength > max_line_length)
|
||||
max_line_length = linelength;
|
||||
|
||||
@@ -1022,9 +1035,36 @@ main (int argc, char **argv)
|
||||
|
||||
if (total_mode != total_never
|
||||
&& (total_mode != total_auto || 1 < argv_iter_n_args (ai)))
|
||||
write_counts (total_lines, total_words, total_chars, total_bytes,
|
||||
max_line_length,
|
||||
total_mode != total_only ? _("total") : NULL);
|
||||
{
|
||||
if (total_lines_overflow)
|
||||
{
|
||||
total_lines = UINTMAX_MAX;
|
||||
error (0, EOVERFLOW, _("total lines"));
|
||||
ok = false;
|
||||
}
|
||||
if (total_words_overflow)
|
||||
{
|
||||
total_words = UINTMAX_MAX;
|
||||
error (0, EOVERFLOW, _("total words"));
|
||||
ok = false;
|
||||
}
|
||||
if (total_chars_overflow)
|
||||
{
|
||||
total_chars = UINTMAX_MAX;
|
||||
error (0, EOVERFLOW, _("total characters"));
|
||||
ok = false;
|
||||
}
|
||||
if (total_bytes_overflow)
|
||||
{
|
||||
total_bytes = UINTMAX_MAX;
|
||||
error (0, EOVERFLOW, _("total bytes"));
|
||||
ok = false;
|
||||
}
|
||||
|
||||
write_counts (total_lines, total_words, total_chars, total_bytes,
|
||||
max_line_length,
|
||||
total_mode != total_only ? _("total") : NULL);
|
||||
}
|
||||
|
||||
argv_iter_free (ai);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# Ensure that cp -b doesn't back up directories.
|
||||
# Ensure that cp -b handles directories appropriately
|
||||
|
||||
# Copyright (C) 2006-2023 Free Software Foundation, Inc.
|
||||
|
||||
@@ -29,4 +29,10 @@ cp -ab x y || fail=1
|
||||
test -d y/x || fail=1
|
||||
test -d y/x~ && fail=1
|
||||
|
||||
# Bug 62607.
|
||||
# This would fail to backup using rename, and thus fail to replace the file
|
||||
mkdir -p src/foo dst/foo || framework_failure_
|
||||
touch src/foo/bar dst/foo/bar || framework_failure_
|
||||
cp --recursive --backup src/* dst || fail=1
|
||||
|
||||
Exit $fail
|
||||
|
||||
@@ -28,12 +28,14 @@ echo n | returns_ 1 cp -iR a b 2>/dev/null || fail=1
|
||||
|
||||
# test miscellaneous combinations of -f -i -n parameters
|
||||
touch c d || framework_failure_
|
||||
echo "'c' -> 'd'" > out_copy
|
||||
> out_empty
|
||||
echo "'c' -> 'd'" > out_copy || framework_failure_
|
||||
echo "skipped 'd'" > out_skip || framework_failure_
|
||||
echo "cp: not replacing 'd'" > err_skip || framework_failure_
|
||||
touch out_empty || framework_failure_
|
||||
|
||||
# ask for overwrite, answer no
|
||||
echo n | returns_ 1 cp -vi c d 2>/dev/null > out1 || fail=1
|
||||
compare out1 out_empty || fail=1
|
||||
compare out1 out_skip || fail=1
|
||||
|
||||
# ask for overwrite, answer yes
|
||||
echo y | cp -vi c d 2>/dev/null > out2 || fail=1
|
||||
@@ -45,6 +47,11 @@ compare out3 out_copy || fail=1
|
||||
|
||||
# -n wins over -i
|
||||
echo y | returns_ 1 cp -vin c d 2>/dev/null > out4 || fail=1
|
||||
compare out4 out_skip || fail=1
|
||||
|
||||
# -n wins over -i non verbose
|
||||
echo y | returns_ 1 cp -in c d 2>err4 > out4 || fail=1
|
||||
compare err4 err_skip || fail=1
|
||||
compare out4 out_empty || fail=1
|
||||
|
||||
# ask for overwrite, answer yes
|
||||
@@ -53,11 +60,11 @@ compare out5 out_copy || fail=1
|
||||
|
||||
# do not ask, prevent from overwrite
|
||||
echo n | returns_ 1 cp -vfn c d 2>/dev/null > out6 || fail=1
|
||||
compare out6 out_empty || fail=1
|
||||
compare out6 out_skip || fail=1
|
||||
|
||||
# do not ask, prevent from overwrite
|
||||
echo n | returns_ 1 cp -vnf c d 2>/dev/null > out7 || fail=1
|
||||
compare out7 out_empty || fail=1
|
||||
compare out7 out_skip || fail=1
|
||||
|
||||
# options --backup and --no-clobber are mutually exclusive
|
||||
returns_ 1 cp -bn c d 2>/dev/null || fail=1
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ cp stat dd
|
||||
print_ver_ cp dd
|
||||
|
||||
touch sparse_chk
|
||||
seek_data_capable_ sparse_chk \
|
||||
@@ -44,18 +44,8 @@ printf x > k || framework_failure_
|
||||
dd bs=1k seek=1 of=k count=255 < /dev/zero || framework_failure_
|
||||
|
||||
# cp should detect the all-zero blocks and convert some of them to holes.
|
||||
# How many it detects/converts currently depends on io_blksize.
|
||||
# Currently, on my F14/ext4 desktop, this K file starts off with size 256KiB,
|
||||
# (note that the K in the preceding test starts off with size 4KiB).
|
||||
# cp from coreutils-8.9 with --sparse=always reduces the size to 32KiB.
|
||||
cp --reflink=never --sparse=always k k2 || fail=1
|
||||
if test $(stat -c %b k2) -ge $(stat -c %b k); then
|
||||
# If not sparse, then double check by creating with dd
|
||||
# as we're not guaranteed that seek will create a hole.
|
||||
# apfs on darwin 19.2.0 for example was seen to not to create holes < 16MiB.
|
||||
hole_size=$(stat -c %o k2) || framework_failure_
|
||||
dd if=k of=k2.dd bs=$hole_size conv=sparse || framework_failure_
|
||||
test $(stat -c %b k2) -eq $(stat -c %b k2.dd) || fail=1
|
||||
fi
|
||||
cp --debug --reflink=never --sparse=always k k2 >cp.out || fail=1
|
||||
cmp k k2 || fail=1
|
||||
grep 'sparse detection: .*zeros' cp.out || { cat cp.out; fail=1; }
|
||||
|
||||
Exit $fail
|
||||
|
||||
@@ -59,7 +59,9 @@ compare exp out || fail=1
|
||||
|
||||
# Perform this test only if "." is on a local file system.
|
||||
# Otherwise, it would fail e.g., on an NFS-mounted Solaris ZFS file system.
|
||||
if is_local_dir_ .; then
|
||||
# Also skip local ZFS as that was seen to fail intermittently
|
||||
# (perhaps due to async compression affecting allocations)
|
||||
if is_local_dir_ . && ! df -T -t zfs .; then
|
||||
rm -f out exp
|
||||
du --block-size=$B -a d | sort -r -k2,2 > out || fail=1
|
||||
echo === >> out
|
||||
|
||||
@@ -302,9 +302,11 @@ all_tests = \
|
||||
tests/misc/csplit-io-err.sh \
|
||||
tests/misc/csplit-suppress-matched.pl \
|
||||
tests/misc/date-debug.sh \
|
||||
tests/misc/date-f.sh \
|
||||
tests/misc/date-sec.sh \
|
||||
tests/misc/date-tz.sh \
|
||||
tests/misc/dircolors.pl \
|
||||
tests/misc/dircolors.sh \
|
||||
tests/misc/dirname.pl \
|
||||
tests/misc/env-null.sh \
|
||||
tests/misc/env-S.pl \
|
||||
|
||||
@@ -25,7 +25,7 @@ vm=$(get_min_ulimit_v_ csplit -z f %n%1) \
|
||||
|| skip_ "this shell lacks ulimit support"
|
||||
|
||||
(
|
||||
ulimit -v $(($vm + 1000)) \
|
||||
ulimit -v $(($vm + 4000)) \
|
||||
&& { yes | head -n2500000; echo n; } | csplit -z - %n%1
|
||||
) || fail=1
|
||||
|
||||
|
||||
29
tests/misc/date-f.sh
Executable file
29
tests/misc/date-f.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
# Verify -f processing
|
||||
|
||||
# Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ date
|
||||
|
||||
# Make sure date fails when it can't read input
|
||||
# (the current directory in this case)
|
||||
if ! cat . >/dev/null; then
|
||||
# can't read() directories
|
||||
returns_ 1 date -f . || fail=1
|
||||
fi
|
||||
|
||||
Exit $fail
|
||||
28
tests/misc/dircolors.sh
Executable file
28
tests/misc/dircolors.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ dircolors
|
||||
|
||||
# Make sure dircolors fails when it can't read input
|
||||
# (the current directory in this case)
|
||||
if ! cat . >/dev/null; then
|
||||
# can't read() directories
|
||||
returns_ 1 dircolors . || fail=1
|
||||
fi
|
||||
|
||||
Exit $fail
|
||||
@@ -101,6 +101,16 @@ my @Tests =
|
||||
. "md5sum: WARNING: 1 line is improperly formatted\n"
|
||||
. "md5sum: WARNING: 2 computed checksums did NOT match\n"},
|
||||
{EXIT=> 1}],
|
||||
# Ensure we use appropriate state to track failures (broken in 9.2)
|
||||
['check-multifail-state', '--check', '--warn',
|
||||
{IN=>{'f.md5' =>
|
||||
"$degenerate f\n"
|
||||
. "$degenerate g\n"
|
||||
. "$degenerate f\n" }},
|
||||
{AUX=> {f=> ''}}, {AUX=> {g=> 'a'}},
|
||||
{OUT=>"f: OK\ng: FAILED\nf: OK\n"},
|
||||
{ERR=>"md5sum: WARNING: 1 computed checksum did NOT match\n"},
|
||||
{EXIT=> 1}],
|
||||
# The sha1sum and md5sum drivers share a lot of code.
|
||||
# Ensure that md5sum does *not* share the part that makes
|
||||
# sha1sum accept BSD format.
|
||||
|
||||
@@ -79,9 +79,11 @@ test -f tee.exited || fail=1 ;;
|
||||
esac
|
||||
|
||||
# Test with unwriteable files
|
||||
touch file.ro || framework_failure_
|
||||
chmod a-w file.ro || framework_failure_
|
||||
returns_ 1 tee -p </dev/null file.ro || fail=1
|
||||
if ! uid_is_privileged_; then # root does not get EPERM.
|
||||
touch file.ro || framework_failure_
|
||||
chmod a-w file.ro || framework_failure_
|
||||
returns_ 1 tee -p </dev/null file.ro || fail=1
|
||||
fi
|
||||
|
||||
mkfifo_or_skip_ fifo
|
||||
|
||||
@@ -97,7 +99,7 @@ dd count=20 bs=100K if=/dev/zero status=none |
|
||||
dd count=0 oflag=nonblock status=none
|
||||
tee || { cleanup_; touch tee.fail; }
|
||||
} >fifo
|
||||
test -f tee.fail && fail=1
|
||||
test -f tee.fail && fail=1 || cleanup_
|
||||
|
||||
# Ensure tee honors --output-error modes
|
||||
read_fifo() { timeout 10 dd count=1 if=fifo of=/dev/null status=none & }
|
||||
|
||||
@@ -69,15 +69,19 @@ $@
|
||||
{
|
||||
my $exp = new Expect;
|
||||
$exp->log_user(0);
|
||||
$ENV{built_programs} =~ /\b$cmd\b/ || next;
|
||||
my $cmd_name = (split(' ', $cmd))[0];
|
||||
$ENV{built_programs} =~ /\b$cmd_name\b/ || next;
|
||||
$exp->spawn("$cmd 2> $stderr")
|
||||
or (warn "$ME: cannot run '$cmd': $!\n"), $fail=1, next;
|
||||
# No input for cut -f2.
|
||||
# Test cut in a different mode, even though it supports the standard flow
|
||||
# Ensure that it exits with no input as it used to not do so
|
||||
$cmd =~ /^cut/
|
||||
or $exp->send("a b\n");
|
||||
$exp->send("\cD"); # This is Control-D. FIXME: what if that's not EOF?
|
||||
$exp->expect (0, '-re', "^a b\\r?\$");
|
||||
my $found = $exp->expect (1, '-re', "^.+\$");
|
||||
$cmd =~ /^cut/
|
||||
or $exp->expect (0, '-re', "^a b\\r?\$");
|
||||
$cmd =~ /^cut/
|
||||
or my $found = $exp->expect (1, '-re', "^.+\$");
|
||||
$found and warn "F: $found: " . $exp->exp_match () . "\n";
|
||||
$exp->expect(10, 'eof');
|
||||
# Expect no output from cut, since we gave it no input.
|
||||
|
||||
@@ -42,6 +42,18 @@ cat <<\EOF > exp
|
||||
EOF
|
||||
compare exp out || fail=1
|
||||
|
||||
# Ensure we update the offset even when not reading,
|
||||
# which wasn't the case from coreutils-8.27 to coreutils-9.2
|
||||
{ wc -c; wc -c; } < no_read > out || fail=1
|
||||
{ wc -c; wc -c; } < do_read >> out || fail=1
|
||||
cat <<\EOF > exp
|
||||
2
|
||||
0
|
||||
1048576
|
||||
0
|
||||
EOF
|
||||
compare exp out || fail=1
|
||||
|
||||
# Ensure we don't read too much when reading,
|
||||
# as was the case on 32 bit systems
|
||||
# from coreutils-8.24 to coreutils-9.1
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ wc
|
||||
require_sparse_support_ # for 'truncate --size=$BIG'
|
||||
getlimits_
|
||||
|
||||
printf '%s\n' '2' > 2b || framework_failure_
|
||||
printf '%s\n' '2 words' > 2w || framework_failure_
|
||||
@@ -40,4 +42,19 @@ compare exp out || fail=1
|
||||
wc --total=always 2b > out || fail=1
|
||||
test "$(wc -l < out)" = 2 || fail=1
|
||||
|
||||
if truncate -s 2E big; then
|
||||
if test "$UINTMAX_MAX" = '18446744073709551615'; then
|
||||
# Ensure overflow is diagnosed
|
||||
returns_ 1 wc --total=only -c big big big big big big big big \
|
||||
> out || fail=1
|
||||
|
||||
# Ensure total is saturated
|
||||
printf '%s\n' "$UINTMAX_MAX" > exp || framework_failure_
|
||||
compare exp out || fail=1
|
||||
|
||||
# Ensure overflow is ignored if totals not shown
|
||||
wc --total=never -c big big big big big big big big || fail=1
|
||||
fi
|
||||
fi
|
||||
|
||||
Exit $fail
|
||||
|
||||
@@ -23,12 +23,14 @@ print_ver_ mv
|
||||
# test miscellaneous combinations of -f -i -n parameters
|
||||
touch a b || framework_failure_
|
||||
echo "renamed 'a' -> 'b'" > out_move
|
||||
echo "skipped 'b'" > out_skip || framework_failure_
|
||||
echo "mv: not replacing 'b'" > err_skip || framework_failure_
|
||||
> out_empty
|
||||
|
||||
# ask for overwrite, answer no
|
||||
touch a b || framework_failure_
|
||||
echo n | returns_ 1 mv -vi a b 2>/dev/null > out1 || fail=1
|
||||
compare out1 out_empty || fail=1
|
||||
compare out1 out_skip || fail=1
|
||||
|
||||
# ask for overwrite, answer yes
|
||||
touch a b || framework_failure_
|
||||
@@ -38,17 +40,23 @@ compare out2 out_move || fail=1
|
||||
# -n wins (as the last option)
|
||||
touch a b || framework_failure_
|
||||
echo y | returns_ 1 mv -vin a b 2>/dev/null > out3 || fail=1
|
||||
compare out3 out_skip || fail=1
|
||||
|
||||
# -n wins (non verbose)
|
||||
touch a b || framework_failure_
|
||||
echo y | returns_ 1 mv -in a b 2>err3 > out3 || fail=1
|
||||
compare out3 out_empty || fail=1
|
||||
compare err3 err_skip || fail=1
|
||||
|
||||
# -n wins (as the last option)
|
||||
touch a b || framework_failure_
|
||||
echo y | returns_ 1 mv -vfn a b 2>/dev/null > out4 || fail=1
|
||||
compare out4 out_empty || fail=1
|
||||
compare out4 out_skip || fail=1
|
||||
|
||||
# -n wins (as the last option)
|
||||
touch a b || framework_failure_
|
||||
echo y | returns_ 1 mv -vifn a b 2>/dev/null > out5 || fail=1
|
||||
compare out5 out_empty || fail=1
|
||||
compare out5 out_skip || fail=1
|
||||
|
||||
# options --backup and --no-clobber are mutually exclusive
|
||||
touch a || framework_failure_
|
||||
|
||||
@@ -19,11 +19,13 @@
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ cp mv
|
||||
|
||||
echo old > old || framework_failure_
|
||||
touch -d yesterday old || framework_failure_
|
||||
echo new > new || framework_failure_
|
||||
|
||||
test_reset() {
|
||||
echo old > old || framework_failure_
|
||||
touch -d yesterday old || framework_failure_
|
||||
echo new > new || framework_failure_
|
||||
}
|
||||
|
||||
test_reset
|
||||
for interactive in '' -i; do
|
||||
for cp_or_mv in cp mv; do
|
||||
# This is a no-op, with no prompt.
|
||||
@@ -36,19 +38,32 @@ for interactive in '' -i; do
|
||||
done
|
||||
done
|
||||
|
||||
# This will actually perform the rename.
|
||||
mv --update new old || fail=1
|
||||
test -f new && fail=1
|
||||
case "$(cat old)" in new) ;; *) fail=1 ;; esac
|
||||
# These should perform the rename / copy
|
||||
for update_option in '--update' '--update=older' '--update=all' \
|
||||
'--update=none --update=all'; do
|
||||
test_reset
|
||||
mv $update_option new old || fail=1
|
||||
test -f new && fail=1
|
||||
case "$(cat old)" in new) ;; *) fail=1 ;; esac
|
||||
|
||||
# Restore initial conditions.
|
||||
echo old > old || framework_failure_
|
||||
touch -d yesterday old || fail=1
|
||||
echo new > new || framework_failure_
|
||||
test_reset
|
||||
cp $update_option new old || fail=1
|
||||
case "$(cat old)" in new) ;; *) fail=1 ;; esac
|
||||
case "$(cat new)" in new) ;; *) fail=1 ;; esac
|
||||
done
|
||||
|
||||
# This will actually perform the copy.
|
||||
cp --update new old || fail=1
|
||||
case "$(cat old)" in new) ;; *) fail=1 ;; esac
|
||||
case "$(cat new)" in new) ;; *) fail=1 ;; esac
|
||||
# These should not perform the rename / copy
|
||||
for update_option in '--update=none' \
|
||||
'--update=all --update=none'; do
|
||||
test_reset
|
||||
mv $update_option new old || fail=1
|
||||
case "$(cat new)" in new) ;; *) fail=1 ;; esac
|
||||
case "$(cat old)" in old) ;; *) fail=1 ;; esac
|
||||
|
||||
test_reset
|
||||
cp $update_option new old || fail=1
|
||||
case "$(cat new)" in new) ;; *) fail=1 ;; esac
|
||||
case "$(cat old)" in old) ;; *) fail=1 ;; esac
|
||||
done
|
||||
|
||||
Exit $fail
|
||||
|
||||
Reference in New Issue
Block a user