diff --git a/internal/wwpackage/package.ww b/internal/wwpackage/package.ww index 455d847a..a55e3a20 100644 --- a/internal/wwpackage/package.ww +++ b/internal/wwpackage/package.ww @@ -440,10 +440,24 @@ fn pkgmakedir(path: str) bool = { return os.mkdir(path, 448i32) == 0; }; +// The coordinator removes only its minted temp root; validating the opened +// inode keeps a replaced path from carrying cleanup outside that ownership. fn pkgremoveall(path: str) bool = { - if (!pkgisdir(path)) { return os.remove(path) == 0; }; + let st: os.filestat; + match (os.lstat(&st, path)) { + case void => void; + case let e: os.oserror => return false; + }; + if (!pkgmodeis(st.mode, os.mode.DIR)) { return os.remove(path) == 0; }; let fd: i32 = os.open(path, os.flag.RDONLY, 0i32); if (fd < 0) { return false; }; + let opened: os.filestat; + match (os.fstat(&opened, fd)) { + case void => void; + case let e: os.oserror => { os.close(fd); return false; }; + }; + if (!pkgmodeis(opened.mode, os.mode.DIR) + || opened.inode != st.inode) { os.close(fd); return false; }; let ok: bool = true; let buf: []u8 = alloc([], 8192u64)!; buf.len = 8192; @@ -476,7 +490,7 @@ fn pkgremoveall(path: str) bool = { n = os.getdents64(fd, buf.ptr, 8192u64); }; if (n < 0i64) { ok = false; }; - os.close(fd); + if (os.close(fd) != 0) { ok = false; }; if (os.rmdir(path) != 0) { ok = false; }; return ok; };