mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-10-28 09:03:46 +08:00
80fbb4f6db
Register vehicle controls, planner modes, UI actions and Galaxy services after their providers exist. Wire the shared runtime entrypoints and cover their combined behavior. Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> Co-authored-by: Daniel Koepping <elkoled@gmail.com> Co-authored-by: Danny <dannyirwin31@yahoo.com> Co-authored-by: DimitriChrysafis <Dimitri.chrysafis@gmail.com> Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com> Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com> Co-authored-by: Kacper Rączy <gfw.kra@gmail.com> Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu> Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com> Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Co-authored-by: stef <19478336+stefpi@users.noreply.github.com> Co-authored-by: whoisdomi <dcantu83@gmail.com> Co-authored-by: Intelli <contact@intelli.software> Co-authored-by: haraschax <6804392+haraschax@users.noreply.github.com> Co-authored-by: prabhaavp <prabhaav@msu.edu>
64 lines
2.0 KiB
Python
64 lines
2.0 KiB
Python
"""Bounded cleanup of entries in an already opened storage-owner directory."""
|
|
import os
|
|
import stat
|
|
|
|
|
|
class DeletionLimit(Exception):
|
|
pass
|
|
|
|
|
|
def remove_entry(directory, name, budget, *, depth=0):
|
|
if name in ('', '.', '..') or '/' in name or '\\' in name or '\0' in name:
|
|
raise ValueError('Invalid stored artifact name')
|
|
if budget[0] <= 0 or depth > 8:
|
|
raise DeletionLimit('Stored artifact cleanup limit reached')
|
|
budget[0] -= 1
|
|
try:
|
|
info = os.stat(name, dir_fd=directory, follow_symlinks=False)
|
|
except FileNotFoundError:
|
|
return
|
|
if stat.S_ISDIR(info.st_mode):
|
|
child = os.open(name, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW, dir_fd=directory)
|
|
try:
|
|
opened = os.fstat(child)
|
|
if (opened.st_dev, opened.st_ino) != (info.st_dev, info.st_ino):
|
|
raise OSError('Stored artifact changed')
|
|
with os.scandir(child) as entries:
|
|
for entry in entries:
|
|
remove_entry(child, entry.name, budget, depth=depth + 1)
|
|
os.fsync(child)
|
|
finally:
|
|
os.close(child)
|
|
os.rmdir(name, dir_fd=directory)
|
|
else:
|
|
# Unlink a symlink itself, never its target; hard links likewise stay bounded.
|
|
os.unlink(name, dir_fd=directory)
|
|
|
|
|
|
def usage(directory, *, budget=None, depth=0):
|
|
budget = [4096] if budget is None else budget
|
|
total = 0
|
|
incomplete = False
|
|
with os.scandir(directory) as entries:
|
|
for entry in entries:
|
|
if entry.name == '.lock':
|
|
continue
|
|
if budget[0] <= 0 or depth > 8:
|
|
return total, True
|
|
budget[0] -= 1
|
|
try:
|
|
info = entry.stat(follow_symlinks=False)
|
|
if stat.S_ISREG(info.st_mode):
|
|
total += info.st_size
|
|
elif stat.S_ISDIR(info.st_mode):
|
|
child = os.open(entry.name, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW, dir_fd=directory)
|
|
try:
|
|
size, partial = usage(child, budget=budget, depth=depth + 1)
|
|
total += size
|
|
incomplete |= partial
|
|
finally:
|
|
os.close(child)
|
|
except OSError:
|
|
incomplete = True
|
|
return total, incomplete
|