From 3545374e9cf0348a7bfb448cd17ac28d63fe0ea3 Mon Sep 17 00:00:00 2001 From: nhmall Date: Thu, 21 Nov 2019 23:41:11 -0500 Subject: [PATCH] internal self-recover fix and bones name buffers --- doc/fixes37.0 | 2 + include/decl.h | 7 +- src/files.c | 192 ++++++++++++++++++++++++++++++----------- sys/winnt/Makefile.msc | 1 + sys/winnt/windmain.c | 4 + 5 files changed, 154 insertions(+), 52 deletions(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index ce51bf64f..08e5903a4 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -7,6 +7,8 @@ hero polymorphed into a vampire can use #monster to shape-shift rather than just do a one-shot polymorph into bat/cloud/wolf and shifted vampire hero can use #monster again to take on another form (randomly chosen among the shiftable shapes and true vampire form) +adjust bones filename buffer sizes to accommodate suffix +fix internal self-recover to work with recent fields added to checkpoint file Fixes to Pre-3.7.0 Problems that Were Exposed Via git Repository diff --git a/include/decl.h b/include/decl.h index c57eafc18..4cd23a7bc 100644 --- a/include/decl.h +++ b/include/decl.h @@ -10,7 +10,7 @@ #if !defined(MICRO) && !defined(VMS) && !defined(WIN32) #define LOCKNAMESIZE (PL_NSIZ + 14) /* long enough for uid+name+.99 */ #define LOCKNAMEINIT "1lock" -#define BONESINIT "bonesnn.xxx" +#define BONESINIT "bonesnn.xxx.le" #define BONESSIZE sizeof(BONESINIT) #else #if defined(MICRO) @@ -22,13 +22,13 @@ #if defined(VMS) #define LOCKNAMESIZE (PL_NSIZ + 17) /* long enough for _uid+name+.99;1 */ #define LOCKNAMEINIT "1lock" -#define BONESINIT "bonesnn.xxx;1" +#define BONESINIT "bonesnn.xxx_le;1" #define BONESSIZE sizeof(BONESINIT) #endif #if defined(WIN32) #define LOCKNAMESIZE (PL_NSIZ + 25) /* long enough for username+-+name+.99 */ #define LOCKNAMEINIT "" -#define BONESINIT "bonesnn.xxx" +#define BONESINIT "bonesnn.xxx.le" #define BONESSIZE sizeof(BONESINIT) #endif #endif @@ -170,6 +170,7 @@ struct sinfo { int exiting; /* an exit handler is executing */ int in_moveloop; int in_impossible; + int in_self_recover; #ifdef PANICLOG int in_paniclog; #endif diff --git a/src/files.c b/src/files.c index 6677f3e64..eb8f09756 100644 --- a/src/files.c +++ b/src/files.c @@ -757,12 +757,12 @@ d_level *lev; char *dptr; /* - * "bonD0.nn" = bones for level nn in the main dungeon; - * "bonM0.T" = bones for Minetown; - * "bonQBar.n" = bones for level n in the Barbarian quest; - * "bon3D0.nn" = \ - * "bon3M0.T" = > same as above, but for bones pool #3. - * "bon3QBar.n" = / + * "bonD0.nn.le" = bones for level nn in the main dungeon; + * "bonM0.T.le" = bones for Minetown; + * "bonQBar.n.le" = bones for level n in the Barbarian quest; + * "bon3D0.nn.le" = \ + * "bon3M0.T.le" = > same as above, but for bones pool #3. + * "bon3QBar.n.le" = / * * Return value for content validation skips "bon" and the * pool number (if present), making it feasible for the admin @@ -1032,6 +1032,17 @@ boolean regularize_it; if (idx > historical && idx <= ascii) sfindicator = sfoprocs[idx].ext; #endif + if (g.program_state.in_self_recover) { + /* self_recover needs to be done as historical + structlevel content until that process is + re-written to use something other than + copy_bytes() to retrieve data content from + level files (which are structlevel) and + place it into the save file. + */ + idx = historical; + sfindicator = sfoprocs[idx].ext; + } #ifdef VMS Sprintf(g.SAVEF, "[.save]%d%s", getuid(), g.plname); regoffset = 7; @@ -1108,7 +1119,7 @@ boolean regularize_it; (idx == lendian) ? 'l' : (idx == ascii) ? 'a' : '\0'; } - sfindicator = sfoprocs[idx].ext; + sfindicator = (g.program_state.in_self_recover) ? "" : sfoprocs[idx].ext; #endif #endif } else @@ -1176,6 +1187,7 @@ create_savefile() int failed = 0; const char *fq_save; NHFILE *nhfp = (NHFILE *) 0; + boolean do_historical = TRUE; fq_save = fqname(g.SAVEF, SAVEPREFIX, 0); nhfp = new_nhfile(); @@ -1186,7 +1198,21 @@ create_savefile() nhfp->mode = WRITING; #ifdef SYSCF if (sysopt.saveformat[0] > historical && - sysopt.saveformat[0] <= ascii) { + sysopt.saveformat[0] <= ascii) + do_historical = FALSE; +#endif /* SYSCF */ + if (g.program_state.in_self_recover) { + do_historical = TRUE; /* force it */ + nhfp->structlevel = TRUE; + nhfp->fieldlevel = FALSE; + nhfp->addinfo = FALSE; + nhfp->style.deflt = FALSE; + nhfp->style.binary = TRUE; + nhfp->fnidx = historical; + nhfp->fd = -1; + nhfp->fpdef = (FILE *) 0; + } + if (!do_historical) { nhfp->structlevel = FALSE; nhfp->fieldlevel = TRUE; nhfp->addinfo = TRUE; @@ -1203,7 +1229,6 @@ create_savefile() failed = errno; } } -#endif /* SYSCF */ if (nhfp->structlevel) { #if defined(MICRO) || defined(WIN32) nhfp->fd = open(fq_save, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK); @@ -1240,6 +1265,7 @@ open_savefile() int failed = 0; const char *fq_save; NHFILE *nhfp = (NHFILE *) 0; + boolean do_historical = TRUE; fq_save = fqname(g.SAVEF, SAVEPREFIX, 0); nhfp = new_nhfile(); @@ -1250,7 +1276,21 @@ open_savefile() nhfp->mode = READING; #ifdef SYSCF if (sysopt.saveformat[0] > historical && - sysopt.saveformat[0] <= ascii) { + sysopt.saveformat[0] <= ascii) + do_historical = FALSE; +#endif /* SYSCF */ + if (g.program_state.in_self_recover) { + do_historical = TRUE; /* force it */ + nhfp->structlevel = TRUE; + nhfp->fieldlevel = FALSE; + nhfp->addinfo = FALSE; + nhfp->style.deflt = FALSE; + nhfp->style.binary = TRUE; + nhfp->fnidx = historical; + nhfp->fd = -1; + nhfp->fpdef = (FILE *) 0; + } + if (!do_historical) { nhfp->structlevel = FALSE; nhfp->fieldlevel = TRUE; nhfp->addinfo = TRUE; @@ -1267,7 +1307,6 @@ open_savefile() failed = errno; } } -#endif /* SYSCF */ if (nhfp->structlevel) { #ifdef MAC nhfp->fd = macopen(fq_save, O_RDONLY | O_BINARY, SAVE_TYPE); @@ -3943,14 +3982,15 @@ boolean recover_savefile() { NHFILE *gnhfp, *lnhfp, *snhfp; - int lev, savelev, hpid, pltmpsiz; + int lev, savelev, hpid, pltmpsiz, filecmc; xchar levc; struct version_info version_data; int processed[256]; - char savename[SAVESIZE], errbuf[BUFSZ]; + char savename[SAVESIZE], errbuf[BUFSZ], indicator; struct savefile_info sfi; char tmpplbuf[PL_NSIZ]; - + const char *savewrite_failure = (const char *) 0; + for (lev = 0; lev < 256; lev++) processed[lev] = 0; @@ -3985,6 +4025,10 @@ recover_savefile() } if ((read(gnhfp->fd, (genericptr_t) savename, sizeof savename) != sizeof savename) + || (read(gnhfp->fd, (genericptr_t) &indicator, sizeof indicator) + != sizeof indicator) + || (read(gnhfp->fd, (genericptr_t) &filecmc, sizeof filecmc) + != sizeof filecmc) || (read(gnhfp->fd, (genericptr_t) &version_data, sizeof version_data) != sizeof version_data) || (read(gnhfp->fd, (genericptr_t) &sfi, sizeof sfi) != sizeof sfi) @@ -3997,6 +4041,7 @@ recover_savefile() } /* save file should contain: + * format indicator and cmc * version info * savefile info * player name @@ -4004,6 +4049,22 @@ recover_savefile() * (non-level-based) game state * other levels */ + + /* + * Things are different now. We could be in a situation + * where the default save file format is not structlevel. + * self-recover is currently written to use copy_bytes() + * to move content from the level files into the savefile. + * Until the code is updated to use something other than + * copy_bytes, what we need to do is force the recovery + * save to be structlevel, finish creating it, then read + * it back in. The save after that can be fieldlevel again. + * + * Set a flag for the savefile routines to know the + * circumstances and act accordingly: + * g.program_state.in_self_recover + */ + g.program_state.in_self_recover = TRUE; set_savefile_name(TRUE); snhfp = create_savefile(); if (!snhfp) { @@ -4021,47 +4082,66 @@ recover_savefile() return FALSE; } - if (write(snhfp->fd, (genericptr_t) &version_data, sizeof version_data) - != sizeof version_data) { - raw_printf("\nError writing %s; recovery failed.", g.SAVEF); - close_nhfile(gnhfp); - close_nhfile(snhfp); - close_nhfile(lnhfp); - delete_savefile(); - return FALSE; + /* + * Our savefile output format might _not_ be structlevel. + * We have to check and use the correct output routine here. + */ + /*store_formatindicator(snhfp); */ + store_version(snhfp); +#if 0 + if (snhfp->structlevel) { + if (write(snhfp->fd, (genericptr_t) &version_data, sizeof version_data) + != sizeof version_data) + savewrite_failure = "version_info"; } - - if (write(snhfp->fd, (genericptr_t) &sfi, sizeof sfi) != sizeof sfi) { - raw_printf("\nError writing %s; recovery failed (savefile_info).\n", - g.SAVEF); - close_nhfile(gnhfp); - close_nhfile(snhfp); - close_nhfile(lnhfp); - delete_savefile(); - return FALSE; + if (snhfp->fieldlevel) { + sfo_version_info(snhfp, (struct version_info *) &version_data, + "version", "version_info", 1); + savewrite_failure = (const char *) 0; } + if (savewrite_failure) + goto cleanup; +#endif - if (write(snhfp->fd, (genericptr_t) &pltmpsiz, sizeof pltmpsiz) - != sizeof pltmpsiz) { - raw_printf("Error writing %s; recovery failed (player name size).\n", - g.SAVEF); - close_nhfile(gnhfp); - close_nhfile(snhfp); - close_nhfile(lnhfp); - delete_savefile(); - return FALSE; + if (snhfp->structlevel) { + if (write(snhfp->fd, (genericptr_t) &sfi, sizeof sfi) != sizeof sfi) + savewrite_failure = "savefileinfo"; } - - if (write(snhfp->fd, (genericptr_t) &tmpplbuf, pltmpsiz) != pltmpsiz) { - raw_printf("Error writing %s; recovery failed (player name).\n", - g.SAVEF); - close_nhfile(gnhfp); - close_nhfile(snhfp); - close_nhfile(lnhfp); - delete_savefile(); - return FALSE; + if (snhfp->fieldlevel) { + sfo_savefile_info(snhfp, &sfsaveinfo, "savefileinfo", "savefile_info", 1); + savewrite_failure = (const char *) 0; } + if (savewrite_failure) + goto cleanup; + if (snhfp->structlevel) { + if (write(snhfp->fd, (genericptr_t) &pltmpsiz, sizeof pltmpsiz) + != sizeof pltmpsiz) + savewrite_failure = "player name size"; + } + if (snhfp->fieldlevel) { + sfo_int(snhfp, &pltmpsiz, "plname", "plname_size", 1); + savewrite_failure = (const char *) 0; + } + if (savewrite_failure) + goto cleanup; + + if (snhfp->structlevel) { + if (write(snhfp->fd, (genericptr_t) &tmpplbuf, pltmpsiz) != pltmpsiz) + savewrite_failure = "player name"; + } + if (snhfp->fieldlevel) { + sfo_str(snhfp, tmpplbuf, "plname", "tmpplbuf", pltmpsiz); + savewrite_failure = (const char *) 0; + } + if (savewrite_failure) + goto cleanup; + + /* + * copy_bytes isn't good enough anymore. + * We could be reading from a structlevel file but + * writing into a fieldlevel save file. Yikes! + */ if (!copy_bytes(lnhfp->fd, snhfp->fd)) { close_nhfile(gnhfp); close_nhfile(snhfp); @@ -4116,6 +4196,20 @@ recover_savefile() (void) unlink(fq_lock); } } + cleanup: + if (savewrite_failure) { + raw_printf("\nError writing %s; recovery failed (%s).\n", + g.SAVEF, savewrite_failure); + close_nhfile(gnhfp); + close_nhfile(snhfp); + close_nhfile(lnhfp); + g.program_state.in_self_recover = FALSE; + delete_savefile(); + return FALSE; + } + /* we don't clear g.program_state.in_self_recover here, we + leave it as a flag to reload the structlevel savefile + in the caller. The caller should then clear it. */ return TRUE; } diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc index a4449bf76..484f5576e 100644 --- a/sys/winnt/Makefile.msc +++ b/sys/winnt/Makefile.msc @@ -2027,6 +2027,7 @@ $(O)vision.o: vision.c $(HACK_H) $(INCL)\vis_tab.h $(O)weapon.o: weapon.c $(HACK_H) $(O)were.o: were.c $(HACK_H) $(O)wield.o: wield.c $(HACK_H) +$(O)windmain.o: $(MSWSYS)\windmain.c $(HACK_H) #$(O)windows.o: windows.c $(HACK_H) $(INCL)\wingem.h $(INCL)\winGnome.h $(O)wizard.o: wizard.c $(HACK_H) $(INCL)\qtext.h $(O)worm.o: worm.c $(HACK_H) $(INCL)\lev.h diff --git a/sys/winnt/windmain.c b/sys/winnt/windmain.c index 56b4e3c6f..9b2e8f4be 100644 --- a/sys/winnt/windmain.c +++ b/sys/winnt/windmain.c @@ -503,6 +503,10 @@ attempt_restore: } } } + if (g.program_state.in_self_recover) { + g.program_state.in_self_recover = FALSE; + set_savefile_name(TRUE); + } } if (!resuming) {