refactor: bunpen: namespace: simplify the error paths
This commit is contained in:
@@ -147,7 +147,11 @@ fn isolate_paths(paths: []path::buffer) void = {
|
|||||||
defer(free(new_fs));
|
defer(free(new_fs));
|
||||||
|
|
||||||
for (let path .. paths) {
|
for (let path .. paths) {
|
||||||
bind_leaf(old_fs, new_fs, &path);
|
errors::ext::swallow(
|
||||||
|
"[namespace] unable to bind {}",
|
||||||
|
bind_leaf(old_fs, new_fs, &path),
|
||||||
|
path::string(&path),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// pivot into the new rootfs
|
// pivot into the new rootfs
|
||||||
@@ -178,7 +182,7 @@ fn isolate_paths(paths: []path::buffer) void = {
|
|||||||
// - [x] path is too long => does not create the leaf *nor any ancestors*.
|
// - [x] path is too long => does not create the leaf *nor any ancestors*.
|
||||||
// - [x] canonical path points outside the fs (e.g. `..`, or `../new/proc`).
|
// - [x] canonical path points outside the fs (e.g. `..`, or `../new/proc`).
|
||||||
// does not create the leaf *nor any of its ancestors* at/after the `..`.
|
// does not create the leaf *nor any of its ancestors* at/after the `..`.
|
||||||
fn bind_leaf(old_fs: *fs::fs, new_fs: *fs::fs, user_path: *path::buffer) void = {
|
fn bind_leaf(old_fs: *fs::fs, new_fs: *fs::fs, user_path: *path::buffer) (void | path::error) = {
|
||||||
let path_str = path::string(user_path);
|
let path_str = path::string(user_path);
|
||||||
log::printfln("[namespace] permit path: {}", path_str);
|
log::printfln("[namespace] permit path: {}", path_str);
|
||||||
|
|
||||||
@@ -194,54 +198,25 @@ fn bind_leaf(old_fs: *fs::fs, new_fs: *fs::fs, user_path: *path::buffer) void =
|
|||||||
// dirfd doesn't do well will absolute paths.
|
// dirfd doesn't do well will absolute paths.
|
||||||
comp = strings::sub(comp, 1, strings::end);
|
comp = strings::sub(comp, 1, strings::end);
|
||||||
};
|
};
|
||||||
cur_strpath = match (path::push(&cur_path, comp)) {
|
cur_strpath = path::push(&cur_path, comp)?;
|
||||||
case let e: path::error =>
|
|
||||||
log::printfln("[namespace] unable to construct intermediate path for binding {} / {}: {}", cur_strpath, comp, path::strerror(e));
|
|
||||||
return;
|
|
||||||
case let other: str =>
|
|
||||||
yield other;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// hmm, should we swallow this, or raise?
|
||||||
|
// seems unlikely we'll fail to bind one part of the path, but then
|
||||||
|
// successfully bind the *next* part.
|
||||||
errors::ext::swallow(
|
errors::ext::swallow(
|
||||||
"[namespace] unable to copy intermediate path {} of {}",
|
"[namespace] unable to copy intermediate path {} of {}",
|
||||||
bind_component(old_fs, new_fs, cur_strpath, path::iterrem(&it)),
|
bind_component(old_fs, new_fs, cur_strpath, path::iterrem(&it)),
|
||||||
cur_strpath, path_str
|
cur_strpath, path_str
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// and now, perform the actual bind mount:
|
|
||||||
// XXX: if the thing being mounted over is a symlink, the `mount` syscall will FAIL
|
|
||||||
// (and be swallowed). that's GOOD; we don't want to mount over a symlink.
|
|
||||||
let old_pathbuf = match (path::init("old", path_str)) {
|
|
||||||
case let e: path::error =>
|
|
||||||
log::printfln("[namespace] unable to construct old path for binding {}: {}", path_str, path::strerror(e));
|
|
||||||
return;
|
|
||||||
case let other: path::buffer =>
|
|
||||||
yield other;
|
|
||||||
};
|
|
||||||
let new_pathbuf = match (path::init("new", path_str)) {
|
|
||||||
case let e: path::error =>
|
|
||||||
log::printfln("[namespace] unable to construct new path for binding {}: {}", path_str, path::strerror(e));
|
|
||||||
return;
|
|
||||||
case let other: path::buffer =>
|
|
||||||
yield other;
|
|
||||||
};
|
|
||||||
|
|
||||||
log::printfln("[namespace/bind] mount {} {}", path::string(&old_pathbuf), path::string(&new_pathbuf));
|
|
||||||
errors::ext::swallow("[namespace/bind] bind_leaf: mount", rt::ext::mount(
|
|
||||||
path::string(&old_pathbuf), path::string(&new_pathbuf), "", rt::ext::mount_flag::BIND | rt::ext::mount_flag::REC, null
|
|
||||||
));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn bind_component(old_fs: *fs::fs, new_fs: *fs::fs, strpath: str, remaining: str) (void | fs::error | path::error) = {
|
fn bind_component(old_fs: *fs::fs, new_fs: *fs::fs, strpath: str, remaining: str) (void | fs::error | path::error | rt::errno) = {
|
||||||
match (fs::stat(new_fs, strpath)) {
|
match (fs::stat(new_fs, strpath)) {
|
||||||
case let e: fs::error => void;
|
case let e: fs::error => void; // hasn't been bound yet (good)
|
||||||
case let other: fs::filestat => return; // already created
|
case let other: fs::filestat => return; // already created
|
||||||
};
|
};
|
||||||
let st = fs::stat(old_fs, strpath)?;
|
let st = fs::stat(old_fs, strpath)?;
|
||||||
// if (st.mode == mode_new) {
|
|
||||||
// return; // already created
|
|
||||||
// };
|
|
||||||
|
|
||||||
if (fs::islink(st.mode)) {
|
if (fs::islink(st.mode)) {
|
||||||
let linktext = fs::readlink(old_fs, strpath)?;
|
let linktext = fs::readlink(old_fs, strpath)?;
|
||||||
@@ -257,7 +232,7 @@ fn bind_component(old_fs: *fs::fs, new_fs: *fs::fs, strpath: str, remaining: str
|
|||||||
// foo/bar/baz/fnord with foo -> target => `foo/target/bar/baz`
|
// foo/bar/baz/fnord with foo -> target => `foo/target/bar/baz`
|
||||||
yield path::init(strpath, "..", linktext, remaining)?;
|
yield path::init(strpath, "..", linktext, remaining)?;
|
||||||
};
|
};
|
||||||
bind_leaf(old_fs, new_fs, &target_path);
|
return bind_leaf(old_fs, new_fs, &target_path);
|
||||||
};
|
};
|
||||||
} else if (fs::isdir(st.mode)) {
|
} else if (fs::isdir(st.mode)) {
|
||||||
log::printfln("[namespace/bind] mkdir new/{}", strpath);
|
log::printfln("[namespace/bind] mkdir new/{}", strpath);
|
||||||
@@ -272,6 +247,22 @@ fn bind_component(old_fs: *fs::fs, new_fs: *fs::fs, strpath: str, remaining: str
|
|||||||
log::printfln("[namespace/bind] touch new/{}", strpath);
|
log::printfln("[namespace/bind] touch new/{}", strpath);
|
||||||
fs::create(new_fs, strpath, st.mode)?;
|
fs::create(new_fs, strpath, st.mode)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (remaining != "")
|
||||||
|
return; // nothing more to do for this path element
|
||||||
|
|
||||||
|
// and now, perform the actual bind mount:
|
||||||
|
let old_pathbuf = path::init("old", strpath)?;
|
||||||
|
let new_pathbuf = path::init("new", strpath)?;
|
||||||
|
|
||||||
|
log::printfln("[namespace/bind] mount {} {}", path::string(&old_pathbuf), path::string(&new_pathbuf));
|
||||||
|
rt::ext::mount(
|
||||||
|
path::string(&old_pathbuf),
|
||||||
|
path::string(&new_pathbuf),
|
||||||
|
"",
|
||||||
|
rt::ext::mount_flag::BIND | rt::ext::mount_flag::REC,
|
||||||
|
null,
|
||||||
|
)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
// make `new_root` the new `/`, and optionally make the old root accessible
|
// make `new_root` the new `/`, and optionally make the old root accessible
|
||||||
|
Reference in New Issue
Block a user