fsutil
Small filesystem helpers shared by the launch logic and the file manager.
attributelogger= logging.getLogger(__name__)funcresolve_within(base, path) -> strReturn 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.
parambasestrTrusted directory the result must stay inside.
parampathstrCandidate path, usually built from client-supplied names.
Returns
strThe resolved absolute path.
funcopen_within(base, path, flags=os.O_RDONLY, mode=420) -> intOpen 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.
parambasestrTrusted directory the opened object must lie inside.
parampathstrThe path, usually one resolve_within returned.
paramflagsint= os.O_RDONLYos.open flags; O_NOFOLLOW and O_CLOEXEC are added.
parammodeint= 420Mode of a file flags creates.
Returns
intThe open descriptor, the caller's to close.
funcopen_parent_within(base, path) -> tuple[int, str]Open the directory holding path as open_within does.
parambasestrparampathstrReturns
intThe 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_fdintparamfilenamestrparammodeint= 420Returns
tupleThe new file's descriptor, open for writing, and the name it took.
funcplace_file(source, base, directory, filename, mode=420) -> strMove 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.
paramsourcestrparambasestrparamdirectorystrparamfilenamestrparammodeint= 420Returns
strThe name the file took.
funcsafe_join(base, *parts) -> strJoin parts onto base and return the resolved path inside base.
parambasestrTrusted directory.
parampartsstr= ()Returns
strThe resolved absolute path.
funcsafe_copytree(src, dst, symlinks=True) -> NoneCopy a directory tree, tolerating dangling symlinks.
paramsrcstrSource directory.
paramdststrDestination directory (must not exist).
paramsymlinksbool= TrueCopy symlinks as symlinks instead of following them.
Returns
Nonefuncsafe_rmtree(path, dir_fd=None) -> NoneRemove a directory tree, translating permission errors to HTTP 403.
parampathstrDirectory to remove, relative to dir_fd when one is given.
paramdir_fdint | None= NoneDirectory descriptor path is relative to.
Returns
Nonefuncsanitize_for_filename(name) -> strTurn an arbitrary display name into a safe directory name.
paramnamestrDisplay name such as an application name.
Returns
strLower-case ASCII letters, digits, and dashes, at most 50 characters,