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*57725Smckusick static char sccsid[] = "@(#)itime.c 5.16 (Berkeley) 01/25/93"; 1046590Storek #endif /* not lint */ 1122036Sdist 12*57725Smckusick #include <sys/param.h> 13*57725Smckusick #include <sys/time.h> 1450494Smckusick #ifdef sunos 15*57725Smckusick #include <sys/vnode.h> 16*57725Smckusick 17*57725Smckusick #include <ufs/fsdir.h> 18*57725Smckusick #include <ufs/inode.h> 1950494Smckusick #include <ufs/fs.h> 2050494Smckusick #else 21*57725Smckusick #include <ufs/ufs/dinode.h> 2254040Smckusick #endif 23*57725Smckusick 2446795Sbostic #include <protocols/dumprestore.h> 25*57725Smckusick 2646795Sbostic #include <errno.h> 27*57725Smckusick #include <fcntl.h> 2846795Sbostic #include <stdio.h> 2946795Sbostic #ifdef __STDC__ 3046795Sbostic #include <stdlib.h> 3146795Sbostic #include <string.h> 32*57725Smckusick #include <unistd.h> 3346795Sbostic #endif 34*57725Smckusick 351422Sroot #include "dump.h" 361422Sroot 3746791Smckusick struct dumpdates **ddatev = 0; 3846791Smckusick int nddates = 0; 3946791Smckusick int ddates_in = 0; 4046791Smckusick struct dumptime *dthead = 0; 411422Sroot 42*57725Smckusick static void dumprecout __P((FILE *, struct dumpdates *)); 43*57725Smckusick static int getrecord __P((FILE *, struct dumpdates *)); 44*57725Smckusick static int makedumpdate __P((struct dumpdates *, char *)); 45*57725Smckusick static void readdumptimes __P((FILE *)); 4646590Storek 47*57725Smckusick #ifdef COMPAT 48*57725Smckusick extern char *calloc(); 49*57725Smckusick #endif 5046590Storek 5146590Storek void 5246791Smckusick initdumptimes() 531422Sroot { 5428858Smckusick FILE *df; 551422Sroot 5646791Smckusick if ((df = fopen(dumpdates, "r")) == NULL) { 5750493Smckusick if (errno != ENOENT) { 5850493Smckusick quit("cannot read %s: %s\n", dumpdates, 5950493Smckusick strerror(errno)); 6050493Smckusick /* NOTREACHED */ 6146590Storek } 6250493Smckusick /* 6350493Smckusick * Dumpdates does not exist, make an empty one. 6450493Smckusick */ 6550493Smckusick msg("WARNING: no file `%s', making an empty one\n", dumpdates); 6650493Smckusick if ((df = fopen(dumpdates, "w")) == NULL) { 6750493Smckusick quit("cannot create %s: %s\n", dumpdates, 6850493Smckusick strerror(errno)); 6950493Smckusick /* NOTREACHED */ 7050493Smckusick } 7150493Smckusick (void) fclose(df); 7250493Smckusick if ((df = fopen(dumpdates, "r")) == NULL) { 7350493Smckusick quit("cannot read %s even after creating it: %s\n", 7450493Smckusick dumpdates, strerror(errno)); 7550493Smckusick /* NOTREACHED */ 7650493Smckusick } 7712589Smckusick } 7828858Smckusick (void) flock(fileno(df), LOCK_SH); 7946791Smckusick readdumptimes(df); 8054040Smckusick (void) fclose(df); 8128858Smckusick } 8228858Smckusick 83*57725Smckusick static void 8446791Smckusick readdumptimes(df) 8528858Smckusick FILE *df; 8628858Smckusick { 8746791Smckusick register int i; 8846791Smckusick register struct dumptime *dtwalk; 8928858Smckusick 9028858Smckusick for (;;) { 9146791Smckusick dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime)); 9246791Smckusick if (getrecord(df, &(dtwalk->dt_value)) < 0) 9328858Smckusick break; 9446791Smckusick nddates++; 9546791Smckusick dtwalk->dt_next = dthead; 9646791Smckusick dthead = dtwalk; 971422Sroot } 981422Sroot 9946791Smckusick ddates_in = 1; 1001422Sroot /* 1011422Sroot * arrayify the list, leaving enough room for the additional 10246791Smckusick * record that we may have to add to the ddate structure 1031422Sroot */ 10446791Smckusick ddatev = (struct dumpdates **) 10554040Smckusick calloc((unsigned) (nddates + 1), sizeof (struct dumpdates *)); 10646791Smckusick dtwalk = dthead; 10746791Smckusick for (i = nddates - 1; i >= 0; i--, dtwalk = dtwalk->dt_next) 10846791Smckusick ddatev[i] = &dtwalk->dt_value; 1091422Sroot } 1101422Sroot 11146590Storek void 11246791Smckusick getdumptime() 1131422Sroot { 11446791Smckusick register struct dumpdates *ddp; 11546791Smckusick register int i; 11646791Smckusick char *fname; 1171422Sroot 1181422Sroot fname = disk; 1191422Sroot #ifdef FDEBUG 12046791Smckusick msg("Looking for name %s in dumpdates = %s for level = %c\n", 12146791Smckusick fname, dumpdates, level); 1221422Sroot #endif 1231422Sroot spcl.c_ddate = 0; 12446791Smckusick lastlevel = '0'; 1251422Sroot 12646791Smckusick initdumptimes(); 1271422Sroot /* 1281422Sroot * Go find the entry with the same name for a lower increment 1291422Sroot * and older date 1301422Sroot */ 13146791Smckusick ITITERATE(i, ddp) { 13246791Smckusick if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0) 1331422Sroot continue; 13446791Smckusick if (ddp->dd_level >= level) 1351422Sroot continue; 13646791Smckusick if (ddp->dd_ddate <= spcl.c_ddate) 1371422Sroot continue; 13846791Smckusick spcl.c_ddate = ddp->dd_ddate; 13946791Smckusick lastlevel = ddp->dd_level; 14028858Smckusick } 1411422Sroot } 1421422Sroot 14346590Storek void 14446791Smckusick putdumptime() 1451422Sroot { 14646791Smckusick FILE *df; 14746791Smckusick register struct dumpdates *dtwalk; 14846791Smckusick register int i; 14946791Smckusick int fd; 15046791Smckusick char *fname; 1511422Sroot 1521422Sroot if(uflag == 0) 1531422Sroot return; 15446791Smckusick if ((df = fopen(dumpdates, "r+")) == NULL) 15546791Smckusick quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno)); 15628858Smckusick fd = fileno(df); 15713151Ssam (void) flock(fd, LOCK_EX); 1581422Sroot fname = disk; 15954040Smckusick free((char *)ddatev); 16046791Smckusick ddatev = 0; 16146791Smckusick nddates = 0; 16246791Smckusick dthead = 0; 16346791Smckusick ddates_in = 0; 16446791Smckusick readdumptimes(df); 16546590Storek if (fseek(df, 0L, 0) < 0) 16646590Storek quit("fseek: %s\n", strerror(errno)); 1671422Sroot spcl.c_ddate = 0; 16846791Smckusick ITITERATE(i, dtwalk) { 16946791Smckusick if (strncmp(fname, dtwalk->dd_name, 17046791Smckusick sizeof (dtwalk->dd_name)) != 0) 1711422Sroot continue; 17246791Smckusick if (dtwalk->dd_level != level) 1731422Sroot continue; 1741422Sroot goto found; 1751422Sroot } 1761422Sroot /* 1771422Sroot * construct the new upper bound; 1781422Sroot * Enough room has been allocated. 1791422Sroot */ 18046791Smckusick dtwalk = ddatev[nddates] = 18152847Sleres (struct dumpdates *)calloc(1, sizeof (struct dumpdates)); 18246791Smckusick nddates += 1; 1831422Sroot found: 18446791Smckusick (void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name)); 18546791Smckusick dtwalk->dd_level = level; 18646791Smckusick dtwalk->dd_ddate = spcl.c_date; 1871422Sroot 18846791Smckusick ITITERATE(i, dtwalk) { 18946791Smckusick dumprecout(df, dtwalk); 1901422Sroot } 19146590Storek if (fflush(df)) 19246791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 19346590Storek if (ftruncate(fd, ftell(df))) 19446791Smckusick quit("ftruncate (%s): %s\n", dumpdates, strerror(errno)); 19512589Smckusick (void) fclose(df); 19646791Smckusick msg("level %c dump on %s", level, 19746791Smckusick spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date)); 1981422Sroot } 1991422Sroot 20046590Storek static void 20146791Smckusick dumprecout(file, what) 20246791Smckusick FILE *file; 20346791Smckusick struct dumpdates *what; 2041422Sroot { 20546590Storek 20646590Storek if (fprintf(file, DUMPOUTFMT, 20746791Smckusick what->dd_name, 20846791Smckusick what->dd_level, 20946791Smckusick ctime(&what->dd_ddate)) < 0) 21046791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 2111422Sroot } 2121422Sroot 2131422Sroot int recno; 214*57725Smckusick 215*57725Smckusick static int 21646791Smckusick getrecord(df, ddatep) 21746791Smckusick FILE *df; 21846791Smckusick struct dumpdates *ddatep; 2191422Sroot { 22052846Sleres char tbuf[BUFSIZ]; 2211422Sroot 2221422Sroot recno = 0; 22352847Sleres if ( (fgets(tbuf, sizeof (tbuf), df)) != tbuf) 2241422Sroot return(-1); 2251422Sroot recno++; 22652846Sleres if (makedumpdate(ddatep, tbuf) < 0) 2271422Sroot msg("Unknown intermediate format in %s, line %d\n", 22846791Smckusick dumpdates, recno); 2291422Sroot 2301422Sroot #ifdef FDEBUG 23146791Smckusick msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level, 23246791Smckusick ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate)); 2331422Sroot #endif 2341422Sroot return(0); 2351422Sroot } 2361422Sroot 237*57725Smckusick static int 23852846Sleres makedumpdate(ddp, tbuf) 23946791Smckusick struct dumpdates *ddp; 24052846Sleres char *tbuf; 2411422Sroot { 24246791Smckusick char un_buf[128]; 2431422Sroot 24454040Smckusick (void) sscanf(tbuf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf); 24546791Smckusick ddp->dd_ddate = unctime(un_buf); 24646791Smckusick if (ddp->dd_ddate < 0) 2471422Sroot return(-1); 2481422Sroot return(0); 2491422Sroot } 250