shithub: rgbds

Download patch

ref: 06fe27c51601e1822b9b3212f350c21609bdf9e9
parent: 187f88aa50f253eb670cdc415e9bc315ca289bb6
author: ISSOtm <[email protected]>
date: Fri Mar 27 07:19:02 EDT 2020

Prevent RGBASM from outputting corrupted files

Properly fixes #451

--- a/src/asm/output.c
+++ b/src/asm/output.c
@@ -408,13 +408,12 @@
  */
 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 @@
 		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);
 }