122036Sdist /* 222036Sdist * Copyright (c) 1980 Regents of the University of California. 322036Sdist * All rights reserved. The Berkeley software License Agreement 422036Sdist * specifies the terms and conditions for redistribution. 522036Sdist */ 612589Smckusick 722036Sdist #ifndef lint 8*46791Smckusick static char sccsid[] = "@(#)itime.c 5.5 (Berkeley) 02/28/91"; 946590Storek #endif /* not lint */ 1022036Sdist 111422Sroot #include "dump.h" 1212589Smckusick #include <sys/file.h> 1346590Storek #include <errno.h> 141422Sroot 15*46791Smckusick struct dumpdates **ddatev = 0; 16*46791Smckusick int nddates = 0; 17*46791Smckusick int ddates_in = 0; 18*46791Smckusick struct dumptime *dthead = 0; 191422Sroot 20*46791Smckusick void readdumptimes(); 2146590Storek int getrecord(); 22*46791Smckusick int makedumpdate(); 2346590Storek 24*46791Smckusick static void dumprecout(); 2546590Storek 2646590Storek void 27*46791Smckusick initdumptimes() 281422Sroot { 2928858Smckusick FILE *df; 301422Sroot 31*46791Smckusick if ((df = fopen(dumpdates, "r")) == NULL) { 3246590Storek if (errno == ENOENT) { 33*46791Smckusick msg("WARNING: no file `%s'\n", dumpdates); 3446590Storek return; 3546590Storek } 36*46791Smckusick quit("cannot read %s: %s\n", dumpdates, strerror(errno)); 3746590Storek /* NOTREACHED */ 3812589Smckusick } 3928858Smckusick (void) flock(fileno(df), LOCK_SH); 40*46791Smckusick readdumptimes(df); 4128858Smckusick fclose(df); 4228858Smckusick } 4328858Smckusick 4446590Storek void 45*46791Smckusick readdumptimes(df) 4628858Smckusick FILE *df; 4728858Smckusick { 48*46791Smckusick register int i; 49*46791Smckusick register struct dumptime *dtwalk; 5028858Smckusick 5128858Smckusick for (;;) { 52*46791Smckusick dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime)); 53*46791Smckusick if (getrecord(df, &(dtwalk->dt_value)) < 0) 5428858Smckusick break; 55*46791Smckusick nddates++; 56*46791Smckusick dtwalk->dt_next = dthead; 57*46791Smckusick dthead = dtwalk; 581422Sroot } 591422Sroot 60*46791Smckusick ddates_in = 1; 611422Sroot /* 621422Sroot * arrayify the list, leaving enough room for the additional 63*46791Smckusick * record that we may have to add to the ddate structure 641422Sroot */ 65*46791Smckusick ddatev = (struct dumpdates **) 66*46791Smckusick calloc(nddates + 1, sizeof (struct dumpdates *)); 67*46791Smckusick dtwalk = dthead; 68*46791Smckusick for (i = nddates - 1; i >= 0; i--, dtwalk = dtwalk->dt_next) 69*46791Smckusick ddatev[i] = &dtwalk->dt_value; 701422Sroot } 711422Sroot 7246590Storek void 73*46791Smckusick getdumptime() 741422Sroot { 75*46791Smckusick register struct dumpdates *ddp; 76*46791Smckusick register int i; 77*46791Smckusick char *fname; 781422Sroot 791422Sroot fname = disk; 801422Sroot #ifdef FDEBUG 81*46791Smckusick msg("Looking for name %s in dumpdates = %s for level = %c\n", 82*46791Smckusick fname, dumpdates, level); 831422Sroot #endif 841422Sroot spcl.c_ddate = 0; 85*46791Smckusick lastlevel = '0'; 861422Sroot 87*46791Smckusick initdumptimes(); 881422Sroot /* 891422Sroot * Go find the entry with the same name for a lower increment 901422Sroot * and older date 911422Sroot */ 92*46791Smckusick ITITERATE(i, ddp) { 93*46791Smckusick if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0) 941422Sroot continue; 95*46791Smckusick if (ddp->dd_level >= level) 961422Sroot continue; 97*46791Smckusick if (ddp->dd_ddate <= spcl.c_ddate) 981422Sroot continue; 99*46791Smckusick spcl.c_ddate = ddp->dd_ddate; 100*46791Smckusick lastlevel = ddp->dd_level; 10128858Smckusick } 1021422Sroot } 1031422Sroot 10446590Storek void 105*46791Smckusick putdumptime() 1061422Sroot { 107*46791Smckusick FILE *df; 108*46791Smckusick register struct dumpdates *dtwalk; 109*46791Smckusick register int i; 110*46791Smckusick int fd; 111*46791Smckusick char *fname; 1121422Sroot 1131422Sroot if(uflag == 0) 1141422Sroot return; 115*46791Smckusick if ((df = fopen(dumpdates, "r+")) == NULL) 116*46791Smckusick quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno)); 11728858Smckusick fd = fileno(df); 11813151Ssam (void) flock(fd, LOCK_EX); 1191422Sroot fname = disk; 120*46791Smckusick free(ddatev); 121*46791Smckusick ddatev = 0; 122*46791Smckusick nddates = 0; 123*46791Smckusick dthead = 0; 124*46791Smckusick ddates_in = 0; 125*46791Smckusick readdumptimes(df); 12646590Storek if (fseek(df, 0L, 0) < 0) 12746590Storek quit("fseek: %s\n", strerror(errno)); 1281422Sroot spcl.c_ddate = 0; 129*46791Smckusick ITITERATE(i, dtwalk) { 130*46791Smckusick if (strncmp(fname, dtwalk->dd_name, 131*46791Smckusick sizeof (dtwalk->dd_name)) != 0) 1321422Sroot continue; 133*46791Smckusick if (dtwalk->dd_level != level) 1341422Sroot continue; 1351422Sroot goto found; 1361422Sroot } 1371422Sroot /* 1381422Sroot * construct the new upper bound; 1391422Sroot * Enough room has been allocated. 1401422Sroot */ 141*46791Smckusick dtwalk = ddatev[nddates] = 142*46791Smckusick (struct dumpdates *)calloc(1, sizeof(struct dumpdates)); 143*46791Smckusick nddates += 1; 1441422Sroot found: 145*46791Smckusick (void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name)); 146*46791Smckusick dtwalk->dd_level = level; 147*46791Smckusick dtwalk->dd_ddate = spcl.c_date; 1481422Sroot 149*46791Smckusick ITITERATE(i, dtwalk) { 150*46791Smckusick dumprecout(df, dtwalk); 1511422Sroot } 15246590Storek if (fflush(df)) 153*46791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 15446590Storek if (ftruncate(fd, ftell(df))) 155*46791Smckusick quit("ftruncate (%s): %s\n", dumpdates, strerror(errno)); 15612589Smckusick (void) fclose(df); 157*46791Smckusick msg("level %c dump on %s", level, 158*46791Smckusick spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date)); 1591422Sroot } 1601422Sroot 16146590Storek static void 162*46791Smckusick dumprecout(file, what) 163*46791Smckusick FILE *file; 164*46791Smckusick struct dumpdates *what; 1651422Sroot { 16646590Storek 16746590Storek if (fprintf(file, DUMPOUTFMT, 168*46791Smckusick what->dd_name, 169*46791Smckusick what->dd_level, 170*46791Smckusick ctime(&what->dd_ddate)) < 0) 171*46791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 1721422Sroot } 1731422Sroot 1741422Sroot int recno; 17546590Storek int 176*46791Smckusick getrecord(df, ddatep) 177*46791Smckusick FILE *df; 178*46791Smckusick struct dumpdates *ddatep; 1791422Sroot { 180*46791Smckusick char buf[BUFSIZ]; 1811422Sroot 1821422Sroot recno = 0; 1831422Sroot if ( (fgets(buf, BUFSIZ, df)) != buf) 1841422Sroot return(-1); 1851422Sroot recno++; 186*46791Smckusick if (makedumpdate(ddatep, buf) < 0) 1871422Sroot msg("Unknown intermediate format in %s, line %d\n", 188*46791Smckusick dumpdates, recno); 1891422Sroot 1901422Sroot #ifdef FDEBUG 191*46791Smckusick msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level, 192*46791Smckusick ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate)); 1931422Sroot #endif 1941422Sroot return(0); 1951422Sroot } 1961422Sroot 1971422Sroot time_t unctime(); 1981422Sroot 19946590Storek int 200*46791Smckusick makedumpdate(ddp, buf) 201*46791Smckusick struct dumpdates *ddp; 202*46791Smckusick char *buf; 2031422Sroot { 204*46791Smckusick char un_buf[128]; 2051422Sroot 206*46791Smckusick sscanf(buf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf); 207*46791Smckusick ddp->dd_ddate = unctime(un_buf); 208*46791Smckusick if (ddp->dd_ddate < 0) 2091422Sroot return(-1); 2101422Sroot return(0); 2111422Sroot } 212