Implement -M to "merge" entries, even with different types.

This can be used in /etc/security to allow special.local to override
types of entries in special (e.g, replacing a dir with a link).

Rename Wflag to mtree_Wflag, to be more "external namespace" friendly.
This commit is contained in:
lukem 2004-07-22 16:51:45 +00:00
parent 1925108989
commit 9cc32040b1
7 changed files with 112 additions and 30 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: compare.c,v 1.44 2004/06/20 22:20:18 jmc Exp $ */
/* $NetBSD: compare.c,v 1.45 2004/07/22 16:51:45 lukem 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.44 2004/06/20 22:20:18 jmc Exp $");
__RCSID("$NetBSD: compare.c,v 1.45 2004/07/22 16:51:45 lukem Exp $");
#endif
#endif /* not lint */
@ -165,7 +165,7 @@ typeerr: LABEL;
nodetype(s->type), inotype(p->fts_statp->st_mode));
return (label);
}
if (Wflag)
if (mtree_Wflag)
goto afterpermwhack;
#if HAVE_STRUCT_STAT_ST_FLAGS
if (iflag && !uflag) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.28 2003/10/27 00:12:44 lukem Exp $ */
/* $NetBSD: extern.h,v 1.29 2004/07/22 16:51:45 lukem Exp $ */
/*-
* Copyright (c) 1991, 1993
@ -70,7 +70,7 @@ const char *rlink(const char *);
int verify(void);
extern int dflag, eflag, iflag, lflag, mflag, rflag, sflag, tflag, uflag;
extern int Wflag;
extern int mtree_Mflag, mtree_Wflag;
extern size_t mtree_lineno;
extern u_int32_t crc_total;
extern int ftsoptions, keys;

View File

@ -1,4 +1,4 @@
.\" $NetBSD: mtree.8,v 1.38 2003/08/07 11:25:36 agc Exp $
.\" $NetBSD: mtree.8,v 1.39 2004/07/22 16:51:45 lukem Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -27,9 +27,43 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" Copyright (c) 2001-2004 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Luke Mewburn of Wasabi Systems.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
.\" contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.\" @(#)mtree.8 8.2 (Berkeley) 12/11/93
.\"
.Dd December 22, 2002
.Dd July 22, 2004
.Dt MTREE 8
.Os
.Sh NAME
@ -37,7 +71,7 @@
.Nd map a directory hierarchy
.Sh SYNOPSIS
.Nm
.Op Fl cCdDelLPruUWx
.Op Fl cCdDelLMPruUWx
.Bk -words
.Op Fl i | Fl m
.Ek
@ -167,6 +201,9 @@ this is only possible with securelevel less than 1 (i. e. in single user mode
or while the system is running in insecure mode). See
.Xr init 8
for information on security levels.
.It Fl M
Permit merging of specification entries with different types,
with the last entry take precedence.
.It Fl N Ar dbdir
Use the user database text file
.Pa master.passwd
@ -508,7 +545,9 @@ All parent directories referenced in the path name must exist.
The current directory path used by relative path names will be updated
appropriately.
Multiple entries for the same full path are permitted if the types
are the same;
are the same (unless
.Fl M
is given, and then the types may differ);
in this case the settings for the last entry take precedence.
.Pp
A path name that does not contain a slash will be treated as a relative path.

View File

@ -1,4 +1,4 @@
/* $NetBSD: mtree.c,v 1.31 2004/06/20 22:20:18 jmc Exp $ */
/* $NetBSD: mtree.c,v 1.32 2004/07/22 16:51:45 lukem Exp $ */
/*-
* Copyright (c) 1989, 1990, 1993
@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1990, 1993\n\
#if 0
static char sccsid[] = "@(#)mtree.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: mtree.c,v 1.31 2004/06/20 22:20:18 jmc Exp $");
__RCSID("$NetBSD: mtree.c,v 1.32 2004/07/22 16:51:45 lukem Exp $");
#endif
#endif /* not lint */
@ -77,7 +77,7 @@ main(int argc, char **argv)
dir = NULL;
init_excludes();
while ((ch = getopt(argc, argv, "cCdDeE:f:I:ik:K:lLmN:p:PrR:s:tuUWxX:"))
while ((ch = getopt(argc, argv, "cCdDeE:f:I:ik:K:lLmMN:p:PrR:s:tuUWxX:"))
!= -1) {
switch((char)ch) {
case 'c':
@ -129,6 +129,9 @@ main(int argc, char **argv)
case 'm':
mflag = 1;
break;
case 'M':
mtree_Mflag = 1;
break;
case 'N':
if (! setup_getid(optarg))
mtree_err(
@ -166,7 +169,7 @@ main(int argc, char **argv)
Uflag = uflag = 1;
break;
case 'W':
Wflag = 1;
mtree_Wflag = 1;
break;
case 'x':
ftsoptions |= FTS_XDEV;
@ -219,7 +222,7 @@ usage(void)
{
fprintf(stderr,
"usage: %s [-cCdDelLPruUWx] [-i|-m] [-f spec] [-k key]\n"
"usage: %s [-cCdDelLMPruUWx] [-i|-m] [-f spec] [-k key]\n"
"\t\t[-K addkey] [-R removekey] [-I inctags] [-E exctags]\n"
"\t\t[-N userdbdir] [-X exclude-file] [-p path] [-s seed]\n",
getprogname());

View File

@ -1,4 +1,4 @@
/* $NetBSD: mtree.h,v 1.21 2003/08/07 11:25:36 agc Exp $ */
/* $NetBSD: mtree.h,v 1.22 2004/07/22 16:51:45 lukem Exp $ */
/*-
* Copyright (c) 1990, 1993
@ -111,6 +111,7 @@ const char *inotype(u_int);
u_int nodetoino(u_int);
int setup_getid(const char *);
NODE *spec(FILE *);
void free_nodes(NODE *);
char *vispath(const char *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: spec.c,v 1.56 2004/06/20 22:20:18 jmc Exp $ */
/* $NetBSD: spec.c,v 1.57 2004/07/22 16:51:45 lukem Exp $ */
/*-
* Copyright (c) 1989, 1993
@ -30,7 +30,7 @@
*/
/*-
* Copyright (c) 2001-2002 The NetBSD Foundation, Inc.
* Copyright (c) 2001-2004 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -74,7 +74,7 @@
#if 0
static char sccsid[] = "@(#)spec.c 8.2 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: spec.c,v 1.56 2004/06/20 22:20:18 jmc Exp $");
__RCSID("$NetBSD: spec.c,v 1.57 2004/07/22 16:51:45 lukem Exp $");
#endif
#endif /* not lint */
@ -96,13 +96,16 @@ __RCSID("$NetBSD: spec.c,v 1.56 2004/06/20 22:20:18 jmc Exp $");
#include "pack_dev.h"
size_t mtree_lineno; /* Current spec line number */
int Wflag; /* Don't "whack" permissions */
int mtree_Mflag; /* Merge duplicate entries */
int mtree_Wflag; /* Don't "whack" permissions */
static dev_t parsedev(char *);
static void replacenode(NODE *, NODE *);
static void set(char *, NODE *);
static void unset(char *, NODE *);
#define REPLACEPTR(x,v) do { if ((x)) free((x)); (x) = (v); } while (0)
NODE *
spec(FILE *fp)
{
@ -274,6 +277,27 @@ noparent: mtree_err("no parent node");
return (root);
}
void
free_nodes(NODE *root)
{
NODE *cur, *next;
if (root == NULL)
return;
next = NULL;
for (cur = root; cur != NULL; cur = next) {
next = cur->next;
free_nodes(cur->child);
REPLACEPTR(cur->slink, NULL);
REPLACEPTR(cur->md5digest, NULL);
REPLACEPTR(cur->rmd160digest, NULL);
REPLACEPTR(cur->sha1digest, NULL);
REPLACEPTR(cur->tags, NULL);
REPLACEPTR(cur, NULL);
}
}
/*
* dump_nodes --
* dump the NODEs from `cur', based in the directory `dir'.
@ -414,11 +438,26 @@ static void
replacenode(NODE *cur, NODE *new)
{
if (cur->type != new->type)
mtree_err("existing entry for `%s', type `%s' does not match type `%s'",
cur->name, nodetype(cur->type), nodetype(new->type));
#define REPLACE(x) cur->x = new->x
#define REPLACESTR(x) if (cur->x) free(cur->x); cur->x = new->x
#define REPLACESTR(x) REPLACEPTR(cur->x,new->x)
if (cur->type != new->type) {
if (mtree_Mflag) {
/*
* merge entries with different types; we
* don't want children retained in this case.
*/
REPLACE(type);
free_nodes(cur->child);
cur->child = NULL;
} else {
mtree_err(
"existing entry for `%s', type `%s'"
" does not match type `%s'",
cur->name, nodetype(cur->type),
nodetype(new->type));
}
}
REPLACE(st_size);
REPLACE(st_mtimespec);
@ -484,7 +523,7 @@ set(char *t, NODE *ip)
mtree_err("invalid gid `%s'", val);
break;
case F_GNAME:
if (Wflag) /* don't parse if whacking */
if (mtree_Wflag) /* don't parse if whacking */
break;
if (gid_from_group(val, &gid) == -1)
mtree_err("unknown group `%s'", val);
@ -565,7 +604,7 @@ set(char *t, NODE *ip)
mtree_err("invalid uid `%s'", val);
break;
case F_UNAME:
if (Wflag) /* don't parse if whacking */
if (mtree_Wflag) /* don't parse if whacking */
break;
if (uid_from_user(val, &uid) == -1)
mtree_err("unknown user `%s'", val);

View File

@ -1,4 +1,4 @@
/* $NetBSD: verify.c,v 1.37 2004/06/20 22:20:18 jmc Exp $ */
/* $NetBSD: verify.c,v 1.38 2004/07/22 16:51:45 lukem 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.37 2004/06/20 22:20:18 jmc Exp $");
__RCSID("$NetBSD: verify.c,v 1.38 2004/07/22 16:51:45 lukem Exp $");
#endif
#endif /* not lint */
@ -193,7 +193,7 @@ miss(NODE *p, char *tail)
create = 0;
if (!(p->flags & F_VISIT) && uflag) {
if (Wflag || p->type == F_LINK)
if (mtree_Wflag || p->type == F_LINK)
goto createit;
if (!(p->flags & (F_UID | F_UNAME)))
printf(
@ -209,7 +209,7 @@ miss(NODE *p, char *tail)
switch (p->type) {
case F_BLOCK:
case F_CHAR:
if (Wflag)
if (mtree_Wflag)
continue;
if (!(p->flags & F_DEV))
printf(
@ -260,7 +260,7 @@ miss(NODE *p, char *tail)
} else
putchar('\n');
if (!create || Wflag)
if (!create || mtree_Wflag)
continue;
if ((p->flags & (F_UID | F_UNAME)) &&
(p->flags & (F_GID | F_GNAME)) &&