carbon-config

config submodule of carbon-core-system
git clone https://ccx.te2000.cz/git/carbon-config
Log | Files | Refs

parse_fs.include.awk (7251B)


      1 BEGIN{
      2 	param_validator["source"] = ".+"
      3 	param_validator["type"] = "[a-z0-9._]+"
      4 	param_validator["options"] = ".*"
      5 	param_validator["bundles"] = "[^ 	]+"
      6 	param_validator["down"] = "(umount|readonly|keep)"
      7 	param_validator["mkdir"] = "(true|false)"
      8 	param_validator["premounted"] = "(true|false)"
      9 	param_validator["service_name"] = "[^ 	/]+"
     10 	param_validator["dependencies"] = "[^/]*"
     11 	param_validator["extra_dependencies"] = "[^/]+"
     12 	fail = 0
     13 }
     14 
     15 function q(s) {  # quote string for execline
     16 	gsub(/\\/, "\\\\", s)
     17 	gsub(/\n/, "\\n", s)
     18 	gsub(/\"/, "\\\"", s)
     19 	return "\"" s "\""
     20 }
     21 
     22 function fatal_mtp(s){
     23 	print mountpoints[mtp] ": Error: " s "  [" mtp "]" >"/dev/stderr"
     24 	fail=1
     25 	exit 1
     26 }
     27 
     28 function fatal_parse(s){
     29 	print FILENAME ":" FNR ": Error: " s >"/dev/stderr"
     30 	fail=1
     31 	exit 1
     32 }
     33 
     34 function dbg(s){
     35 	if(debug) {
     36 		print("#" s)
     37 	}
     38 }
     39 
     40 function is_parent(child_path, parent_path) {
     41 	if(child_path == "/") {
     42 		return 0
     43 	}
     44 	if(parent_path == "/") {
     45 		return 1
     46 	}
     47 	parent_path = parent_path "/"
     48 	return substr(child_path, 1, length(parent_path)) == parent_path
     49 }
     50 # function is_parent(child_path, parent_path,  result) {
     51 # 	result = is_parent_(child_path, parent_path)
     52 # 	dbg("++ '" parent_path "' " (result?"is":"is NOT") " parent of '" child_path "'")
     53 # 	return result
     54 # }
     55 
     56 function mtp_get(mtp_x, name) {
     57 	if(!((mtp_x,name) in params)) {
     58 		fatal_mtp("parameter '" name "' not set")
     59 	}
     60 	if(name in param_validator) {
     61 		if(params[mtp_x,name] !~ ("^" param_validator[name] "$")) {
     62 			fatal_mtp("Internal: parameter '" mtp_x "','" name "' set to unrecognized value '" params[mtp_x,name] "'")
     63 		}
     64 	} else if (!(name in param_extras)) {
     65 		fatal_mtp("Internal: parameter name '" mtp_x "','" name "' not known")
     66 	}
     67 	return params[mtp_x,name]
     68 }
     69 
     70 function get(name) {
     71 	return mtp_get(mtp, name)
     72 }
     73 
     74 function set(name, value) {
     75 	if(name in param_validator) {
     76 		if(value !~ ("^" param_validator[name] "$")) {
     77 			fatal_mtp("Internal: tried to set '" name "' set to unrecognized value '" value "'")
     78 		}
     79 	} else if (!(name in param_extras)) {
     80 		fatal_mtp("Internal: parameter name '" name "' not known")
     81 	}
     82 	params[mtp,name] = value
     83 }
     84 
     85 function set1(name, value) {
     86 	if((mtp,name) in params) {
     87 		fatal_mtp("parameter '" name "' already set to '" params[mtp,value] "', tried to assign '" value "'")
     88 	}
     89 	set(name, value)
     90 }
     91 
     92 function boolean(name) {  # Check boolean parameter
     93 	return get(name) == "true"
     94 }
     95 
     96 function down(is_value) {  # Check "down" parameter
     97 	return is_value == get("down")
     98 }
     99 
    100 function down_umount() { return down("umount") }
    101 function down_keep() { return down("keep") }
    102 function down_readonly() { return down("readonly") }
    103 
    104 function dependencies(     s, i) {
    105 	s = ""
    106 	for(i=1; i<=dn; i++) {
    107 		s = s "\t" ds[i] "\n"
    108 	}
    109 	return s
    110 }
    111 
    112 function find_topmost_mount(     found, mtp2) {
    113 	found = ""
    114 	for(mtp2 in mountpoints) {
    115 		if(length(mtp2) > length(found) && is_parent(mtp, mtp2)) {
    116 			found = mtp2
    117 		}
    118 	}
    119 	if(!length(found)) {
    120 		# consider if this should be error for mtp != "/"
    121 		return ""
    122 	}
    123 	dbg(" dep FOUND: '" found "' -> svc: '" mtp_get(found, "service_name") "'")
    124 	if(!boolean("mkdir")) {
    125 		if(mtp_get(found,"premounted") == "true" && mtp_get(found,"down") != "umount") {
    126 			# Dependency would be superfluous
    127 			return ""
    128 		}
    129 	}
    130 	# fatal_mtp("FOUND: '" found "' -> svc: '" mtp_get(found, "service_name") "'")
    131 	return params[found, "service_name"]
    132 }
    133 
    134 function process_record(    name, i, mtp2) {
    135 	dbg("## ----------------------------------------------------------------------")
    136 	if(!((mtp,"premounted") in params)) {
    137 		set1("premounted", "false")
    138 	}
    139 
    140 	if(!((mtp,"mkdir") in params)) {
    141 		set1("mkdir", boolean("premounted") ? "false" : "true")
    142 	}
    143 
    144 	if(!((mtp,"down") in params)) {
    145 		set1("down", "umount")
    146 	}
    147 
    148 	if(!((mtp,"options") in params)) {
    149 		set1("options", "rw")
    150 	}
    151 
    152 	# set1("dependencies", "foo bar")
    153 	if(((mtp,"dependencies") in params)) {
    154 		if(((mtp,"extra_dependencies") in params)) {
    155 			fatal_mtp("Define either 'extra_dependencies' or 'dependencies', not both")
    156 		}
    157 		dn = split(get("dependencies"), ds)
    158 
    159 	} else {
    160 		if(((mtp,"extra_dependencies") in params)) {
    161 			dn = split(get("extra_dependencies"), ds)
    162 		} else {
    163 			dn = 0
    164 		}
    165 		i = find_topmost_mount()
    166 		if(length(i)) {
    167 			dn += 1
    168 			ds[dn] = i
    169 		}
    170 
    171 	}
    172 
    173 	#print(">>> " mtp " <<< " ((mtp,"service_name") in params))
    174 	# if(!((mtp,"service_name") in params)) {
    175 	# It may be initialized by access from find_topmost_mount()
    176 	if(length(params[mtp,"service_name"]) == 0) {
    177 		if(mtp == "/") {
    178 			if(!boolean("premounted")) {
    179 				fatal_mtp("rootfs not set as premounted")
    180 			}
    181 			set("service_name", "rootfs")
    182 		} else {
    183 			svc_name = mtp
    184 			gsub("/", "-", svc_name)
    185 			set("service_name", "mount" svc_name)
    186 		}
    187 	}
    188 	svc_name = get("service_name")
    189 	if(svc_name !~ ("^" param_validator["service_name"] "$")) {
    190 		fatal_mtp("Service name '" svc_name "' not valid")
    191 	}
    192 	if(svc_name in services) {
    193 		fatal_mtp("Service name '" svc_name "' collides with mountpoint '" services[svc_name] "' defined at " mountpoints[services[svc_name]])
    194 	}
    195 	services[svc_name] = mtp
    196 
    197 	if(debug) {
    198 		printf("#>> mtp='%s'\n", mtp)
    199 		for(name in params) {
    200 			if(substr(name, 1, length(mtp)+1) == mtp SUBSEP) {
    201 				printf("#>> %s='%s'\n", substr(name, length(mtp)+1), params[name])
    202 			}
    203 		}
    204 	}
    205 
    206 
    207 	q_file = q(mtp)
    208 	q_spec = q(get("source"))
    209 	q_vfstype = q(get("type"))
    210 	q_remount_options = get("options") == "defaults" ? "remount" : q("remount," get("options"))
    211 	q_options = q(get("options"))
    212 
    213 	write_oneshot()
    214 
    215 	if((mtp,"bundles") in params) {
    216 		split(get("bundles"), bundle_list)
    217 		for(i in bundle_list) {
    218 			add_to_bundle(bundle_list[i], svc_name)
    219 		}
    220 		delete bundle_list
    221 	}
    222 
    223 	#delete params
    224 	mtp = ""
    225 }
    226 
    227 function process_bundles(    name) {
    228 	for(name in bundles) {
    229 		write_bundle(name)
    230 	}
    231 }
    232 
    233 function validate_mountpoint(    mtp2) {
    234 	if(mtp in mountpoints) {
    235 		fatal_parse("duplicate definition of mountpoint '" $0 "', previous definition at " mountpoints[$0])
    236 	}
    237 	if(mtp != "/" && mtp ~ "/$") {
    238 		fatal_parse("Trailing slash not allowed: '" mtp "'")
    239 	}
    240 	if(mtp ~ "/(|\\.|\\.\\.)/") {
    241 		fatal_parse("Mountpoint '" mtp "' is not canonical absolute path")
    242 	}
    243 	for(mtp2 in mountpoints) {
    244 		if(is_parent(mtp2, mtp)) {
    245 			fatal_parse("mountpoint '" mtp "' defined after implicit reverse dependency '" mtp2 "' located at " mountpoints[mtp2])
    246 		}
    247 	}
    248 }
    249 
    250 # Skip comments
    251 /^[ \t]*#/{ next }
    252 
    253 # mountpoint (aka fs_file in fstab)
    254 /^\//{
    255 	if(mtp) {
    256 		process_record()
    257 	}
    258 	mtp=$0
    259 	validate_mountpoint()
    260 	mountpoints[mtp] = FILENAME ":" FNR
    261 	next
    262 }
    263 
    264 # All other lines
    265 {
    266 	line=$0
    267 	m = match(line, /^[ \t]+/)
    268 	if(m) {
    269 		# Strip leading whitespace
    270 		line = substr(line, m+RLENGTH)
    271 	}
    272 	if(length(line) == 0) {
    273 		# Skip empty lines
    274 		next
    275 	}
    276 	m = match(line, /=/)
    277 	if(m) {
    278 		name = substr(line, 1, m-1)
    279 		value = substr(line, m+RLENGTH)
    280 		if((mtp, name) in params) {
    281 			fatal_parse("Duplicate definition of parameter '" name "'")
    282 		}
    283 		if(!(name in param_validator)) {
    284 			fatal_parse("Unrecognized parameter '" name "'")
    285 		}
    286 		if(value !~ ("^" param_validator[name] "$")) {
    287 			fatal_parse("Invalid value for parameter '" name "': '" value "'")
    288 		}
    289 		params[mtp,name] = value
    290 	} else {
    291 		fatal_parse("missing '=' in parameter definition")
    292 	}
    293 }
    294 
    295 END{
    296 	if(fail) {
    297 		exit fail
    298 	}
    299 	if(mtp) {
    300 		process_record()
    301 	}
    302 	print_bundles()
    303 }