From 06fe27c51601e1822b9b3212f350c21609bdf9e9 Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Fri, 27 Mar 2020 11:19:02 +0100 Subject: [PATCH] Prevent RGBASM from outputting corrupted files Properly fixes #451 --- src/asm/output.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/asm/output.c b/src/asm/output.c index e0eb1f0d..de688b82 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -408,13 +408,12 @@ static void registerExportedSymbol(struct sSymbol *symbol, void *arg) */ void out_WriteObject(void) { - FILE *f; struct Section *pSect; struct Assertion *assert = assertions; + FILE *f = tmpfile(); /* Avoids producing a corrupted file on error */ - f = fopen(tzObjectname, "wb"); if (!f) - err(1, "Couldn't write file '%s'", tzObjectname); + err(1, "Couldn't create temporary file"); /* Also write exported symbols that weren't written above */ sym_ForEach(registerExportedSymbol, NULL); @@ -441,6 +440,31 @@ void out_WriteObject(void) assert = assert->next; } + /* We're finished writing the file; now, copy it to the final one */ + FILE *objFile = fopen(tzObjectname, "wb"); + long size = ftell(f); + char buf[1024]; + + rewind(f); + while (size) { + long blockSize = size < sizeof(buf) ? size : sizeof(buf); + + if (fread(buf, blockSize, 1, f) < 1 + || fwrite(buf, blockSize, 1, objFile) < 1) { + char const *errmsg = + ferror(f) || ferror(objFile) ? strerror(errno) + : "end of file"; + + fclose(objFile); + fclose(f); + remove(tzObjectname); + errx(1, "Failed to write file \"%s\": %s", tzObjectname, + errmsg); + } + size -= blockSize; + } + + fclose(objFile); fclose(f); }