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*54040Smckusick static char sccsid[] = "@(#)itime.c 5.14 (Berkeley) 06/18/92"; 1046590Storek #endif /* not lint */ 1122036Sdist 1250494Smckusick #ifdef sunos 1350494Smckusick #include <stdio.h> 1450494Smckusick #include <ctype.h> 1546795Sbostic #include <sys/param.h> 1650494Smckusick #include <sys/stat.h> 1750494Smckusick #include <ufs/fs.h> 1850494Smckusick #else 1950494Smckusick #include <sys/param.h> 2053656Smckusick #include <sys/time.h> 21*54040Smckusick #endif 2251605Sbostic #include <ufs/ufs/dinode.h> 2346795Sbostic #include <fcntl.h> 2446795Sbostic #include <protocols/dumprestore.h> 2546795Sbostic #include <errno.h> 2646795Sbostic #include <stdio.h> 2746795Sbostic #ifdef __STDC__ 2846795Sbostic #include <time.h> 2946795Sbostic #include <unistd.h> 3046795Sbostic #include <stdlib.h> 3146795Sbostic #include <string.h> 3246795Sbostic #endif 331422Sroot #include "dump.h" 341422Sroot 3546791Smckusick struct dumpdates **ddatev = 0; 3646791Smckusick int nddates = 0; 3746791Smckusick int ddates_in = 0; 3846791Smckusick struct dumptime *dthead = 0; 391422Sroot 4046791Smckusick void readdumptimes(); 4146590Storek int getrecord(); 4246791Smckusick int makedumpdate(); 4346590Storek 4446791Smckusick static void dumprecout(); 4546590Storek 4646590Storek void 4746791Smckusick initdumptimes() 481422Sroot { 4928858Smckusick FILE *df; 501422Sroot 5146791Smckusick if ((df = fopen(dumpdates, "r")) == NULL) { 5250493Smckusick if (errno != ENOENT) { 5350493Smckusick quit("cannot read %s: %s\n", dumpdates, 5450493Smckusick strerror(errno)); 5550493Smckusick /* NOTREACHED */ 5646590Storek } 5750493Smckusick /* 5850493Smckusick * Dumpdates does not exist, make an empty one. 5950493Smckusick */ 6050493Smckusick msg("WARNING: no file `%s', making an empty one\n", dumpdates); 6150493Smckusick if ((df = fopen(dumpdates, "w")) == NULL) { 6250493Smckusick quit("cannot create %s: %s\n", dumpdates, 6350493Smckusick strerror(errno)); 6450493Smckusick /* NOTREACHED */ 6550493Smckusick } 6650493Smckusick (void) fclose(df); 6750493Smckusick if ((df = fopen(dumpdates, "r")) == NULL) { 6850493Smckusick quit("cannot read %s even after creating it: %s\n", 6950493Smckusick dumpdates, strerror(errno)); 7050493Smckusick /* NOTREACHED */ 7150493Smckusick } 7212589Smckusick } 7328858Smckusick (void) flock(fileno(df), LOCK_SH); 7446791Smckusick readdumptimes(df); 75*54040Smckusick (void) fclose(df); 7628858Smckusick } 7728858Smckusick 7846590Storek void 7946791Smckusick readdumptimes(df) 8028858Smckusick FILE *df; 8128858Smckusick { 8246791Smckusick register int i; 8346791Smckusick register struct dumptime *dtwalk; 8428858Smckusick 8528858Smckusick for (;;) { 8646791Smckusick dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime)); 8746791Smckusick if (getrecord(df, &(dtwalk->dt_value)) < 0) 8828858Smckusick break; 8946791Smckusick nddates++; 9046791Smckusick dtwalk->dt_next = dthead; 9146791Smckusick dthead = dtwalk; 921422Sroot } 931422Sroot 9446791Smckusick ddates_in = 1; 951422Sroot /* 961422Sroot * arrayify the list, leaving enough room for the additional 9746791Smckusick * record that we may have to add to the ddate structure 981422Sroot */ 9946791Smckusick ddatev = (struct dumpdates **) 100*54040Smckusick calloc((unsigned) (nddates + 1), sizeof (struct dumpdates *)); 10146791Smckusick dtwalk = dthead; 10246791Smckusick for (i = nddates - 1; i >= 0; i--, dtwalk = dtwalk->dt_next) 10346791Smckusick ddatev[i] = &dtwalk->dt_value; 1041422Sroot } 1051422Sroot 10646590Storek void 10746791Smckusick getdumptime() 1081422Sroot { 10946791Smckusick register struct dumpdates *ddp; 11046791Smckusick register int i; 11146791Smckusick char *fname; 1121422Sroot 1131422Sroot fname = disk; 1141422Sroot #ifdef FDEBUG 11546791Smckusick msg("Looking for name %s in dumpdates = %s for level = %c\n", 11646791Smckusick fname, dumpdates, level); 1171422Sroot #endif 1181422Sroot spcl.c_ddate = 0; 11946791Smckusick lastlevel = '0'; 1201422Sroot 12146791Smckusick initdumptimes(); 1221422Sroot /* 1231422Sroot * Go find the entry with the same name for a lower increment 1241422Sroot * and older date 1251422Sroot */ 12646791Smckusick ITITERATE(i, ddp) { 12746791Smckusick if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0) 1281422Sroot continue; 12946791Smckusick if (ddp->dd_level >= level) 1301422Sroot continue; 13146791Smckusick if (ddp->dd_ddate <= spcl.c_ddate) 1321422Sroot continue; 13346791Smckusick spcl.c_ddate = ddp->dd_ddate; 13446791Smckusick lastlevel = ddp->dd_level; 13528858Smckusick } 1361422Sroot } 1371422Sroot 13846590Storek void 13946791Smckusick putdumptime() 1401422Sroot { 14146791Smckusick FILE *df; 14246791Smckusick register struct dumpdates *dtwalk; 14346791Smckusick register int i; 14446791Smckusick int fd; 14546791Smckusick char *fname; 1461422Sroot 1471422Sroot if(uflag == 0) 1481422Sroot return; 14946791Smckusick if ((df = fopen(dumpdates, "r+")) == NULL) 15046791Smckusick quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno)); 15128858Smckusick fd = fileno(df); 15213151Ssam (void) flock(fd, LOCK_EX); 1531422Sroot fname = disk; 154*54040Smckusick free((char *)ddatev); 15546791Smckusick ddatev = 0; 15646791Smckusick nddates = 0; 15746791Smckusick dthead = 0; 15846791Smckusick ddates_in = 0; 15946791Smckusick readdumptimes(df); 16046590Storek if (fseek(df, 0L, 0) < 0) 16146590Storek quit("fseek: %s\n", strerror(errno)); 1621422Sroot spcl.c_ddate = 0; 16346791Smckusick ITITERATE(i, dtwalk) { 16446791Smckusick if (strncmp(fname, dtwalk->dd_name, 16546791Smckusick sizeof (dtwalk->dd_name)) != 0) 1661422Sroot continue; 16746791Smckusick if (dtwalk->dd_level != level) 1681422Sroot continue; 1691422Sroot goto found; 1701422Sroot } 1711422Sroot /* 1721422Sroot * construct the new upper bound; 1731422Sroot * Enough room has been allocated. 1741422Sroot */ 17546791Smckusick dtwalk = ddatev[nddates] = 17652847Sleres (struct dumpdates *)calloc(1, sizeof (struct dumpdates)); 17746791Smckusick nddates += 1; 1781422Sroot found: 17946791Smckusick (void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name)); 18046791Smckusick dtwalk->dd_level = level; 18146791Smckusick dtwalk->dd_ddate = spcl.c_date; 1821422Sroot 18346791Smckusick ITITERATE(i, dtwalk) { 18446791Smckusick dumprecout(df, dtwalk); 1851422Sroot } 18646590Storek if (fflush(df)) 18746791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 18846590Storek if (ftruncate(fd, ftell(df))) 18946791Smckusick quit("ftruncate (%s): %s\n", dumpdates, strerror(errno)); 19012589Smckusick (void) fclose(df); 19146791Smckusick msg("level %c dump on %s", level, 19246791Smckusick spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date)); 1931422Sroot } 1941422Sroot 19546590Storek static void 19646791Smckusick dumprecout(file, what) 19746791Smckusick FILE *file; 19846791Smckusick struct dumpdates *what; 1991422Sroot { 20046590Storek 20146590Storek if (fprintf(file, DUMPOUTFMT, 20246791Smckusick what->dd_name, 20346791Smckusick what->dd_level, 20446791Smckusick ctime(&what->dd_ddate)) < 0) 20546791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 2061422Sroot } 2071422Sroot 2081422Sroot int recno; 20946590Storek int 21046791Smckusick getrecord(df, ddatep) 21146791Smckusick FILE *df; 21246791Smckusick struct dumpdates *ddatep; 2131422Sroot { 21452846Sleres char tbuf[BUFSIZ]; 2151422Sroot 2161422Sroot recno = 0; 21752847Sleres if ( (fgets(tbuf, sizeof (tbuf), df)) != tbuf) 2181422Sroot return(-1); 2191422Sroot recno++; 22052846Sleres if (makedumpdate(ddatep, tbuf) < 0) 2211422Sroot msg("Unknown intermediate format in %s, line %d\n", 22246791Smckusick dumpdates, recno); 2231422Sroot 2241422Sroot #ifdef FDEBUG 22546791Smckusick msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level, 22646791Smckusick ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate)); 2271422Sroot #endif 2281422Sroot return(0); 2291422Sroot } 2301422Sroot 2311422Sroot time_t unctime(); 2321422Sroot 23346590Storek int 23452846Sleres makedumpdate(ddp, tbuf) 23546791Smckusick struct dumpdates *ddp; 23652846Sleres char *tbuf; 2371422Sroot { 23846791Smckusick char un_buf[128]; 2391422Sroot 240*54040Smckusick (void) sscanf(tbuf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf); 24146791Smckusick ddp->dd_ddate = unctime(un_buf); 24246791Smckusick if (ddp->dd_ddate < 0) 2431422Sroot return(-1); 2441422Sroot return(0); 2451422Sroot } 246