Brad Bishop | c342db3 | 2019-05-15 21:57:59 -0400 | [diff] [blame] | 1 | # |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 2 | # Copyright OpenEmbedded Contributors |
| 3 | # |
Brad Bishop | c342db3 | 2019-05-15 21:57:59 -0400 | [diff] [blame] | 4 | # SPDX-License-Identifier: GPL-2.0-only |
| 5 | # |
| 6 | |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 7 | import os |
| 8 | |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 9 | def sort_shadowutils_file(filename, mapping): |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 10 | """ |
| 11 | Sorts a passwd or group file based on the numeric ID in the third column. |
| 12 | If a mapping is given, the name from the first column is mapped via that |
| 13 | dictionary instead (necessary for /etc/shadow and /etc/gshadow). If not, |
| 14 | a new mapping is created on the fly and returned. |
| 15 | """ |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 16 | |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 17 | new_mapping = {} |
| 18 | with open(filename, 'rb+') as f: |
| 19 | lines = f.readlines() |
| 20 | # No explicit error checking for the sake of simplicity. /etc |
| 21 | # files are assumed to be well-formed, causing exceptions if |
| 22 | # not. |
| 23 | for line in lines: |
| 24 | entries = line.split(b':') |
| 25 | name = entries[0] |
| 26 | if mapping is None: |
| 27 | id = int(entries[2]) |
| 28 | else: |
| 29 | id = mapping[name] |
| 30 | new_mapping[name] = id |
| 31 | # Sort by numeric id first, with entire line as secondary key |
| 32 | # (just in case that there is more than one entry for the same id). |
| 33 | lines.sort(key=lambda line: (new_mapping[line.split(b':')[0]], line)) |
| 34 | # We overwrite the entire file, i.e. no truncate() necessary. |
| 35 | f.seek(0) |
| 36 | f.write(b''.join(lines)) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 37 | |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 38 | return new_mapping |
| 39 | |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 40 | def sort_shadowutils_files(sysconfdir): |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 41 | """ |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 42 | Sorts shadow-utils 'passwd' and 'group' files in a rootfs' /etc directory |
| 43 | by ID. |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 44 | """ |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 45 | |
| 46 | for main, shadow in (('passwd', 'shadow'), |
| 47 | ('group', 'gshadow')): |
| 48 | filename = os.path.join(sysconfdir, main) |
| 49 | if os.path.exists(filename): |
| 50 | mapping = sort_shadowutils_file(filename, None) |
| 51 | filename = os.path.join(sysconfdir, shadow) |
| 52 | if os.path.exists(filename): |
| 53 | sort_shadowutils_file(filename, mapping) |
| 54 | |
| 55 | def remove_shadowutils_backup_file(filename): |
| 56 | """ |
| 57 | Remove shadow-utils backup file for files like /etc/passwd. |
| 58 | """ |
| 59 | |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 60 | backup_filename = filename + '-' |
| 61 | if os.path.exists(backup_filename): |
| 62 | os.unlink(backup_filename) |
| 63 | |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 64 | def remove_shadowutils_backup_files(sysconfdir): |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 65 | """ |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 66 | Remove shadow-utils backup files in a rootfs /etc directory. They are not |
| 67 | needed in the initial root filesystem and sorting them can be inconsistent |
| 68 | (YOCTO #11043). |
Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 69 | """ |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 70 | |
| 71 | for filename in ( |
| 72 | 'group', |
| 73 | 'gshadow', |
| 74 | 'passwd', |
| 75 | 'shadow', |
| 76 | 'subgid', |
| 77 | 'subuid', |
| 78 | ): |
| 79 | filepath = os.path.join(sysconfdir, filename) |
| 80 | remove_shadowutils_backup_file(filepath) |
| 81 | |
| 82 | def tidy_shadowutils_files(sysconfdir): |
| 83 | """ |
| 84 | Tidy up shadow-utils files. |
| 85 | """ |
| 86 | |
| 87 | remove_shadowutils_backup_files(sysconfdir) |
| 88 | sort_shadowutils_files(sysconfdir) |
| 89 | |
| 90 | return True |