diff --git a/include/extern.h b/include/extern.h index 533523198..e3375627f 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1036,7 +1036,7 @@ extern char *fname_encode(const char *, char, extern char *fname_decode(char, char *, char *, int) NONNULLPTRS; extern const char *fqname(const char *, int, int); extern FILE *fopen_datafile(const char *, const char *, int) NONNULLPTRS; -extern void zero_nhfile(NHFILE *) NONNULLARG1; +extern void init_nhfile(NHFILE *) NONNULLARG1; extern void close_nhfile(NHFILE *) NONNULLARG1; extern void rewind_nhfile(NHFILE *) NONNULLARG1; extern void set_levelfile_name(char *, int) NONNULLARG1; @@ -1059,6 +1059,7 @@ extern void set_error_savefile(void); extern NHFILE *create_savefile(void); extern NHFILE *open_savefile(void); extern int delete_savefile(void); +extern NHFILE *get_freeing_nhfile(void); extern NHFILE *restore_saved_game(void); extern int check_panic_save(void); #ifdef SELECTSAVED diff --git a/src/cmd.c b/src/cmd.c index 8b912dc40..68a8b1304 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -981,7 +981,7 @@ enter_explore_mode(void) void makemap_prepost(boolean pre, boolean wiztower) { - NHFILE tmpnhfp; + NHFILE *tmpnhfp; struct monst *mtmp; if (pre) { @@ -1029,9 +1029,9 @@ makemap_prepost(boolean pre, boolean wiztower) dobjsfree(); /* discard current level; "saving" is used to release dynamic data */ - zero_nhfile(&tmpnhfp); /* also sets fd to -1 as desired */ - tmpnhfp.mode = FREEING; - savelev(&tmpnhfp, ledger_no(&u.uz)); + tmpnhfp = get_freeing_nhfile(); + savelev(tmpnhfp, ledger_no(&u.uz)); + close_nhfile(tmpnhfp); } else { vision_reset(); gv.vision_full_recalc = 1; diff --git a/src/files.c b/src/files.c index a1a49d527..c9e90562e 100644 --- a/src/files.c +++ b/src/files.c @@ -458,23 +458,35 @@ static const int bei = 1; #define IS_BIGENDIAN() ( (*(char*)&bei) == 0 ) void -zero_nhfile(NHFILE *nhfp) +init_nhfile(NHFILE *nhfp) { + if (nhfp->structlevel) { + if (nhfp->fd != -1) { + impossible("Warning - Unclosed structlevel file being reinitialized"); + (void) nhclose(nhfp->fd); + } + } else if (nhfp->fpdef) { + if (nhfp->fpdef) { + impossible("Warning - Unclosed fieldlevel file being reinitialized"); + (void) fclose(nhfp->fpdef); + } + } nhfp->fd = -1; + nhfp->fpdef = (FILE *) 0; + nhfp->mode = COUNTING; nhfp->structlevel = TRUE; nhfp->fieldlevel = FALSE; nhfp->addinfo = FALSE; nhfp->bendian = IS_BIGENDIAN(); - nhfp->fpdef = (FILE *) 0; nhfp->fplog = (FILE *) 0; nhfp->fpdebug = (FILE *) 0; nhfp->rcount = nhfp->wcount = 0; nhfp->eof = FALSE; nhfp->fnidx = 0; - nhfp->style.deflt = FALSE; - nhfp->style.binary = TRUE; - nhfp->nhfpconvert = 0; + nhfp->style.deflt = FALSE; + nhfp->style.binary = TRUE; + nhfp->nhfpconvert = 0; } #ifndef SFCTOOL @@ -483,9 +495,10 @@ staticfn NHFILE * new_nhfile(void) { - NHFILE *nhfp = (NHFILE *) alloc(sizeof(NHFILE)); + NHFILE *nhfp = (NHFILE *) alloc(sizeof *nhfp); - zero_nhfile(nhfp); + memset((genericptr_t) nhfp, 0, sizeof *nhfp); + init_nhfile(nhfp); return nhfp; } @@ -496,7 +509,7 @@ void free_nhfile(NHFILE *nhfp) { if (nhfp) { - zero_nhfile(nhfp); + init_nhfile(nhfp); free(nhfp); } } @@ -514,7 +527,7 @@ close_nhfile(NHFILE *nhfp) (void) fclose(nhfp->fplog); if (nhfp->fpdebug) (void) fclose(nhfp->fpdebug); - zero_nhfile(nhfp); + init_nhfile(nhfp); free_nhfile(nhfp); } @@ -559,7 +572,7 @@ viable_nhfile(NHFILE *nhfp) if (nhfp->fpdebug) (void) fclose(nhfp->fpdebug); } - zero_nhfile(nhfp); + init_nhfile(nhfp); free_nhfile(nhfp); nhfp = (NHFILE *) 0; } @@ -1254,6 +1267,18 @@ restore_saved_game(void) return nhfp; } +NHFILE * +get_freeing_nhfile(void) +{ + NHFILE *nhfp = (NHFILE *) 0; + + nhfp = new_nhfile(); /* also sets fd to -1 */ + if (nhfp) { + nhfp->mode = FREEING; + } + return nhfp; +} + /* called if there is no save file for current character */ int check_panic_save(void) diff --git a/src/restore.c b/src/restore.c index dc87cb696..25f96f239 100644 --- a/src/restore.c +++ b/src/restore.c @@ -806,15 +806,11 @@ dorecover(NHFILE *nhfp) */ getlev(nhfp, 0, (xint8) 0); if (!restgamestate(nhfp)) { - NHFILE tnhfp; + NHFILE *tnhfp = get_freeing_nhfile(); display_nhwindow(WIN_MESSAGE, TRUE); - zero_nhfile(&tnhfp); - tnhfp.mode = FREEING; - tnhfp.fd = -1; - savelev(&tnhfp, 0); /* discard current level */ - /* no need for close_nhfile(&tnhfp), which - is not really affiliated with an open file */ + savelev(tnhfp, 0); /* discard current level */ + close_nhfile(tnhfp); close_nhfile(nhfp); (void) delete_savefile(); u.usteed_mid = u.ustuck_mid = 0; diff --git a/src/save.c b/src/save.c index bc420a041..aa9e32c3d 100644 --- a/src/save.c +++ b/src/save.c @@ -1037,13 +1037,12 @@ void free_dungeons(void) { #ifdef FREE_ALL_MEMORY - NHFILE tnhfp; + NHFILE *tnhfp = get_freeing_nhfile(); - zero_nhfile(&tnhfp); /* also sets fd to -1 */ - tnhfp.mode = FREEING; - savelevchn(&tnhfp); - save_dungeon(&tnhfp, FALSE, TRUE); + savelevchn(tnhfp); + save_dungeon(tnhfp, FALSE, TRUE); free_luathemes(all_themes); + close_nhfile(tnhfp); #endif return; } @@ -1054,13 +1053,11 @@ extern int options_set_window_colors_flag; /* options.c */ void freedynamicdata(void) { - NHFILE tnhfp; + NHFILE *tnhfp = get_freeing_nhfile(); #if defined(UNIX) && defined(MAIL) free_maildata(); #endif - zero_nhfile(&tnhfp); /* also sets fd to -1 */ - tnhfp.mode = FREEING; free_menu_coloring(); free_invbuf(); /* let_to_name (invent.c) */ free_youbuf(); /* You_buf,&c (pline.c) */ @@ -1069,18 +1066,18 @@ freedynamicdata(void) tmp_at(DISP_FREEMEM, 0); /* temporary display effects */ purge_all_custom_entries(); #ifdef FREE_ALL_MEMORY -#define free_current_level() savelev(&tnhfp, -1) -#define freeobjchn(X) (saveobjchn(&tnhfp, &X), X = 0) -#define freemonchn(X) (savemonchn(&tnhfp, X), X = 0) -#define freefruitchn() savefruitchn(&tnhfp) -#define freenames() savenames(&tnhfp) -#define free_killers() save_killers(&tnhfp) -#define free_oracles() save_oracles(&tnhfp) -#define free_waterlevel() save_waterlevel(&tnhfp) -#define free_timers(R) save_timers(&tnhfp, R) -#define free_light_sources(R) save_light_sources(&tnhfp, R) +#define free_current_level() savelev(tnhfp, -1) +#define freeobjchn(X) (saveobjchn(tnhfp, &X), X = 0) +#define freemonchn(X) (savemonchn(tnhfp, X), X = 0) +#define freefruitchn() savefruitchn(tnhfp) +#define freenames() savenames(tnhfp) +#define free_killers() save_killers(tnhfp) +#define free_oracles() save_oracles(tnhfp) +#define free_waterlevel() save_waterlevel(tnhfp) +#define free_timers(R) save_timers(tnhfp, R) +#define free_light_sources(R) save_light_sources(tnhfp, R) #define free_animals() mon_animal_list(FALSE) -#define discard_gamelog() save_gamelog(&tnhfp); +#define discard_gamelog() save_gamelog(tnhfp); /* move-specific data */ dmonsfree(); /* release dead monsters */ @@ -1155,6 +1152,11 @@ freedynamicdata(void) if (glyphid_cache_status()) free_glyphid_cache(); + if (tnhfp) { + close_nhfile(tnhfp); + tnhfp = 0; + } + /* last, because it frees data that might be used by panic() to provide feedback to the user; conceivably other freeing might trigger panic */ sysopt_release(); /* SYSCF strings */ diff --git a/util/sfctool.c b/util/sfctool.c index fe016748f..de25963a4 100644 --- a/util/sfctool.c +++ b/util/sfctool.c @@ -80,7 +80,7 @@ static int length_without_val(const char *user_string, int len); static void usage(int argc, char **argv); static const char *briefname(const char *fnam); -void zero_nhfile(NHFILE *); +void init_nhfile(NHFILE *); NHFILE *new_nhfile(void); void free_nhfile(NHFILE *); void my_close_nhfile(NHFILE *); @@ -462,7 +462,7 @@ open_srcfile(const char *fnam, enum saveformats mystyle) if (nhfp && nhfp->structlevel) { fd = open(fq_name, O_RDONLY | O_BINARY, 0); if (fd < 0) { - zero_nhfile(nhfp); + init_nhfile(nhfp); free_nhfile(nhfp); fprintf(stderr, "\nsfctool error - unable to open historical-style " @@ -482,7 +482,7 @@ open_srcfile(const char *fnam, enum saveformats mystyle) nhfp->fpdef = fopen(fnam, RDBMODE); if (!nhfp->fpdef) { - zero_nhfile(nhfp); + init_nhfile(nhfp); free_nhfile(nhfp); fprintf(stderr, "\nsfctool error - unable to open fieldlevel-style " @@ -577,7 +577,7 @@ create_dstfile(char *fnam, enum saveformats mystyle) fd = creat(dstfnam, FCMASK); #endif if (fd < 0) { - zero_nhfile(nhfp); + init_nhfile(nhfp); free_nhfile(nhfp); fprintf( stderr, @@ -594,7 +594,7 @@ create_dstfile(char *fnam, enum saveformats mystyle) fq_name = fqname(dstfnam, SAVEPREFIX, 0); nhfp->fpdef = fopen(fq_name, WRBMODE); if (!nhfp->fpdef) { - zero_nhfile(nhfp); + init_nhfile(nhfp); free_nhfile(nhfp); fprintf( stderr,