Yocto 2.3

Move OpenBMC to Yocto 2.3(pyro).

Tested: Built and verified Witherspoon and Palmetto images
Change-Id: I50744030e771f4850afc2a93a10d3507e76d36bc
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
Resolves: openbmc/openbmc#2461
diff --git a/import-layers/yocto-poky/meta/lib/rootfspostcommands.py b/import-layers/yocto-poky/meta/lib/rootfspostcommands.py
new file mode 100644
index 0000000..4742e06
--- /dev/null
+++ b/import-layers/yocto-poky/meta/lib/rootfspostcommands.py
@@ -0,0 +1,56 @@
+import os
+
+def sort_file(filename, mapping):
+    """
+    Sorts a passwd or group file based on the numeric ID in the third column.
+    If a mapping is given, the name from the first column is mapped via that
+    dictionary instead (necessary for /etc/shadow and /etc/gshadow). If not,
+    a new mapping is created on the fly and returned.
+    """
+    new_mapping = {}
+    with open(filename, 'rb+') as f:
+        lines = f.readlines()
+        # No explicit error checking for the sake of simplicity. /etc
+        # files are assumed to be well-formed, causing exceptions if
+        # not.
+        for line in lines:
+            entries = line.split(b':')
+            name = entries[0]
+            if mapping is None:
+                id = int(entries[2])
+            else:
+                id = mapping[name]
+            new_mapping[name] = id
+        # Sort by numeric id first, with entire line as secondary key
+        # (just in case that there is more than one entry for the same id).
+        lines.sort(key=lambda line: (new_mapping[line.split(b':')[0]], line))
+        # We overwrite the entire file, i.e. no truncate() necessary.
+        f.seek(0)
+        f.write(b''.join(lines))
+    return new_mapping
+
+def remove_backup(filename):
+    """
+    Removes the backup file for files like /etc/passwd.
+    """
+    backup_filename = filename + '-'
+    if os.path.exists(backup_filename):
+        os.unlink(backup_filename)
+
+def sort_passwd(sysconfdir):
+    """
+    Sorts passwd and group files in a rootfs /etc directory by ID.
+    Backup files are sometimes are inconsistent and then cannot be
+    sorted (YOCTO #11043), and more importantly, are not needed in
+    the initial rootfs, so they get deleted.
+    """
+    for main, shadow in (('passwd', 'shadow'),
+                         ('group', 'gshadow')):
+        filename = os.path.join(sysconfdir, main)
+        remove_backup(filename)
+        if os.path.exists(filename):
+            mapping = sort_file(filename, None)
+            filename = os.path.join(sysconfdir, shadow)
+            remove_backup(filename)
+            if os.path.exists(filename):
+                 sort_file(filename, mapping)