mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-28 08:02:54 +00:00
cp: Refactor the core logic.
Rewrite `copy_file()` so the lflag and sflag are handled as early as possible instead of constantly checking that they're not set and then handling them at the end. This also opens the door to changing the failure logic at some future point (for instance, we might decide to fall back to copying if `errno` indicates that the file system does not support links). MFC after: 1 week Sponsored by: Klara, Inc. Reviewed by: kevans, allanjude Differential Revision: https://reviews.freebsd.org/D43055
This commit is contained in:
parent
d3a8e9b43b
commit
d002316fd7
121
bin/cp/utils.c
121
bin/cp/utils.c
@ -62,6 +62,11 @@
|
||||
*/
|
||||
#define BUFSIZE_SMALL (MAXPHYS)
|
||||
|
||||
/*
|
||||
* Prompt used in -i case.
|
||||
*/
|
||||
#define YESNO "(y/n [n]) "
|
||||
|
||||
static ssize_t
|
||||
copy_fallback(int from_fd, int to_fd)
|
||||
{
|
||||
@ -119,7 +124,6 @@ copy_file(const FTSENT *entp, int dne)
|
||||
* modified by the umask.)
|
||||
*/
|
||||
if (!dne) {
|
||||
#define YESNO "(y/n [n]) "
|
||||
if (nflag) {
|
||||
if (vflag)
|
||||
printf("%s not overwritten\n", to.p_path);
|
||||
@ -139,70 +143,68 @@ copy_file(const FTSENT *entp, int dne)
|
||||
}
|
||||
|
||||
if (fflag) {
|
||||
/*
|
||||
* Remove existing destination file name create a new
|
||||
* file.
|
||||
*/
|
||||
/* remove existing destination file */
|
||||
(void)unlink(to.p_path);
|
||||
if (!lflag && !sflag) {
|
||||
to_fd = open(to.p_path,
|
||||
O_WRONLY | O_TRUNC | O_CREAT,
|
||||
fs->st_mode & ~(S_ISUID | S_ISGID));
|
||||
}
|
||||
} else if (!lflag && !sflag) {
|
||||
/* Overwrite existing destination file name. */
|
||||
to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
|
||||
}
|
||||
} else if (!lflag && !sflag) {
|
||||
}
|
||||
|
||||
rval = 0;
|
||||
|
||||
if (lflag) {
|
||||
if (link(entp->fts_path, to.p_path) != 0) {
|
||||
warn("%s", to.p_path);
|
||||
rval = 1;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (sflag) {
|
||||
if (symlink(entp->fts_path, to.p_path) != 0) {
|
||||
warn("%s", to.p_path);
|
||||
rval = 1;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!dne && !fflag) {
|
||||
/* overwrite existing destination file */
|
||||
to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
|
||||
} else {
|
||||
/* create new destination file */
|
||||
to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
|
||||
fs->st_mode & ~(S_ISUID | S_ISGID));
|
||||
}
|
||||
|
||||
if (!lflag && !sflag && to_fd == -1) {
|
||||
if (to_fd == -1) {
|
||||
warn("%s", to.p_path);
|
||||
rval = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rval = 0;
|
||||
|
||||
if (!lflag && !sflag) {
|
||||
wtotal = 0;
|
||||
do {
|
||||
if (use_copy_file_range) {
|
||||
wcount = copy_file_range(from_fd, NULL,
|
||||
to_fd, NULL, SSIZE_MAX, 0);
|
||||
if (wcount < 0 && errno == EINVAL) {
|
||||
/* Prob a non-seekable FD */
|
||||
use_copy_file_range = 0;
|
||||
}
|
||||
wtotal = 0;
|
||||
do {
|
||||
if (use_copy_file_range) {
|
||||
wcount = copy_file_range(from_fd, NULL,
|
||||
to_fd, NULL, SSIZE_MAX, 0);
|
||||
if (wcount < 0 && errno == EINVAL) {
|
||||
/* probably a non-seekable descriptor */
|
||||
use_copy_file_range = 0;
|
||||
}
|
||||
if (!use_copy_file_range) {
|
||||
wcount = copy_fallback(from_fd, to_fd);
|
||||
}
|
||||
wtotal += wcount;
|
||||
if (info) {
|
||||
info = 0;
|
||||
(void)fprintf(stderr,
|
||||
"%s -> %s %3d%%\n",
|
||||
entp->fts_path, to.p_path,
|
||||
cp_pct(wtotal, fs->st_size));
|
||||
}
|
||||
} while (wcount > 0);
|
||||
if (wcount < 0) {
|
||||
warn("%s", entp->fts_path);
|
||||
rval = 1;
|
||||
}
|
||||
} else if (lflag) {
|
||||
if (link(entp->fts_path, to.p_path)) {
|
||||
warn("%s", to.p_path);
|
||||
rval = 1;
|
||||
if (!use_copy_file_range) {
|
||||
wcount = copy_fallback(from_fd, to_fd);
|
||||
}
|
||||
} else if (sflag) {
|
||||
if (symlink(entp->fts_path, to.p_path)) {
|
||||
warn("%s", to.p_path);
|
||||
rval = 1;
|
||||
wtotal += wcount;
|
||||
if (info) {
|
||||
info = 0;
|
||||
(void)fprintf(stderr,
|
||||
"%s -> %s %3d%%\n",
|
||||
entp->fts_path, to.p_path,
|
||||
cp_pct(wtotal, fs->st_size));
|
||||
}
|
||||
} while (wcount > 0);
|
||||
if (wcount < 0) {
|
||||
warn("%s", entp->fts_path);
|
||||
rval = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -211,16 +213,13 @@ copy_file(const FTSENT *entp, int dne)
|
||||
* or its contents might be irreplaceable. It would only be safe
|
||||
* to remove it if we created it and its length is 0.
|
||||
*/
|
||||
|
||||
if (!lflag && !sflag) {
|
||||
if (pflag && setfile(fs, to_fd))
|
||||
rval = 1;
|
||||
if (pflag && preserve_fd_acls(from_fd, to_fd) != 0)
|
||||
rval = 1;
|
||||
if (close(to_fd)) {
|
||||
warn("%s", to.p_path);
|
||||
rval = 1;
|
||||
}
|
||||
if (pflag && setfile(fs, to_fd))
|
||||
rval = 1;
|
||||
if (pflag && preserve_fd_acls(from_fd, to_fd) != 0)
|
||||
rval = 1;
|
||||
if (close(to_fd)) {
|
||||
warn("%s", to.p_path);
|
||||
rval = 1;
|
||||
}
|
||||
|
||||
done:
|
||||
|
Loading…
Reference in New Issue
Block a user