Page MenuHomeFreeBSD

D58348.id182253.diff
No OneTemporary

D58348.id182253.diff

diff --git a/usr.bin/xinstall/install.1 b/usr.bin/xinstall/install.1
--- a/usr.bin/xinstall/install.1
+++ b/usr.bin/xinstall/install.1
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd June 3, 2026
+.Dd July 19, 2026
.Dt INSTALL 1
.Os
.Sh NAME
@@ -286,6 +286,11 @@
Installing
.Pa /dev/null
creates an empty file.
+Installing
+.Pa /dev/stdin
+or
+.Sy -
+copies data from standard input to the target.
.Sh ENVIRONMENT
The
.Nm
diff --git a/usr.bin/xinstall/tests/install_test.sh b/usr.bin/xinstall/tests/install_test.sh
--- a/usr.bin/xinstall/tests/install_test.sh
+++ b/usr.bin/xinstall/tests/install_test.sh
@@ -557,6 +557,36 @@
done
}
+atf_test_case null
+null_head() {
+ atf_set "descr" "Install empty file"
+}
+null_body() {
+ atf_check mkdir dst
+ atf_check -s exit:71 -e not-empty install /dev/null dst
+ atf_check install /dev/null dst/file
+ atf_check test -f dst/file
+ atf_check test ! -s dst/file
+}
+
+atf_test_case stdin
+stdin_head() {
+ atf_set "descr" "Install stdin"
+}
+stdin_body() {
+ atf_check mkdir dst
+ echo "The Magic Words are Squeamish Ossifrage" >file
+ atf_check -s exit:71 -e not-empty install - dst <file
+ atf_check test ! -e dst/file
+ atf_check install - dst/file <file
+ atf_check cmp -s file dst/file
+ atf_check rm dst/file
+ atf_check -s exit:71 -e not-empty install /dev/stdin dst <file
+ atf_check test ! -e dst/file
+ atf_check install /dev/stdin dst/file <file
+ atf_check cmp -s file dst/file
+}
+
atf_init_test_cases() {
atf_add_test_case incompatible_opts
atf_add_test_case copy_to_empty
@@ -605,4 +635,6 @@
atf_add_test_case set_optional_exec
atf_add_test_case metalog
atf_add_test_case digest
+ atf_add_test_case null
+ atf_add_test_case stdin
}
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
@@ -62,6 +62,13 @@
#include "mtree.h"
+#ifndef _PATH_STDIN
+# ifndef _PATH_DEV
+# defne _PATH_DEV "/dev/"
+# endif
+# define _PATH_STDIN _PATH_DEV "stdin"
+#endif
+
/*
* Memory strategy threshold, in pages: if physmem is larger than this, use a
* large buffer.
@@ -808,7 +815,7 @@
{
struct stat from_sb, temp_sb, to_sb;
struct timespec tsb[2];
- int devnull, files_match, from_fd, serrno, stripped, target;
+ int devnull, files_match, from_fd, ispipe, serrno, stripped, target;
int temp_fd, to_fd;
char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN];
char *digestresult;
@@ -819,7 +826,15 @@
to_fd = -1;
/* If try to install NULL file to a directory, fails. */
- if (flags & DIRECTORY || strcmp(from_name, _PATH_DEVNULL)) {
+ if ((devnull = strcmp(from_name, _PATH_DEVNULL) == 0) ||
+ strcmp(from_name, _PATH_STDIN) == 0 ||
+ strcmp(from_name, "-") == 0) {
+ if ((flags & DIRECTORY) != 0)
+ errc(EX_OSERR, EFTYPE, "%s", from_name);
+ if (!devnull)
+ from_fd = STDIN_FILENO;
+ ispipe = 1;
+ } else {
if (!dolink) {
if (stat(from_name, &from_sb))
err(EX_OSERR, "%s", from_name);
@@ -834,9 +849,7 @@
(p = strrchr(from_name, '/')) ? ++p : from_name);
to_name = pathbuf;
}
- devnull = 0;
- } else {
- devnull = 1;
+ ispipe = 0;
}
if (*to_name == '\0')
errx(EX_USAGE, "destination cannot be an empty string");
@@ -851,19 +864,24 @@
if (target && !S_ISREG(to_sb.st_mode) && !S_ISLNK(to_sb.st_mode))
errc(EX_CANTCREAT, EFTYPE, "%s", to_name);
- if (!devnull && (from_fd = open(from_name, O_RDONLY, 0)) < 0)
- err(EX_OSERR, "%s", from_name);
+ if (!ispipe) {
+ if ((from_fd = open(from_name, O_RDONLY)) < 0)
+ err(EX_OSERR, "%s", from_name);
+ }
/* If we don't strip, we can compare first. */
if (docompare && !dostrip && target && S_ISREG(to_sb.st_mode)) {
- if ((to_fd = open(to_name, O_RDONLY, 0)) < 0)
+ if ((to_fd = open(to_name, O_RDONLY)) < 0)
err(EX_OSERR, "%s", to_name);
if (devnull)
files_match = to_sb.st_size == 0;
- else
+ else if (ispipe)
+ files_match = 0;
+ else {
files_match = !(compare(from_fd, from_name,
(size_t)from_sb.st_size, to_fd,
to_name, (size_t)to_sb.st_size, &digestresult));
+ }
/* Close "to" file unless we match. */
if (!files_match)
@@ -1070,7 +1088,7 @@
#endif
(void)close(to_fd);
- if (!devnull)
+ if (!ispipe)
(void)close(from_fd);
metadata_log(to_name, "file", tsb, NULL, digestresult, to_sb.st_size);
@@ -1188,12 +1206,6 @@
#endif
DIGEST_CTX ctx;
- /* Rewind file descriptors. */
- if (lseek(from_fd, 0, SEEK_SET) < 0)
- err(EX_OSERR, "lseek: %s", from_name);
- 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) {

File Metadata

Mime Type
text/plain
Expires
Fri, Jul 24, 6:51 AM (19 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35434724
Default Alt Text
D58348.id182253.diff (4 KB)

Event Timeline