summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
Diffstat (limited to 'meta')
-rw-r--r--meta/classes/rootfs-postcommands.bbclass22
-rw-r--r--meta/lib/rootfspostcommands.py44
2 files changed, 66 insertions, 0 deletions
diff --git a/meta/classes/rootfs-postcommands.bbclass b/meta/classes/rootfs-postcommands.bbclass
index 8d48a2d1d9..53a4fda4b1 100644
--- a/meta/classes/rootfs-postcommands.bbclass
+++ b/meta/classes/rootfs-postcommands.bbclass
@@ -30,6 +30,23 @@ ROOTFS_POSTPROCESS_COMMAND += 'empty_var_volatile;'
30SSH_DISABLE_DNS_LOOKUP ?= " ssh_disable_dns_lookup ; " 30SSH_DISABLE_DNS_LOOKUP ?= " ssh_disable_dns_lookup ; "
31ROOTFS_POSTPROCESS_COMMAND_append_qemuall = "${SSH_DISABLE_DNS_LOOKUP}" 31ROOTFS_POSTPROCESS_COMMAND_append_qemuall = "${SSH_DISABLE_DNS_LOOKUP}"
32 32
33# Sort the user and group entries in /etc by ID in order to make the content
34# deterministic. Package installs are not deterministic, causing the ordering
35# of entries to change between builds. In case that this isn't desired,
36# the command can be overridden.
37#
38# Note that useradd-staticids.bbclass has to be used to ensure that
39# the numeric IDs of dynamically created entries remain stable.
40#
41# We want this to run as late as possible, in particular after
42# systemd_sysusers_create and set_user_group. Using _append is not
43# enough for that, set_user_group is added that way and would end
44# up running after us.
45SORT_PASSWD_POSTPROCESS_COMMAND ??= " sort_passwd; "
46python () {
47 d.appendVar('ROOTFS_POSTPROCESS_COMMAND', '${SORT_PASSWD_POSTPROCESS_COMMAND}')
48}
49
33systemd_create_users () { 50systemd_create_users () {
34 for conffile in ${IMAGE_ROOTFS}/usr/lib/sysusers.d/systemd.conf ${IMAGE_ROOTFS}/usr/lib/sysusers.d/systemd-remote.conf; do 51 for conffile in ${IMAGE_ROOTFS}/usr/lib/sysusers.d/systemd.conf ${IMAGE_ROOTFS}/usr/lib/sysusers.d/systemd-remote.conf; do
35 [ -e $conffile ] || continue 52 [ -e $conffile ] || continue
@@ -146,6 +163,11 @@ ssh_disable_dns_lookup () {
146 fi 163 fi
147} 164}
148 165
166python sort_passwd () {
167 import rootfspostcommands
168 rootfspostcommands.sort_passwd(d.expand('${IMAGE_ROOTFS}${sysconfdir}'))
169}
170
149# 171#
150# Enable postinst logging if debug-tweaks is enabled 172# Enable postinst logging if debug-tweaks is enabled
151# 173#
diff --git a/meta/lib/rootfspostcommands.py b/meta/lib/rootfspostcommands.py
new file mode 100644
index 0000000000..6a9b8b47b7
--- /dev/null
+++ b/meta/lib/rootfspostcommands.py
@@ -0,0 +1,44 @@
1import os
2
3def sort_file(filename, mapping):
4 """
5 Sorts a passwd or group file based on the numeric ID in the third column.
6 If a mapping is given, the name from the first column is mapped via that
7 dictionary instead (necessary for /etc/shadow and /etc/gshadow). If not,
8 a new mapping is created on the fly and returned.
9 """
10 new_mapping = {}
11 with open(filename, 'rb+') as f:
12 lines = f.readlines()
13 # No explicit error checking for the sake of simplicity. /etc
14 # files are assumed to be well-formed, causing exceptions if
15 # not.
16 for line in lines:
17 entries = line.split(b':')
18 name = entries[0]
19 if mapping is None:
20 id = int(entries[2])
21 else:
22 id = mapping[name]
23 new_mapping[name] = id
24 # Sort by numeric id first, with entire line as secondary key
25 # (just in case that there is more than one entry for the same id).
26 lines.sort(key=lambda line: (new_mapping[line.split(b':')[0]], line))
27 # We overwrite the entire file, i.e. no truncate() necessary.
28 f.seek(0)
29 f.write(b''.join(lines))
30 return new_mapping
31
32def sort_passwd(sysconfdir):
33 """
34 Sorts passwd and group files in a rootfs /etc directory by ID.
35 """
36 for suffix in '', '-':
37 for main, shadow in (('passwd', 'shadow'),
38 ('group', 'gshadow')):
39 filename = os.path.join(sysconfdir, main + suffix)
40 if os.path.exists(filename):
41 mapping = sort_file(filename, None)
42 filename = os.path.join(sysconfdir, shadow + suffix)
43 if os.path.exists(filename):
44 sort_file(filename, mapping)