OSDN Git Service

fs_config: generate friendly in AID class
authorWilliam Roberts <william.c.roberts@intel.com>
Mon, 25 Apr 2016 19:27:43 +0000 (12:27 -0700)
committerDan Albert <danalbert@google.com>
Wed, 30 Nov 2016 00:21:17 +0000 (16:21 -0800)
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 <william.c.roberts@intel.com>
tools/fs_config/fs_config_generator.py

index ad54487..b9f0d53 100755 (executable)
@@ -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