From dfecf83fb3caeaa5dc9b779c7f21c5e020608bad Mon Sep 17 00:00:00 2001 From: rofl0r Date: Mon, 29 Aug 2022 22:53:33 +0000 Subject: [PATCH] agsinject: fix return value, rename on windows the logic processing the return value from inject() was actually wrong, it returned success in some cases even on error. also, rename() on windows doesn't work like on unix, overwriting the destination, therefore we need to delete the target first. in my experiments with wine i couldn't get rename() to work anyway, but this might be due to a bug in wine. in such a case we now print the temp filename, so the user can manually copy the file to its destination. closes #29 --- agsinject.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/agsinject.c b/agsinject.c index 8a227b3..0d1362f 100644 --- a/agsinject.c +++ b/agsinject.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "version.h" #define ADS ":::AGSinject " VERSION " by rofl0r:::" @@ -24,6 +25,12 @@ static char *tempnam(const char *dir, const char *pfx) { sprintf(p, "%016llx", (unsigned long long) _rdtsc()); return strdup(buf); } +static int RENAME(const char *OLD, const char *NEW) { + unlink(NEW); + return rename(OLD, NEW); +} +#else +#define RENAME(OLD, NEW) rename(OLD, NEW) #endif int usage(char *argv0) { @@ -57,25 +64,25 @@ static int inject(const char *o, const char *inj, unsigned which) { AF f_b, *f = &f_b; unsigned long long index, found; int isroom = !strcmp(".crm", inj + strlen(inj) - 4); - if(isroom && which != 0) return -1; - if(!AF_open(f, inj)) return 0; + if(isroom && which != 0) return -2; + if(!AF_open(f, inj)) return -1; long long start; for(index = found = 0; 1 ; found++, index = start + 4) { int room_length_bytes = 4; if(!isroom && (start = ARF_find_code_start(f, index)) == -1LL) { fprintf(stderr, "error, only %llu scripts found\n", (long long)found); - return 0; + return -3; } else if(isroom) { /* use roomfile specific script lookup, as it's faster */ struct RoomFile rinfo = {0}; - if(!RoomFile_read(f, &rinfo)) return 0; + if(!RoomFile_read(f, &rinfo)) return -3; start = rinfo.blockpos[BLOCKTYPE_COMPSCRIPT3]; if(rinfo.version >= 32) room_length_bytes = 8; } if(found != which) continue; char *tmp = tempnam(".", "agsinject.tmp"); FILE *out = fopen(tmp, "wb"); - if(!out) return 0; + if(!out) return -1; /* 1) dump header */ AF_dump_chunk_stream(f, 0, isroom ? start -room_length_bytes : start, out); @@ -112,15 +119,21 @@ static int inject(const char *o, const char *inj, unsigned which) { ASI s; if(!ASI_read_script(f, &s)) { fprintf(stderr, "trouble finding script in %s\n", inj); - return 0; + return -3; } /* 3) dump rest of file */ AF_dump_chunk_stream(f, start + s.len, ByteArray_get_length(f->b) - (start + s.len), out); AF_close(f); fclose(out); - return !rename(tmp, inj); + + int rnret = RENAME(tmp, inj); + if(rnret == -1 && errno == EEXIST) { + /* windows is special, as usual */ + fprintf(stderr, "rename failed from %s to %s\n", tmp, inj); + } + return rnret; } - return 0; + return -5; } static int check_objname(const char* o) { @@ -135,15 +148,16 @@ static int check_objname(const char* o) { static int injectpr(const char *obj, const char *out, unsigned which) { printf("injecting %s into %s as %d'th script ...", obj, out, which); int ret = inject(obj, out, which); - if(ret >= 0) printf("OK\n"); + if(ret == 0) printf("OK\n"); else { printf("FAIL\n"); - if(ret == -1) { + if(ret == -2) { fprintf(stderr, "invalid index %d for roomfile, only 0 possible\n", which); ret = 0; - } else perror("error:"); + } else if (ret == -1) perror("error"); + return 0; } - return ret; + return 1; } static int getstamp(const char* fn, time_t *stamp) { -- 2.11.4.GIT