ww: preserve compiler sink outputs
This commit is contained in:
@@ -14,6 +14,7 @@ type publication = struct {
|
||||
backup: str,
|
||||
hadold: bool,
|
||||
installed: bool,
|
||||
passthrough: bool,
|
||||
};
|
||||
|
||||
fn publicationpath(dst: *u8, kind: str) str = {
|
||||
@@ -21,6 +22,17 @@ fn publicationpath(dst: *u8, kind: str) str = {
|
||||
strconv.i32tos(os.getpid(), strconv.base.DEC), ".", kind);
|
||||
};
|
||||
|
||||
fn pathischardevice(path: *u8) bool = {
|
||||
let fi: os.filestat;
|
||||
match (os.lstat(&fi, pathstr(path))) {
|
||||
case void => {
|
||||
return (((fi.mode: u32) & 61440u32) == (os.mode.CHR: u32));
|
||||
};
|
||||
case let e: os.oserror => return false;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
// Open a destination-adjacent file and immediately unlink its name. Cgen's
|
||||
// fatal exit then leaves only a kernel-owned fd, never a partial destination
|
||||
// or named staging artifact.
|
||||
@@ -28,6 +40,12 @@ fn anonymousfd(dst: *u8, kind: str) i32 = {
|
||||
let path: str = publicationpath(dst, kind);
|
||||
let fd: i32 = os.open(path,
|
||||
os.flag.RDWR | os.flag.CREATE | os.flag.EXCL, 384i32);
|
||||
if (fd < 0 && pathischardevice(dst)) {
|
||||
path = strings.concat("/tmp/ww-w6c.",
|
||||
strconv.i32tos(os.getpid(), strconv.base.DEC), ".", kind);
|
||||
fd = os.open(path,
|
||||
os.flag.RDWR | os.flag.CREATE | os.flag.EXCL, 384i32);
|
||||
};
|
||||
if (fd < 0) {
|
||||
os.write(2, "w6c: cannot create anonymous output\n".ptr,
|
||||
"w6c: cannot create anonymous output\n".len: u64);
|
||||
@@ -60,6 +78,21 @@ fn copystream(src: i32, dst: i32) bool = {
|
||||
|
||||
fn materializestream(src: i32, dst: *u8, p: *publication) bool = {
|
||||
p.dst = dst;
|
||||
p.passthrough = false;
|
||||
let fi: os.filestat;
|
||||
match (os.lstat(&fi, pathstr(dst))) {
|
||||
case void => {
|
||||
if (((fi.mode: u32) & 61440u32) == (os.mode.CHR: u32)) {
|
||||
let sink: i32 = os.open(pathstr(dst), os.flag.WRONLY, 0i32);
|
||||
if (sink < 0) { return false; };
|
||||
let sinkok: bool = copystream(src, sink);
|
||||
if (os.close(sink) != 0) { sinkok = false; };
|
||||
if (sinkok) { p.passthrough = true; };
|
||||
return sinkok;
|
||||
};
|
||||
};
|
||||
case let e: os.oserror => void;
|
||||
};
|
||||
p.stage = publicationpath(dst, "new");
|
||||
p.backup = publicationpath(dst, "old");
|
||||
p.hadold = false;
|
||||
@@ -110,6 +143,7 @@ fn publishall(p: *publication, n: i32) bool = {
|
||||
let i: i32 = 0;
|
||||
let ok: bool = true;
|
||||
for (i < n) {
|
||||
if (p[i].passthrough) { i += 1; continue; };
|
||||
if (!pathisregularnofollow(p[i].stage)) {
|
||||
publishdiag("w6c: publication stage is not a regular file for ",
|
||||
p[i].dst);
|
||||
@@ -140,6 +174,7 @@ fn publishall(p: *publication, n: i32) bool = {
|
||||
if (ok) {
|
||||
i = 0;
|
||||
for (i < n) {
|
||||
if (p[i].passthrough) { i += 1; continue; };
|
||||
let exists: i32 = pathexistsnofollow(p[i].backup);
|
||||
if (exists != 0) {
|
||||
if (exists < 0) {
|
||||
@@ -157,6 +192,7 @@ fn publishall(p: *publication, n: i32) bool = {
|
||||
if (ok) {
|
||||
i = 0;
|
||||
for (i < n) {
|
||||
if (p[i].passthrough) { i += 1; continue; };
|
||||
let rc: i32 = os.rename(pathstr(p[i].dst), p[i].backup);
|
||||
if (rc == 0) { p[i].hadold = true; }
|
||||
else { if (rc != -2) {
|
||||
@@ -170,6 +206,7 @@ fn publishall(p: *publication, n: i32) bool = {
|
||||
if (ok) {
|
||||
i = 0;
|
||||
for (i < n) {
|
||||
if (p[i].passthrough) { i += 1; continue; };
|
||||
if (os.rename(p[i].stage, pathstr(p[i].dst)) != 0) {
|
||||
publishdiag("w6c: cannot publish ", p[i].dst);
|
||||
ok = false;
|
||||
@@ -183,7 +220,8 @@ fn publishall(p: *publication, n: i32) bool = {
|
||||
// truthfully turn a completely installed pair into rejection.
|
||||
i = 0;
|
||||
for (i < n) {
|
||||
if (p[i].hadold && os.remove(p[i].backup) != 0) {
|
||||
if (!p[i].passthrough && p[i].hadold
|
||||
&& os.remove(p[i].backup) != 0) {
|
||||
publishdiag("w6c: cannot remove backup for ", p[i].dst);
|
||||
};
|
||||
i += 1;
|
||||
@@ -193,6 +231,7 @@ fn publishall(p: *publication, n: i32) bool = {
|
||||
};
|
||||
i = n - 1;
|
||||
for (i >= 0) {
|
||||
if (p[i].passthrough) { i -= 1; continue; };
|
||||
if (p[i].installed) { os.remove(pathstr(p[i].dst)); };
|
||||
if (p[i].hadold) { os.rename(p[i].backup, pathstr(p[i].dst)); };
|
||||
if (p[i].stage.len != 0) { os.remove(p[i].stage); };
|
||||
@@ -882,6 +921,7 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
||||
pubs[pi].backup = "";
|
||||
pubs[pi].hadold = false;
|
||||
pubs[pi].installed = false;
|
||||
pubs[pi].passthrough = false;
|
||||
pi += 1;
|
||||
};
|
||||
let npub: i32 = 0;
|
||||
|
||||
Reference in New Issue
Block a user