SealSkin

fsutil

Small filesystem helpers shared by the launch logic and the file manager.

attributelogger
= logging.getLogger(__name__)
funcresolve_within(base, path) -> str

Return the real path of path after checking that it lies inside base.

Both paths are resolved with os.path.realpath, so neither .. segments nor symlinks can be used to escape base. Trailing components that do not exist yet are allowed, which makes the helper usable for paths about to be created.

parambasestr

Trusted directory the result must stay inside.

parampathstr

Candidate path, usually built from client-supplied names.

Returns

str

The resolved absolute path.

funcopen_within(base, path, flags=os.O_RDONLY, mode=420) -> int

Open path and return the descriptor once what it opened lies inside base.

A path checked by resolve_within can change before a later call follows it: whoever writes the tree (a session container mounts its user's home read-write) can swap a symlink in for its last component, or for a directory on the way. The open refuses a symlink in the last place, and the path the kernel resolved for the descriptor is checked against base before a byte is read or written through it.

parambasestr

Trusted directory the opened object must lie inside.

parampathstr

The path, usually one resolve_within returned.

paramflagsint
= os.O_RDONLY

os.open flags; O_NOFOLLOW and O_CLOEXEC are added.

parammodeint
= 420

Mode of a file flags creates.

Returns

int

The open descriptor, the caller's to close.

funcopen_parent_within(base, path) -> tuple[int, str]

Open the directory holding path as open_within does.

parambasestr
parampathstr

Returns

int

The directory's descriptor, the caller's to close, and path's last

funccreate_exclusive(dir_fd, filename, mode=420) -> tuple[int, str]

Create filename, or the first free name-N.ext variant, in the directory dir_fd.

The name is taken by the create itself, never by a check before it, and a symlink already holding a name is passed over rather than followed.

paramdir_fdint
paramfilenamestr
parammodeint
= 420

Returns

tuple

The new file's descriptor, open for writing, and the name it took.

funcplace_file(source, base, directory, filename, mode=420) -> str

Move the file source into directory, inside base, under filename or the next free variant.

directory is one its user's sessions write, so it is opened and checked inside base (open_within), the name is taken by creating it (create_exclusive), and the file is renamed onto that name within the opened directory, or copied into it across filesystems: no symlink planted in the directory, or swapped in for it, takes the file anywhere else.

paramsourcestr
parambasestr
paramdirectorystr
paramfilenamestr
parammodeint
= 420

Returns

str

The name the file took.

funcsafe_join(base, *parts) -> str

Join parts onto base and return the resolved path inside base.

parambasestr

Trusted directory.

parampartsstr
= ()

Returns

str

The resolved absolute path.

funcsafe_copytree(src, dst, symlinks=True) -> None

Copy a directory tree, tolerating dangling symlinks.

paramsrcstr

Source directory.

paramdststr

Destination directory (must not exist).

paramsymlinksbool
= True

Copy symlinks as symlinks instead of following them.

Returns

None
funcsafe_rmtree(path, dir_fd=None) -> None

Remove a directory tree, translating permission errors to HTTP 403.

parampathstr

Directory to remove, relative to dir_fd when one is given.

paramdir_fdint | None
= None

Directory descriptor path is relative to.

Returns

None
funcsanitize_for_filename(name) -> str

Turn an arbitrary display name into a safe directory name.

paramnamestr

Display name such as an application name.

Returns

str

Lower-case ASCII letters, digits, and dashes, at most 50 characters,