poky/meta/lib/rootfspostcommands.py
Andrei Gherzan 29bb84b82b rootfspostcommands.py: Restructure sort_passwd and related functions
This change proposes a restructure of the functions in
rootfspostcommandstests.py to clarify the purpose of each function and
also, make it scalable for other use cases (for example adding support
for removing subid backup files).

The main function of interest here is 'tidy_shadowutils_files' which
brings in the functionality of the old 'sort_passwd' making it clear
that it doesn't only sort the passwd file:
- delete backup files
- it sorts passwd, group and the associated shadow files

The other functions are also renamed for consistency and clarity and
more documentation was added.

(From OE-Core rev: 81a0a4dbfb0313b967a7a98eb7fd1e13edb1a9be)

Signed-off-by: Andrei Gherzan <andrei.gherzan@huawei.com>
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2022-08-25 11:08:06 +01:00

89 lines
2.7 KiB
Python

#
# Copyright OpenEmbedded Contributors
#
# SPDX-License-Identifier: GPL-2.0-only
#
import os
def sort_shadowutils_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 sort_shadowutils_files(sysconfdir):
"""
Sorts shadow-utils 'passwd' and 'group' files in a rootfs' /etc directory
by ID.
"""
for main, shadow in (('passwd', 'shadow'),
('group', 'gshadow')):
filename = os.path.join(sysconfdir, main)
if os.path.exists(filename):
mapping = sort_shadowutils_file(filename, None)
filename = os.path.join(sysconfdir, shadow)
if os.path.exists(filename):
sort_shadowutils_file(filename, mapping)
def remove_shadowutils_backup_file(filename):
"""
Remove shadow-utils backup file for files like /etc/passwd.
"""
backup_filename = filename + '-'
if os.path.exists(backup_filename):
os.unlink(backup_filename)
def remove_shadowutils_backup_files(sysconfdir):
"""
Remove shadow-utils backup files in a rootfs /etc directory. They are not
needed in the initial root filesystem and sorting them can be inconsistent
(YOCTO #11043).
"""
for filename in (
'group',
'gshadow',
'passwd',
'shadow',
):
filepath = os.path.join(sysconfdir, filename)
remove_shadowutils_backup_file(filepath)
def tidy_shadowutils_files(sysconfdir):
"""
Tidy up shadow-utils files.
"""
remove_shadowutils_backup_files(sysconfdir)
sort_shadowutils_files(sysconfdir)
return True