Import latest mtree from NetBSD
Merge commit 'f600477feb4ae61a75f61949eb600caff4aeea8c' MFC after: 1 week Discussed with: brooks
This commit is contained in:
+24
-15
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: compare.c,v 1.58 2013/11/21 18:39:50 christos Exp $ */
|
||||
/* $NetBSD: compare.c,v 1.61 2024/12/05 17:17:43 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1989, 1993
|
||||
@@ -38,7 +38,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)compare.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: compare.c,v 1.58 2013/11/21 18:39:50 christos Exp $");
|
||||
__RCSID("$NetBSD: compare.c,v 1.61 2024/12/05 17:17:43 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@@ -135,8 +135,9 @@ do { \
|
||||
int
|
||||
compare(NODE *s, FTSENT *p)
|
||||
{
|
||||
u_int32_t len, val, flags;
|
||||
uint32_t len, val, flags;
|
||||
int fd, label;
|
||||
bool was_unlinked;
|
||||
const char *cp, *tab;
|
||||
#if !defined(NO_MD5) || !defined(NO_RMD160) || !defined(NO_SHA1) || !defined(NO_SHA2)
|
||||
char *digestbuf;
|
||||
@@ -144,6 +145,7 @@ compare(NODE *s, FTSENT *p)
|
||||
|
||||
tab = NULL;
|
||||
label = 0;
|
||||
was_unlinked = false;
|
||||
switch(s->type) {
|
||||
case F_BLOCK:
|
||||
if (!S_ISBLK(p->fts_statp->st_mode))
|
||||
@@ -210,47 +212,53 @@ typeerr: LABEL;
|
||||
s->st_mode | nodetoino(s->type),
|
||||
s->st_rdev) == -1) ||
|
||||
(lchown(p->fts_accpath, p->fts_statp->st_uid,
|
||||
p->fts_statp->st_gid) == -1) )
|
||||
p->fts_statp->st_gid) == -1) ) {
|
||||
printf(", not modified: %s%s\n",
|
||||
strerror(errno),
|
||||
flavor == F_FREEBSD9 ? "" : ")");
|
||||
else
|
||||
} else {
|
||||
printf(", modified%s\n",
|
||||
flavor == F_FREEBSD9 ? "" : ")");
|
||||
was_unlinked = true;
|
||||
}
|
||||
} else
|
||||
printf(")\n");
|
||||
tab = "\t";
|
||||
}
|
||||
/* Set the uid/gid first, then set the mode. */
|
||||
if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) {
|
||||
if (s->flags & (F_UID | F_UNAME) &&
|
||||
(was_unlinked || s->st_uid != p->fts_statp->st_uid)) {
|
||||
LABEL;
|
||||
printf(flavor == F_FREEBSD9 ?
|
||||
"%suser expected %lu found %lu" : "%suser (%lu, %lu",
|
||||
tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid);
|
||||
if (uflag) {
|
||||
if (lchown(p->fts_accpath, s->st_uid, -1))
|
||||
if (lchown(p->fts_accpath, s->st_uid, (gid_t)-1))
|
||||
printf(", not modified: %s%s\n",
|
||||
strerror(errno),
|
||||
flavor == F_FREEBSD9 ? "" : ")");
|
||||
else
|
||||
printf(", modified%s\n",
|
||||
printf(", modified%s%s\n",
|
||||
was_unlinked ? " by unlink" : "",
|
||||
flavor == F_FREEBSD9 ? "" : ")");
|
||||
} else
|
||||
printf(")\n");
|
||||
tab = "\t";
|
||||
}
|
||||
if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) {
|
||||
if (s->flags & (F_GID | F_GNAME) &&
|
||||
(was_unlinked || s->st_gid != p->fts_statp->st_gid)) {
|
||||
LABEL;
|
||||
printf(flavor == F_FREEBSD9 ?
|
||||
"%sgid expected %lu found %lu" : "%sgid (%lu, %lu",
|
||||
tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid);
|
||||
if (uflag) {
|
||||
if (lchown(p->fts_accpath, -1, s->st_gid))
|
||||
if (lchown(p->fts_accpath, (uid_t)-1, s->st_gid))
|
||||
printf(", not modified: %s%s\n",
|
||||
strerror(errno),
|
||||
flavor == F_FREEBSD9 ? "" : ")");
|
||||
else
|
||||
printf(", modified%s\n",
|
||||
printf(", modified%s%s\n",
|
||||
was_unlinked ? " by unlink" : "",
|
||||
flavor == F_FREEBSD9 ? "" : ")");
|
||||
}
|
||||
else
|
||||
@@ -258,8 +266,8 @@ typeerr: LABEL;
|
||||
tab = "\t";
|
||||
}
|
||||
if (s->flags & F_MODE &&
|
||||
s->st_mode != (p->fts_statp->st_mode & MBITS)) {
|
||||
if (lflag) {
|
||||
(was_unlinked || s->st_mode != (p->fts_statp->st_mode & MBITS))) {
|
||||
if (lflag && !was_unlinked) {
|
||||
mode_t tmode, mode;
|
||||
|
||||
tmode = s->st_mode;
|
||||
@@ -287,7 +295,8 @@ typeerr: LABEL;
|
||||
strerror(errno),
|
||||
flavor == F_FREEBSD9 ? "" : ")");
|
||||
else
|
||||
printf(", modified%s\n",
|
||||
printf(", modified%s%s\n",
|
||||
was_unlinked ? " by unlink" : "",
|
||||
flavor == F_FREEBSD9 ? "" : ")");
|
||||
}
|
||||
else
|
||||
@@ -567,7 +576,7 @@ const char *
|
||||
rlink(const char *name)
|
||||
{
|
||||
static char lbuf[MAXPATHLEN];
|
||||
int len;
|
||||
ssize_t len;
|
||||
|
||||
if ((len = readlink(name, lbuf, sizeof(lbuf) - 1)) == -1)
|
||||
mtree_err("%s: %s", name, strerror(errno));
|
||||
|
||||
+10
-10
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: crc.c,v 1.9 2012/10/05 00:40:51 christos Exp $ */
|
||||
/* $NetBSD: crc.c,v 1.11 2024/12/05 17:17:43 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
@@ -41,7 +41,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)crc.c 8.1 (Berkeley) 6/17/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: crc.c,v 1.9 2012/10/05 00:40:51 christos Exp $");
|
||||
__RCSID("$NetBSD: crc.c,v 1.11 2024/12/05 17:17:43 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@@ -53,7 +53,7 @@ __RCSID("$NetBSD: crc.c,v 1.9 2012/10/05 00:40:51 christos Exp $");
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
static const u_int32_t crctab[] = {
|
||||
static const uint32_t crctab[] = {
|
||||
0x0,
|
||||
0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
|
||||
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
|
||||
@@ -114,15 +114,15 @@ static const u_int32_t crctab[] = {
|
||||
* locations to store the crc and the number of bytes read. It returns 0 on
|
||||
* success and 1 on failure. Errno is set on failure.
|
||||
*/
|
||||
u_int32_t crc_total = ~0; /* The crc over a number of files. */
|
||||
uint32_t crc_total = ~0u; /* The crc over a number of files. */
|
||||
|
||||
int
|
||||
crc(int fd, u_int32_t *cval, u_int32_t *clen)
|
||||
crc(int fd, uint32_t *cval, uint32_t *clen)
|
||||
{
|
||||
u_char *p;
|
||||
int nr;
|
||||
u_int32_t thecrc, len;
|
||||
u_int32_t crctot;
|
||||
ssize_t nr;
|
||||
uint32_t thecrc, len;
|
||||
uint32_t crctot;
|
||||
u_char buf[16 * 1024];
|
||||
|
||||
#define COMPUTE(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
|
||||
@@ -132,12 +132,12 @@ crc(int fd, u_int32_t *cval, u_int32_t *clen)
|
||||
crctot = ~crc_total;
|
||||
while ((nr = read(fd, buf, sizeof(buf))) > 0)
|
||||
if (sflag) {
|
||||
for (len += nr, p = buf; nr--; ++p) {
|
||||
for (len += (uint32_t)nr, p = buf; nr--; ++p) {
|
||||
COMPUTE(thecrc, *p);
|
||||
COMPUTE(crctot, *p);
|
||||
}
|
||||
} else {
|
||||
for (len += nr, p = buf; nr--; ++p)
|
||||
for (len += (uint32_t)nr, p = buf; nr--; ++p)
|
||||
COMPUTE(thecrc, *p);
|
||||
}
|
||||
if (nr < 0)
|
||||
|
||||
+60
-84
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: create.c,v 1.73 2014/04/24 17:22:41 christos Exp $ */
|
||||
/* $NetBSD: create.c,v 1.79 2024/12/05 17:17:43 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1989, 1993
|
||||
@@ -38,7 +38,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)create.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: create.c,v 1.73 2014/04/24 17:22:41 christos Exp $");
|
||||
__RCSID("$NetBSD: create.c,v 1.79 2024/12/05 17:17:43 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@@ -84,13 +84,6 @@ static uid_t uid;
|
||||
static mode_t mode;
|
||||
static u_long flags;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define FTS_CONST const
|
||||
#else
|
||||
#define FTS_CONST
|
||||
#endif
|
||||
|
||||
static int dcmp(const FTSENT *FTS_CONST *, const FTSENT *FTS_CONST *);
|
||||
static void output(FILE *, int, int *, const char *, ...)
|
||||
__printflike(4, 5);
|
||||
static int statd(FILE *, FTS *, FTSENT *, uid_t *, gid_t *, mode_t *,
|
||||
@@ -180,15 +173,59 @@ cwalk(FILE *fp)
|
||||
mtree_err("%s checksum: %u", fullpath, crc_total);
|
||||
}
|
||||
|
||||
static void
|
||||
dosum(FILE *fp, int indent, FTSENT *p, int *offset, int flag,
|
||||
char * (*func)(const char *, char *), const char *key)
|
||||
{
|
||||
char *digestbuf;
|
||||
|
||||
if ((keys & flag) == 0)
|
||||
return;
|
||||
|
||||
digestbuf = (*func)(p->fts_accpath, NULL);
|
||||
if (digestbuf != NULL) {
|
||||
output(fp, indent, offset, "%s=%s", key, digestbuf);
|
||||
free(digestbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (qflag) {
|
||||
warn("%s: %s failed", p->fts_path, key);
|
||||
return;
|
||||
}
|
||||
|
||||
mtree_err("%s: %s failed: %s", p->fts_path, key, strerror(errno));
|
||||
}
|
||||
|
||||
static char *
|
||||
crcFile(const char *fname, char *dummy __unused)
|
||||
{
|
||||
char *ptr;
|
||||
uint32_t val, len;
|
||||
int fd, e;
|
||||
|
||||
if ((fd = open(fname, O_RDONLY)) == -1)
|
||||
goto out;
|
||||
|
||||
e = crc(fd, &val, &len);
|
||||
close(fd);
|
||||
if (e)
|
||||
goto out;
|
||||
|
||||
if (asprintf(&ptr, "%u", val) < 0)
|
||||
goto out;
|
||||
|
||||
return ptr;
|
||||
out:
|
||||
mtree_err("%s: %s", fname, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
statf(FILE *fp, int indent, FTSENT *p)
|
||||
{
|
||||
u_int32_t len, val;
|
||||
int fd, offset;
|
||||
int offset;
|
||||
const char *name = NULL;
|
||||
#if !defined(NO_MD5) || !defined(NO_RMD160) || !defined(NO_SHA1) || !defined(NO_SHA2)
|
||||
char *digestbuf;
|
||||
#endif
|
||||
|
||||
offset = fprintf(fp, "%*s%s%s", indent, "",
|
||||
S_ISDIR(p->fts_statp->st_mode) ? "" : " ", vispath(p->fts_name));
|
||||
@@ -241,65 +278,25 @@ statf(FILE *fp, int indent, FTSENT *p)
|
||||
output(fp, indent, &offset, "time=%jd.%09ld",
|
||||
(intmax_t)p->fts_statp->st_mtime, (long)0);
|
||||
#endif
|
||||
if (keys & F_CKSUM && S_ISREG(p->fts_statp->st_mode)) {
|
||||
if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0 ||
|
||||
crc(fd, &val, &len))
|
||||
mtree_err("%s: %s", p->fts_accpath, strerror(errno));
|
||||
close(fd);
|
||||
output(fp, indent, &offset, "cksum=%lu", (long)val);
|
||||
}
|
||||
if (S_ISREG(p->fts_statp->st_mode)) {
|
||||
dosum(fp, indent, p, &offset, F_CKSUM, crcFile, "cksum");
|
||||
#ifndef NO_MD5
|
||||
if (keys & F_MD5 && S_ISREG(p->fts_statp->st_mode)) {
|
||||
if ((digestbuf = MD5File(p->fts_accpath, NULL)) == NULL)
|
||||
mtree_err("%s: MD5File failed: %s", p->fts_accpath,
|
||||
strerror(errno));
|
||||
output(fp, indent, &offset, "%s=%s", MD5KEY, digestbuf);
|
||||
free(digestbuf);
|
||||
}
|
||||
dosum(fp, indent, p, &offset, F_MD5, MD5File, MD5KEY);
|
||||
#endif /* ! NO_MD5 */
|
||||
#ifndef NO_RMD160
|
||||
if (keys & F_RMD160 && S_ISREG(p->fts_statp->st_mode)) {
|
||||
if ((digestbuf = RMD160File(p->fts_accpath, NULL)) == NULL)
|
||||
mtree_err("%s: RMD160File failed: %s", p->fts_accpath,
|
||||
strerror(errno));
|
||||
output(fp, indent, &offset, "%s=%s", RMD160KEY, digestbuf);
|
||||
free(digestbuf);
|
||||
}
|
||||
dosum(fp, indent, p, &offset, F_RMD160, RMD160File, RMD160KEY);
|
||||
#endif /* ! NO_RMD160 */
|
||||
#ifndef NO_SHA1
|
||||
if (keys & F_SHA1 && S_ISREG(p->fts_statp->st_mode)) {
|
||||
if ((digestbuf = SHA1File(p->fts_accpath, NULL)) == NULL)
|
||||
mtree_err("%s: SHA1File failed: %s", p->fts_accpath,
|
||||
strerror(errno));
|
||||
output(fp, indent, &offset, "%s=%s", SHA1KEY, digestbuf);
|
||||
free(digestbuf);
|
||||
}
|
||||
dosum(fp, indent, p, &offset, F_SHA1, SHA1File, SHA1KEY);
|
||||
#endif /* ! NO_SHA1 */
|
||||
#ifndef NO_SHA2
|
||||
if (keys & F_SHA256 && S_ISREG(p->fts_statp->st_mode)) {
|
||||
if ((digestbuf = SHA256_File(p->fts_accpath, NULL)) == NULL)
|
||||
mtree_err("%s: SHA256_File failed: %s", p->fts_accpath,
|
||||
strerror(errno));
|
||||
output(fp, indent, &offset, "%s=%s", SHA256KEY, digestbuf);
|
||||
free(digestbuf);
|
||||
}
|
||||
dosum(fp, indent, p, &offset, F_SHA256, SHA256_File, SHA256KEY);
|
||||
#ifdef SHA384_BLOCK_LENGTH
|
||||
if (keys & F_SHA384 && S_ISREG(p->fts_statp->st_mode)) {
|
||||
if ((digestbuf = SHA384_File(p->fts_accpath, NULL)) == NULL)
|
||||
mtree_err("%s: SHA384_File failed: %s", p->fts_accpath,
|
||||
strerror(errno));
|
||||
output(fp, indent, &offset, "%s=%s", SHA384KEY, digestbuf);
|
||||
free(digestbuf);
|
||||
}
|
||||
dosum(fp, indent, p, &offset, F_SHA384, SHA384_File, SHA384KEY);
|
||||
#endif
|
||||
if (keys & F_SHA512 && S_ISREG(p->fts_statp->st_mode)) {
|
||||
if ((digestbuf = SHA512_File(p->fts_accpath, NULL)) == NULL)
|
||||
mtree_err("%s: SHA512_File failed: %s", p->fts_accpath,
|
||||
strerror(errno));
|
||||
output(fp, indent, &offset, "%s=%s", SHA512KEY, digestbuf);
|
||||
free(digestbuf);
|
||||
}
|
||||
dosum(fp, indent, p, &offset, F_SHA512, SHA512_File, SHA512KEY);
|
||||
#endif /* ! NO_SHA2 */
|
||||
}
|
||||
if (keys & F_SLINK &&
|
||||
(p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE))
|
||||
output(fp, indent, &offset, "link=%s",
|
||||
@@ -440,27 +437,6 @@ statd(FILE *fp, FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode,
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* dcmp --
|
||||
* used as a comparison function passed to fts_open() to control
|
||||
* the order in which fts_read() returns results. We make
|
||||
* directories sort after non-directories, but otherwise sort in
|
||||
* strcmp() order.
|
||||
*
|
||||
* Keep this in sync with nodecmp() in spec.c.
|
||||
*/
|
||||
static int
|
||||
dcmp(const FTSENT *FTS_CONST *a, const FTSENT *FTS_CONST *b)
|
||||
{
|
||||
|
||||
if (S_ISDIR((*a)->fts_statp->st_mode)) {
|
||||
if (!S_ISDIR((*b)->fts_statp->st_mode))
|
||||
return (1);
|
||||
} else if (S_ISDIR((*b)->fts_statp->st_mode))
|
||||
return (-1);
|
||||
return (strcmp((*a)->fts_name, (*b)->fts_name));
|
||||
}
|
||||
|
||||
void
|
||||
output(FILE *fp, int indent, int *offset, const char *fmt, ...)
|
||||
{
|
||||
|
||||
+10
-3
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: extern.h,v 1.39 2014/04/24 17:22:41 christos Exp $ */
|
||||
/* $NetBSD: extern.h,v 1.41 2024/12/05 17:17:43 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
@@ -49,6 +49,12 @@
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) && !defined(HAVE_NBTOOL_CONFIG_H)
|
||||
#define FTS_CONST const
|
||||
#else
|
||||
#define FTS_CONST
|
||||
#endif
|
||||
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 256
|
||||
#endif
|
||||
@@ -62,8 +68,9 @@ enum flavor {
|
||||
void addtag(slist_t *, char *);
|
||||
int check_excludes(const char *, const char *);
|
||||
int compare(NODE *, FTSENT *);
|
||||
int crc(int, u_int32_t *, u_int32_t *);
|
||||
int crc(int, uint32_t *, uint32_t *);
|
||||
void cwalk(FILE *);
|
||||
int dcmp(const FTSENT *FTS_CONST *, const FTSENT *FTS_CONST *);
|
||||
void dump_nodes(FILE *, const char *, NODE *, int);
|
||||
void init_excludes(void);
|
||||
int matchtags(NODE *);
|
||||
@@ -83,7 +90,7 @@ extern int bflag, dflag, eflag, iflag, jflag, lflag, mflag,
|
||||
extern int mtree_Mflag, mtree_Sflag, mtree_Wflag;
|
||||
extern size_t mtree_lineno;
|
||||
extern enum flavor flavor;
|
||||
extern u_int32_t crc_total;
|
||||
extern uint32_t crc_total;
|
||||
extern int ftsoptions, keys;
|
||||
extern char fullpath[];
|
||||
extern slist_t includetags, excludetags;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: misc.c,v 1.34 2012/12/20 19:09:25 christos Exp $ */
|
||||
/* $NetBSD: misc.c,v 1.35 2024/12/05 17:17:43 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(__RCSID) && !defined(lint)
|
||||
__RCSID("$NetBSD: misc.c,v 1.34 2012/12/20 19:09:25 christos Exp $");
|
||||
__RCSID("$NetBSD: misc.c,v 1.35 2024/12/05 17:17:43 christos Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -111,7 +111,7 @@ slist_t excludetags, includetags;
|
||||
int keys = KEYDEFAULT;
|
||||
|
||||
|
||||
int keycompare(const void *, const void *);
|
||||
static int keycompare(const void *, const void *);
|
||||
|
||||
u_int
|
||||
parsekey(const char *name, int *needvaluep)
|
||||
@@ -153,7 +153,7 @@ parsetype(const char *name)
|
||||
return (k->val);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
keycompare(const void *a, const void *b)
|
||||
{
|
||||
|
||||
@@ -198,7 +198,7 @@ void
|
||||
parsetags(slist_t *list, char *args)
|
||||
{
|
||||
char *p, *e;
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
if (args == NULL) {
|
||||
addtag(list, NULL);
|
||||
|
||||
+108
-31
@@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: mtree.8,v 1.69 2013/02/03 19:16:06 christos Exp $
|
||||
.\" $NetBSD: mtree.8,v 1.78 2023/12/02 13:26:09 christos Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@@ -56,7 +56,7 @@
|
||||
.\"
|
||||
.\" @(#)mtree.8 8.2 (Berkeley) 12/11/93
|
||||
.\"
|
||||
.Dd February 3, 2013
|
||||
.Dd December 2, 2023
|
||||
.Dt MTREE 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -93,9 +93,11 @@ characteristics do not match the specification, or which are
|
||||
missing from either the file hierarchy or the specification.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Xxxexcludexfilexx
|
||||
.Bl -tag -width Fl
|
||||
.
|
||||
.It Fl b
|
||||
Suppress blank lines before entering and after exiting directories.
|
||||
.
|
||||
.It Fl C
|
||||
Convert a specification into
|
||||
a format that's easier to parse with various tools.
|
||||
@@ -105,8 +107,7 @@ from the file given by
|
||||
In the output, each file or directory is represented using a single line
|
||||
(which might be very long).
|
||||
The full path name
|
||||
(beginning with
|
||||
.Dq \&./ )
|
||||
.Pq beginning with Ql \&./
|
||||
is always printed as the first field;
|
||||
.Fl K ,
|
||||
.Fl k ,
|
||||
@@ -120,19 +121,25 @@ can be used to control which files are printed;
|
||||
and the
|
||||
.Fl S
|
||||
option can be used to sort the output.
|
||||
.
|
||||
.It Fl c
|
||||
Print a specification for the file hierarchy originating at
|
||||
the current working directory (or the directory provided by
|
||||
.Fl p Ar path )
|
||||
the current working directory
|
||||
.Po or the directory provided by
|
||||
.Fl p Ar path
|
||||
.Pc
|
||||
to the standard output.
|
||||
The output is in a style using relative path names.
|
||||
.
|
||||
.It Fl D
|
||||
As per
|
||||
.Fl C ,
|
||||
except that the path name is always printed as the last field instead of
|
||||
the first.
|
||||
.
|
||||
.It Fl d
|
||||
Ignore everything except directory type files.
|
||||
.
|
||||
.It Fl E Ar tags
|
||||
Add the comma separated tags to the
|
||||
.Dq exclusion
|
||||
@@ -141,9 +148,11 @@ Non-directories with tags which are in the exclusion list are not printed with
|
||||
.Fl C
|
||||
and
|
||||
.Fl D .
|
||||
.
|
||||
.It Fl e
|
||||
Don't complain about files that are in the file hierarchy, but not in the
|
||||
specification.
|
||||
.
|
||||
.It Fl F Ar flavor
|
||||
Set the compatibility flavor of the
|
||||
.Nm
|
||||
@@ -151,22 +160,23 @@ utility.
|
||||
The
|
||||
.Ar flavor
|
||||
can be one of
|
||||
.Sy mtree ,
|
||||
.Sy freebsd9 ,
|
||||
.Cm mtree ,
|
||||
.Cm freebsd9 ,
|
||||
or
|
||||
.Sy netbsd6 .
|
||||
.Cm netbsd6 .
|
||||
The default is
|
||||
.Sy mtree .
|
||||
.Cm mtree .
|
||||
The
|
||||
.Sy freebsd9
|
||||
.Cm freebsd9
|
||||
and
|
||||
.Sy netbsd6
|
||||
flavors attempt to preserve output compatiblity and command line option
|
||||
.Cm netbsd6
|
||||
flavors attempt to preserve output compatibility and command line option
|
||||
backward compatibility with
|
||||
.Fx 9.0
|
||||
and
|
||||
.Nx 6.0
|
||||
respectively.
|
||||
.
|
||||
.It Fl f Ar spec
|
||||
Read the specification from
|
||||
.Ar file ,
|
||||
@@ -178,10 +188,18 @@ The specifications will be sorted like output generated using
|
||||
.Fl c .
|
||||
The output format in this case is somewhat reminiscent of
|
||||
.Xr comm 1 ,
|
||||
having "in first spec only", "in second spec only", and "different"
|
||||
columns, prefixed by zero, one and two TAB characters respectively.
|
||||
Each entry in the "different" column occupies two lines, one from each
|
||||
specification.
|
||||
having
|
||||
.Dq in first spec only ,
|
||||
.Dq in second spec only ,
|
||||
and
|
||||
.Dq different
|
||||
columns, prefixed by zero, one and two
|
||||
.Tn TAB
|
||||
characters respectively.
|
||||
Each entry in the
|
||||
.Dq different
|
||||
column occupies two lines, one from each specification.
|
||||
.
|
||||
.It Fl I Ar tags
|
||||
Add the comma separated tags to the
|
||||
.Dq inclusion
|
||||
@@ -191,14 +209,22 @@ Non-directories with tags which are in the inclusion list are printed with
|
||||
and
|
||||
.Fl D .
|
||||
If no inclusion list is provided, the default is to display all files.
|
||||
.
|
||||
.It Fl i
|
||||
If specified, set the schg and/or sappnd flags.
|
||||
If specified, set the
|
||||
.Ql schg
|
||||
and/or
|
||||
.Ql sappnd
|
||||
flags.
|
||||
.
|
||||
.It Fl j
|
||||
Indent the output 4 spaces each time a directory level is descended when
|
||||
creating a specification with the
|
||||
.Fl c
|
||||
option.
|
||||
This does not affect either the /set statements or the comment before each
|
||||
This does not affect either the
|
||||
.Ql /set
|
||||
statements or the comment before each
|
||||
directory.
|
||||
It does however affect the comment before the close of each directory.
|
||||
This is the equivalent of the
|
||||
@@ -207,26 +233,31 @@ option in the
|
||||
.Fx
|
||||
version of
|
||||
.Nm .
|
||||
.
|
||||
.It Fl K Ar keywords
|
||||
Add the specified (whitespace or comma separated) keywords to the current
|
||||
set of keywords.
|
||||
If
|
||||
.Ql all
|
||||
is specified, add all of the other keywords.
|
||||
.
|
||||
.It Fl k Ar keywords
|
||||
Use the
|
||||
.Sy type
|
||||
keyword plus the specified (whitespace or comma separated)
|
||||
keywords instead of the current set of keywords.
|
||||
.Ar keywords
|
||||
instead of the current set of keywords.
|
||||
If
|
||||
.Ql all
|
||||
is specified, use all of the other keywords.
|
||||
If the
|
||||
.Sy type
|
||||
keyword is not desired, suppress it with
|
||||
.Fl R Ar type .
|
||||
.Fl R Cm type .
|
||||
.
|
||||
.It Fl L
|
||||
Follow all symbolic links in the file hierarchy.
|
||||
.
|
||||
.It Fl l
|
||||
Do
|
||||
.Dq loose
|
||||
@@ -235,7 +266,7 @@ will match less stringent ones.
|
||||
For example, a file marked mode 0444
|
||||
will pass a check for mode 0644.
|
||||
.Dq Loose
|
||||
checks apply only to read, write and execute permissions -- in
|
||||
checks apply only to read, write and execute permissions \(em in
|
||||
particular, if other bits like the sticky bit or suid/sgid bits are
|
||||
set either in the specification or the file, exact checking will be
|
||||
performed.
|
||||
@@ -244,17 +275,25 @@ This option may not be set at the same time as the
|
||||
or
|
||||
.Fl u
|
||||
option.
|
||||
.
|
||||
.It Fl M
|
||||
Permit merging of specification entries with different types,
|
||||
with the last entry taking precedence.
|
||||
.
|
||||
.It Fl m
|
||||
If the schg and/or sappnd flags are specified, reset these flags.
|
||||
Note that this is only possible with securelevel less than 1 (i.e.,
|
||||
in single user mode or while the system is running in insecure
|
||||
mode).
|
||||
If the
|
||||
.Ql schg
|
||||
and/or
|
||||
.Ql sappnd
|
||||
flags are specified, reset these flags.
|
||||
Note that this is only possible with securelevel less than 1
|
||||
.Po
|
||||
i.e., in single user mode or while the system is running in insecure mode
|
||||
.Pc .
|
||||
See
|
||||
.Xr init 8
|
||||
for information on security levels.
|
||||
.
|
||||
.It Fl n
|
||||
Do not emit pathname comments when creating a specification.
|
||||
Normally
|
||||
@@ -262,6 +301,7 @@ a comment is emitted before each directory and before the close of that
|
||||
directory when using the
|
||||
.Fl c
|
||||
option.
|
||||
.
|
||||
.It Fl N Ar dbdir
|
||||
Use the user database text file
|
||||
.Pa master.passwd
|
||||
@@ -274,31 +314,42 @@ rather than using the results from the system's
|
||||
and
|
||||
.Xr getgrnam 3
|
||||
(and related) library calls.
|
||||
.
|
||||
.It Fl O Ar onlypaths
|
||||
Only include files included in this list of pathnames.
|
||||
.
|
||||
.It Fl P
|
||||
Don't follow symbolic links in the file hierarchy, instead consider
|
||||
the symbolic link itself in any comparisons.
|
||||
This is the default.
|
||||
.
|
||||
.It Fl p Ar path
|
||||
Use the file hierarchy rooted in
|
||||
.Ar path ,
|
||||
instead of the current directory.
|
||||
.
|
||||
.It Fl q
|
||||
Quiet mode.
|
||||
Do not complain when a
|
||||
.Dq missing
|
||||
directory cannot be created because it already exists.
|
||||
This occurs when the directory is a symbolic link.
|
||||
.
|
||||
.It Fl R Ar keywords
|
||||
Remove the specified (whitespace or comma separated) keywords from the current
|
||||
set of keywords.
|
||||
If
|
||||
.Ql all
|
||||
is specified, remove all of the other keywords.
|
||||
.
|
||||
.It Fl r
|
||||
Remove any files in the file hierarchy that are not described in the
|
||||
specification.
|
||||
Repeating the flag more than once will attempt to reset all the
|
||||
file flags via
|
||||
.Xr lchflags 2
|
||||
before attempting to remove the file in case the file was immutable.
|
||||
.
|
||||
.It Fl S
|
||||
When reading a specification into an internal data structure,
|
||||
sort the entries.
|
||||
@@ -320,19 +371,23 @@ By default, if the
|
||||
.Fl S
|
||||
option is not used, entries within the same directory are collected
|
||||
together (separated from entries for other directories), but not sorted.
|
||||
.
|
||||
.It Fl s Ar seed
|
||||
Display a single checksum to the standard error output that represents all
|
||||
of the files for which the keyword
|
||||
.Sy cksum
|
||||
was specified.
|
||||
The checksum is seeded with the specified value.
|
||||
.
|
||||
.It Fl t
|
||||
Modify the modified time of existing files, the device type of devices, and
|
||||
symbolic link targets, to match the specification.
|
||||
.
|
||||
.It Fl U
|
||||
Same as
|
||||
.Fl u
|
||||
except that a mismatch is not considered to be an error if it was corrected.
|
||||
.
|
||||
.It Fl u
|
||||
Modify the owner, group, permissions, and flags of existing files,
|
||||
the device type of devices, and symbolic link targets,
|
||||
@@ -350,6 +405,7 @@ is given, these flags will be reset.
|
||||
Exit with a status of 0 on success,
|
||||
2 if the file hierarchy did not match the specification, and
|
||||
1 if any other error occurred.
|
||||
.
|
||||
.It Fl W
|
||||
Don't attempt to set various file attributes such as the
|
||||
ownership, mode, flags, or time
|
||||
@@ -358,6 +414,7 @@ This option will be most useful when used in conjunction with
|
||||
.Fl U
|
||||
or
|
||||
.Fl u .
|
||||
.
|
||||
.It Fl X Ar exclude-file
|
||||
The specified file contains
|
||||
.Xr fnmatch 3
|
||||
@@ -370,11 +427,14 @@ the starting directory); otherwise,
|
||||
it will be matched against basenames only.
|
||||
Comments are permitted in
|
||||
the
|
||||
.Ar exclude-list
|
||||
.Ar exclude-file
|
||||
file.
|
||||
.
|
||||
.It Fl x
|
||||
Don't descend below mount points in the file hierarchy.
|
||||
.
|
||||
.El
|
||||
.
|
||||
.Pp
|
||||
Specifications are mostly composed of
|
||||
.Dq keywords ,
|
||||
@@ -384,7 +444,8 @@ No keywords have default values, and if a keyword has no value set, no
|
||||
checks based on it are performed.
|
||||
.Pp
|
||||
Currently supported keywords are as follows:
|
||||
.Bl -tag -width sha384digestxx
|
||||
.
|
||||
.Bl -tag -width Sy
|
||||
.It Sy cksum
|
||||
The checksum of the file using the default algorithm specified by
|
||||
the
|
||||
@@ -420,6 +481,7 @@ format.)
|
||||
.It Ar number
|
||||
Opaque number (as stored on the file system).
|
||||
.El
|
||||
.
|
||||
.Pp
|
||||
The following values for
|
||||
.Ar format
|
||||
@@ -614,9 +676,24 @@ they match.
|
||||
.Nm
|
||||
uses
|
||||
.Xr strsvis 3
|
||||
(in VIS_CSTYLE format) to encode path names containing
|
||||
(in
|
||||
.Dv VIS_OCTAL
|
||||
format) to encode path names containing
|
||||
non-printable characters.
|
||||
Whitespace characters are encoded as
|
||||
.Ql \e040
|
||||
(space),
|
||||
.Ql \e011
|
||||
(tab), and
|
||||
.Ql \e012
|
||||
(new line).
|
||||
When flavor
|
||||
.Sy netbsd6
|
||||
is selected,
|
||||
.Xr strsvis 3
|
||||
(in
|
||||
.Dv VIS_CSTYLE
|
||||
format) is used and whitespace characters are encoded as
|
||||
.Ql \es
|
||||
(space),
|
||||
.Ql \et
|
||||
@@ -678,7 +755,7 @@ The
|
||||
utility exits with a status of 0 on success, 1 if any error occurred,
|
||||
and 2 if the file hierarchy did not match the specification.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /etc/mtree -compact
|
||||
.Bl -tag -width Pa -compact
|
||||
.It Pa /etc/mtree
|
||||
system specification directory
|
||||
.El
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mtree.c,v 1.49 2014/04/24 17:22:41 christos Exp $ */
|
||||
/* $NetBSD: mtree.c,v 1.51 2024/12/05 17:17:15 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1989, 1990, 1993
|
||||
@@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1990, 1993\
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mtree.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: mtree.c,v 1.49 2014/04/24 17:22:41 christos Exp $");
|
||||
__RCSID("$NetBSD: mtree.c,v 1.51 2024/12/05 17:17:15 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@@ -195,7 +195,7 @@ main(int argc, char **argv)
|
||||
qflag = 1;
|
||||
break;
|
||||
case 'r':
|
||||
rflag = 1;
|
||||
rflag++;
|
||||
break;
|
||||
case 'R':
|
||||
while ((p = strsep(&optarg, " \t,")) != NULL)
|
||||
@@ -204,7 +204,7 @@ main(int argc, char **argv)
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
crc_total = ~strtol(optarg, &p, 0);
|
||||
crc_total = (uint32_t)~strtol(optarg, &p, 0);
|
||||
if (*p)
|
||||
mtree_err("illegal seed value -- %s", optarg);
|
||||
break;
|
||||
|
||||
+36
-8
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: spec.c,v 1.89 2014/04/24 17:22:41 christos Exp $ */
|
||||
/* $NetBSD: spec.c,v 1.92 2024/12/05 17:17:43 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1989, 1993
|
||||
@@ -67,7 +67,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)spec.c 8.2 (Berkeley) 4/28/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: spec.c,v 1.89 2014/04/24 17:22:41 christos Exp $");
|
||||
__RCSID("$NetBSD: spec.c,v 1.92 2024/12/05 17:17:43 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@@ -224,10 +224,14 @@ noparent: mtree_err("no parent node");
|
||||
*/
|
||||
if (strcmp(centry->name, ".") == 0 && centry->type == 0)
|
||||
centry->type = F_DIR;
|
||||
if (strcmp(centry->name, ".") != 0 ||
|
||||
centry->type != F_DIR)
|
||||
if (strcmp(centry->name, ".") != 0)
|
||||
mtree_err(
|
||||
"root node must be the directory `.'");
|
||||
"root node must be the directory `.',"
|
||||
" found `%s'", centry->name);
|
||||
if (centry->type != F_DIR)
|
||||
mtree_err(
|
||||
"root node must type %#x != %#x",
|
||||
F_DIR, centry->type);
|
||||
last = root = centry;
|
||||
root->parent = root;
|
||||
} else if (pathparent != NULL) {
|
||||
@@ -539,7 +543,8 @@ replacenode(NODE *cur, NODE *new)
|
||||
static void
|
||||
set(char *t, NODE *ip)
|
||||
{
|
||||
int type, value, len;
|
||||
int type, value;
|
||||
size_t len;
|
||||
gid_t gid;
|
||||
uid_t uid;
|
||||
char *kw, *val, *md, *ep;
|
||||
@@ -838,7 +843,7 @@ addchild(NODE *pathparent, NODE *centry)
|
||||
* directories sort after non-directories, but otherwise sort in
|
||||
* strcmp() order.
|
||||
*
|
||||
* Keep this in sync with dcmp() in create.c.
|
||||
* Keep this in sync with dcmp() below.
|
||||
*/
|
||||
static int
|
||||
nodecmp(const NODE *a, const NODE *b)
|
||||
@@ -847,7 +852,30 @@ nodecmp(const NODE *a, const NODE *b)
|
||||
if ((a->type & F_DIR) != 0) {
|
||||
if ((b->type & F_DIR) == 0)
|
||||
return 1;
|
||||
} else if ((b->type & F_DIR) != 0)
|
||||
} else if ((b->type & F_DIR) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return strcmp(a->name, b->name);
|
||||
}
|
||||
|
||||
/*
|
||||
* dcmp --
|
||||
* used as a comparison function passed to fts_open() to control
|
||||
* the order in which fts_read() returns results. We make
|
||||
* directories sort after non-directories, but otherwise sort in
|
||||
* strcmp() order.
|
||||
*
|
||||
* Keep this in sync with nodecmp() above.
|
||||
*/
|
||||
int
|
||||
dcmp(const FTSENT *FTS_CONST *a, const FTSENT *FTS_CONST *b)
|
||||
{
|
||||
|
||||
if (S_ISDIR((*a)->fts_statp->st_mode)) {
|
||||
if (!S_ISDIR((*b)->fts_statp->st_mode))
|
||||
return 1;
|
||||
} else if (S_ISDIR((*b)->fts_statp->st_mode)) {
|
||||
return -1;
|
||||
}
|
||||
return strcmp((*a)->fts_name, (*b)->fts_name);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: specspec.c,v 1.2 2012/10/05 01:27:29 christos Exp $ */
|
||||
/* $NetBSD: specspec.c,v 1.5 2023/12/02 13:24:00 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 Poul-Henning Kamp
|
||||
@@ -31,7 +31,7 @@
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: specspec.c,v 1.2 2012/10/05 01:27:29 christos Exp $");
|
||||
__RCSID("$NetBSD: specspec.c,v 1.5 2023/12/02 13:24:00 christos Exp $");
|
||||
|
||||
#include <err.h>
|
||||
#include <grp.h>
|
||||
|
||||
+12
-5
@@ -1,4 +1,4 @@
|
||||
/* $NetBSD: verify.c,v 1.44 2013/02/03 19:15:17 christos Exp $ */
|
||||
/* $NetBSD: verify.c,v 1.50 2024/12/11 14:52:26 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
@@ -38,7 +38,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)verify.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: verify.c,v 1.44 2013/02/03 19:15:17 christos Exp $");
|
||||
__RCSID("$NetBSD: verify.c,v 1.50 2024/12/11 14:52:26 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@@ -86,7 +86,7 @@ vwalk(void)
|
||||
argv[0] = dot;
|
||||
argv[1] = NULL;
|
||||
|
||||
if ((t = fts_open(argv, ftsoptions, NULL)) == NULL)
|
||||
if ((t = fts_open(argv, ftsoptions, dcmp)) == NULL)
|
||||
mtree_err("fts_open: %s", strerror(errno));
|
||||
level = root;
|
||||
specdepth = rval = 0;
|
||||
@@ -147,8 +147,15 @@ vwalk(void)
|
||||
continue;
|
||||
extra:
|
||||
if (!eflag && !(dflag && p->fts_info == FTS_SL)) {
|
||||
printf("extra: %s", RP(p));
|
||||
printf(flavor == F_FREEBSD9 ? "%s extra" : "extra: %s",
|
||||
RP(p));
|
||||
if (rflag) {
|
||||
#if HAVE_STRUCT_STAT_ST_FLAGS
|
||||
if (rflag > 1 &&
|
||||
lchflags(p->fts_accpath, 0) == -1)
|
||||
printf(" (chflags %s)",
|
||||
strerror(errno));
|
||||
#endif
|
||||
if ((S_ISDIR(p->fts_statp->st_mode)
|
||||
? rmdir : unlink)(p->fts_accpath)) {
|
||||
printf(", not removed: %s",
|
||||
@@ -174,7 +181,7 @@ miss(NODE *p, char *tail)
|
||||
int create;
|
||||
char *tp;
|
||||
const char *type;
|
||||
u_int32_t flags;
|
||||
u_long flags;
|
||||
|
||||
for (; p; p = p->next) {
|
||||
if (p->flags & F_OPT && !(p->flags & F_VISIT))
|
||||
|
||||
Reference in New Issue
Block a user