Page MenuHomeFreeBSD

D57411.diff
No OneTemporary

D57411.diff

Index: usr.bin/xinstall/install.1
===================================================================
--- usr.bin/xinstall/install.1
+++ usr.bin/xinstall/install.1
@@ -187,11 +187,25 @@
symbolic
.It Sy m
mixed
+.It Sy c
+metalog contents reference
.El
.Pp
Absolute and relative have effect only for symbolic links.
Mixed links
are hard links for files on the same filesystem, symbolic otherwise.
+.Pp
+The
+.Ar c
+link type does not create a filesystem object.
+Instead, the source file's absolute path is recorded using the
+.Xr mtree 5
+.Cm contents
+tag in the
+.Ar metalog
+file.
+It must be used with
+.Fl M Ar metalog .
.It Fl M Ar metalog
Write the metadata associated with each item installed to
.Ar metalog
Index: usr.bin/xinstall/tests/install_test.sh
===================================================================
--- usr.bin/xinstall/tests/install_test.sh
+++ usr.bin/xinstall/tests/install_test.sh
@@ -32,6 +32,8 @@
install -s -d dir1
atf_check -s not-exit:0 -e match:"specified together" \
install -s -l s testf copyf
+ atf_check -s not-exit:0 -e match:"requires -M metalog" \
+ install -l c testf copyf
}
atf_test_case copy_to_empty
Index: usr.bin/xinstall/xinstall.c
===================================================================
--- usr.bin/xinstall/xinstall.c
+++ usr.bin/xinstall/xinstall.c
@@ -95,6 +95,7 @@
#define LN_HARD 0x04
#define LN_SYMBOLIC 0x08
#define LN_MIXED 0x10
+#define LN_CONTENTS 0x20
#define DIRECTORY 0x01 /* Tell install it's a directory. */
#define SETFLAGS 0x02 /* Tell install to set flags. */
@@ -155,7 +156,8 @@
static void install(const char *, const char *, u_long, u_int);
static void install_dir(char *);
static void metadata_log(const char *, const char *, struct timespec *,
- const char *, const char *, off_t);
+ const char *, const char *, off_t, const char *);
+static void parse_l_args(const char *p);
static int parseid(const char *, id_t *);
static int strip(const char *, int, const char *, char **);
static void usage(void);
@@ -168,7 +170,6 @@
u_long fset;
int ch, no_target;
u_int iflags;
- char *p;
const char *to_name;
uint64_t num;
@@ -209,32 +210,7 @@
digest = optarg;
break;
case 'l':
- for (p = optarg; *p != '\0'; p++)
- switch (*p) {
- case 's':
- dolink &= ~(LN_HARD|LN_MIXED);
- dolink |= LN_SYMBOLIC;
- break;
- case 'h':
- dolink &= ~(LN_SYMBOLIC|LN_MIXED);
- dolink |= LN_HARD;
- break;
- case 'm':
- dolink &= ~(LN_SYMBOLIC|LN_HARD);
- dolink |= LN_MIXED;
- break;
- case 'a':
- dolink &= ~LN_RELATIVE;
- dolink |= LN_ABSOLUTE;
- break;
- case 'r':
- dolink &= ~LN_ABSOLUTE;
- dolink |= LN_RELATIVE;
- break;
- default:
- errx(1, "%c: invalid link type", *p);
- /* NOTREACHED */
- }
+ parse_l_args(optarg);
break;
case 'M':
metafile = optarg;
@@ -299,6 +275,11 @@
usage();
}
+ if ((dolink & LN_CONTENTS) && metafile == NULL) {
+ warnx("-l c requires -M metalog");
+ usage();
+ }
+
/*
* Default permissions based on whether we're a directory or not, since
* an +X may mean that we need to set the execute bit.
@@ -427,6 +408,42 @@
/* NOTREACHED */
}
+static void
+parse_l_args(const char *p)
+{
+ for (p = optarg; *p != '\0'; p++) {
+ switch (*p) {
+ case 'c':
+ dolink &= ~(LN_SYMBOLIC | LN_HARD | LN_MIXED);
+ dolink |= LN_CONTENTS;
+ break;
+ case 's':
+ dolink &= ~(LN_CONTENTS | LN_HARD | LN_MIXED);
+ dolink |= LN_SYMBOLIC;
+ break;
+ case 'h':
+ dolink &= ~(LN_CONTENTS | LN_SYMBOLIC | LN_MIXED);
+ dolink |= LN_HARD;
+ break;
+ case 'm':
+ dolink &= ~(LN_CONTENTS | LN_SYMBOLIC | LN_HARD);
+ dolink |= LN_MIXED;
+ break;
+ case 'a':
+ dolink &= ~LN_RELATIVE;
+ dolink |= LN_ABSOLUTE;
+ break;
+ case 'r':
+ dolink &= ~LN_ABSOLUTE;
+ dolink |= LN_RELATIVE;
+ break;
+ default:
+ errx(1, "%c: invalid link type", *p);
+ /* NOTREACHED */
+ }
+ }
+}
+
static char *
digest_file(const char *name)
{
@@ -673,7 +690,25 @@
const char *base, *dir;
struct stat to_sb;
- /* Try hard links first. */
+ /* First check for mtree contents reference. */
+ if (dolink & LN_CONTENTS) {
+ struct stat from_sb;
+ char *dres;
+
+ if (dolink & LN_RELATIVE)
+ errx(EX_OSERR, "relative contents not yet supported");
+ if (stat(from_name, &from_sb))
+ err(EX_OSERR, "%s: stat", from_name);
+ if (realpath(from_name, src) == NULL)
+ err(EX_OSERR, "%s: realpath", from_name);
+ dres = digest_file(from_name);
+ metadata_log(to_name, "file", NULL, NULL, dres,
+ from_sb.st_size, src);
+ free(dres);
+ return;
+ }
+
+ /* Try hard links next. */
if (dolink & (LN_HARD|LN_MIXED)) {
if (do_link(from_name, to_name, target_sb) == -1) {
if ((dolink & LN_HARD) || errno != EXDEV)
@@ -709,7 +744,7 @@
fflags = NULL;
dres = digest_file(from_name);
metadata_log(to_name, "file", NULL, NULL,
- dres, to_sb.st_size);
+ dres, to_sb.st_size, NULL);
free(dres);
mode = omode;
owner = oowner;
@@ -727,7 +762,7 @@
err(EX_OSERR, "%s: realpath", from_name);
do_symlink(src, to_name, target_sb);
/* XXX: src may point outside of destdir */
- metadata_log(to_name, "link", NULL, src, NULL, 0);
+ metadata_log(to_name, "link", NULL, src, NULL, 0, NULL);
return;
}
@@ -736,7 +771,8 @@
/* this is already a relative link */
do_symlink(from_name, to_name, target_sb);
/* XXX: from_name may point outside of destdir. */
- metadata_log(to_name, "link", NULL, from_name, NULL, 0);
+ metadata_log(to_name, "link", NULL, from_name, NULL, 0,
+ NULL);
return;
}
@@ -797,7 +833,7 @@
do_symlink(lnk, to_name, target_sb);
/* XXX: Link may point outside of destdir. */
- metadata_log(to_name, "link", NULL, lnk, NULL, 0);
+ metadata_log(to_name, "link", NULL, lnk, NULL, 0, NULL);
return;
}
@@ -807,7 +843,7 @@
*/
do_symlink(from_name, to_name, target_sb);
/* XXX: from_name may point outside of destdir. */
- metadata_log(to_name, "link", NULL, from_name, NULL, 0);
+ metadata_log(to_name, "link", NULL, from_name, NULL, 0, NULL);
}
/*
@@ -1084,7 +1120,8 @@
if (!devnull)
(void)close(from_fd);
- metadata_log(to_name, "file", tsb, NULL, digestresult, to_sb.st_size);
+ metadata_log(to_name, "file", tsb, NULL, digestresult, to_sb.st_size,
+ NULL);
free(digestresult);
}
@@ -1392,7 +1429,7 @@
if (chmod(path, mode))
warn("chmod %o %s", mode, path);
}
- metadata_log(path, "dir", NULL, NULL, NULL, 0);
+ metadata_log(path, "dir", NULL, NULL, NULL, 0, NULL);
}
/*
@@ -1403,7 +1440,8 @@
*/
static void
metadata_log(const char *path, const char *type, struct timespec *ts,
- const char *slink, const char *digestresult, off_t size)
+ const char *slink, const char *digestresult, off_t size,
+ const char *contents)
{
static const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' };
const char *p;
@@ -1413,10 +1451,12 @@
if (!metafp)
return;
- /* Buffer for strsnvis(3), used for both path and slink. */
+ /* Buffer for strsnvis(3), used for path, slink, and contents. */
buflen = strlen(path);
if (slink && strlen(slink) > buflen)
buflen = strlen(slink);
+ if (contents && strlen(contents) > buflen)
+ buflen = strlen(contents);
buflen = 4 * buflen + 1;
if ((buf = malloc(buflen)) == NULL) {
warn(NULL);
@@ -1469,6 +1509,10 @@
strsnvis(buf, buflen, slink, VIS_CSTYLE, extra);
fprintf(metafp, " link=%s", buf);
}
+ if (contents) {
+ strsnvis(buf, buflen, contents, VIS_OCTAL, extra);
+ fprintf(metafp, " contents=%s", buf);
+ }
if (*type == 'f') /* type=file */
fprintf(metafp, " size=%llu", (unsigned long long)size);
if (ts != NULL && dopreserve)

File Metadata

Mime Type
text/plain
Expires
Mon, Jul 6, 11:18 PM (10 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34732290
Default Alt Text
D57411.diff (7 KB)

Event Timeline