Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Dec 2015 01:12:45 +0000 (UTC)
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r291831 - head/tools/tools/nanobsd
Message-ID:  <201512050112.tB51CjRE050428@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: imp
Date: Sat Dec  5 01:12:44 2015
New Revision: 291831
URL: https://svnweb.freebsd.org/changeset/base/291831

Log:
  Awk helper script that reads in a mtree METALOG file from installworld
  (and soon augmented by nanobsd), performs the actions documented in
  the script, and then spits out a new mtree file suitable for feeding
  to makefs.
  
  Discussed on: arch@

Added:
  head/tools/tools/nanobsd/mtree-dedup.awk   (contents, props changed)

Added: head/tools/tools/nanobsd/mtree-dedup.awk
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/nanobsd/mtree-dedup.awk	Sat Dec  5 01:12:44 2015	(r291831)
@@ -0,0 +1,197 @@
+#!/usr/bin/awk -f
+
+#
+# Copyright (c) 2015 M. Warner Losh.
+# All rights reserved.
+#
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# $FreeBSD$
+#
+
+#
+# Takes a meta-log created by installworld and friends, plus
+# additions from NanoBSD to augment its build to communicate when
+# files move around after installworld / installkernel phase of
+# NanoBSD.
+#
+# All mtree lines from the metafile have a path, followed by
+# a number of keywords.
+#
+# This script recognizes the following new keywords
+#
+# unlink[=x]	remove the path from the output.
+# copy_from=x	create new entry for path copied from
+#		the keywords from x.
+# move_from=x	create new entry for path copied from
+#		the keywords from x. Remove path from
+#		the output.
+#
+# In addition, when path matches a previous entry, the
+# new entry and previous entry are merged.
+#
+# Special note: when uid and uname are both present,
+# uid is ignored. Ditto gid/gname.
+#
+# Also, the paths above have to match exactly, so X
+# should start with "./".
+#
+
+function die(str)
+{
+	print str > "/dev/stderr";
+	exit 1;
+}
+
+function kv(str)
+{
+	if (split(str, xxx, "=") == 2) {
+		kv_key = xxx[1];
+		kv_value = xxx[2];
+	} else {
+		kv_key = str;
+		kv_value = nv;
+	}
+}
+
+# Output the mtree for path based on the kvs.
+function mtree_from_kvs(path, kvs)
+{
+	lv = path " ";
+	for (k in kvs) {
+		if (kvs[k] == nv)
+			lv = lv k " ";
+		else
+			lv = lv k "=" kvs[k] " ";
+	}
+	return lv;
+}
+
+# Parse the mtree line into path + KVs. Use a sentinal value
+# for a bare keyword, which is extremely unlikely to be used
+# for real.
+function line2kv(kvs, str)
+{
+	delete kvs;
+
+	n = split(str, yyy, " ");
+	for (i = 2; i <= n; i++) {
+		s = yyy[i];
+		if (split(s, xxx, "=") == 2)
+			kvs[xxx[1]] = xxx[2];
+		else
+			kvs[s] = nv;
+	}
+}
+
+
+# old += new
+function merge_kvs(old, new)
+{
+	for (k in new) {
+		# uname / uid -- last one wins.
+		if (k == "uid" && "uname" in old)
+			delete old["uname"]
+		if (k == "uname" && "uid" in old)
+			delete old["uid"];
+		# gname / gid -- last one wins.
+		if (k == "gid" && "gname" in old)
+			delete old["gname"]
+		if (k == "gname" && "gid" in old)
+			delete old["gid"];
+		# Otherwise newest value wins
+		old[k] = new[k];
+	}
+}
+
+# Process the line we've read in, per the comments below
+function process_line(path, new)
+{
+	# Clear kvs
+	line2kv(new_kvs, new);
+
+	if ("unlink" in new_kvs) {
+		# A file removed
+		# Sanity check to see if tree[path] exists? 
+		# Makes sure when foo/bar/baz exists and foo/bar
+		# unlinked, baz is gone (for all baz).
+		if (path !~ "^\./")
+			die("bad path in : " new);
+		delete tree[path];		# unlink
+		return;
+	# } else if (new_kvs["append_from"]) { # not implemented
+	} else if ("copy_from" in new_kvs) {
+		# A file copied from another location, preserve its
+		# attribute for new file.
+		# Also merge any new attributes from this line.
+		from = new_kvs["copy_from"];
+		if (from !~ "^\./")
+			die("bad path in : " new);
+		delete new_kvs["copy_from"];
+		line2kv(old_kvs, tree[from]);	# old_kvs = kv's in entry
+		merge_kvs(old_kvs, new_kvs);	# old_kvs += new_kvs
+		tree[path] = mtree_from_kvs(path, old_kvs);
+	} else if ("move_from" in new_kvs) {
+		# A file moved from another location, preserve its
+		# attribute for new file, and scrag old location
+		# Also merge any new attributes from this line.
+		from = new_kvs["move_from"];
+		if (from !~ "^\./")
+			die("bad path in : " new);
+		delete new_kvs["move_from"];
+		line2kv(old_kvs, tree[from]);	# old_kvs = kv's in entry
+		merge_kvs(old_kvs, new_kvs);	# old_kvs += new_kvs
+		tree[path] = mtree_from_kvs(path, old_kvs);
+		delete tree[from];		# unlink
+	} else if (tree[path]) {	# Update existing entry with new line
+		line2kv(old_kvs, tree[path]);	# old_kvs = kv's in entry
+		merge_kvs(old_kvs, new_kvs);	# old_kvs += new_kvs
+		tree[path] = mtree_from_kvs(path, old_kvs);
+	} else {			# Add entry plus defaults
+		delete old_kvs;
+		merge_kvs(old_kvs, defaults);
+		merge_kvs(old_kvs, new_kvs);
+		tree[path] = mtree_from_kvs(path, old_kvs);
+	}
+}
+
+BEGIN {
+	nv = "___NO__VALUE___";
+
+	while ((getline < "/dev/stdin") > 0) {
+		if ($1 == "/set") {
+			for (i = 2; i <= NF; i++) {
+				kv($i);
+				defaults[kv_key] = kv_value;
+			}
+		} else if ($1 == "/unset") {
+			for (i = 2; i <= NF; i++) {
+				kv($i);
+				delete defaults[kv_key];
+			}
+		} else
+			process_line($1, $0);
+	}
+
+	for (x in tree)
+		print tree[x];
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201512050112.tB51CjRE050428>