summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/mtree/Makefile4
-rw-r--r--usr.sbin/mtree/compare.c22
-rw-r--r--usr.sbin/mtree/create.c40
-rw-r--r--usr.sbin/mtree/extern.h4
-rw-r--r--usr.sbin/mtree/misc.c1
-rw-r--r--usr.sbin/mtree/mtree.811
-rw-r--r--usr.sbin/mtree/mtree.h5
-rw-r--r--usr.sbin/mtree/spec.c10
-rw-r--r--usr.sbin/mtree/verify.c6
9 files changed, 93 insertions, 10 deletions
diff --git a/usr.sbin/mtree/Makefile b/usr.sbin/mtree/Makefile
index 6a5d615..a85aa4c 100644
--- a/usr.sbin/mtree/Makefile
+++ b/usr.sbin/mtree/Makefile
@@ -2,9 +2,9 @@
# $FreeBSD$
PROG= mtree
-SRCS= compare.c crc.c create.c misc.c mtree.c spec.c verify.c
+SRCS= compare.c crc.c create.c misc.c mtree.c spec.c verify.c stat_flags.c
MAN8= mtree.8
-.PATH: ${.CURDIR}/../../usr.bin/cksum
+.PATH: ${.CURDIR}/../../usr.bin/cksum ${.CURDIR}/../../bin/ls
.if !defined(WORLD)
DPADD+= ${LIBMD}
diff --git a/usr.sbin/mtree/compare.c b/usr.sbin/mtree/compare.c
index d48db41..9f2db9f 100644
--- a/usr.sbin/mtree/compare.c
+++ b/usr.sbin/mtree/compare.c
@@ -216,6 +216,28 @@ typeerr: LABEL;
tab = "\t";
}
}
+ /*
+ * XXX
+ * since chflags(2) will reset file times, the utimes() above
+ * may have been useless! oh well, we'd rather have correct
+ * flags, rather than times?
+ */
+ if ((s->flags & F_FLAGS) && s->st_flags != p->fts_statp->st_flags) {
+ LABEL;
+ (void)printf("%sflags (\"%s\" is not ", tab,
+ flags_to_string(s->st_flags, "none"));
+ (void)printf("\"%s\"",
+ flags_to_string(p->fts_statp->st_flags, "none"));
+ if (uflag)
+ if (chflags(p->fts_accpath, s->st_flags))
+ (void)printf(", not modified: %s)\n",
+ strerror(errno));
+ else
+ (void)printf(", modified)\n");
+ else
+ (void)printf(")\n");
+ tab = "\t";
+ }
#ifdef MD5
if (s->flags & F_MD5) {
char *new_digest, buf[33];
diff --git a/usr.sbin/mtree/create.c b/usr.sbin/mtree/create.c
index 6075099..72049f4 100644
--- a/usr.sbin/mtree/create.c
+++ b/usr.sbin/mtree/create.c
@@ -77,10 +77,12 @@ extern int lineno;
static gid_t gid;
static uid_t uid;
static mode_t mode;
+static u_long flags;
static int dsort __P((const FTSENT **, const FTSENT **));
static void output __P((int, int *, const char *, ...));
-static int statd __P((FTS *, FTSENT *, uid_t *, gid_t *, mode_t *));
+static int statd __P((FTS *, FTSENT *, uid_t *, gid_t *, mode_t *,
+ u_long *));
static void statf __P((int, FTSENT *));
void
@@ -111,7 +113,7 @@ cwalk()
(void)printf("\n");
if (!nflag)
(void)printf("# %s\n", p->fts_path);
- statd(t, p, &uid, &gid, &mode);
+ statd(t, p, &uid, &gid, &mode, &flags);
statf(indent, p);
break;
case FTS_DP:
@@ -250,31 +252,40 @@ statf(indent, p)
if (keys & F_SLINK &&
(p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE))
output(indent, &offset, "link=%s", rlink(p->fts_accpath));
+ if (keys & F_FLAGS && p->fts_statp->st_flags != flags)
+ output(indent, &offset, "flags=%s",
+ flags_to_string(p->fts_statp->st_flags, "none"));
(void)putchar('\n');
}
#define MAXGID 5000
#define MAXUID 5000
#define MAXMODE MBITS + 1
+#define MAXFLAGS 256
+#define MAXS 16
static int
-statd(t, parent, puid, pgid, pmode)
+statd(t, parent, puid, pgid, pmode, pflags)
FTS *t;
FTSENT *parent;
uid_t *puid;
gid_t *pgid;
mode_t *pmode;
+ u_long *pflags;
{
register FTSENT *p;
register gid_t sgid;
register uid_t suid;
register mode_t smode;
+ register u_long sflags;
struct group *gr;
struct passwd *pw;
gid_t savegid = *pgid;
uid_t saveuid = *puid;
mode_t savemode = *pmode;
- u_short maxgid, maxuid, maxmode, g[MAXGID], u[MAXUID], m[MAXMODE];
+ u_long saveflags = 0;
+ u_short maxgid, maxuid, maxmode, maxflags;
+ u_short g[MAXGID], u[MAXUID], m[MAXMODE], f[MAXFLAGS];
static int first = 1;
if ((p = fts_children(t, 0)) == NULL) {
@@ -286,8 +297,9 @@ statd(t, parent, puid, pgid, pmode)
bzero(g, sizeof(g));
bzero(u, sizeof(u));
bzero(m, sizeof(m));
+ bzero(f, sizeof(f));
- maxuid = maxgid = maxmode = 0;
+ maxuid = maxgid = maxmode = maxflags = 0;
for (; p; p = p->fts_link) {
if (!dflag || (dflag && S_ISDIR(p->fts_statp->st_mode))) {
smode = p->fts_statp->st_mode & MBITS;
@@ -305,6 +317,20 @@ statd(t, parent, puid, pgid, pmode)
saveuid = suid;
maxuid = u[suid];
}
+
+ /*
+ * XXX
+ * note that the below will break when file flags
+ * are extended beyond the first 4 bytes of each
+ * half word of the flags
+ */
+#define FLAGS2IDX(f) ((f & 0xf) | ((f >> 12) & 0xf0))
+ sflags = p->fts_statp->st_flags;
+ if (FLAGS2IDX(sflags) < MAXFLAGS &&
+ ++f[FLAGS2IDX(sflags)] > maxflags) {
+ saveflags = sflags;
+ maxflags = u[FLAGS2IDX(sflags)];
+ }
}
}
/*
@@ -344,10 +370,14 @@ statd(t, parent, puid, pgid, pmode)
(void)printf(" mode=%#o", savemode);
if (keys & F_NLINK)
(void)printf(" nlink=1");
+ if (keys & F_FLAGS && saveflags)
+ (void)printf(" flags=%s",
+ flags_to_string(saveflags, "none"));
(void)printf("\n");
*puid = saveuid;
*pgid = savegid;
*pmode = savemode;
+ *pflags = saveflags;
}
return (0);
}
diff --git a/usr.sbin/mtree/extern.h b/usr.sbin/mtree/extern.h
index f3b6230..c9a00b2 100644
--- a/usr.sbin/mtree/extern.h
+++ b/usr.sbin/mtree/extern.h
@@ -31,11 +31,15 @@
* SUCH DAMAGE.
*
* @(#)extern.h 8.1 (Berkeley) 6/6/93
+ * $FreeBSD$
*/
int compare __P((char *, NODE *, FTSENT *));
int crc __P((int, u_long *, u_long *));
void cwalk __P((void));
+char *flags_to_string __P((u_long, char *));
+int string_to_flags __P((char **, u_long *, u_long *));
+
char *inotype __P((u_int));
u_int parsekey __P((char *, int *));
char *rlink __P((char *));
diff --git a/usr.sbin/mtree/misc.c b/usr.sbin/mtree/misc.c
index bc94b32..ea413dd 100644
--- a/usr.sbin/mtree/misc.c
+++ b/usr.sbin/mtree/misc.c
@@ -60,6 +60,7 @@ typedef struct _key {
/* NB: the following table must be sorted lexically. */
static KEY keylist[] = {
{"cksum", F_CKSUM, NEEDVALUE},
+ {"flags", F_FLAGS, NEEDVALUE},
{"gid", F_GID, NEEDVALUE},
{"gname", F_GNAME, NEEDVALUE},
{"ignore", F_IGN, 0},
diff --git a/usr.sbin/mtree/mtree.8 b/usr.sbin/mtree/mtree.8
index fc3ad4a..d01438f 100644
--- a/usr.sbin/mtree/mtree.8
+++ b/usr.sbin/mtree/mtree.8
@@ -131,6 +131,12 @@ The checksum of the file using the default algorithm specified by
the
.Xr cksum 1
utility.
+.It Cm flags
+The file flags as a symbolic name. See
+.Xr chflags 1
+for information on these names. If no flags are to be set the string
+.Dq none
+may be used to override the current default.
.It Cm ignore
Ignore any file hierarchy below this file.
.It Cm gid
@@ -188,6 +194,7 @@ socket
.El
.Pp
The default set of keywords are
+.Cm flags ,
.Cm gid ,
.Cm mode ,
.Cm nlink ,
@@ -282,6 +289,7 @@ distribution.
system specification directory
.El
.Sh SEE ALSO
+.Xr chflags 1 ,
.Xr chgrp 1 ,
.Xr chmod 1 ,
.Xr cksum 1 ,
@@ -309,3 +317,6 @@ digests were added in
.Fx 4.0 ,
as new attacks have demonstrated weaknesses in
.Tn MD5 .
+Support for file flags was added in
+.Fx 4.0 ,
+and mostly comes from NetBSD.
diff --git a/usr.sbin/mtree/mtree.h b/usr.sbin/mtree/mtree.h
index 7ffb798..9d8af5d 100644
--- a/usr.sbin/mtree/mtree.h
+++ b/usr.sbin/mtree/mtree.h
@@ -31,13 +31,14 @@
* SUCH DAMAGE.
*
* @(#)mtree.h 8.1 (Berkeley) 6/6/93
+ * $FreeBSD$
*/
#include <string.h>
#include <stdlib.h>
#define KEYDEFAULT \
- (F_GID | F_MODE | F_NLINK | F_SIZE | F_SLINK | F_TIME | F_UID)
+ (F_GID | F_MODE | F_NLINK | F_SIZE | F_SLINK | F_TIME | F_UID | F_FLAGS)
#define MISMATCHEXIT 2
@@ -55,6 +56,7 @@ typedef struct _node {
gid_t st_gid; /* gid */
#define MBITS (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO)
mode_t st_mode; /* mode */
+ u_long st_flags; /* flags */
nlink_t st_nlink; /* link count */
#define F_CKSUM 0x0001 /* check sum */
@@ -77,6 +79,7 @@ typedef struct _node {
/* not change */
#define F_SHA1 0x20000 /* SHA-1 digest */
#define F_RMD160 0x40000 /* RIPEMD160 digest */
+#define F_FLAGS 0x80000 /* file flags */
u_int flags; /* items set */
#define F_BLOCK 0x001 /* block special */
diff --git a/usr.sbin/mtree/spec.c b/usr.sbin/mtree/spec.c
index 4a23073..3fa9e7c 100644
--- a/usr.sbin/mtree/spec.c
+++ b/usr.sbin/mtree/spec.c
@@ -172,10 +172,10 @@ noparent: errx(1, "line %d: no parent node", lineno);
static void
set(t, ip)
char *t;
- register NODE *ip;
+ NODE *ip;
{
register int type;
- register char *kw, *val = NULL;
+ char *kw, *val = NULL;
struct group *gr;
struct passwd *pw;
mode_t *m;
@@ -211,6 +211,12 @@ set(t, ip)
errx(1, "strdup");
}
break;
+ case F_FLAGS:
+ if (strcmp("none", val) == 0)
+ ip->st_flags = 0;
+ else if (string_to_flags(&val, &ip->st_flags,NULL) != 0)
+ errx(1, "line %d: invalid flag %s",lineno, val);
+ break;
case F_GID:
ip->st_gid = strtoul(val, &ep, 10);
if (*ep)
diff --git a/usr.sbin/mtree/verify.c b/usr.sbin/mtree/verify.c
index 9b165cf..9422e5e 100644
--- a/usr.sbin/mtree/verify.c
+++ b/usr.sbin/mtree/verify.c
@@ -201,10 +201,16 @@ miss(p, tail)
if (chown(path, p->st_uid, p->st_gid)) {
(void)printf("%s: user/group/mode not modified: %s\n",
path, strerror(errno));
+ (void)printf("%s: warning: file mode %snot set\n", path,
+ (p->flags & F_FLAGS) ? "and file flags " : "");
continue;
}
if (chmod(path, p->st_mode))
(void)printf("%s: permissions not set: %s\n",
path, strerror(errno));
+ if ((p->flags & F_FLAGS) && p->st_flags &&
+ chflags(path, p->st_flags))
+ (void)printf("%s: file flags not set: %s\n",
+ path, strerror(errno));
}
}
OpenPOWER on IntegriCloud