Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F140122560
D45243.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
D45243.diff
View Options
diff --git a/Makefile.inc1 b/Makefile.inc1
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -2481,6 +2481,11 @@
_kldxref= usr.sbin/kldxref
${_bt}-usr.sbin/kldxref: ${_bt_libelf_depend}
+.if !defined(CROSSBUILD_HOST)
+_libutil= lib/libutil
+${_bt}-usr.bin/xinstall: ${_bt}-lib/libutil
+.endif
+
# flua is required to regenerate syscall files. It first appeared during the
# 13.0-CURRENT cycle, thus needs to be built on -older releases and stable
# branches.
@@ -2744,6 +2749,7 @@
${_elftoolchain_libs} \
${_kldxref} \
lib/libopenbsd \
+ ${_libutil} \
usr.bin/mandoc \
usr.bin/rpcgen \
${_yacc} \
diff --git a/bin/cat/Makefile b/bin/cat/Makefile
--- a/bin/cat/Makefile
+++ b/bin/cat/Makefile
@@ -4,6 +4,8 @@
PACKAGE=runtime
PROG= cat
+LIBADD= util
+
.ifdef BOOTSTRAPPING
# For the bootstrap cat we disable all wide char support to allow building
# on Linux/macOS
diff --git a/bin/cat/cat.c b/bin/cat/cat.c
--- a/bin/cat/cat.c
+++ b/bin/cat/cat.c
@@ -46,6 +46,7 @@
#include <err.h>
#include <errno.h>
#include <fcntl.h>
+#include <libutil.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
@@ -67,9 +68,7 @@
static void scanfiles(char *argv[], int cooked);
#ifndef BOOTSTRAP_CAT
static void cook_cat(FILE *);
-static ssize_t in_kernel_copy(int);
#endif
-static void raw_cat(int);
#ifndef NO_UDOM_SUPPORT
static cap_channel_t *capnet;
@@ -231,53 +230,49 @@
static void
scanfiles(char *argv[], int cooked __unused)
{
- int fd, i;
+ int i, rfd, wfd;
char *path;
+ ssize_t done;
#ifndef BOOTSTRAP_CAT
FILE *fp;
#endif
i = 0;
- fd = -1;
+ rfd = -1;
while ((path = argv[i]) != NULL || i == 0) {
if (path == NULL || strcmp(path, "-") == 0) {
filename = "stdin";
- fd = STDIN_FILENO;
+ rfd = STDIN_FILENO;
} else {
filename = path;
- fd = fileargs_open(fa, path);
+ rfd = fileargs_open(fa, path);
#ifndef NO_UDOM_SUPPORT
- if (fd < 0 && errno == EOPNOTSUPP)
- fd = udom_open(path, O_RDONLY);
+ if (rfd < 0 && errno == EOPNOTSUPP)
+ rfd = udom_open(path, O_RDONLY);
#endif
}
- if (fd < 0) {
+ if (rfd < 0) {
warn("%s", path);
rval = 1;
#ifndef BOOTSTRAP_CAT
} else if (cooked) {
- if (fd == STDIN_FILENO)
+ if (rfd == STDIN_FILENO)
cook_cat(stdin);
else {
- fp = fdopen(fd, "r");
+ fp = fdopen(rfd, "r");
cook_cat(fp);
fclose(fp);
}
#endif
} else {
-#ifndef BOOTSTRAP_CAT
- if (in_kernel_copy(fd) != 0) {
- if (errno == EINVAL || errno == EBADF ||
- errno == EISDIR)
- raw_cat(fd);
- else
- err(1, "stdout");
- }
-#else
- raw_cat(fd);
-#endif
- if (fd != STDIN_FILENO)
- close(fd);
+ wfd = fileno(stdout);
+ do {
+ done = fcopydata(rfd, wfd);
+ } while (done > 0);
+ if (done < 0)
+ err(1, "%s", filename);
+ if (rfd != STDIN_FILENO)
+ close(rfd);
}
if (path == NULL)
break;
@@ -375,62 +370,8 @@
if (ferror(stdout))
err(1, "stdout");
}
-
-static ssize_t
-in_kernel_copy(int rfd)
-{
- int wfd;
- ssize_t ret;
-
- wfd = fileno(stdout);
- ret = 1;
-
- while (ret > 0)
- ret = copy_file_range(rfd, NULL, wfd, NULL, SSIZE_MAX, 0);
-
- return (ret);
-}
#endif /* BOOTSTRAP_CAT */
-static void
-raw_cat(int rfd)
-{
- long pagesize;
- int off, wfd;
- ssize_t nr, nw;
- static size_t bsize;
- static char *buf = NULL;
- struct stat sbuf;
-
- wfd = fileno(stdout);
- if (buf == NULL) {
- if (fstat(wfd, &sbuf))
- err(1, "stdout");
- if (S_ISREG(sbuf.st_mode)) {
- /* If there's plenty of RAM, use a large copy buffer */
- if (sysconf(_SC_PHYS_PAGES) > PHYSPAGES_THRESHOLD)
- bsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
- else
- bsize = BUFSIZE_SMALL;
- } else {
- bsize = sbuf.st_blksize;
- pagesize = sysconf(_SC_PAGESIZE);
- if (pagesize > 0)
- bsize = MAX(bsize, (size_t)pagesize);
- }
- if ((buf = malloc(bsize)) == NULL)
- err(1, "malloc() failure of IO buffer");
- }
- while ((nr = read(rfd, buf, bsize)) > 0)
- for (off = 0; nr; nr -= nw, off += nw)
- if ((nw = write(wfd, buf + off, (size_t)nr)) < 0)
- err(1, "stdout");
- if (nr < 0) {
- warn("%s", filename);
- rval = 1;
- }
-}
-
#ifndef NO_UDOM_SUPPORT
static int
diff --git a/bin/cp/Makefile b/bin/cp/Makefile
--- a/bin/cp/Makefile
+++ b/bin/cp/Makefile
@@ -6,6 +6,8 @@
SRCS= cp.c utils.c
CFLAGS+= -D_ACL_PRIVATE
+LIBADD= util
+
HAS_TESTS=
SUBDIR.${MK_TESTS}= tests
diff --git a/bin/cp/utils.c b/bin/cp/utils.c
--- a/bin/cp/utils.c
+++ b/bin/cp/utils.c
@@ -37,6 +37,7 @@
#include <errno.h>
#include <fcntl.h>
#include <fts.h>
+#include <libutil.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
@@ -45,66 +46,43 @@
#include "extern.h"
-#define cp_pct(x, y) ((y == 0) ? 0 : (int)(100.0 * (x) / (y)))
-
-/*
- * Memory strategy threshold, in pages: if physmem is larger then this, use a
- * large buffer.
- */
-#define PHYSPAGES_THRESHOLD (32*1024)
-
-/* Maximum buffer size in bytes - do not allow it to grow larger than this. */
-#define BUFSIZE_MAX (2*1024*1024)
-
-/*
- * Small (default) buffer size in bytes. It's inefficient for this to be
- * smaller than MAXPHYS.
- */
-#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)
+#define cp_pct(x, y) ((y == 0) ? 0 : (int)(100.0 * (x) / (y)))
+static void
+copy_file_progress(const char *frompath, const char *topath,
+ struct stat *fromst, size_t done)
{
- static char *buf = NULL;
- static size_t bufsize;
- ssize_t rcount, wresid, wcount = 0;
- char *bufp;
-
- if (buf == NULL) {
- if (sysconf(_SC_PHYS_PAGES) > PHYSPAGES_THRESHOLD)
- bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
- else
- bufsize = BUFSIZE_SMALL;
- buf = malloc(bufsize);
- if (buf == NULL)
- err(1, "Not enough memory");
- }
- rcount = read(from_fd, buf, bufsize);
- if (rcount <= 0)
- return (rcount);
- for (bufp = buf, wresid = rcount; ; bufp += wcount, wresid -= wcount) {
- wcount = write(to_fd, bufp, wresid);
- if (wcount <= 0)
- break;
- if (wcount >= wresid)
- break;
- }
- return (wcount < 0 ? wcount : rcount);
+ char sdone[5], ssize[5];
+
+ humanize_number(sdone, sizeof(sdone), (int64_t)done, "", HN_AUTOSCALE,
+ HN_B | HN_NOSPACE | HN_DECIMAL);
+ if (S_ISREG(fromst->st_mode)) {
+ humanize_number(ssize, sizeof(ssize), (int64_t)fromst->st_size,
+ "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+ (void)fprintf(stderr, "%s -> %s %d%% (%s / %s)\n", frompath,
+ topath, cp_pct(done, fromst->st_size), sdone, ssize);
+ } else {
+ /*
+ * If this isn't a regular file, we most likely don't have
+ * its size, so reporting the progress in percents makes no
+ * sense.
+ */
+ (void)fprintf(stderr, "%s -> %s %s\n", frompath, topath,
+ sdone);
+ }
}
+#undef cp_pct
int
copy_file(const FTSENT *entp, int dne)
{
struct stat sb, *fs;
- ssize_t wcount;
- off_t wtotal;
+ ssize_t wcount, wtotal;
int ch, checkch, from_fd, rval, to_fd;
- int use_copy_file_range = 1;
fs = entp->fts_statp;
from_fd = to_fd = -1;
@@ -199,24 +177,12 @@
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);
- }
+ wcount = fcopydata_sig(from_fd, to_fd, &info);
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));
+ copy_file_progress(entp->fts_path, to.p_path, fs,
+ wtotal);
}
} while (wcount > 0);
if (wcount < 0) {
diff --git a/bin/mv/Makefile b/bin/mv/Makefile
--- a/bin/mv/Makefile
+++ b/bin/mv/Makefile
@@ -4,6 +4,9 @@
PACKAGE=runtime
PROG= mv
+CFLAGS+=-I${SRCTOP}/lib/libutil
+LIBADD= util
+
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests
diff --git a/bin/mv/mv.c b/bin/mv/mv.c
--- a/bin/mv/mv.c
+++ b/bin/mv/mv.c
@@ -44,9 +44,11 @@
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
+#include <libutil.h>
#include <limits.h>
#include <paths.h>
#include <pwd.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -57,6 +59,7 @@
#define EXEC_FAILED 127
static int fflg, hflg, iflg, nflg, vflg;
+static volatile sig_atomic_t info;
static int copy(const char *, const char *);
static int do_move(const char *, const char *);
@@ -64,6 +67,7 @@
static void usage(void);
static void preserve_fd_acls(int source_fd, int dest_fd, const char *source_path,
const char *dest_path);
+static void siginfo(int sig __unused);
int
main(int argc, char *argv[])
@@ -104,6 +108,8 @@
if (argc < 2)
usage();
+ (void)signal(SIGINFO, siginfo);
+
/*
* If the stat on the target fails or the target isn't a directory,
* try the move. More than 2 arguments is an error in this case.
@@ -258,25 +264,45 @@
fastcopy(from, to, &sb) : copy(from, to));
}
+#define cp_pct(x, y) ((y == 0) ? 0 : (int)(100.0 * (x) / (y)))
+static void
+fastcopy_progress(const char *frompath, const char *topath,
+ struct stat *fromst, size_t done)
+{
+ char sdone[5], ssize[5];
+
+ humanize_number(sdone, sizeof(sdone), (int64_t)done, "", HN_AUTOSCALE,
+ HN_B | HN_NOSPACE | HN_DECIMAL);
+ if (S_ISREG(fromst->st_mode)) {
+ humanize_number(ssize, sizeof(ssize), (int64_t)fromst->st_size,
+ "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+ (void)fprintf(stderr, "%s -> %s %d%% (%s / %s)\n", frompath,
+ topath, cp_pct(done, fromst->st_size), sdone, ssize);
+ } else {
+ /*
+ * If this isn't a regular file, we most likely don't have
+ * its size, so reporting the progress in percents makes no
+ * sense.
+ */
+ (void)fprintf(stderr, "%s -> %s %s\n", frompath, topath,
+ sdone);
+ }
+}
+#undef cp_pct
+
static int
fastcopy(const char *from, const char *to, struct stat *sbp)
{
struct timespec ts[2];
- static u_int blen = MAXPHYS;
- static char *bp = NULL;
mode_t oldmode;
- int nread, from_fd, to_fd;
+ int from_fd, to_fd;
+ ssize_t wcount, wtotal;
struct stat tsb;
if ((from_fd = open(from, O_RDONLY, 0)) < 0) {
warn("fastcopy: open() failed (from): %s", from);
return (1);
}
- if (bp == NULL && (bp = malloc((size_t)blen)) == NULL) {
- warnx("malloc(%u) failed", blen);
- (void)close(from_fd);
- return (1);
- }
while ((to_fd =
open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)) < 0) {
if (errno == EEXIST && unlink(to) == 0)
@@ -285,14 +311,18 @@
(void)close(from_fd);
return (1);
}
- while ((nread = read(from_fd, bp, (size_t)blen)) > 0)
- if (write(to_fd, bp, (size_t)nread) != nread) {
- warn("fastcopy: write() failed: %s", to);
- goto err;
+ wtotal = 0;
+ do {
+ wcount = fcopydata_sig(from_fd, to_fd, &info);
+ wtotal += wcount;
+ if (info) {
+ info = 0;
+ fastcopy_progress(from, to, sbp, wtotal);
}
- if (nread < 0) {
- warn("fastcopy: read() failed: %s", from);
-err: if (unlink(to))
+ } while (wcount > 0);
+ if (wcount < 0) {
+ warn("fastcopy: failed: %s -> %s", from, to);
+ if (unlink(to))
warn("%s: remove", to);
(void)close(from_fd);
(void)close(to_fd);
@@ -490,6 +520,13 @@
acl_free(acl);
}
+static void
+siginfo(int sig __unused)
+{
+
+ info = 1;
+}
+
static void
usage(void)
{
diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile
--- a/lib/libutil/Makefile
+++ b/lib/libutil/Makefile
@@ -10,8 +10,9 @@
LIB= util
SHLIB_MAJOR= 9
-SRCS= _secure_path.c auth.c cpuset.c expand_number.c flopen.c fparseln.c \
- ftime.c getlocalbase.c gr_util.c \
+SRCS= _secure_path.c auth.c cpuset.c expand_number.c \
+ fcopydata.c flopen.c fparseln.c ftime.c \
+ getlocalbase.c gr_util.c \
hexdump.c humanize_number.c kinfo_getfile.c \
kinfo_getallproc.c kinfo_getproc.c kinfo_getvmmap.c \
kinfo_getvmobject.c kld.c \
@@ -22,6 +23,7 @@
INCS= libutil.h login_cap.h
CFLAGS+= -DNO__SCCSID
+CFLAGS+= -DHAVE_COPY_FILE_RANGE
.if ${MK_INET6_SUPPORT} != "no"
CFLAGS+= -DINET6
diff --git a/lib/libutil/fcopydata.c b/lib/libutil/fcopydata.c
new file mode 100644
--- /dev/null
+++ b/lib/libutil/fcopydata.c
@@ -0,0 +1,151 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Pawel Jakub Dawidek <pawel@dawidek.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <libutil.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ * Memory strategy threshold, in pages: if physmem is larger then this, use a
+ * large buffer.
+ */
+#define PHYSPAGES_THRESHOLD (32 * 1024)
+
+/* Maximum buffer size in bytes - do not allow it to grow larger than this. */
+#define BUFSIZE_MAX (2 * 1024 * 1024)
+
+/*
+ * Small (default) buffer size in bytes. It's inefficient for this to be
+ * smaller than MAXPHYS.
+ */
+#define BUFSIZE_SMALL (MAXPHYS)
+
+ssize_t
+fcopydata_sig(int infd, int outfd, volatile sig_atomic_t *gotsigp)
+{
+ unsigned char *buf;
+ ssize_t done, tdone;
+ size_t bufsize;
+ int serrno;
+
+ serrno = errno;
+
+#ifdef HAVE_COPY_FILE_RANGE
+ /*
+ * Let's try copy_file_range(2), which should always work if we are
+ * dealing with regular files.
+ */
+ done = copy_file_range(infd, NULL, outfd, NULL, SSIZE_MAX, 0);
+ if (done >= 0) {
+ errno = serrno;
+ return (done);
+ }
+ /*
+ * Fall back to read(2)/write(2) in case of the following errors:
+ * EBADF - outfd might be opened with O_APPEND flag
+ * EINVAL - we may be operating on non-regular file,
+ * like a fifo or a device
+ * EISDIR - file system may support reading directories directly
+ * when security.bsd.allow_read_dir is set
+ */
+ if (errno != EBADF && errno != EINVAL && errno != EISDIR) {
+ return (done);
+ }
+ /*
+ * Probably a non-seekable descriptor, fallback to read/write.
+ */
+#endif /* HAVE_COPY_FILE_RANGE */
+
+ if (sysconf(_SC_PHYS_PAGES) > PHYSPAGES_THRESHOLD)
+ bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
+ else
+ bufsize = BUFSIZE_SMALL;
+ buf = malloc(bufsize);
+ if (buf == NULL) {
+ return (-1);
+ }
+ tdone = 0;
+ for (;;) {
+ size_t todo, written;
+
+ done = read(infd, buf, bufsize);
+ if (done == 0) {
+ done = tdone;
+ break;
+ } else if (done < 0) {
+ break;
+ }
+
+ written = 0;
+ todo = done;
+ do {
+ done = write(outfd, buf + written, todo - written);
+ if (done < 0) {
+ break;
+ } else if (done == 0) {
+ /* This should not happen... */
+ assert(todo - written > 0);
+ errno = EINVAL;
+ done = -1;
+ break;
+ }
+ written += done;
+ tdone += done;
+ assert(written <= todo);
+ } while (written < todo);
+ if (done < 0) {
+ break;
+ }
+ assert(written == todo);
+
+ if (todo < bufsize || (gotsigp != NULL && *gotsigp)) {
+ /*
+ * We had a short read, so return now.
+ */
+ done = tdone;
+ break;
+ }
+ }
+ free(buf);
+
+ if (done >= 0) {
+ errno = serrno;
+ }
+ return (done);
+}
+
+ssize_t
+fcopydata(int infd, int outfd)
+{
+
+ return (fcopydata_sig(infd, outfd, NULL));
+}
diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h
--- a/lib/libutil/libutil.h
+++ b/lib/libutil/libutil.h
@@ -42,6 +42,7 @@
#include <sys/cdefs.h>
#include <sys/_types.h>
#include <sys/_stdint.h>
+#include <sys/signal.h>
#ifndef _GID_T_DECLARED
typedef __gid_t gid_t;
@@ -63,6 +64,11 @@
#define _SIZE_T_DECLARED
#endif
+#ifndef _SSIZE_T_DECLARED
+typedef __ssize_t ssize_t;
+#define _SSIZE_T_DECLARED
+#endif
+
#ifndef _UID_T_DECLARED
typedef __uid_t uid_t;
#define _UID_T_DECLARED
@@ -92,6 +98,8 @@
int expand_number(const char *_buf, uint64_t *_num);
int extattr_namespace_to_string(int _attrnamespace, char **_string);
int extattr_string_to_namespace(const char *_string, int *_attrnamespace);
+ssize_t fcopydata(int infd, int outfd);
+ssize_t fcopydata_sig(int infd, int outfd, volatile sig_atomic_t *gotsigp);
int flopen(const char *_path, int _flags, ...);
int flopenat(int _dirfd, const char *_path, int _flags, ...);
int forkpty(int *_amaster, char *_name,
diff --git a/tools/build/Makefile b/tools/build/Makefile
--- a/tools/build/Makefile
+++ b/tools/build/Makefile
@@ -234,6 +234,7 @@
# expand_number() is not provided by either Linux or MacOS libutil
.PATH: ${SRCTOP}/lib/libutil
SRCS+= expand_number.c
+SRCS+= fcopydata.c
# Linux libutil also doesn't have fparseln
SRCS+= fparseln.c
# A dummy sysctl for tzsetup:
diff --git a/tools/build/cross-build/include/common/libutil.h b/tools/build/cross-build/include/common/libutil.h
--- a/tools/build/cross-build/include/common/libutil.h
+++ b/tools/build/cross-build/include/common/libutil.h
@@ -40,3 +40,4 @@
#endif
int expand_number(const char *_buf, uint64_t *_num);
+ssize_t fcopydata(int infd, int outfd);
diff --git a/tools/build/cross-build/include/linux/libutil.h b/tools/build/cross-build/include/linux/libutil.h
--- a/tools/build/cross-build/include/linux/libutil.h
+++ b/tools/build/cross-build/include/linux/libutil.h
@@ -48,6 +48,8 @@
int scale, int flags);
int expand_number(const char *_buf, uint64_t *_num);
+ssize_t fcopydata(int infd, int outfd);
+
int flopen(const char *_path, int _flags, ...);
int flopenat(int dirfd, const char *path, int flags, ...);
diff --git a/usr.bin/xinstall/Makefile b/usr.bin/xinstall/Makefile
--- a/usr.bin/xinstall/Makefile
+++ b/usr.bin/xinstall/Makefile
@@ -11,15 +11,13 @@
.PATH: ${SRCTOP}/contrib/mtree
CFLAGS+= -I${SRCTOP}/contrib/mtree
CFLAGS+= -I${SRCTOP}/lib/libnetbsd
+.if ${.MAKE.OS} == "FreeBSD"
+CFLAGS+= -I${SRCTOP}/lib/libutil
+.endif
-LIBADD= md
+LIBADD= md util
CFLAGS+= -DWITH_MD5 -DWITH_RIPEMD160
-.ifdef BOOTSTRAPPING
-# For the bootstrap we disable copy_file_range()
-CFLAGS+= -DBOOTSTRAP_XINSTALL
-.endif
-
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests
diff --git a/usr.bin/xinstall/xinstall.c b/usr.bin/xinstall/xinstall.c
--- a/usr.bin/xinstall/xinstall.c
+++ b/usr.bin/xinstall/xinstall.c
@@ -39,6 +39,7 @@
#include <fcntl.h>
#include <grp.h>
#include <libgen.h>
+#include <libutil.h>
#ifdef WITH_MD5
#include <md5.h>
#endif
@@ -1182,9 +1183,7 @@
static size_t bufsize;
int nr, nw;
int serrno;
-#ifndef BOOTSTRAP_XINSTALL
ssize_t ret;
-#endif
DIGEST_CTX ctx;
/* Rewind file descriptors. */
@@ -1193,24 +1192,19 @@
if (lseek(to_fd, 0, SEEK_SET) < 0)
err(EX_OSERR, "lseek: %s", to_name);
-#ifndef BOOTSTRAP_XINSTALL
/* Try copy_file_range() if no digest is requested */
if (digesttype == DIGEST_NONE) {
do {
- ret = copy_file_range(from_fd, NULL, to_fd, NULL,
- (size_t)size, 0);
+ ret = fcopydata(from_fd, to_fd);
} while (ret > 0);
if (ret == 0)
goto done;
- if (errno != EINVAL) {
- serrno = errno;
- (void)unlink(to_name);
- errno = serrno;
- err(EX_OSERR, "%s", to_name);
- }
- /* Fall back */
+ serrno = errno;
+ (void)unlink(to_name);
+ errno = serrno;
+ err(EX_OSERR, "%s", to_name);
}
-#endif
+
digest_init(&ctx);
if (buf == NULL) {
@@ -1250,9 +1244,7 @@
errno = serrno;
err(EX_OSERR, "%s", from_name);
}
-#ifndef BOOTSTRAP_XINSTALL
done:
-#endif
if (safecopy && fsync(to_fd) == -1) {
serrno = errno;
(void)unlink(to_name);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 21, 1:15 PM (6 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27113595
Default Alt Text
D45243.diff (20 KB)
Attached To
Mode
D45243: Introduce fcopydata() and fcopydata_sig() functions.
Attached
Detach File
Event Timeline
Log In to Comment