Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163446069
D58348.id182253.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D58348.id182253.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D58348: install: Allow installing stdin
Attached
Detach File
Event Timeline
Log In to Comment