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*52847Sleres static char sccsid[] = "@(#)itime.c 5.12 (Berkeley) 03/05/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 <sys/time.h> 1850494Smckusick #include <sys/dir.h> 1950494Smckusick #include <sys/vnode.h> 2050494Smckusick #include <ufs/inode.h> 2150494Smckusick #include <ufs/fs.h> 2250494Smckusick #else 2350494Smckusick #include <sys/param.h> 2451605Sbostic #include <ufs/ufs/dinode.h> 2550494Smckusick #endif 2646795Sbostic #include <fcntl.h> 2746795Sbostic #include <protocols/dumprestore.h> 2846795Sbostic #include <errno.h> 2946795Sbostic #include <stdio.h> 3046795Sbostic #ifdef __STDC__ 3146795Sbostic #include <time.h> 3246795Sbostic #include <unistd.h> 3346795Sbostic #include <stdlib.h> 3446795Sbostic #include <string.h> 3546795Sbostic #endif 361422Sroot #include "dump.h" 371422Sroot 3846791Smckusick struct dumpdates **ddatev = 0; 3946791Smckusick int nddates = 0; 4046791Smckusick int ddates_in = 0; 4146791Smckusick struct dumptime *dthead = 0; 421422Sroot 4346791Smckusick void readdumptimes(); 4446590Storek int getrecord(); 4546791Smckusick int makedumpdate(); 4646590Storek 4746791Smckusick static void dumprecout(); 4846590Storek 4946590Storek void 5046791Smckusick initdumptimes() 511422Sroot { 5228858Smckusick FILE *df; 531422Sroot 5446791Smckusick if ((df = fopen(dumpdates, "r")) == NULL) { 5550493Smckusick if (errno != ENOENT) { 5650493Smckusick quit("cannot read %s: %s\n", dumpdates, 5750493Smckusick strerror(errno)); 5850493Smckusick /* NOTREACHED */ 5946590Storek } 6050493Smckusick /* 6150493Smckusick * Dumpdates does not exist, make an empty one. 6250493Smckusick */ 6350493Smckusick msg("WARNING: no file `%s', making an empty one\n", dumpdates); 6450493Smckusick if ((df = fopen(dumpdates, "w")) == NULL) { 6550493Smckusick quit("cannot create %s: %s\n", dumpdates, 6650493Smckusick strerror(errno)); 6750493Smckusick /* NOTREACHED */ 6850493Smckusick } 6950493Smckusick (void) fclose(df); 7050493Smckusick if ((df = fopen(dumpdates, "r")) == NULL) { 7150493Smckusick quit("cannot read %s even after creating it: %s\n", 7250493Smckusick dumpdates, strerror(errno)); 7350493Smckusick /* NOTREACHED */ 7450493Smckusick } 7512589Smckusick } 7628858Smckusick (void) flock(fileno(df), LOCK_SH); 7746791Smckusick readdumptimes(df); 7828858Smckusick fclose(df); 7928858Smckusick } 8028858Smckusick 8146590Storek void 8246791Smckusick readdumptimes(df) 8328858Smckusick FILE *df; 8428858Smckusick { 8546791Smckusick register int i; 8646791Smckusick register struct dumptime *dtwalk; 8728858Smckusick 8828858Smckusick for (;;) { 8946791Smckusick dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime)); 9046791Smckusick if (getrecord(df, &(dtwalk->dt_value)) < 0) 9128858Smckusick break; 9246791Smckusick nddates++; 9346791Smckusick dtwalk->dt_next = dthead; 9446791Smckusick dthead = dtwalk; 951422Sroot } 961422Sroot 9746791Smckusick ddates_in = 1; 981422Sroot /* 991422Sroot * arrayify the list, leaving enough room for the additional 10046791Smckusick * record that we may have to add to the ddate structure 1011422Sroot */ 10246791Smckusick ddatev = (struct dumpdates **) 10346791Smckusick calloc(nddates + 1, sizeof (struct dumpdates *)); 10446791Smckusick dtwalk = dthead; 10546791Smckusick for (i = nddates - 1; i >= 0; i--, dtwalk = dtwalk->dt_next) 10646791Smckusick ddatev[i] = &dtwalk->dt_value; 1071422Sroot } 1081422Sroot 10946590Storek void 11046791Smckusick getdumptime() 1111422Sroot { 11246791Smckusick register struct dumpdates *ddp; 11346791Smckusick register int i; 11446791Smckusick char *fname; 1151422Sroot 1161422Sroot fname = disk; 1171422Sroot #ifdef FDEBUG 11846791Smckusick msg("Looking for name %s in dumpdates = %s for level = %c\n", 11946791Smckusick fname, dumpdates, level); 1201422Sroot #endif 1211422Sroot spcl.c_ddate = 0; 12246791Smckusick lastlevel = '0'; 1231422Sroot 12446791Smckusick initdumptimes(); 1251422Sroot /* 1261422Sroot * Go find the entry with the same name for a lower increment 1271422Sroot * and older date 1281422Sroot */ 12946791Smckusick ITITERATE(i, ddp) { 13046791Smckusick if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0) 1311422Sroot continue; 13246791Smckusick if (ddp->dd_level >= level) 1331422Sroot continue; 13446791Smckusick if (ddp->dd_ddate <= spcl.c_ddate) 1351422Sroot continue; 13646791Smckusick spcl.c_ddate = ddp->dd_ddate; 13746791Smckusick lastlevel = ddp->dd_level; 13828858Smckusick } 1391422Sroot } 1401422Sroot 14146590Storek void 14246791Smckusick putdumptime() 1431422Sroot { 14446791Smckusick FILE *df; 14546791Smckusick register struct dumpdates *dtwalk; 14646791Smckusick register int i; 14746791Smckusick int fd; 14846791Smckusick char *fname; 1491422Sroot 1501422Sroot if(uflag == 0) 1511422Sroot return; 15246791Smckusick if ((df = fopen(dumpdates, "r+")) == NULL) 15346791Smckusick quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno)); 15428858Smckusick fd = fileno(df); 15513151Ssam (void) flock(fd, LOCK_EX); 1561422Sroot fname = disk; 15746791Smckusick free(ddatev); 15846791Smckusick ddatev = 0; 15946791Smckusick nddates = 0; 16046791Smckusick dthead = 0; 16146791Smckusick ddates_in = 0; 16246791Smckusick readdumptimes(df); 16346590Storek if (fseek(df, 0L, 0) < 0) 16446590Storek quit("fseek: %s\n", strerror(errno)); 1651422Sroot spcl.c_ddate = 0; 16646791Smckusick ITITERATE(i, dtwalk) { 16746791Smckusick if (strncmp(fname, dtwalk->dd_name, 16846791Smckusick sizeof (dtwalk->dd_name)) != 0) 1691422Sroot continue; 17046791Smckusick if (dtwalk->dd_level != level) 1711422Sroot continue; 1721422Sroot goto found; 1731422Sroot } 1741422Sroot /* 1751422Sroot * construct the new upper bound; 1761422Sroot * Enough room has been allocated. 1771422Sroot */ 17846791Smckusick dtwalk = ddatev[nddates] = 179*52847Sleres (struct dumpdates *)calloc(1, sizeof (struct dumpdates)); 18046791Smckusick nddates += 1; 1811422Sroot found: 18246791Smckusick (void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name)); 18346791Smckusick dtwalk->dd_level = level; 18446791Smckusick dtwalk->dd_ddate = spcl.c_date; 1851422Sroot 18646791Smckusick ITITERATE(i, dtwalk) { 18746791Smckusick dumprecout(df, dtwalk); 1881422Sroot } 18946590Storek if (fflush(df)) 19046791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 19146590Storek if (ftruncate(fd, ftell(df))) 19246791Smckusick quit("ftruncate (%s): %s\n", dumpdates, strerror(errno)); 19312589Smckusick (void) fclose(df); 19446791Smckusick msg("level %c dump on %s", level, 19546791Smckusick spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date)); 1961422Sroot } 1971422Sroot 19846590Storek static void 19946791Smckusick dumprecout(file, what) 20046791Smckusick FILE *file; 20146791Smckusick struct dumpdates *what; 2021422Sroot { 20346590Storek 20446590Storek if (fprintf(file, DUMPOUTFMT, 20546791Smckusick what->dd_name, 20646791Smckusick what->dd_level, 20746791Smckusick ctime(&what->dd_ddate)) < 0) 20846791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 2091422Sroot } 2101422Sroot 2111422Sroot int recno; 21246590Storek int 21346791Smckusick getrecord(df, ddatep) 21446791Smckusick FILE *df; 21546791Smckusick struct dumpdates *ddatep; 2161422Sroot { 21752846Sleres char tbuf[BUFSIZ]; 2181422Sroot 2191422Sroot recno = 0; 220*52847Sleres if ( (fgets(tbuf, sizeof (tbuf), df)) != tbuf) 2211422Sroot return(-1); 2221422Sroot recno++; 22352846Sleres if (makedumpdate(ddatep, tbuf) < 0) 2241422Sroot msg("Unknown intermediate format in %s, line %d\n", 22546791Smckusick dumpdates, recno); 2261422Sroot 2271422Sroot #ifdef FDEBUG 22846791Smckusick msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level, 22946791Smckusick ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate)); 2301422Sroot #endif 2311422Sroot return(0); 2321422Sroot } 2331422Sroot 2341422Sroot time_t unctime(); 2351422Sroot 23646590Storek int 23752846Sleres makedumpdate(ddp, tbuf) 23846791Smckusick struct dumpdates *ddp; 23952846Sleres char *tbuf; 2401422Sroot { 24146791Smckusick char un_buf[128]; 2421422Sroot 24352846Sleres sscanf(tbuf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf); 24446791Smckusick ddp->dd_ddate = unctime(un_buf); 24546791Smckusick if (ddp->dd_ddate < 0) 2461422Sroot return(-1); 2471422Sroot return(0); 2481422Sroot } 249