X-Git-Url: https://git.ralfj.de/bubblebox.git/blobdiff_plain/0778e2d24706e9287d0594336cd5907b022e6ce8..9f759e738ebda4bc95c177c3d2206bb5481483bc:/bubblebox.py diff --git a/bubblebox.py b/bubblebox.py index 1af0c87..cb7f514 100644 --- a/bubblebox.py +++ b/bubblebox.py @@ -16,9 +16,6 @@ def flat_map(f, xs): ys.extend(x_mapped) return ys -def globexpand(base, names): - return flat_map(lambda x: glob.glob(base + "/" + x), names) - def randname(): # choose from all lowercase letter letters = string.ascii_lowercase @@ -64,7 +61,11 @@ def collect_flags(*flags): # Run the application in the bubblebox with the given flags. def bubblebox(*flags): - flags = collect_flags(*flags) + if len(sys.argv) <= 1: + print(f"USAGE: {sys.argv[0]} ") + sys.exit(1) + # Make sure `--die-with-parent` is always set. + flags = collect_flags(bwrap_flags("--die-with-parent"), *flags) bwrap = "/usr/bin/bwrap" extraflags = [] if flags.dbus_proxy_flags: @@ -73,19 +74,57 @@ def bubblebox(*flags): #pprint(args) os.execvp(args[0], args) -# Convenient methods to give access to the host file system -def ro_host_access(*names): - return bwrap_flags(*flat_map(lambda x: ["--ro-bind", x, x], names)) -def rw_host_access(*names): - return bwrap_flags(*flat_map(lambda x: ["--bind", x, x], names)) -def dev_host_access(*names): - return bwrap_flags(*flat_map(lambda x: ["--dev-bind", x, x], names)) - # Give all instances of the same box a shared XDG_RUNTIME_DIR def shared_runtime_dir(boxname): dirname = BUBBLEBOX_DIR + "/" + boxname os.makedirs(dirname, exist_ok=True) return bwrap_flags("--bind", dirname, XDG_RUNTIME_DIR) +# Convenient way to declare host access +class Access: + Read = 0 + Write = 1 + Device = 2 + + def flag(val): + if val == Access.Read: + return "--ro-bind" + elif val == Access.Write: + return "--bind" + elif val == Access.Device: + return "--dev-bind" + else: + raise Exception(f"invalid access value: {val}") +def host_access(dirs): + def expand(root, names): + """`names` is one or more strings that can contain globs. Expand them all relative to `root`.""" + if isinstance(names, str): + names = (names,) + assert isinstance(names, tuple) + for name in names: + assert not (name.startswith("../") or name.__contains__("/../") or name.endswith("../")) + path = root + "/" + name + # prettification + path = path.replace("//", "/") + path = path.removesuffix("/.") + # glob expansion + yield from glob.glob(path) + def recursive_host_access(root, dirs, out): + for names, desc in dirs.items(): + for path in expand(root, names): + if isinstance(desc, dict): + # Recurse into children + recursive_host_access(path, desc, out) + else: + # Allow access to this path + out.extend([Access.flag(desc), path, path]) + # Start the recursive traversal + out = [] + recursive_host_access("", dirs, out) + #pprint(out) + return bwrap_flags(*out) +def home_access(dirs): + return host_access({ HOME: dirs }) + # Profile the profiles when importing bubblebox. import profiles