summaryrefslogtreecommitdiff
path: root/pkgtools/mtree/files/spec.c
diff options
context:
space:
mode:
Diffstat (limited to 'pkgtools/mtree/files/spec.c')
-rw-r--r--pkgtools/mtree/files/spec.c68
1 files changed, 57 insertions, 11 deletions
diff --git a/pkgtools/mtree/files/spec.c b/pkgtools/mtree/files/spec.c
index 3ad9493a717..184808a68ca 100644
--- a/pkgtools/mtree/files/spec.c
+++ b/pkgtools/mtree/files/spec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: spec.c,v 1.2 2003/12/20 04:52:50 grant Exp $ */
+/* $NetBSD: spec.c,v 1.3 2004/08/21 04:10:45 jlam 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
@@ -68,6 +68,10 @@
#if HAVE_CONFIG_H
#include "config.h"
#endif
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
#include <nbcompat.h>
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
@@ -76,7 +80,7 @@
#if 0
static char sccsid[] = "@(#)spec.c 8.2 (Berkeley) 4/28/95";
#else
-__RCSID("$NetBSD: spec.c,v 1.2 2003/12/20 04:52:50 grant Exp $");
+__RCSID("$NetBSD: spec.c,v 1.3 2004/08/21 04:10:45 jlam Exp $");
#endif
#endif /* not lint */
@@ -122,13 +126,16 @@ __RCSID("$NetBSD: spec.c,v 1.2 2003/12/20 04:52:50 grant 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)
{
@@ -300,6 +307,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'.
@@ -406,6 +434,7 @@ parsedev(char *arg)
int argc;
pack_t *pack;
dev_t result;
+ const char *error = NULL;
if ((dev = strchr(arg, ',')) != NULL) {
*dev++='\0';
@@ -424,7 +453,9 @@ parsedev(char *arg)
}
if (argc < 2)
mtree_err("not enough arguments");
- result = (*pack)(argc, numbers);
+ result = (*pack)(argc, numbers, &error);
+ if (error != NULL)
+ mtree_err(error);
} else {
result = (dev_t)strtoul(arg, &ep, 0);
if (*ep != '\0')
@@ -437,11 +468,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);
@@ -507,7 +553,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);
@@ -588,7 +634,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);