From owner-svn-src-all@freebsd.org Fri Sep 11 20:49:37 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 54AE43E5EDD; Fri, 11 Sep 2020 20:49:37 +0000 (UTC) (envelope-from asomers@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Bp7D11bgfz3bB4; Fri, 11 Sep 2020 20:49:37 +0000 (UTC) (envelope-from asomers@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 01A919F18; Fri, 11 Sep 2020 20:49:37 +0000 (UTC) (envelope-from asomers@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 08BKnaoh032213; Fri, 11 Sep 2020 20:49:36 GMT (envelope-from asomers@FreeBSD.org) Received: (from asomers@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 08BKnavL032212; Fri, 11 Sep 2020 20:49:36 GMT (envelope-from asomers@FreeBSD.org) Message-Id: <202009112049.08BKnavL032212@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: asomers set sender to asomers@FreeBSD.org using -f From: Alan Somers Date: Fri, 11 Sep 2020 20:49:36 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r365643 - head/bin/cp X-SVN-Group: head X-SVN-Commit-Author: asomers X-SVN-Commit-Paths: head/bin/cp X-SVN-Commit-Revision: 365643 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 11 Sep 2020 20:49:37 -0000 Author: asomers Date: Fri Sep 11 20:49:36 2020 New Revision: 365643 URL: https://svnweb.freebsd.org/changeset/base/365643 Log: cp: fall back to read/write if copy_file_range fails Even though copy_file_range has a file-system agnostic version, it still fails on devfs (perhaps because the file descriptor is non-seekable?) In that case, fallback to old-fashioned read/write. Fixes "cp /dev/null /tmp/null" PR: 249248 Reported by: Michael Butler Reviewed by: mjg MFC-With: 365549 Differential Revision: https://reviews.freebsd.org/D26395 Modified: head/bin/cp/utils.c Modified: head/bin/cp/utils.c ============================================================================== --- head/bin/cp/utils.c Fri Sep 11 20:32:40 2020 (r365642) +++ head/bin/cp/utils.c Fri Sep 11 20:49:36 2020 (r365643) @@ -74,6 +74,26 @@ __FBSDID("$FreeBSD$"); */ #define BUFSIZE_SMALL (MAXPHYS) +static int +copy_fallback(int from_fd, int to_fd, char *buf, size_t bufsize) +{ + int rcount; + ssize_t wresid, wcount = 0; + char *bufp; + + 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 >= (ssize_t)wresid) + break; + } + return (wcount < 0 ? wcount : rcount); +} + int copy_file(const FTSENT *entp, int dne) { @@ -88,6 +108,7 @@ copy_file(const FTSENT *entp, int dne) #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED char *p; #endif + int use_copy_file_range = 1; from_fd = to_fd = -1; if (!lflag && !sflag && @@ -212,9 +233,19 @@ copy_file(const FTSENT *entp, int dne) err(1, "Not enough memory"); } wtotal = 0; - while ((rcount = copy_file_range(from_fd, NULL, - to_fd, NULL, bufsize, 0)) > 0) - { + do { + if (use_copy_file_range) { + rcount = copy_file_range(from_fd, NULL, + to_fd, NULL, bufsize, 0); + if (rcount < 0 && errno == EINVAL) { + /* Prob a non-seekable FD */ + use_copy_file_range = 0; + } + } + if (!use_copy_file_range) { + rcount = copy_fallback(from_fd, to_fd, + buf, bufsize); + } wtotal += rcount; if (info) { info = 0; @@ -223,7 +254,7 @@ copy_file(const FTSENT *entp, int dne) entp->fts_path, to.p_path, cp_pct(wtotal, fs->st_size)); } - } + } while (rcount > 0); if (rcount < 0) { warn("%s", entp->fts_path); rval = 1;