The cirros image was rebuilt against the 3.13.0-83 kernel, drivers e1000e, igbvf...
[packages/trusty/cirros-testvm.git] / cirros-testvm / src-cirros / src / usr / bin / json2fstree
diff --git a/cirros-testvm/src-cirros/src/usr/bin/json2fstree b/cirros-testvm/src-cirros/src/usr/bin/json2fstree
new file mode 100755 (executable)
index 0000000..d412ebf
--- /dev/null
@@ -0,0 +1,342 @@
+#!/usr/bin/awk -f
+
+### begin from awkenough (https://github.com/dubiousjim/awkenough) ####
+function assert(test, msg) {
+       if (!test) die(msg ? msg : "assertion failed")
+}
+
+# if you call die, assert, or check*: start END blocks with
+#      { if (EXITCODE) exit EXITCODE; ... }
+function die(msg) {
+       EXITCODE=1
+       printf("%s: %s\n", ARGV[0], msg) > "/dev/stderr"
+       exit EXITCODE
+}
+
+function parse_json(str, T, V,  slack, c,s,n,a,A,b,B,C,U,W,i,j,k,u,v,w,root) {
+       # use strings, numbers, booleans as separators
+       # c = "[^\"\\\\[:cntrl:]]|\\\\[\"\\\\/bfnrt]|\\u[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]"
+       c = "[^\"\\\\\001-\037]|\\\\[\"\\\\/bfnrt]|\\\\u[[:xdigit:]A-F][[:xdigit:]A-F][[:xdigit:]A-F][[:xdigit:]A-F]"
+       s ="\"(" c ")*\""
+       n = "-?(0|[1-9][[:digit:]]*)([.][[:digit:]]+)?([eE][+-]?[[:digit:]]+)?"
+
+       root = gsplit(str, A, s "|" n "|true|false|null", T)
+       assert(root > 0, "unexpected")
+
+       # rejoin string using value indices
+       str = ""
+       for (i=1; i<root; i++)
+               str = str A[i] i
+       str = str A[root]
+
+       # cleanup types and values
+       for (i=1; i<root; i++) {
+               if (T[i] ~ /^\"/) {
+                       b = split(substr(T[i], 2, length(T[i])-2), B, /\\/)
+                       if (b == 0) v = ""
+                       else {
+                               v = B[1]
+                               k = 0
+                               for (j=2; j <= b; j++) {
+                                       u = B[j]
+                                       if (u == "") {
+                                               if (++k % 2 == 1) v = v "\\"
+                                       } else {
+                                               w = substr(u, 1, 1)  
+                                               if (w == "b") v = v "\b" substr(u, 2)
+                                               else if (w == "f") v = v "\f" substr(u, 2)
+                                               else if (w == "n") v = v "\n" substr(u, 2)
+                                               else if (w == "r") v = v "\r" substr(u, 2)
+                                               else if (w == "t") v = v "\t" substr(u, 2)
+                                               else v = v u
+                                       }
+                               }
+                       }
+                       V[i] = v
+                       T[i] = "string"
+               } else if (T[i] !~ /true|false|null/) {
+                       V[i] = T[i] + 0
+                       T[i] = "number"
+               } else {
+                       V[i] = T[i]
+               }
+       }
+
+       # sanitize string
+       gsub(/[[:space:]]+/, "", str)
+       if (str !~ /^[][{}[:digit:],:]+$/) {
+               if (slack !~ /:/) return -1
+               # handle ...unquoted:...
+               a = gsplit(str, A, "[[:alpha:]_][[:alnum:]_]*:", B)
+               str = ""
+               for (i=1; i < a; i++) {
+                       T[root] = "string"
+                       V[root] = substr(B[i], 1, length(B[i])-1)
+                       str = str A[i] root ":"
+                       root++
+               }
+               str = str A[a]
+               if (str !~ /^[][{}[:digit:],:]+$/) return -10
+       }
+
+       # atomic value?
+       a = gsplit(str, A, "[[{]", B)
+       if (A[1] != "") {
+               if (a > 1) return -2
+               else if (A[1] !~ /^[[:digit:]]+$/) return -3
+               else return A[1]+0
+       }
+
+       # parse objects and arrays
+       k = root
+       C[0] = 0
+       for (i=2; i<=a; i++) {
+               T[k] = (B[i-1] ~ /\{/) ? "object" : "array"
+               C[k] = C[0]
+               C[0] = k
+               u = gsplit(A[i], U, "[]}]", W)
+               assert(u > 0, "unexpected")
+               V[k++] = U[1]
+               if (i < a && A[i] != "" && U[u] !~ /[,:]$/)
+                       return -4
+               for (j=1; j<u; j++) {
+                       if (C[0] == 0 || T[C[0]] != ((W[j] == "}") ? "object" : "array")) return -5
+                       v = C[0]
+                       w = C[v]
+                       C[0] = w
+                       delete C[v]
+                       if (w) V[w] = V[w] v U[j+1]
+               }
+       }
+       if (C[0] != 0) return -6
+
+       # check contents
+       for (i=root; i<k; i++) {
+               if (T[i] == "object") {
+                       # check object contents
+                       b = split(V[i], B, /,/) 
+                       for (j=1; j <= b; j++) {
+                               if (B[j] !~ /^[[:digit:]]+:[[:digit:]]+$/)
+                                       return -7
+                               if (T[substr(B[j], 1, index(B[j],":")-1)] != "string")
+                                       return -8
+                       }
+               } else if (V[i] != "") {
+                       # check array contents
+                       if (slack ~ /,/ && V[i] ~ /,$/)
+                               V[i] = substr(V[i], 1, length(V[i] -1))
+                       if (V[i] !~ /^[[:digit:]]+(,[[:digit:]]+)*$/)
+                               return -9
+               }
+       }
+       return root
+}
+
+# populate array from str="key key=value key=value"
+# can optionally supply "re" for equals, space; if they're the same or equals is "", array will be setlike
+function asplit(str, array,  equals, space,   aux, i, n) {
+       n = split(str, aux, (space == "") ? "[ \n]+" : space)
+       if (space && equals == space)
+               equals = ""
+       else if (ismissing(equals))
+               equals = "="
+       split("", array) # delete array
+       for (i=1; i<=n; i++) {
+               if (equals && match(aux[i], equals))
+                       array[substr(aux[i], 1, RSTART-1)] = substr(aux[i], RSTART+RLENGTH)
+               else
+                       array[aux[i]]
+       }
+       split("", aux) # does it help to delete the aux array?
+       return n
+}
+
+function query_json(str, X,  root, slack,   T, V, A, B, C, i, j, k) {
+       k = parse_json(str, T, V, slack)
+       if (k < 1) return k
+       split(root, C, ".")
+       j = 1
+       while (j in C) {
+               if (T[k] == "array")
+                       split(V[k], A, ",")
+               else {
+                       split("", A)
+                       asplit(V[k], B, ":", ",")
+                       for (i in B)
+                               A[V[i]] = B[i]
+               }
+               if (C[j] in A) {
+                       k = A[C[j]]
+                       j++
+               } else return -11 # can't find requested root
+       }
+       # split("", B)
+       # split("", C)
+       split("", X)
+       B[k] = ""
+       C[k] = 0
+       C[0] = k
+       do {
+               C[0] = C[k]
+               delete C[k]
+               j = T[k]
+               if (j == "array") {
+                       j = split(V[k], A, ",")
+                       k = B[k] ? B[k] SUBSEP : ""
+                       X[k 0] = j
+                       for (i=1; i<=j; i++) {
+                               # push A[i] to C, (B[k],i) to B 
+                               C[A[i]] = C[0]
+                               B[A[i]] = k i
+                               C[0] = A[i]
+                       }
+               } else if (j == "object") {
+                       asplit(V[k], A, ":", ",")
+                       k = B[k] ? B[k] SUBSEP : ""
+                       for (i in A) {
+                               # push A[i] to C, (B[k],V[i]) to B 
+                               C[A[i]] = C[0]
+                               B[A[i]] = k V[i]
+                               C[0] = A[i]
+                       }
+               } else if (j == "number") {
+                       X[B[k]] = V[k]
+               } else if (j == "true") {
+                       X[B[k]] = 1
+               } else if (j == "false") {
+                       X[B[k]] = 0
+               } else if (j == "string") {
+                       X[B[k]] = V[k]
+               } else {
+                       # null will satisfy ismissing()
+                       X[B[k]]
+               }
+               k = C[0]
+       } while (k)
+       return 0
+}
+
+# unitialized scalar
+function ismissing(u) {
+       return u == 0 && u == ""
+}
+
+# behaves like gawk's split; special cases re == "" and " "
+# unlike split, will honor 0-length matches
+function gsplit(str, items, re,  seps,   n, i, start, stop, sep1, sep2, sepn) {
+       n = 0
+       # find separators that don't occur in str
+       i = 1
+       do
+               sep1 = sprintf("%c", i++)
+       while (index(str, sep1))
+       do
+               sep2 = sprintf("%c", i++)
+       while (index(str, sep2))
+       sepn = 1
+       split("", seps) # delete array
+       if (ismissing(re))
+               re = FS
+       if (re == "") {
+               split(str, items, "")
+               n = length(str)
+               for (i=1; i<n; i++)
+                       seps[i]
+               return n
+       }
+       split("", items) # delete array
+       if (re == " ") {
+               re = "[ \t\n]+"
+               if (match(str, /^[ \t\n]+/)) {
+                       seps[0] = substr(str, 1, RLENGTH)
+                       str = substr(str, RLENGTH+1)
+               }
+               if (match(str, /[ \t\n]+$/)) {
+                       sepn = substr(str, RSTART, RLENGTH)
+                       str = substr(str, 1, RSTART-1)
+               }
+       }
+       i = gsub(re, sep1 "&" sep2, str)
+       while (i--) {
+               start = index(str, sep1)
+               stop = index(str, sep2) - 1
+               seps[++n] = substr(str, start + 1, stop - start)
+               items[n] = substr(str, 1, start - 1)
+               str = substr(str, stop + 2)
+       }
+       items[++n] = str
+       if (sepn != 1) seps[n] = sepn
+       return n
+}
+
+function basename(path, suffix) {
+       sub(/\/$/, "", path)
+       if (path == "")
+               return "/"
+       sub(/^.*\//, "", path)
+       if(suffix != "" && has_suffix(path, suffix))
+               path = substr(path, 1, length(path) - length(suffix))
+       return path
+}
+
+function dirname(path) {
+       if (!sub(/\/[^\/]*\/?$/, "", path))
+               return "."
+       else if (path != "")
+               return path
+       else
+               return "/"
+}
+
+function has_suffix(str, suf, len1, len2) {
+       len1 = length(str)
+       len2 = length(suf)
+       return len2 <= len1 && substr(str, len1 - len2 + 1) == suf
+}
+### end from awkenough ####
+
+BEGIN {
+       EXITCODE = ""
+       USAGE = "json2fstree: basedir [file]\n\
+       read json data in file and create directory tree under basedir\n"
+
+       if (ARGC != 2 && ARGC != 3) {
+               printf(USAGE) >"/dev/stderr"
+               EXITCODE = 1
+               exit(1)
+       }
+       if (ARGV[1] == "-h" || ARGV[1] == "--help") {
+               EXITCODE = 0
+               print USAGE
+               exit(0)
+       }
+       outd = ARGV[1]
+       if (ARGC == 3) {
+               ARGV[1] = ARGV[2]
+               ARGC = 2
+       } else {
+               ARGC = 1
+               ARGV[1] = ""
+       }
+       RS = SUBSEP
+}
+
+END {
+       if (EXITCODE != "") {
+               exit(EXITCODE)
+       }
+       ret = query_json($0, data)
+       assert(ret == 0, "failed to parse json\n")
+
+       for (key in data) {
+               path = key
+               gsub("/", "_", path)
+               gsub(SUBSEP, "/", path)
+               fpath = outd "/" path
+               ret = system("mkdir -p " dirname(fpath))
+               assert(ret == 0, "failed to mkdir " fpath)
+               printf("%s", data[key]) > fpath
+       }
+}
+
+# vi: ts=4 noexpandtab