rootfspostcommands.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. import os
  2. def sort_file(filename, mapping):
  3. """
  4. Sorts a passwd or group file based on the numeric ID in the third column.
  5. If a mapping is given, the name from the first column is mapped via that
  6. dictionary instead (necessary for /etc/shadow and /etc/gshadow). If not,
  7. a new mapping is created on the fly and returned.
  8. """
  9. new_mapping = {}
  10. with open(filename, 'rb+') as f:
  11. lines = f.readlines()
  12. # No explicit error checking for the sake of simplicity. /etc
  13. # files are assumed to be well-formed, causing exceptions if
  14. # not.
  15. for line in lines:
  16. entries = line.split(b':')
  17. name = entries[0]
  18. if mapping is None:
  19. id = int(entries[2])
  20. else:
  21. id = mapping[name]
  22. new_mapping[name] = id
  23. # Sort by numeric id first, with entire line as secondary key
  24. # (just in case that there is more than one entry for the same id).
  25. lines.sort(key=lambda line: (new_mapping[line.split(b':')[0]], line))
  26. # We overwrite the entire file, i.e. no truncate() necessary.
  27. f.seek(0)
  28. f.write(b''.join(lines))
  29. return new_mapping
  30. def remove_backup(filename):
  31. """
  32. Removes the backup file for files like /etc/passwd.
  33. """
  34. backup_filename = filename + '-'
  35. if os.path.exists(backup_filename):
  36. os.unlink(backup_filename)
  37. def sort_passwd(sysconfdir):
  38. """
  39. Sorts passwd and group files in a rootfs /etc directory by ID.
  40. Backup files are sometimes are inconsistent and then cannot be
  41. sorted (YOCTO #11043), and more importantly, are not needed in
  42. the initial rootfs, so they get deleted.
  43. """
  44. for main, shadow in (('passwd', 'shadow'),
  45. ('group', 'gshadow')):
  46. filename = os.path.join(sysconfdir, main)
  47. remove_backup(filename)
  48. if os.path.exists(filename):
  49. mapping = sort_file(filename, None)
  50. filename = os.path.join(sysconfdir, shadow)
  51. remove_backup(filename)
  52. if os.path.exists(filename):
  53. sort_file(filename, mapping)