4 # Copyright (c) 2015 M. Warner Losh.
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
10 # 1. Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # 2. Redistributions in binary form must reproduce the above copyright
13 # notice, this list of conditions and the following disclaimer in the
14 # documentation and/or other materials provided with the distribution.
16 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 # Takes a meta-log created by installworld and friends, plus
33 # additions from NanoBSD to augment its build to communicate when
34 # files move around after installworld / installkernel phase of
37 # All mtree lines from the metafile have a path, followed by
38 # a number of keywords.
40 # This script recognizes the following new keywords
42 # unlink[=x] remove the path from the output.
43 # copy_from=x create new entry for path copied from
44 # the keywords from x.
45 # move_from=x create new entry for path copied from
46 # the keywords from x. Remove path from
49 # In addition, when path matches a previous entry, the
50 # new entry and previous entry are merged.
52 # Special note: when uid and uname are both present,
53 # uid is ignored. Ditto gid/gname.
55 # Also, the paths above have to match exactly, so X
56 # should start with "./".
61 print str > "/dev/stderr";
67 if (split(str, xxx, "=") == 2) {
76 # Output the mtree for path based on the kvs.
77 function mtree_from_kvs(path, kvs)
84 lv = lv k "=" kvs[k] " ";
89 # Parse the mtree line into path + KVs. Use a sentinal value
90 # for a bare keyword, which is extremely unlikely to be used
92 function line2kv(kvs, str)
96 n = split(str, yyy, " ");
97 for (i = 2; i <= n; i++) {
99 if (split(s, xxx, "=") == 2)
100 kvs[xxx[1]] = xxx[2];
108 function merge_kvs(old, new)
111 # uname / uid -- last one wins.
112 if (k == "uid" && "uname" in old)
114 if (k == "uname" && "uid" in old)
116 # gname / gid -- last one wins.
117 if (k == "gid" && "gname" in old)
119 if (k == "gname" && "gid" in old)
121 # Otherwise newest value wins
126 # Process the line we've read in, per the comments below
127 function process_line(path, new)
130 line2kv(new_kvs, new);
132 if ("unlink" in new_kvs) {
134 # Sanity check to see if tree[path] exists?
135 # Makes sure when foo/bar/baz exists and foo/bar
136 # unlinked, baz is gone (for all baz).
138 die("bad path in : " new);
139 delete tree[path]; # unlink
141 # } else if (new_kvs["append_from"]) { # not implemented
142 } else if ("copy_from" in new_kvs) {
143 # A file copied from another location, preserve its
144 # attribute for new file.
145 # Also merge any new attributes from this line.
146 from = new_kvs["copy_from"];
148 die("bad path in : " new);
149 delete new_kvs["copy_from"];
150 line2kv(old_kvs, tree[from]); # old_kvs = kv's in entry
151 merge_kvs(old_kvs, new_kvs); # old_kvs += new_kvs
152 tree[path] = mtree_from_kvs(path, old_kvs);
153 } else if ("move_from" in new_kvs) {
154 # A file moved from another location, preserve its
155 # attribute for new file, and scrag old location
156 # Also merge any new attributes from this line.
157 from = new_kvs["move_from"];
159 die("bad path in : " new);
160 delete new_kvs["move_from"];
161 line2kv(old_kvs, tree[from]); # old_kvs = kv's in entry
162 merge_kvs(old_kvs, new_kvs); # old_kvs += new_kvs
163 tree[path] = mtree_from_kvs(path, old_kvs);
164 delete tree[from]; # unlink
165 } else if (tree[path]) { # Update existing entry with new line
166 line2kv(old_kvs, tree[path]); # old_kvs = kv's in entry
167 merge_kvs(old_kvs, new_kvs); # old_kvs += new_kvs
168 tree[path] = mtree_from_kvs(path, old_kvs);
169 } else { # Add entry plus defaults
171 merge_kvs(old_kvs, defaults);
172 merge_kvs(old_kvs, new_kvs);
173 tree[path] = mtree_from_kvs(path, old_kvs);
178 nv = "___NO__VALUE___";
180 while ((getline < "/dev/stdin") > 0) {
184 for (i = 2; i <= NF; i++) {
186 defaults[kv_key] = kv_value;
188 } else if ($1 == "/unset") {
189 for (i = 2; i <= NF; i++) {
191 delete defaults[kv_key];
194 process_line($1, $0);
197 # Print the last set of defaults. This will carry
198 # over, I think, to makefs' defaults
199 print mtree_from_kvs("/set", defaults)