147082Smckusick /*- 247082Smckusick * Copyright (c) 1980 The Regents of the University of California. 347082Smckusick * All rights reserved. 447082Smckusick * 547082Smckusick * %sccs.include.redist.c% 622036Sdist */ 712589Smckusick 822036Sdist #ifndef lint 9*50493Smckusick static char sccsid[] = "@(#)itime.c 5.8 (Berkeley) 07/23/91"; 1046590Storek #endif /* not lint */ 1122036Sdist 1246795Sbostic #include <sys/param.h> 1346795Sbostic #include <ufs/dinode.h> 1446795Sbostic #include <fcntl.h> 1546795Sbostic #include <protocols/dumprestore.h> 1646795Sbostic #include <errno.h> 1746795Sbostic #include <stdio.h> 1846795Sbostic #ifdef __STDC__ 1946795Sbostic #include <time.h> 2046795Sbostic #include <unistd.h> 2146795Sbostic #include <stdlib.h> 2246795Sbostic #include <string.h> 2346795Sbostic #endif 241422Sroot #include "dump.h" 251422Sroot 2646791Smckusick struct dumpdates **ddatev = 0; 2746791Smckusick int nddates = 0; 2846791Smckusick int ddates_in = 0; 2946791Smckusick struct dumptime *dthead = 0; 301422Sroot 3146791Smckusick void readdumptimes(); 3246590Storek int getrecord(); 3346791Smckusick int makedumpdate(); 3446590Storek 3546791Smckusick static void dumprecout(); 3646590Storek 3746590Storek void 3846791Smckusick initdumptimes() 391422Sroot { 4028858Smckusick FILE *df; 411422Sroot 4246791Smckusick if ((df = fopen(dumpdates, "r")) == NULL) { 43*50493Smckusick if (errno != ENOENT) { 44*50493Smckusick quit("cannot read %s: %s\n", dumpdates, 45*50493Smckusick strerror(errno)); 46*50493Smckusick /* NOTREACHED */ 4746590Storek } 48*50493Smckusick /* 49*50493Smckusick * Dumpdates does not exist, make an empty one. 50*50493Smckusick */ 51*50493Smckusick msg("WARNING: no file `%s', making an empty one\n", dumpdates); 52*50493Smckusick if ((df = fopen(dumpdates, "w")) == NULL) { 53*50493Smckusick quit("cannot create %s: %s\n", dumpdates, 54*50493Smckusick strerror(errno)); 55*50493Smckusick /* NOTREACHED */ 56*50493Smckusick } 57*50493Smckusick (void) fclose(df); 58*50493Smckusick if ((df = fopen(dumpdates, "r")) == NULL) { 59*50493Smckusick quit("cannot read %s even after creating it: %s\n", 60*50493Smckusick dumpdates, strerror(errno)); 61*50493Smckusick /* NOTREACHED */ 62*50493Smckusick } 6312589Smckusick } 6428858Smckusick (void) flock(fileno(df), LOCK_SH); 6546791Smckusick readdumptimes(df); 6628858Smckusick fclose(df); 6728858Smckusick } 6828858Smckusick 6946590Storek void 7046791Smckusick readdumptimes(df) 7128858Smckusick FILE *df; 7228858Smckusick { 7346791Smckusick register int i; 7446791Smckusick register struct dumptime *dtwalk; 7528858Smckusick 7628858Smckusick for (;;) { 7746791Smckusick dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime)); 7846791Smckusick if (getrecord(df, &(dtwalk->dt_value)) < 0) 7928858Smckusick break; 8046791Smckusick nddates++; 8146791Smckusick dtwalk->dt_next = dthead; 8246791Smckusick dthead = dtwalk; 831422Sroot } 841422Sroot 8546791Smckusick ddates_in = 1; 861422Sroot /* 871422Sroot * arrayify the list, leaving enough room for the additional 8846791Smckusick * record that we may have to add to the ddate structure 891422Sroot */ 9046791Smckusick ddatev = (struct dumpdates **) 9146791Smckusick calloc(nddates + 1, sizeof (struct dumpdates *)); 9246791Smckusick dtwalk = dthead; 9346791Smckusick for (i = nddates - 1; i >= 0; i--, dtwalk = dtwalk->dt_next) 9446791Smckusick ddatev[i] = &dtwalk->dt_value; 951422Sroot } 961422Sroot 9746590Storek void 9846791Smckusick getdumptime() 991422Sroot { 10046791Smckusick register struct dumpdates *ddp; 10146791Smckusick register int i; 10246791Smckusick char *fname; 1031422Sroot 1041422Sroot fname = disk; 1051422Sroot #ifdef FDEBUG 10646791Smckusick msg("Looking for name %s in dumpdates = %s for level = %c\n", 10746791Smckusick fname, dumpdates, level); 1081422Sroot #endif 1091422Sroot spcl.c_ddate = 0; 11046791Smckusick lastlevel = '0'; 1111422Sroot 11246791Smckusick initdumptimes(); 1131422Sroot /* 1141422Sroot * Go find the entry with the same name for a lower increment 1151422Sroot * and older date 1161422Sroot */ 11746791Smckusick ITITERATE(i, ddp) { 11846791Smckusick if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0) 1191422Sroot continue; 12046791Smckusick if (ddp->dd_level >= level) 1211422Sroot continue; 12246791Smckusick if (ddp->dd_ddate <= spcl.c_ddate) 1231422Sroot continue; 12446791Smckusick spcl.c_ddate = ddp->dd_ddate; 12546791Smckusick lastlevel = ddp->dd_level; 12628858Smckusick } 1271422Sroot } 1281422Sroot 12946590Storek void 13046791Smckusick putdumptime() 1311422Sroot { 13246791Smckusick FILE *df; 13346791Smckusick register struct dumpdates *dtwalk; 13446791Smckusick register int i; 13546791Smckusick int fd; 13646791Smckusick char *fname; 1371422Sroot 1381422Sroot if(uflag == 0) 1391422Sroot return; 14046791Smckusick if ((df = fopen(dumpdates, "r+")) == NULL) 14146791Smckusick quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno)); 14228858Smckusick fd = fileno(df); 14313151Ssam (void) flock(fd, LOCK_EX); 1441422Sroot fname = disk; 14546791Smckusick free(ddatev); 14646791Smckusick ddatev = 0; 14746791Smckusick nddates = 0; 14846791Smckusick dthead = 0; 14946791Smckusick ddates_in = 0; 15046791Smckusick readdumptimes(df); 15146590Storek if (fseek(df, 0L, 0) < 0) 15246590Storek quit("fseek: %s\n", strerror(errno)); 1531422Sroot spcl.c_ddate = 0; 15446791Smckusick ITITERATE(i, dtwalk) { 15546791Smckusick if (strncmp(fname, dtwalk->dd_name, 15646791Smckusick sizeof (dtwalk->dd_name)) != 0) 1571422Sroot continue; 15846791Smckusick if (dtwalk->dd_level != level) 1591422Sroot continue; 1601422Sroot goto found; 1611422Sroot } 1621422Sroot /* 1631422Sroot * construct the new upper bound; 1641422Sroot * Enough room has been allocated. 1651422Sroot */ 16646791Smckusick dtwalk = ddatev[nddates] = 16746791Smckusick (struct dumpdates *)calloc(1, sizeof(struct dumpdates)); 16846791Smckusick nddates += 1; 1691422Sroot found: 17046791Smckusick (void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name)); 17146791Smckusick dtwalk->dd_level = level; 17246791Smckusick dtwalk->dd_ddate = spcl.c_date; 1731422Sroot 17446791Smckusick ITITERATE(i, dtwalk) { 17546791Smckusick dumprecout(df, dtwalk); 1761422Sroot } 17746590Storek if (fflush(df)) 17846791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 17946590Storek if (ftruncate(fd, ftell(df))) 18046791Smckusick quit("ftruncate (%s): %s\n", dumpdates, strerror(errno)); 18112589Smckusick (void) fclose(df); 18246791Smckusick msg("level %c dump on %s", level, 18346791Smckusick spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date)); 1841422Sroot } 1851422Sroot 18646590Storek static void 18746791Smckusick dumprecout(file, what) 18846791Smckusick FILE *file; 18946791Smckusick struct dumpdates *what; 1901422Sroot { 19146590Storek 19246590Storek if (fprintf(file, DUMPOUTFMT, 19346791Smckusick what->dd_name, 19446791Smckusick what->dd_level, 19546791Smckusick ctime(&what->dd_ddate)) < 0) 19646791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 1971422Sroot } 1981422Sroot 1991422Sroot int recno; 20046590Storek int 20146791Smckusick getrecord(df, ddatep) 20246791Smckusick FILE *df; 20346791Smckusick struct dumpdates *ddatep; 2041422Sroot { 20546791Smckusick char buf[BUFSIZ]; 2061422Sroot 2071422Sroot recno = 0; 2081422Sroot if ( (fgets(buf, BUFSIZ, df)) != buf) 2091422Sroot return(-1); 2101422Sroot recno++; 21146791Smckusick if (makedumpdate(ddatep, buf) < 0) 2121422Sroot msg("Unknown intermediate format in %s, line %d\n", 21346791Smckusick dumpdates, recno); 2141422Sroot 2151422Sroot #ifdef FDEBUG 21646791Smckusick msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level, 21746791Smckusick ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate)); 2181422Sroot #endif 2191422Sroot return(0); 2201422Sroot } 2211422Sroot 2221422Sroot time_t unctime(); 2231422Sroot 22446590Storek int 22546791Smckusick makedumpdate(ddp, buf) 22646791Smckusick struct dumpdates *ddp; 22746791Smckusick char *buf; 2281422Sroot { 22946791Smckusick char un_buf[128]; 2301422Sroot 23146791Smckusick sscanf(buf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf); 23246791Smckusick ddp->dd_ddate = unctime(un_buf); 23346791Smckusick if (ddp->dd_ddate < 0) 2341422Sroot return(-1); 2351422Sroot return(0); 2361422Sroot } 237