summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHelmut Grohne <helmut@subdivi.de>2025-08-13 11:03:08 +0200
committerHelmut Grohne <helmut@subdivi.de>2025-08-13 11:03:08 +0200
commite6d2aa979cea1a4d98f588a66b01d742f685971a (patch)
tree624e2f164d8e851b5d3e10348f4580c4050678d5
parent60a8ec7dc195df0a98492d96e954b35fcd9d1eab (diff)
downloadpython-linuxnamespaces-e6d2aa979cea1a4d98f588a66b01d742f685971a.tar.gz
support parsing /etc/sub?id files keyed on UID
Link: https://bugs.debian.org/1110876
-rw-r--r--linuxnamespaces/idmap.py34
1 files changed, 28 insertions, 6 deletions
diff --git a/linuxnamespaces/idmap.py b/linuxnamespaces/idmap.py
index d9cf0eb..f66456d 100644
--- a/linuxnamespaces/idmap.py
+++ b/linuxnamespaces/idmap.py
@@ -7,7 +7,7 @@ namespace.
import bisect
import dataclasses
-import getpass
+import pwd
import os
import subprocess
import typing
@@ -16,17 +16,36 @@ from .atlocation import AtLocation, AtLocationLike
def subidranges(
- kind: typing.Literal["uid", "gid"], login: str | None = None
+ kind: typing.Literal["uid", "gid"],
+ login: str | None = None,
+ uid: int | None = None,
) -> typing.Iterator[tuple[int, int]]:
"""Parse a `/etc/sub?id` file for ranges allocated to the given or current
user. Return all ranges as (start, count) pairs.
"""
+ if uid is None:
+ if login is None:
+ uid = os.getuid()
+ else:
+ try:
+ uid = pwd.getpwnam(login).pw_uid
+ except KeyError:
+ pass
if login is None:
- login = getpass.getuser()
+ try:
+ login = pwd.getpwuid(uid).pw_name
+ except KeyError:
+ pass
with open(f"/etc/sub{kind}") as filelike:
for line in filelike:
parts = line.strip().split(":")
- if parts[0] == login:
+ try:
+ curuid = int(parts[0])
+ except ValueError:
+ curuid = None
+ if (login is not None and parts[0] == login) or (
+ curuid is not None and uid is not None and curuid == uid
+ ):
yield (int(parts[1]), int(parts[2]))
@@ -95,13 +114,16 @@ class IDAllocation:
@classmethod
def loadsubid(
- cls, kind: typing.Literal["uid", "gid"], login: str | None = None,
+ cls,
+ kind: typing.Literal["uid", "gid"],
+ login: str | None = None,
+ uid: int | None = None,
) -> "IDAllocation":
"""Load a `/etc/sub?id` file and return ids allocated to the given
login or current user.
"""
self = cls()
- for start, count in subidranges(kind, login):
+ for start, count in subidranges(kind, login, uid):
self.add_range(start, count)
return self