blob: 6a16feacb97aed16fc93d4c33c63d480332a15ba [file] [log] [blame]
William Robertsc950a352016-03-04 18:12:29 -08001#!/usr/bin/env python
2
3import ConfigParser
4import re
5import sys
William Robertsd7104bc2016-04-11 21:17:12 -07006
William Robertsc950a352016-03-04 18:12:29 -08007
Elliott Hughesfad4b4b2016-12-12 17:28:44 -08008GENERATED = '''
9/*
10 * THIS IS AN AUTOGENERATED FILE! DO NOT MODIFY
11 */
12'''
William Robertsc950a352016-03-04 18:12:29 -080013
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080014INCLUDE = '#include <private/android_filesystem_config.h>'
William Robertsc950a352016-03-04 18:12:29 -080015
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080016DEFINE_NO_DIRS = '#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS\n'
17DEFINE_NO_FILES = '#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES\n'
William Robertsc950a352016-03-04 18:12:29 -080018
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080019DEFAULT_WARNING = '#warning No device-supplied android_filesystem_config.h, using empty default.'
William Robertsc950a352016-03-04 18:12:29 -080020
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080021NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS_ENTRY = '{ 00000, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_dirs" },'
22NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES_ENTRY = '{ 00000, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_files" },'
William Robertsc950a352016-03-04 18:12:29 -080023
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080024IFDEF_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS = '#ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS'
25ENDIF = '#endif'
William Robertsc950a352016-03-04 18:12:29 -080026
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080027OPEN_FILE_STRUCT = 'static const struct fs_path_config android_device_files[] = {'
28OPEN_DIR_STRUCT = 'static const struct fs_path_config android_device_dirs[] = {'
29CLOSE_FILE_STRUCT = '};'
William Robertsc950a352016-03-04 18:12:29 -080030
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080031GENERIC_DEFINE = "#define %s\t%s"
William Robertsc950a352016-03-04 18:12:29 -080032
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080033FILE_COMMENT = '// Defined in file: \"%s\"'
William Robertsc950a352016-03-04 18:12:29 -080034
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080035# from system/core/include/private/android_filesystem_config.h
36AID_OEM_RESERVED_RANGES = [
37 (2900, 2999),
38 (5000, 5999),
39]
William Robertsc950a352016-03-04 18:12:29 -080040
41
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080042AID_MATCH = re.compile('AID_[a-zA-Z]+')
William Roberts64edf5b2016-04-11 17:12:47 -070043
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080044def handle_aid(file_name, section_name, config, aids, seen_aids):
45 value = config.get(section_name, 'value')
William Roberts64edf5b2016-04-11 17:12:47 -070046
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080047 errmsg = '%s for: \"' + section_name + '" file: \"' + file_name + '\"'
William Roberts64edf5b2016-04-11 17:12:47 -070048
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080049 if not value:
50 raise Exception(errmsg % 'Found specified but unset "value"')
William Roberts64edf5b2016-04-11 17:12:47 -070051
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080052 v = convert_int(value)
53 if not v:
54 raise Exception(errmsg % ('Invalid "value", not a number, got: \"%s\"' % value))
William Roberts64edf5b2016-04-11 17:12:47 -070055
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080056 # Values must be within OEM range
57 if not any(lower <= v <= upper for (lower, upper) in AID_OEM_RESERVED_RANGES):
58 s = '"value" not in valid range %s, got: %s'
59 s = s % (str(AID_OEM_RESERVED_RANGES), value)
60 raise Exception(errmsg % s)
William Roberts64edf5b2016-04-11 17:12:47 -070061
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080062 # use the normalized int value in the dict and detect
63 # duplicate definitions of the same vallue
64 v = str(v)
65 if v in seen_aids[1]:
66 # map of value to aid name
67 a = seen_aids[1][v]
William Roberts1c4721c2016-04-26 13:05:34 -070068
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080069 # aid name to file
70 f = seen_aids[0][a]
William Roberts1c4721c2016-04-26 13:05:34 -070071
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080072 s = 'Duplicate AID value "%s" found on AID: "%s".' % (value, seen_aids[1][v])
73 s += ' Previous found in file: "%s."' % f
74 raise Exception(errmsg % s)
William Roberts1c4721c2016-04-26 13:05:34 -070075
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080076 seen_aids[1][v] = section_name
William Roberts1c4721c2016-04-26 13:05:34 -070077
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080078 # Append a tuple of (AID_*, base10(value), str(value))
79 # We keep the str version of value so we can print that out in the
80 # generated header so investigating parties can identify parts.
81 # We store the base10 value for sorting, so everything is ascending
82 # later.
83 aids.append((file_name, section_name, v, value))
William Roberts1c4721c2016-04-26 13:05:34 -070084
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080085def convert_int(num):
William Roberts64edf5b2016-04-11 17:12:47 -070086
87 try:
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080088 if num.startswith('0x'):
89 return int(num, 16)
90 elif num.startswith('0b'):
91 return int(num, 2)
92 elif num.startswith('0'):
93 return int(num, 8)
94 else:
95 return int(num, 10)
William Roberts64edf5b2016-04-11 17:12:47 -070096 except ValueError:
Elliott Hughesfad4b4b2016-12-12 17:28:44 -080097 pass
98 return None
William Roberts64edf5b2016-04-11 17:12:47 -070099
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800100def handle_path(file_name, section_name, config, files, dirs):
William Roberts64edf5b2016-04-11 17:12:47 -0700101
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800102 mode = config.get(section_name, 'mode')
103 user = config.get(section_name, 'user')
104 group = config.get(section_name, 'group')
105 caps = config.get(section_name, 'caps')
William Roberts64edf5b2016-04-11 17:12:47 -0700106
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800107 errmsg = 'Found specified but unset option: \"%s" in file: \"' + file_name + '\"'
William Roberts64edf5b2016-04-11 17:12:47 -0700108
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800109 if not mode:
110 raise Exception(errmsg % 'mode')
William Roberts64edf5b2016-04-11 17:12:47 -0700111
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800112 if not user:
113 raise Exception(errmsg % 'user')
William Roberts64edf5b2016-04-11 17:12:47 -0700114
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800115 if not group:
116 raise Exception(errmsg % 'group')
William Roberts64edf5b2016-04-11 17:12:47 -0700117
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800118 if not caps:
119 raise Exception(errmsg % 'caps')
William Roberts64edf5b2016-04-11 17:12:47 -0700120
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800121 caps = caps.split()
William Roberts64edf5b2016-04-11 17:12:47 -0700122
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800123 tmp = []
124 for x in caps:
125 if convert_int(x):
126 tmp.append('(' + x + ')')
127 else:
128 tmp.append('(1ULL << CAP_' + x.upper() + ')')
William Roberts64edf5b2016-04-11 17:12:47 -0700129
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800130 caps = tmp
William Roberts64edf5b2016-04-11 17:12:47 -0700131
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800132 path = '"' + section_name + '"'
William Roberts64edf5b2016-04-11 17:12:47 -0700133
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800134 if len(mode) == 3:
135 mode = '0' + mode
William Roberts64edf5b2016-04-11 17:12:47 -0700136
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800137 try:
138 int(mode, 8)
139 except:
140 raise Exception('Mode must be octal characters, got: "' + mode + '"')
William Roberts64edf5b2016-04-11 17:12:47 -0700141
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800142 if len(mode) != 4:
143 raise Exception('Mode must be 3 or 4 characters, got: "' + mode + '"')
William Roberts64edf5b2016-04-11 17:12:47 -0700144
145
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800146 caps = '|'.join(caps)
William Roberts11c29282016-04-09 10:32:30 -0700147
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800148 x = [ mode, user, group, caps, section_name ]
149 if section_name[-1] == '/':
150 dirs.append((file_name, x))
151 else:
152 files.append((file_name, x))
William Roberts11c29282016-04-09 10:32:30 -0700153
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800154def handle_dup(name, file_name, section_name, seen):
155 if section_name in seen:
156 dups = '"' + seen[section_name] + '" and '
157 dups += file_name
158 raise Exception('Duplicate ' + name + ' "' + section_name + '" found in files: ' + dups)
William Roberts5f059a72016-04-25 10:36:45 -0700159
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800160def parse(file_name, files, dirs, aids, seen_paths, seen_aids):
William Robertsc950a352016-03-04 18:12:29 -0800161
162 config = ConfigParser.ConfigParser()
163 config.read(file_name)
164
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800165 for s in config.sections():
William Robertsc950a352016-03-04 18:12:29 -0800166
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800167 if AID_MATCH.match(s) and config.has_option(s, 'value'):
168 handle_dup('AID', file_name, s, seen_aids[0])
169 seen_aids[0][s] = file_name
170 handle_aid(file_name, s, config, aids, seen_aids)
171 else:
172 handle_dup('path', file_name, s, seen_paths)
173 seen_paths[s] = file_name
174 handle_path(file_name, s, config, files, dirs)
William Roberts5f059a72016-04-25 10:36:45 -0700175
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800176def generate(files, dirs, aids):
177 print GENERATED
178 print INCLUDE
179 print
William Roberts5f059a72016-04-25 10:36:45 -0700180
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800181 are_dirs = len(dirs) > 0
182 are_files = len(files) > 0
183 are_aids = len(aids) > 0
William Roberts5f059a72016-04-25 10:36:45 -0700184
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800185 if are_aids:
186 for a in aids:
187 # use the preserved str value
188 print FILE_COMMENT % a[0]
189 print GENERIC_DEFINE % (a[1], a[2])
William Roberts11c29282016-04-09 10:32:30 -0700190
William Robertscfc51f52016-04-12 08:51:13 -0700191 print
192
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800193 if not are_dirs:
194 print DEFINE_NO_DIRS
William Robertsc950a352016-03-04 18:12:29 -0800195
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800196 if not are_files:
197 print DEFINE_NO_FILES
William Roberts8f42ce72016-04-25 12:27:43 -0700198
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800199 if not are_files and not are_dirs and not are_aids:
200 print DEFAULT_WARNING
201 return
William Robertsc950a352016-03-04 18:12:29 -0800202
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800203 if are_files:
204 print OPEN_FILE_STRUCT
205 for tup in files:
206 f = tup[0]
207 c = tup[1]
208 c[4] = '"' + c[4] + '"'
209 c = '{ ' + ' ,'.join(c) + ' },'
210 print FILE_COMMENT % f
211 print ' ' + c
William Robertsc950a352016-03-04 18:12:29 -0800212
213 if not are_dirs:
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800214 print IFDEF_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
215 print ' ' + NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS_ENTRY
216 print ENDIF
217 print CLOSE_FILE_STRUCT
William Robertsc950a352016-03-04 18:12:29 -0800218
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800219 if are_dirs:
220 print OPEN_DIR_STRUCT
221 for d in dirs:
222 f[4] = '"' + f[4] + '"'
223 d = '{ ' + ' ,'.join(d) + ' },'
224 print ' ' + d
William Robertsc950a352016-03-04 18:12:29 -0800225
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800226 print CLOSE_FILE_STRUCT
William Robertsc950a352016-03-04 18:12:29 -0800227
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800228def file_key(x):
William Robertsc950a352016-03-04 18:12:29 -0800229
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800230 # Wrapper class for custom prefix matching strings
231 class S(object):
232 def __init__(self, str):
William Robertsc950a352016-03-04 18:12:29 -0800233
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800234 self.orig = str
235 self.is_prefix = str[-1] == '*'
236 if self.is_prefix:
237 self.str = str[:-1]
238 else:
239 self.str = str
William Robertsc950a352016-03-04 18:12:29 -0800240
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800241 def __lt__(self, other):
William Robertsc950a352016-03-04 18:12:29 -0800242
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800243 # if were both suffixed the smallest string
244 # is 'bigger'
245 if self.is_prefix and other.is_prefix:
246 b = len(self.str) > len(other.str)
247 # If I am an the suffix match, im bigger
248 elif self.is_prefix:
249 b = False
250 # If other is the suffix match, he's bigger
251 elif other.is_prefix:
252 b = True
253 # Alphabetical
254 else:
255 b = self.str < other.str
256 return b
William Robertsc950a352016-03-04 18:12:29 -0800257
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800258 return S(x[4])
William Roberts1c4721c2016-04-26 13:05:34 -0700259
William Robertsc950a352016-03-04 18:12:29 -0800260def main():
261
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800262 files = []
263 dirs = []
264 aids = []
265 seen_paths = {}
William Robertsc950a352016-03-04 18:12:29 -0800266
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800267 # (name to file, value to aid)
268 seen_aids = ({}, {})
William Robertsc950a352016-03-04 18:12:29 -0800269
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800270 for x in sys.argv[1:]:
271 parse(x, files, dirs, aids, seen_paths, seen_aids)
William Robertsc950a352016-03-04 18:12:29 -0800272
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800273 # sort entries:
274 # * specified path before prefix match
275 # ** ie foo before f*
276 # * lexicographical less than before other
277 # ** ie boo before foo
278 # Given these paths:
279 # paths=['ac', 'a', 'acd', 'an', 'a*', 'aa', 'ac*']
280 # The sort order would be:
281 # paths=['a', 'aa', 'ac', 'acd', 'an', 'ac*', 'a*']
282 # Thus the fs_config tools will match on specified paths before attempting
283 # prefix, and match on the longest matching prefix.
284 files.sort(key= lambda x: file_key(x[1]))
William Roberts8cb6a182016-04-08 22:06:19 -0700285
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800286 # sort on value of (file_name, name, value, strvalue)
287 # This is only cosmetic so AIDS are arranged in ascending order
288 # within the generated file.
289 aids.sort(key=lambda x: x[2])
William Roberts8cb6a182016-04-08 22:06:19 -0700290
Elliott Hughesfad4b4b2016-12-12 17:28:44 -0800291 generate(files, dirs, aids)
William Robertsc950a352016-03-04 18:12:29 -0800292
293if __name__ == '__main__':
294 main()