From nobody Wed Feb 11 16:25:24 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4fB3gm6Jzrz6Rm0l for ; Wed, 11 Feb 2026 16:25:24 +0000 (UTC) (envelope-from git@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 "R13" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4fB3gm50L1z40vV for ; Wed, 11 Feb 2026 16:25:24 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1770827124; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=wC6GfrqII7oE3SnjydEU/w6EYo+gS2PetJefvMQxv48=; b=d8MFOG9oJ7/2BsfZSyGbgjzuGXoJVDru2s7gfnnunYdx45Clfjs7mXrTRQFBmvKYl5sGuY QduuRyfWgahPUU1CvSB1JpOzKZMtF6V9LCEM1lYLeiySEa/YGPCuPy+uRGDBdO7lbiKgDm cDd72AAOVw758NyRkinRQ2UDr9hWOi0mYavZY8mfPDFZ2cQ0aZ/KGjWLoMwewhlmQM8Tmo F0/uhFqfz6ocHMSGl1mSOj66KNW8590lWhq7zTGrLti6G/KcoRuaO2nPkZ3Ny04pzZ0T/8 ZT9PPsdw8gVE/k/DJLvmNU/4pR2+MQRifW2mz5N8nIfWk847eWuCmZ4M3f4rQg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1770827124; a=rsa-sha256; cv=none; b=E/fKyOZ1Kh4FSFQV/1af6ybl4iF89WdV2Wo/CBaq+PytMWDkW1SkIh8xEAKVisLmv0Ont5 r9Uue+/N8gLfq2R83ZEzbIqrZ+Wa2g+f1qxDxDWDtwAsPfgKeQ8CdqnqfZx+wZPTGzLIHq 4VdAKRcM9yWLrFy2l+1tAgFVwRIPF+eO89x88mE1aOLTUM2oKAsin++897yQpnGPkdNpIq nGos1mALobgbgjb/GLNYeGCPIJH7W3QnLkPUzLDNkZ8W+xaLvZk8S2ZSmTGupgqEKk2vuQ oLeJ1oqj2jtfqur7yhfxOt2ajEJHSlYrHOcHXrwdoYCD6+BcjpH/ij+Dpq+RBQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1770827124; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=wC6GfrqII7oE3SnjydEU/w6EYo+gS2PetJefvMQxv48=; b=DCnCZBIe0bI+7V09k550+qJtRamVQtvyT6bNKeH15je38ikYnrm4Z/M4Pt/1wLvvfO7xbo oimayNxfT4Os8zpqykEX8uWkNvbdK3aieseXUhlCojXpVQghsUSxZyYlKczhnRbMJOqC9D qEU57/7+Uj85d8LcpZ9iGqtd73nuGAWIJJX0dwNKkYyaGukz854DGJ3xP/7M6kOVkaLuzb Dxx48dYsrUV7cjQsTAXzLpPp8sy0FOQevy2FPpp1qwuyjy5x1nyKuTYFAkFAjX0DXwpveJ BS3e5Ia5/df498r+oggSfeMCvFdQq3fLAUuAX5U+eM3JQNJ3wrN/VuDYFUen8w== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fB3gm4NG4zxDX for ; Wed, 11 Feb 2026 16:25:24 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 25425 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 11 Feb 2026 16:25:24 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Dag-Erling=?utf-8?Q? Sm=C3=B8rg?=rav Subject: git: 0fb940fd63dd - main - install: Expect EINTR while copying List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: des X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 0fb940fd63dd9b6d6b848421c53b1e9ac8387265 Auto-Submitted: auto-generated Date: Wed, 11 Feb 2026 16:25:24 +0000 Message-Id: <698cad74.25425.5153e53a@gitrepo.freebsd.org> The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=0fb940fd63dd9b6d6b848421c53b1e9ac8387265 commit 0fb940fd63dd9b6d6b848421c53b1e9ac8387265 Author: Dag-Erling Smørgrav AuthorDate: 2026-02-11 16:24:50 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2026-02-11 16:24:50 +0000 install: Expect EINTR while copying Both copy_file_range() and read() / write() in our fallback loop can be interrupted before copying anything at all, in which case it returns -1 and sets errno to EINTR. If that happens, we should retry, not fail. While here, drop the size argument from copy() (we always want to copy the entire file anyway) and add test cases which exercise the metalog and digest functionality. PR: 293028 MFC after: 1 week Reviewed by: kevans Differential Revision: https://reviews.freebsd.org/D55168 --- usr.bin/xinstall/tests/install_test.sh | 38 +++++++++++++++++++++++++++++ usr.bin/xinstall/xinstall.c | 44 +++++++++++++++++----------------- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/usr.bin/xinstall/tests/install_test.sh b/usr.bin/xinstall/tests/install_test.sh index 0f1f93ab4c63..3cea648aa805 100755 --- a/usr.bin/xinstall/tests/install_test.sh +++ b/usr.bin/xinstall/tests/install_test.sh @@ -512,6 +512,42 @@ set_optional_exec_body() atf_check test ! -x testfile } +atf_test_case metalog +metalog_head() { + atf_set "descr" "Test metalog generation" +} +metalog_body() { + atf_check install -M metalog -D dst -m 0755 -d dst + echo ". type=dir mode=0755" >expect + atf_check install -M metalog -D dst -m 0705 -d dst/dir + echo "./dir type=dir mode=0705" >>expect + atf_check -o save:file echo "Hello, world!" + atf_check install -M metalog -D dst -m 0604 file dst/dir + echo "./dir/file type=file mode=0604 size=14" >>expect + atf_check install -M metalog -D dst -lrs dir/file dst/"li nk" + echo "./li\040nk type=link mode=0755 link=dir/file" >>expect + atf_check mtree -f expect -p dst + atf_check -o file:expect cat metalog +} + +atf_test_case digest +digest_head() { + atf_set "descr" "Compute digest while copying" +} +digest_body() { + atf_check mkdir src dst + atf_check -e ignore dd if=/dev/random of=src/file bs=1m count=1 + for alg in md5 rmd160 sha1 sha256 sha512 ; do + rm -f dst/file digest metalog + atf_check -o save:digest $alg -q src/file + atf_check install -M metalog -D dst -h $alg -m 0644 src/file dst + echo -n "./file type=file mode=0644 size=1048576 $alg=" >expect + cat digest >>expect + atf_check cmp src/file dst/file + atf_check -o file:expect cat metalog + done +} + atf_init_test_cases() { atf_add_test_case copy_to_empty atf_add_test_case copy_to_nonexistent @@ -557,4 +593,6 @@ atf_init_test_cases() { atf_add_test_case set_owner_group_mode atf_add_test_case set_owner_group_mode_unpriv atf_add_test_case set_optional_exec + atf_add_test_case metalog + atf_add_test_case digest } diff --git a/usr.bin/xinstall/xinstall.c b/usr.bin/xinstall/xinstall.c index 28b546bc80c2..1aed8c1b24e4 100644 --- a/usr.bin/xinstall/xinstall.c +++ b/usr.bin/xinstall/xinstall.c @@ -140,7 +140,7 @@ static char *destdir, *digest, *fflags, *metafile, *tags; static int compare(int, const char *, size_t, int, const char *, size_t, char **); -static char *copy(int, const char *, int, const char *, off_t); +static char *copy(int, const char *, int, const char *); static int create_tempfile(const char *, char *, size_t); static char *quiet_mktemp(char *template); static char *digest_file(const char *); @@ -877,7 +877,7 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags) } if (!stripped) { digestresult = copy(from_fd, from_name, to_fd, - tempfile, from_sb.st_size); + tempfile); } } } @@ -1175,8 +1175,7 @@ create_tempfile(const char *path, char *temp, size_t tsize) * copy from one file to another */ static char * -copy(int from_fd, const char *from_name, int to_fd, const char *to_name, - off_t size) +copy(int from_fd, const char *from_name, int to_fd, const char *to_name) { static char *buf = NULL; static size_t bufsize; @@ -1198,8 +1197,8 @@ copy(int from_fd, const char *from_name, int to_fd, const char *to_name, if (digesttype == DIGEST_NONE) { do { ret = copy_file_range(from_fd, NULL, to_fd, NULL, - (size_t)size, 0); - } while (ret > 0); + SSIZE_MAX, 0); + } while (ret > 0 || (ret < 0 && errno == EINTR)); if (ret == 0) goto done; if (errno != EINVAL) { @@ -1227,28 +1226,29 @@ copy(int from_fd, const char *from_name, int to_fd, const char *to_name, if (buf == NULL) err(1, "Not enough memory"); } - while ((nr = read(from_fd, buf, bufsize)) > 0) { - if ((nw = write(to_fd, buf, nr)) != nr) { + for (;;) { + if ((nr = read(from_fd, buf, bufsize)) < 0) { + if (errno == EINTR) + continue; serrno = errno; (void)unlink(to_name); - if (nw >= 0) { - errx(EX_OSERR, - "short write to %s: %jd bytes written, " - "%jd bytes asked to write", - to_name, (uintmax_t)nw, - (uintmax_t)size); - } else { + errno = serrno; + err(EX_OSERR, "%s", from_name); + } + if (nr <= 0) + break; + digest_update(&ctx, buf, nr); + while (nr > 0) { + if ((nw = write(to_fd, buf, nr)) < 0) { + if (errno == EINTR) + continue; + serrno = errno; + (void)unlink(to_name); errno = serrno; err(EX_OSERR, "%s", to_name); } + nr -= nw; } - digest_update(&ctx, buf, nr); - } - if (nr != 0) { - serrno = errno; - (void)unlink(to_name); - errno = serrno; - err(EX_OSERR, "%s", from_name); } #ifndef BOOTSTRAP_XINSTALL done: