From 8f42ce71aceef823176c7bc14e60791be1b12f64 Mon Sep 17 00:00:00 2001 From: William Roberts Date: Mon, 25 Apr 2016 12:27:43 -0700 Subject: [PATCH] fs_config: generate friendly in AID class Generate the friendly name in one location. This prepares the tool for generatting passwd and group files. Also support mapping friendly names to identifiers. Test: That output files stay the same as before. Change-Id: I12198611126613eae81ca61614ed269c2439b72b Signed-off-by: William Roberts --- tools/fs_config/fs_config_generator.py | 180 ++++++++++++++++++++++----------- 1 file changed, 120 insertions(+), 60 deletions(-) diff --git a/tools/fs_config/fs_config_generator.py b/tools/fs_config/fs_config_generator.py index ad5448716..b9f0d533d 100755 --- a/tools/fs_config/fs_config_generator.py +++ b/tools/fs_config/fs_config_generator.py @@ -98,8 +98,20 @@ class AID(object): value (str) The User Id (uid) of the associate define. found (str) The file it was found in, can be None. normalized_value (str): Same as value, but base 10. + friendly (str): The friendly name of aid. """ + PREFIX = 'AID_' + + # Some of the AIDS like AID_MEDIA_EX had names like mediaex + # list a map of things to fixup until we can correct these + # at a later date. + _FIXUPS = { + 'media_drm': 'mediadrm', + 'media_ex': 'mediaex', + 'media_codec': 'mediacodec' + } + def __init__(self, identifier, value, found): """ Args: @@ -116,6 +128,39 @@ class AID(object): self.found = found self.normalized_value = str(int(value, 0)) + # Where we calculate the friendly name + friendly = identifier[len(AID.PREFIX):].lower() + self.friendly = AID._fixup_friendly(friendly) + + @staticmethod + def is_friendly(name): + """Determines if an AID is a freindly name or C define. + + For example if name is AID_SYSTEM it returns false, if name + was system, it would return true. + + Returns: + True if name is a friendly name False otherwise. + """ + + return not name.startswith(AID.PREFIX) + + @staticmethod + def _fixup_friendly(friendly): + """Fixup friendly names that historically don't follow the convention. + + Args: + friendly (str): The friendly name. + + Returns: + The fixedup friendly name as a str. + """ + + if friendly in AID._FIXUPS: + return AID._FIXUPS[friendly] + + return friendly + class FSConfig(object): """Represents a filesystem config array entry. @@ -160,22 +205,12 @@ class AIDHeaderParser(object): """ _SKIPWORDS = ['UNUSED'] - _AID_KW = 'AID_' - _AID_DEFINE = re.compile(r'\s*#define\s+%s.*' % _AID_KW) + _AID_DEFINE = re.compile(r'\s*#define\s+%s.*' % AID.PREFIX) _OEM_START_KW = 'START' _OEM_END_KW = 'END' _OEM_RANGE = re.compile('AID_OEM_RESERVED_[0-9]*_{0,1}(%s|%s)' % (_OEM_START_KW, _OEM_END_KW)) - # Some of the AIDS like AID_MEDIA_EX had names like mediaex - # list a map of things to fixup until we can correct these - # at a later date. - _FIXUPS = { - 'media_drm': 'mediadrm', - 'media_ex': 'mediaex', - 'media_codec': 'mediacodec' - } - def __init__(self, aid_header): """ Args: @@ -240,19 +275,18 @@ class AIDHeaderParser(object): ValueError: With message set to indicate the error. """ - # friendly name - name = AIDHeaderParser._convert_friendly(identifier) + aid = AID(identifier, value, self._aid_header) # duplicate name - if name in self._aid_name_to_value: + if aid.friendly in self._aid_name_to_value: raise ValueError('Duplicate aid "%s"' % identifier) if value in self._aid_value_to_name: raise ValueError('Duplicate aid value "%u" for %s' % value, identifier) - self._aid_name_to_value[name] = AID(identifier, value, self._aid_header) - self._aid_value_to_name[value] = name + self._aid_name_to_value[aid.friendly] = aid + self._aid_value_to_name[value] = aid.friendly def _handle_oem_range(self, identifier, value): """Handle an OEM range C #define. @@ -363,7 +397,7 @@ class AIDHeaderParser(object): Returns: A list of AID() objects. """ - return self._aid_name_to_value + return self._aid_name_to_value.values() @staticmethod def _convert_lst_to_tup(name, lst): @@ -386,25 +420,6 @@ class AIDHeaderParser(object): return tuple(lst) @staticmethod - def _convert_friendly(identifier): - """ - Translate AID_FOO_BAR to foo_bar (ie name) - - Args: - identifier (str): The name of the #define. - - Returns: - The friendly name as a str. - """ - - name = identifier[len(AIDHeaderParser._AID_KW):].lower() - - if name in AIDHeaderParser._FIXUPS: - return AIDHeaderParser._FIXUPS[name] - - return name - - @staticmethod def _is_oem_range(aid): """Detects if a given aid is within the reserved OEM range. @@ -449,8 +464,7 @@ class FSConfigFileParser(object): # Since _AID_PREFIX is within the set of _AID_MATCH the error logic only # checks end, if you change this, you may have to update the error # detection code. - _AID_PREFIX = 'AID_' - _AID_MATCH = re.compile('%s[A-Z0-9_]+' % _AID_PREFIX) + _AID_MATCH = re.compile('%s[A-Z0-9_]+' % AID.PREFIX) _AID_ERR_MSG = 'Expecting upper case, a number or underscore' # list of handler to required options, used to identify the @@ -560,7 +574,7 @@ class FSConfigFileParser(object): self._seen_aids[0]) match = FSConfigFileParser._AID_MATCH.match(section_name) - invalid = match.end() if match else len(FSConfigFileParser._AID_PREFIX) + invalid = match.end() if match else len(AID.PREFIX) if invalid != len(section_name): tmp_errmsg = ('Invalid characters in AID section at "%d" for: "%s"' % (invalid, FSConfigFileParser._AID_ERR_MSG)) @@ -861,6 +875,13 @@ class FSConfigGen(BaseGenerator): _FILE_COMMENT = '// Defined in file: \"%s\"' + def __init__(self, *args, **kwargs): + BaseGenerator.__init__(args, kwargs) + + self._oem_parser = None + self._base_parser = None + self._friendly_to_aid = None + def add_opts(self, opt_group): opt_group.add_argument( @@ -874,19 +895,46 @@ class FSConfigGen(BaseGenerator): def __call__(self, args): - hdr = AIDHeaderParser(args['aid_header']) - oem_ranges = hdr.oem_ranges + self._base_parser = AIDHeaderParser(args['aid_header']) + self._oem_parser = FSConfigFileParser(args['fsconfig'], + self._base_parser.oem_ranges) + base_aids = self._base_parser.aids + oem_aids = self._oem_parser.aids - parser = FSConfigFileParser(args['fsconfig'], oem_ranges) - FSConfigGen._generate(parser.files, parser.dirs, parser.aids) + # Detect name collisions on AIDs. Since friendly works as the + # identifier for collision testing and we need friendly later on for + # name resolution, just calculate and use friendly. + # {aid.friendly: aid for aid in base_aids} + base_friendly = {aid.friendly: aid for aid in base_aids} + oem_friendly = {aid.friendly: aid for aid in oem_aids} - @staticmethod - def _to_fs_entry(fs_config): - """ - Given an FSConfig entry, converts it to a proper - array entry for the array entry. + base_set = set(base_friendly.keys()) + oem_set = set(oem_friendly.keys()) + + common = base_set & oem_set + + if len(common) > 0: + emsg = 'Following AID Collisions detected for: \n' + for friendly in common: + base = base_friendly[friendly] + oem = oem_friendly[friendly] + emsg += ( + 'Identifier: "%s" Friendly Name: "%s" ' + 'found in file "%s" and "%s"' % + (base.identifier, base.friendly, base.found, oem.found)) + sys.exit(emsg) + + self._friendly_to_aid = oem_friendly + self._friendly_to_aid.update(base_friendly) + + self._generate() + + def _to_fs_entry(self, fs_config): + """Converts an FSConfig entry to an fs entry. - { mode, user, group, caps, "path" }, + Prints '{ mode, user, group, caps, "path" },'. + + Calls sys.exit() on error. Args: fs_config (FSConfig): The entry to convert to @@ -901,6 +949,19 @@ class FSConfigGen(BaseGenerator): caps = fs_config.caps path = fs_config.path + emsg = 'Cannot convert friendly name "%s" to identifier!' + + # remap friendly names to identifier names + if AID.is_friendly(user): + if user not in self._friendly_to_aid: + sys.exit(emsg % user) + user = self._friendly_to_aid[user].identifier + + if AID.is_friendly(group): + if group not in self._friendly_to_aid: + sys.exit(emsg % group) + group = self._friendly_to_aid[group].identifier + fmt = '{ %s, %s, %s, %s, "%s" },' expanded = fmt % (mode, user, group, caps, path) @@ -910,15 +971,11 @@ class FSConfigGen(BaseGenerator): @staticmethod def _gen_inc(): - """ - Generate the include header lines and print to stdout. - Internal use only. - """ + """Generate the include header lines and print to stdout.""" for include in FSConfigGen._INCLUDES: print '#include %s' % include - @staticmethod - def _generate(files, dirs, aids): + def _generate(self): """Generates an OEM android_filesystem_config.h header file to stdout. Args: @@ -933,6 +990,10 @@ class FSConfigGen(BaseGenerator): FSConfigGen._gen_inc() print + dirs = self._oem_parser.dirs + files = self._oem_parser.files + aids = self._oem_parser.aids + are_dirs = len(dirs) > 0 are_files = len(files) > 0 are_aids = len(aids) > 0 @@ -952,13 +1013,12 @@ class FSConfigGen(BaseGenerator): print FSConfigGen._DEFINE_NO_FILES + '\n' if not are_files and not are_dirs and not are_aids: - print FSConfigGen._DEFAULT_WARNING return if are_files: print FSConfigGen._OPEN_FILE_STRUCT for fs_config in files: - FSConfigGen._to_fs_entry(fs_config) + self._to_fs_entry(fs_config) if not are_dirs: print FSConfigGen._IFDEF_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS @@ -971,7 +1031,7 @@ class FSConfigGen(BaseGenerator): if are_dirs: print FSConfigGen._OPEN_DIR_STRUCT for dir_entry in dirs: - FSConfigGen._to_fs_entry(dir_entry) + self._to_fs_entry(dir_entry) print FSConfigGen._CLOSE_FILE_STRUCT @@ -1019,8 +1079,8 @@ class AIDArrayGen(BaseGenerator): print print AIDArrayGen._OPEN_ID_ARRAY - for name, aid in hdr.aids.iteritems(): - print AIDArrayGen._ID_ENTRY % (name, aid.identifier) + for aid in hdr.aids: + print AIDArrayGen._ID_ENTRY % (aid.friendly, aid.identifier) print AIDArrayGen._CLOSE_FILE_STRUCT print -- 2.11.0