]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/tools/nanobsd/mtree-dedup.awk
nanobsd: Set a GPT label for EFI and cfg partitions
[FreeBSD/FreeBSD.git] / tools / tools / nanobsd / mtree-dedup.awk
1 #!/usr/bin/awk -f
2
3 #
4 # Copyright (c) 2015 M. Warner Losh <imp@FreeBSD.org>
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 #    notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 #    notice, this list of conditions and the following disclaimer in the
13 #    documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 # SUCH DAMAGE.
26 #
27 #
28
29 #
30 # Takes a meta-log created by installworld and friends, plus
31 # additions from NanoBSD to augment its build to communicate when
32 # files move around after installworld / installkernel phase of
33 # NanoBSD.
34 #
35 # All mtree lines from the metafile have a path, followed by
36 # a number of keywords.
37 #
38 # This script recognizes the following new keywords
39 #
40 # unlink[=x]    remove the path from the output.
41 # copy_from=x   create new entry for path copied from
42 #               the keywords from x.
43 # move_from=x   create new entry for path copied from
44 #               the keywords from x. Remove path from
45 #               the output.
46 #
47 # In addition, when path matches a previous entry, the
48 # new entry and previous entry are merged.
49 #
50 # Special note: when uid and uname are both present,
51 # uid is ignored. Ditto gid/gname.
52 #
53 # Also, the paths above have to match exactly, so X
54 # should start with "./".
55 #
56
57 function die(str)
58 {
59         print str > "/dev/stderr";
60         exit 1;
61 }
62
63 function kv(str)
64 {
65         if (split(str, xxx, "=") == 2) {
66                 kv_key = xxx[1];
67                 kv_value = xxx[2];
68         } else {
69                 kv_key = str;
70                 kv_value = nv;
71         }
72 }
73
74 # Output the mtree for path based on the kvs.
75 function mtree_from_kvs(path, kvs)
76 {
77         lv = path " ";
78         for (k in kvs) {
79                 if (kvs[k] == nv)
80                         lv = lv k " ";
81                 else
82                         lv = lv k "=" kvs[k] " ";
83         }
84         return lv;
85 }
86
87 # Parse the mtree line into path + KVs. Use a sentinal value
88 # for a bare keyword, which is extremely unlikely to be used
89 # for real.
90 function line2kv(kvs, str)
91 {
92         delete kvs;
93
94         n = split(str, yyy, " ");
95         for (i = 2; i <= n; i++) {
96                 s = yyy[i];
97                 if (split(s, xxx, "=") == 2)
98                         kvs[xxx[1]] = xxx[2];
99                 else
100                         kvs[s] = nv;
101         }
102 }
103
104
105 # old += new
106 function merge_kvs(old, new)
107 {
108         for (k in new) {
109                 # uname / uid -- last one wins.
110                 if (k == "uid" && "uname" in old)
111                         delete old["uname"]
112                 if (k == "uname" && "uid" in old)
113                         delete old["uid"];
114                 # gname / gid -- last one wins.
115                 if (k == "gid" && "gname" in old)
116                         delete old["gname"]
117                 if (k == "gname" && "gid" in old)
118                         delete old["gid"];
119                 # Otherwise newest value wins
120                 old[k] = new[k];
121         }
122 }
123
124 # Process the line we've read in, per the comments below
125 function process_line(path, new)
126 {
127         # Clear kvs
128         line2kv(new_kvs, new);
129
130         if ("unlink" in new_kvs) {
131                 # A file removed
132                 # Sanity check to see if tree[path] exists? 
133                 # Makes sure when foo/bar/baz exists and foo/bar
134                 # unlinked, baz is gone (for all baz).
135                 if (path !~ "^\./")
136                         die("bad path in : " new);
137                 delete tree[path];              # unlink
138                 return;
139         # } else if (new_kvs["append_from"]) { # not implemented
140         } else if ("copy_from" in new_kvs) {
141                 # A file copied from another location, preserve its
142                 # attribute for new file.
143                 # Also merge any new attributes from this line.
144                 from = new_kvs["copy_from"];
145                 if (from !~ "^\./")
146                         die("bad path in : " new);
147                 delete new_kvs["copy_from"];
148                 line2kv(old_kvs, tree[from]);   # old_kvs = kv's in entry
149                 merge_kvs(old_kvs, new_kvs);    # old_kvs += new_kvs
150                 tree[path] = mtree_from_kvs(path, old_kvs);
151         } else if ("move_from" in new_kvs) {
152                 # A file moved from another location, preserve its
153                 # attribute for new file, and scrag old location
154                 # Also merge any new attributes from this line.
155                 from = new_kvs["move_from"];
156                 if (from !~ "^\./")
157                         die("bad path in : " new);
158                 delete new_kvs["move_from"];
159                 line2kv(old_kvs, tree[from]);   # old_kvs = kv's in entry
160                 merge_kvs(old_kvs, new_kvs);    # old_kvs += new_kvs
161                 tree[path] = mtree_from_kvs(path, old_kvs);
162                 delete tree[from];              # unlink
163         } else if (tree[path]) {        # Update existing entry with new line
164                 line2kv(old_kvs, tree[path]);   # old_kvs = kv's in entry
165                 merge_kvs(old_kvs, new_kvs);    # old_kvs += new_kvs
166                 tree[path] = mtree_from_kvs(path, old_kvs);
167         } else {                        # Add entry plus defaults
168                 delete old_kvs;
169                 merge_kvs(old_kvs, defaults);
170                 merge_kvs(old_kvs, new_kvs);
171                 tree[path] = mtree_from_kvs(path, old_kvs);
172         }
173 }
174
175 BEGIN {
176         nv = "___NO__VALUE___";
177
178         while ((getline < "/dev/stdin") > 0) {
179                 if ($1 ~ "^#")
180                         continue;
181                 if ($1 == "/set") {
182                         for (i = 2; i <= NF; i++) {
183                                 kv($i);
184                                 defaults[kv_key] = kv_value;
185                         }
186                 } else if ($1 == "/unset") {
187                         for (i = 2; i <= NF; i++) {
188                                 kv($i);
189                                 delete defaults[kv_key];
190                         }
191                 } else
192                         process_line($1, $0);
193         }
194
195         # Print the last set of defaults. This will carry
196         # over, I think, to makefs' defaults
197         print mtree_from_kvs("/set", defaults)
198         for (x in tree)
199                 print tree[x];
200 }