From a9cb4f8245c0143ddd963b9eb0cf7226b4369746 Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Sat, 9 Nov 2019 01:09:54 +0100 Subject: [PATCH 1/2] Make RGBASM overwrite output files atomically Fixes rednex/#446. I am not sure this is the best (in cases where the target directory is not writable but the target file is), but maybe this can be toggled via a flag, for example. --- src/asm/output.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/asm/output.c b/src/asm/output.c index 1a019682..1c83f8e9 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include "asm/asm.h" #include "asm/charmap.h" @@ -532,13 +534,25 @@ static void checksectionoverflow(uint32_t delta_size) */ void out_WriteObject(void) { + /* Write to a temporary file in the target's folder */ + char *objectNameCopy = strdup(tzObjectname); + char const *dirPath = dirname(objectNameCopy); + char tmpFileName[strlen(dirPath) + 1 + 16 + 1]; + + sprintf(tmpFileName, "%s/rgbasm_tmpXXXXXX", dirPath); + free(objectNameCopy); + int fd = mkstemp(tmpFileName); + FILE *f; struct PatchSymbol *pSym; struct Section *pSect; + if (fd == -1) + err(1, "Couldn't create temporary file"); + addexports(); - f = fopen(tzObjectname, "wb"); + f = fdopen(fd, "wb"); if (f == NULL) fatalerror("Couldn't write file '%s'\n", tzObjectname); @@ -560,6 +574,11 @@ void out_WriteObject(void) } fclose(f); + close(fd); + + if (rename(tmpFileName, tzObjectname) != 0) + err(1, "Couldn't create object file (temp file kept as %s)", + tmpFileName); } /* From 2e8094b71237c139d08ab373513112b258c143e4 Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Tue, 28 Jan 2020 11:07:46 +0100 Subject: [PATCH 2/2] Allow RGBASM to overwrite object files on Windows --- src/asm/output.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/asm/output.c b/src/asm/output.c index 1c83f8e9..dce91101 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -19,6 +19,21 @@ #include #include +#ifdef _WIN32 +#include +#include +/* + * The semantics of `rename` on Windows differ from POSIX in that it errors out + * when the target file exists, instead of overwriting it. + * Thus, shim `rename` with similar semantics (note that the return value of + * `MoveFileExA` is inverted, and it uses `GetLastError` instead of `errno`) + */ +#define rename(oldname, newname) \ + MoveFileExA(oldname, newname, MOVEFILE_WRITE_THROUGH | \ + MOVEFILE_REPLACE_EXISTING) \ + ? 0 : (errno = GetLastError(), -1) +#endif + #include "asm/asm.h" #include "asm/charmap.h" #include "asm/fstack.h"