support multiple entries for "." and full paths if the types match; the last

listed entry's settings override the existing settings for that node.
This commit is contained in:
lukem 2002-02-11 12:43:55 +00:00
parent e644076000
commit b927725af9
2 changed files with 87 additions and 21 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: mtree.8,v 1.30 2002/02/05 12:15:13 lukem Exp $
.\" $NetBSD: mtree.8,v 1.31 2002/02/11 12:43:55 lukem Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -33,7 +33,7 @@
.\"
.\" @(#)mtree.8 8.2 (Berkeley) 12/11/93
.\"
.Dd February 5, 2002
.Dd February 11, 2002
.Dt MTREE 8
.Os
.Sh NAME
@ -494,6 +494,10 @@ The first path name entry listed must be a directory named
.Ql \&. ,
as this ensures that intermixing full and relative path names will
work consistently and correctly.
Multiple entries for a directory named
.Ql \&.
are permitted; the settings for the last such entry override those
of the existing entry.
.Pp
A path name that contains a slash
.Pq Ql /
@ -502,6 +506,9 @@ that is not the first character will be treated as a full path
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;
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.
Specifying a directory will cause subsequent files to be searched

View File

@ -1,4 +1,4 @@
/* $NetBSD: spec.c,v 1.46 2002/02/05 12:15:14 lukem Exp $ */
/* $NetBSD: spec.c,v 1.47 2002/02/11 12:43:55 lukem Exp $ */
/*-
* Copyright (c) 1989, 1993
@ -74,7 +74,7 @@
#if 0
static char sccsid[] = "@(#)spec.c 8.2 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: spec.c,v 1.46 2002/02/05 12:15:14 lukem Exp $");
__RCSID("$NetBSD: spec.c,v 1.47 2002/02/11 12:43:55 lukem Exp $");
#endif
#endif /* not lint */
@ -97,9 +97,10 @@ __RCSID("$NetBSD: spec.c,v 1.46 2002/02/05 12:15:14 lukem Exp $");
size_t mtree_lineno; /* Current spec line number */
int Wflag; /* Don't "whack" permissions */
static dev_t parsedev(char *);
static void set(char *, NODE *);
static void unset(char *, NODE *);
static dev_t parsedev(char *);
static void replacenode(NODE *, NODE *);
static void set(char *, NODE *);
static void unset(char *, NODE *);
NODE *
spec(FILE *fp)
@ -181,7 +182,8 @@ noparent: mtree_err("no parent node");
continue; /* handle // */
*e = '\0';
if (strcmp(p, ".") != 0) {
while (cur && strcmp(cur->name, p)) {
while (cur &&
strcmp(cur->name, p) != 0) {
cur = cur->next;
}
}
@ -195,11 +197,6 @@ noparent: mtree_err("no parent node");
}
if (*p == '\0')
mtree_err("%s: empty leaf element", tname);
for (; cur != NULL; cur = cur->next) {
if (strcmp(cur->name, p) == 0)
mtree_err("%s: %s", p,
strerror(EEXIST));
}
}
if ((centry = calloc(1, sizeof(NODE) + strlen(p))) == NULL)
@ -213,27 +210,60 @@ noparent: mtree_err("no parent node");
set(next, centry);
if (root == NULL) {
if (strcmp(centry->name, ".") || centry->type != F_DIR)
/*
* empty tree
*/
if (strcmp(centry->name, ".") != 0 ||
centry->type != F_DIR)
mtree_err(
"root node must be the directory `.'");
last = root = centry;
root->parent = root;
} else if (pathparent != NULL) {
/*
* full path entry
*/
centry->parent = pathparent;
cur = pathparent->child;
if (cur == NULL)
if (cur == NULL) {
pathparent->child = centry;
else {
while (cur->next != NULL)
cur = cur->next;
cur->next = centry;
centry->prev = cur;
last = centry;
} else {
for (; cur != NULL; cur = cur->next) {
if (strcmp(cur->name, centry->name)
== 0) {
/* existing entry; replace */
replacenode(cur, centry);
break;
}
if (cur->next == NULL) {
/* last entry; add new */
cur->next = centry;
centry->prev = cur;
break;
}
}
last = cur;
while (last->next != NULL)
last = last->next;
}
last = centry;
} else if (strcmp(centry->name, ".") == 0) {
/*
* duplicate "." entry; always replace
*/
replacenode(root, centry);
} else if (last->type == F_DIR && !(last->flags & F_DONE)) {
/*
* new relative child
* (no duplicate check)
*/
centry->parent = last;
last = last->child = centry;
} else {
/*
* relative entry, up one directory
* (no duplicate check)
*/
centry->parent = last->parent;
centry->prev = last;
last = last->next = centry;
@ -353,6 +383,35 @@ parsedev(char *arg)
return (result);
}
static void
replacenode(NODE *cur, NODE *new)
{
if (cur->type != new->type)
mtree_err("existing entry type `%s' does not match type `%s'",
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
REPLACE(st_size);
REPLACE(st_mtimespec);
REPLACESTR(slink);
REPLACE(st_uid);
REPLACE(st_gid);
REPLACE(st_mode);
REPLACE(st_rdev);
REPLACE(st_flags);
REPLACE(st_nlink);
REPLACE(cksum);
REPLACESTR(md5digest);
REPLACESTR(rmd160digest);
REPLACESTR(sha1digest);
REPLACESTR(tags);
REPLACE(lineno);
REPLACE(flags);
free(new);
}
static void
set(char *t, NODE *ip)
{