diff --git a/src/battle.c b/src/battle.c index 65b2cff7b..ca8bdc3b8 100644 --- a/src/battle.c +++ b/src/battle.c @@ -3595,14 +3595,15 @@ battle *make_battle(region * r) if (battledebug) { char zText[MAX_PATH]; char zFilename[MAX_PATH]; - sprintf(zText, "%s/battles", basepath()); + join_path(basepath(), "battles", zText, sizeof(zText)); if (_mkdir(zText) != 0) { log_error("could not create subdirectory for battle logs: %s", zText); battledebug = false; } else { - sprintf(zFilename, "%s/battle-%d-%s.log", zText, obs_count++, simplename(r)); - bdebug = fopen(zFilename, "w"); + sprintf(zFilename, "battle-%d-%s.log", obs_count++, simplename(r)); + join_path(zText, zFilename, zText, sizeof(zText)); + bdebug = fopen(zText, "w"); if (!bdebug) log_error("battles cannot be debugged"); else { diff --git a/src/bind_config.c b/src/bind_config.c index 945c7f603..3959cc22c 100644 --- a/src/bind_config.c +++ b/src/bind_config.c @@ -1,6 +1,7 @@ #include "bind_config.h" #include +#include #include #include #include @@ -58,11 +59,11 @@ int config_read(const char *filename, const char * relpath) json_relpath = relpath; if (relpath) { - _snprintf(name, sizeof(name), "%s/%s", relpath, filename); - F = fopen(name, "rt"); + join_path(relpath, filename, name, sizeof(name)); + F = fopen(name, "r"); } else { - F = fopen(filename, "rt"); + F = fopen(filename, "r"); } if (F) { long size; diff --git a/src/bind_eressea.c b/src/bind_eressea.c index 270cb44e8..d7683ec18 100755 --- a/src/bind_eressea.c +++ b/src/bind_eressea.c @@ -32,7 +32,7 @@ int eressea_read_orders(const char * filename) { } int eressea_export_json(const char * filename, int flags) { - FILE *F = fopen(filename, "wt"); + FILE *F = fopen(filename, "w"); if (F) { stream out = { 0 }; int err; @@ -46,7 +46,7 @@ int eressea_export_json(const char * filename, int flags) { } int eressea_import_json(const char * filename) { - FILE *F = fopen(filename, "rt"); + FILE *F = fopen(filename, "r"); if (F) { stream out = { 0 }; int err; diff --git a/src/bind_storage.c b/src/bind_storage.c index aaeb84128..ca83f199a 100644 --- a/src/bind_storage.c +++ b/src/bind_storage.c @@ -32,7 +32,7 @@ without prior permission by the authors of Eressea. static int tolua_storage_create(lua_State * L) { const char *filename = tolua_tostring(L, 1, 0); - const char *type = tolua_tostring(L, 2, "r"); + const char *type = tolua_tostring(L, 2, "rb"); gamedata *data; data = gamedata_open(filename, type); diff --git a/src/creport.c b/src/creport.c index 186afab4d..c202029e0 100644 --- a/src/creport.c +++ b/src/creport.c @@ -1502,7 +1502,7 @@ report_computer(const char *filename, report_context * ctx, const char *charset) const char *mailto = LOC(f->locale, "mailto"); const attrib *a; seen_region *sr = NULL; - FILE *F = fopen(filename, "wt"); + FILE *F = fopen(filename, "w"); if (era < 0) { era = config_get_int("world.era", 1); diff --git a/src/gmtool.c b/src/gmtool.c index 3c50aaf45..3a48535a0 100644 --- a/src/gmtool.c +++ b/src/gmtool.c @@ -848,7 +848,7 @@ static void handlekey(state * st, int c) break; case 'B': if (!new_players) { - sprintf(sbuffer, "%s/newfactions", basepath()); + join_path(basepath(), "newfactions", sbuffer, sizeof(sbuffer)); new_players = read_newfactions(sbuffer); } cnormalize(&st->cursor, &nx, &ny); @@ -1063,7 +1063,7 @@ static void handlekey(state * st, int c) break; case 'A': if (!new_players) { - sprintf(sbuffer, "%s/newfactions", basepath()); + join_path(basepath(), "newfactions", sbuffer, sizeof(sbuffer)); new_players = read_newfactions(sbuffer); } seed_players(&new_players, false); @@ -1236,11 +1236,10 @@ void run_mapper(void) WINDOW *hwininfo; WINDOW *hwinmap; int width, height, x, y; - int split = 20, old_flags = log_flags; + int split = 20; state *st; point tl; - log_flags &= ~(LOG_CPERROR | LOG_CPWARNING); init_curses(); curs_set(1); @@ -1332,7 +1331,6 @@ void run_mapper(void) set_readline(NULL); curs_set(1); endwin(); - log_flags = old_flags; state_close(st); } diff --git a/src/kernel/config.c b/src/kernel/config.c index 08b7f53c9..64afd98d3 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -659,11 +659,16 @@ void set_basepath(const char *path) #define PATH_DELIM '/' #endif - char * join_path(const char *p1, const char *p2, char *dst, size_t len) { size_t sz; assert(p1 && p2); - sz = strlcpy(dst, p1, len); + assert(p2 != dst); + if (dst == p1) { + sz = strlen(p1); + } + else { + sz = strlcpy(dst, p1, len); + } assert(sz < len); dst[sz++] = PATH_DELIM; strlcpy(dst + sz, p2, len - sz); diff --git a/src/kernel/faction.c b/src/kernel/faction.c index cf1372950..aa04470f0 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -853,7 +853,7 @@ int writepasswd(void) FILE *F; char zText[128]; - sprintf(zText, "%s/passwd", basepath()); + join_path(basepath(), "passwd", zText, sizeof(zText)); F = fopen(zText, "w"); if (!F) { perror(zText); diff --git a/src/kernel/group.test.c b/src/kernel/group.test.c index 35b25aad5..46d794d2d 100644 --- a/src/kernel/group.test.c +++ b/src/kernel/group.test.c @@ -23,7 +23,7 @@ static void test_group_readwrite(CuTest * tc) FILE *F; stream strm; - F = fopen("test.dat", "w"); + F = fopen("test.dat", "wb"); fstream_init(&strm, F); binstore_init(&store, &strm); test_cleanup(); @@ -36,7 +36,7 @@ static void test_group_readwrite(CuTest * tc) binstore_done(&store); fstream_done(&strm); - F = fopen("test.dat", "r"); + F = fopen("test.dat", "rb"); fstream_init(&strm, F); binstore_init(&store, &strm); f->groups = 0; diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index 099b7a228..aac4bce10 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -828,11 +828,11 @@ static void json_include(cJSON *json) { FILE *F; if (json_relpath) { char name[MAX_PATH]; - _snprintf(name, sizeof(name), "%s/%s", json_relpath, child->valuestring); - F = fopen(name, "rt"); + join_path(json_relpath, child->valuestring, name, sizeof(name)); + F = fopen(name, "r"); } else { - F = fopen(child->valuestring, "rt"); + F = fopen(child->valuestring, "r"); } if (F) { long pos; diff --git a/src/kernel/jsonconf.test.c b/src/kernel/jsonconf.test.c index 5e7d3047e..63c5fe0ff 100644 --- a/src/kernel/jsonconf.test.c +++ b/src/kernel/jsonconf.test.c @@ -438,7 +438,7 @@ static void test_configs(CuTest * tc) test_cleanup(); - F = fopen("test.json", "wt"); + F = fopen("test.json", "w"); fwrite(building_data, 1, strlen(building_data), F); fclose(F); CuAssertPtrNotNull(tc, json); diff --git a/src/kernel/save.c b/src/kernel/save.c index 25ae2d858..7e5112443 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -552,7 +552,7 @@ int current_turn(void) int cturn = 0; FILE *F; - sprintf(zText, "%s/turn", basepath()); + join_path(basepath(), "turn", zText, sizeof(zText)); F = fopen(zText, "r"); if (!F) { perror(zText); @@ -1166,6 +1166,7 @@ faction *readfaction(struct gamedata * data) char name[DISPLAYSIZE]; READ_INT(data->store, &n); + assert(n > 0); f = findfaction(n); if (f == NULL) { f = (faction *)calloc(1, sizeof(faction)); @@ -1401,13 +1402,13 @@ int readgame(const char *filename, bool backup) init_locales(); log_debug("- reading game data from %s\n", filename); - sprintf(path, "%s/%s", datapath(), filename); + join_path(datapath(), filename, path, sizeof(path)); if (backup) { create_backup(path); } - F = fopen(path, "r"); + F = fopen(path, "rb"); if (!F) { perror(path); return -1; @@ -1753,7 +1754,7 @@ int writegame(const char *filename) /* make sure we don't overwrite an existing file (hard links) */ unlink(path); #endif - F = fopen(path, "w"); + F = fopen(path, "wb"); if (!F) { perror(path); return -1; diff --git a/src/kernel/save.test.c b/src/kernel/save.test.c index e7f85ad7e..4762bf6e0 100644 --- a/src/kernel/save.test.c +++ b/src/kernel/save.test.c @@ -15,10 +15,10 @@ static void test_readwrite_data(CuTest * tc) const char *filename = "test.dat"; char path[MAX_PATH]; test_cleanup(); - sprintf(path, "%s/%s", datapath(), filename); CuAssertIntEquals(tc, 0, writegame(filename)); CuAssertIntEquals(tc, 0, readgame(filename, false)); CuAssertIntEquals(tc, RELEASE_VERSION, global.data_version); + join_path(datapath(), filename, path, sizeof(path)); CuAssertIntEquals(tc, 0, remove(path)); test_cleanup(); } @@ -42,15 +42,15 @@ static void test_readwrite_unit(CuTest * tc) u = test_create_unit(f, r); join_path(datapath(), filename, path, sizeof(path)); - data = gamedata_open(path, "w"); - CuAssertPtrNotNull(tc, data); // TODO: intermittent test + data = gamedata_open(path, "wb"); + CuAssertPtrNotNull(tc, data); // TODO: intermittent test (even after the 'b' fix!) write_unit(data, u); gamedata_close(data); free_gamedata(); f = test_create_faction(0); renumber_faction(f, fno); - data = gamedata_open(path, "r"); + data = gamedata_open(path, "rb"); u = read_unit(data); gamedata_close(data); diff --git a/src/laws.c b/src/laws.c index eb079b8ac..e72472aec 100755 --- a/src/laws.c +++ b/src/laws.c @@ -4442,8 +4442,7 @@ void update_subscriptions(void) FILE *F; char zText[MAX_PATH]; - strlcpy(zText, basepath(), sizeof(zText)); - strlcat(zText, "/subscriptions", sizeof(zText)); + join_path(basepath(), "subscriptions", zText, sizeof(zText)); F = fopen(zText, "r"); if (F == NULL) { log_warning(0, "could not open %s.\n", zText); @@ -4463,17 +4462,6 @@ void update_subscriptions(void) } } fclose(F); - - sprintf(zText, "subscriptions.%u", turn); - F = fopen(zText, "w"); - if (F) { - faction *f; - for (f = factions; f != NULL; f = f->next) { - fprintf(F, "%s:%u:%s:%s:%u:\n", - itoa36(f->no), f->subscription, f->email, dbrace(f->race), f->lastorders); - } - fclose(F); - } } bool diff --git a/src/main.c b/src/main.c index 305d4a901..f96c04d2e 100644 --- a/src/main.c +++ b/src/main.c @@ -296,7 +296,7 @@ int main(int argc, char **argv) /* parse arguments again, to override ini file */ parse_args(argc, argv, &err); - log_open(logfile); + log_open(logfile, LOG_CPERROR | LOG_CPWARNING | LOG_CPDEBUG | LOG_FLUSH); locale_init(); #ifdef CRTDBG diff --git a/src/modules/score.c b/src/modules/score.c index ed8f4e458..74eb0898b 100644 --- a/src/modules/score.c +++ b/src/modules/score.c @@ -152,7 +152,7 @@ void score(void) allscores = 1; } - sprintf(path, "%s/score", basepath()); + join_path(basepath(), "score", path, sizeof(path)); scoreFP = fopen(path, "w"); if (scoreFP) { const unsigned char utf8_bom[4] = { 0xef, 0xbb, 0xbf, 0 }; @@ -177,7 +177,7 @@ void score(void) alliance *a; const item_type *token = it_find("conquesttoken"); - sprintf(path, "%s/score.alliances", basepath()); + join_path(basepath(), "score.alliances", path, sizeof(path)); scoreFP = fopen(path, "w"); if (scoreFP) { const unsigned char utf8_bom[4] = { 0xef, 0xbb, 0xbf, 0 }; diff --git a/src/report.c b/src/report.c index 323a94f02..15c5f1b2c 100644 --- a/src/report.c +++ b/src/report.c @@ -1403,7 +1403,7 @@ report_template(const char *filename, report_context * ctx, const char *charset) const resource_type *rsilver = get_resourcetype(R_SILVER); faction *f = ctx->f; region *r; - FILE *F = fopen(filename, "wt"); + FILE *F = fopen(filename, "w"); stream strm = { 0 }, *out = &strm; seen_region *sr = NULL; char buf[8192], *bufp; @@ -2067,7 +2067,7 @@ const char *charset) unsigned char op; int maxh, bytes, ix = want(O_STATISTICS); int wants_stats = (f->options & ix); - FILE *F = fopen(filename, "wt"); + FILE *F = fopen(filename, "w"); stream strm = { 0 }, *out = &strm; seen_region *sr = NULL; char buf[8192]; diff --git a/src/reports.c b/src/reports.c index 11c235011..67f5133f8 100644 --- a/src/reports.c +++ b/src/reports.c @@ -1558,11 +1558,13 @@ int write_reports(faction * f, time_t ltime) if (f->options & rtype->flag) { int error; do { - char filename[MAX_PATH]; - sprintf(filename, "%s/%d-%s.%s", reportpath(), turn, factionid(f), + char filename[32]; + char path[MAX_PATH]; + sprintf(filename, "%d-%s.%s", turn, factionid(f), rtype->extension); + join_path(reportpath(), filename, path, sizeof(path)); error = 0; - if (rtype->write(filename, &ctx, encoding) == 0) { + if (rtype->write(path, &ctx, encoding) == 0) { gotit = true; } if (errno) { @@ -1657,15 +1659,6 @@ int reports(void) if (mailit) fclose(mailit); free_seen(); -#ifdef GLOBAL_REPORT - { - const char *str = config_get("globalreport"); - if (str != NULL) { - sprintf(path, "%s/%s.%u.cr", reportpath(), str, turn); - global_report(path); - } - } -#endif return retval; } diff --git a/src/summary.c b/src/summary.c index 093481c76..51c549cf3 100644 --- a/src/summary.c +++ b/src/summary.c @@ -152,7 +152,7 @@ static void writeturn(void) char zText[MAX_PATH]; FILE *f; - sprintf(zText, "%s/datum", basepath()); + join_path(basepath(), "datum", zText, sizeof(zText)); f = fopen(zText, "w"); if (!f) { perror(zText); @@ -160,7 +160,7 @@ static void writeturn(void) } fputs(gamedate2(default_locale), f); fclose(f); - sprintf(zText, "%s/turn", basepath()); + join_path(basepath(), "turn", zText, sizeof(zText)); f = fopen(zText, "w"); if (!f) { perror(zText); @@ -178,10 +178,10 @@ void report_summary(summary * s, summary * o, bool full) char zText[MAX_PATH]; if (full) { - sprintf(zText, "%s/parteien.full", basepath()); + join_path(basepath(), "parteien.full", zText, sizeof(zText)); } else { - sprintf(zText, "%s/parteien", basepath()); + join_path(basepath(), "parteien", zText, sizeof(zText)); } F = fopen(zText, "w"); if (!F) { diff --git a/src/test_eressea.c b/src/test_eressea.c index a9b9b941c..4d69ad954 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -58,10 +58,6 @@ bool list = false; int RunAllTests(int argc, char *argv[]) { - int flags = log_flags; - - log_flags = LOG_FLUSH | LOG_CPERROR; - /* self-test */ ADD_SUITE(tests); ADD_SUITE(callback); @@ -146,7 +142,6 @@ int RunAllTests(int argc, char *argv[]) suites = s; } printf("\ntest summary: %d tests, %d failed\n", summary->count, summary->failCount); - log_flags = flags; fail_count = summary->failCount; CuSuiteDelete(summary); game_done(); diff --git a/src/util/log.c b/src/util/log.c index 958e26e2f..4afee68b4 100644 --- a/src/util/log.c +++ b/src/util/log.c @@ -31,22 +31,23 @@ static int stdio_codepage = STDIO_CP; static int stdio_codepage = 0; #endif -typedef struct logger { +typedef struct log_t { void(*log)(void *data, int level, const char *module, const char *format, va_list args); void *data; int flags; - struct logger *next; -} logger; + struct log_t *next; +} log_t; -static logger *loggers; +static log_t *loggers; -void log_create(int flags, void *data, log_fun call) { - logger *lgr = malloc(sizeof(logger)); +log_t *log_create(int flags, void *data, log_fun call) { + log_t *lgr = malloc(sizeof(log_t)); lgr->log = call; lgr->flags = flags; lgr->data = data; lgr->next = loggers; loggers = lgr; + return lgr; } #define MAXLENGTH 4096 /* because I am lazy, CP437 output is limited to this many chars */ @@ -122,10 +123,8 @@ static int check_dupe(const char *format, int type) return 1; } if (dupes) { - if (log_flags & LOG_CPERROR) { - fprintf(stderr, "%s: last message repeated %d times\n", log_prefix(last_type), - dupes + 1); - } + fprintf(stderr, "%s: last message repeated %d times\n", log_prefix(last_type), + dupes + 1); dupes = 0; } strlcpy(last_message, format, sizeof(last_message)); @@ -167,12 +166,12 @@ static void log_stdio(void *data, int level, const char *module, const char *for } } -void log_to_file(int flags, FILE *out) { - log_create(flags, out, log_stdio); +log_t *log_to_file(int flags, FILE *out) { + return log_create(flags, out, log_stdio); } static void log_write(int flags, const char *module, const char *format, va_list args) { - logger *lg; + log_t *lg; for (lg = loggers; lg; lg = lg->next) { int level = flags & LOG_LEVELS; if (lg->flags & level) { @@ -241,7 +240,7 @@ static FILE *logfile; void log_close(void) { while (loggers) { - logger *lgr = loggers; + log_t *lgr = loggers; loggers = lgr->next; free(lgr); } @@ -254,7 +253,7 @@ void log_close(void) logfile = 0; } -void log_open(const char *filename) +log_t *log_open(const char *filename, int log_flags) { log_rotate(filename, LOG_MAXBACKUPS); logfile = fopen(filename, "a"); @@ -263,6 +262,14 @@ void log_open(const char *filename) time_t ltime; time(<ime); fprintf(logfile, "===\n=== Logfile started at %s===\n", ctime(<ime)); - log_create(log_flags, logfile, log_stdio); + return log_create(log_flags, logfile, log_stdio); } + return 0; +} + +int log_level(log_t * log, int flags) +{ + int old = log->flags; + log->flags = flags; + return old; } diff --git a/src/util/log.h b/src/util/log.h index 8fd8f2a95..56adfa1c3 100644 --- a/src/util/log.h +++ b/src/util/log.h @@ -17,10 +17,16 @@ extern "C" { #include #include - extern void log_open(const char *filename); - extern void log_close(void); + struct log_t; + + typedef void(*log_fun)(void *data, int level, const char *module, const char *format, va_list args); + + struct log_t * log_open(const char *filename, int flags); + struct log_t * log_create(int flags, void *data, log_fun call); + struct log_t * log_to_file(int flags, FILE *out); + int log_level(struct log_t *log, int flags); + void log_close(void); - /* use macros above instead of these: */ extern void log_fatal(const char *format, ...); extern void log_error(const char *format, ...); extern void log_warning(const char *format, ...); @@ -36,13 +42,6 @@ extern "C" { #define LOG_FLUSH 0x10 #define LOG_BRIEF 0x20 - typedef void(*log_fun)(void *data, int level, const char *module, const char *format, va_list args); - - void log_create(int flags, void *data, log_fun call); - void log_to_file(int flags, FILE *out); - - extern int log_flags; - extern int log_stderr; #ifdef __cplusplus } #endif diff --git a/tests/score b/tests/score new file mode 100644 index 000000000..5f282702b --- /dev/null +++ b/tests/score @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tests/score.alliances b/tests/score.alliances new file mode 100644 index 000000000..003fe8605 --- /dev/null +++ b/tests/score.alliances @@ -0,0 +1,3 @@ +# alliance:factions:persons:score +1248287:1:0:0 +1490214:1:0:2105