diff --git a/src/asm/output.c b/src/asm/output.c index e1cfd87d..e8d08cba 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -16,6 +16,23 @@ #include #include #include +#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" @@ -531,13 +548,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 +589,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); } /*