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*46795Sbostic static char sccsid[] = "@(#)itime.c 5.6 (Berkeley) 02/28/91"; 946590Storek #endif /* not lint */ 1022036Sdist 11*46795Sbostic #include <sys/param.h> 12*46795Sbostic #include <ufs/dir.h> 13*46795Sbostic #include <ufs/dinode.h> 14*46795Sbostic #include <fcntl.h> 15*46795Sbostic #include <protocols/dumprestore.h> 16*46795Sbostic #include <errno.h> 17*46795Sbostic #include <stdio.h> 18*46795Sbostic #ifdef __STDC__ 19*46795Sbostic #include <time.h> 20*46795Sbostic #include <unistd.h> 21*46795Sbostic #include <stdlib.h> 22*46795Sbostic #include <string.h> 23*46795Sbostic #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) { 4346590Storek if (errno == ENOENT) { 4446791Smckusick msg("WARNING: no file `%s'\n", dumpdates); 4546590Storek return; 4646590Storek } 4746791Smckusick quit("cannot read %s: %s\n", dumpdates, strerror(errno)); 4846590Storek /* NOTREACHED */ 4912589Smckusick } 5028858Smckusick (void) flock(fileno(df), LOCK_SH); 5146791Smckusick readdumptimes(df); 5228858Smckusick fclose(df); 5328858Smckusick } 5428858Smckusick 5546590Storek void 5646791Smckusick readdumptimes(df) 5728858Smckusick FILE *df; 5828858Smckusick { 5946791Smckusick register int i; 6046791Smckusick register struct dumptime *dtwalk; 6128858Smckusick 6228858Smckusick for (;;) { 6346791Smckusick dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime)); 6446791Smckusick if (getrecord(df, &(dtwalk->dt_value)) < 0) 6528858Smckusick break; 6646791Smckusick nddates++; 6746791Smckusick dtwalk->dt_next = dthead; 6846791Smckusick dthead = dtwalk; 691422Sroot } 701422Sroot 7146791Smckusick ddates_in = 1; 721422Sroot /* 731422Sroot * arrayify the list, leaving enough room for the additional 7446791Smckusick * record that we may have to add to the ddate structure 751422Sroot */ 7646791Smckusick ddatev = (struct dumpdates **) 7746791Smckusick calloc(nddates + 1, sizeof (struct dumpdates *)); 7846791Smckusick dtwalk = dthead; 7946791Smckusick for (i = nddates - 1; i >= 0; i--, dtwalk = dtwalk->dt_next) 8046791Smckusick ddatev[i] = &dtwalk->dt_value; 811422Sroot } 821422Sroot 8346590Storek void 8446791Smckusick getdumptime() 851422Sroot { 8646791Smckusick register struct dumpdates *ddp; 8746791Smckusick register int i; 8846791Smckusick char *fname; 891422Sroot 901422Sroot fname = disk; 911422Sroot #ifdef FDEBUG 9246791Smckusick msg("Looking for name %s in dumpdates = %s for level = %c\n", 9346791Smckusick fname, dumpdates, level); 941422Sroot #endif 951422Sroot spcl.c_ddate = 0; 9646791Smckusick lastlevel = '0'; 971422Sroot 9846791Smckusick initdumptimes(); 991422Sroot /* 1001422Sroot * Go find the entry with the same name for a lower increment 1011422Sroot * and older date 1021422Sroot */ 10346791Smckusick ITITERATE(i, ddp) { 10446791Smckusick if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0) 1051422Sroot continue; 10646791Smckusick if (ddp->dd_level >= level) 1071422Sroot continue; 10846791Smckusick if (ddp->dd_ddate <= spcl.c_ddate) 1091422Sroot continue; 11046791Smckusick spcl.c_ddate = ddp->dd_ddate; 11146791Smckusick lastlevel = ddp->dd_level; 11228858Smckusick } 1131422Sroot } 1141422Sroot 11546590Storek void 11646791Smckusick putdumptime() 1171422Sroot { 11846791Smckusick FILE *df; 11946791Smckusick register struct dumpdates *dtwalk; 12046791Smckusick register int i; 12146791Smckusick int fd; 12246791Smckusick char *fname; 1231422Sroot 1241422Sroot if(uflag == 0) 1251422Sroot return; 12646791Smckusick if ((df = fopen(dumpdates, "r+")) == NULL) 12746791Smckusick quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno)); 12828858Smckusick fd = fileno(df); 12913151Ssam (void) flock(fd, LOCK_EX); 1301422Sroot fname = disk; 13146791Smckusick free(ddatev); 13246791Smckusick ddatev = 0; 13346791Smckusick nddates = 0; 13446791Smckusick dthead = 0; 13546791Smckusick ddates_in = 0; 13646791Smckusick readdumptimes(df); 13746590Storek if (fseek(df, 0L, 0) < 0) 13846590Storek quit("fseek: %s\n", strerror(errno)); 1391422Sroot spcl.c_ddate = 0; 14046791Smckusick ITITERATE(i, dtwalk) { 14146791Smckusick if (strncmp(fname, dtwalk->dd_name, 14246791Smckusick sizeof (dtwalk->dd_name)) != 0) 1431422Sroot continue; 14446791Smckusick if (dtwalk->dd_level != level) 1451422Sroot continue; 1461422Sroot goto found; 1471422Sroot } 1481422Sroot /* 1491422Sroot * construct the new upper bound; 1501422Sroot * Enough room has been allocated. 1511422Sroot */ 15246791Smckusick dtwalk = ddatev[nddates] = 15346791Smckusick (struct dumpdates *)calloc(1, sizeof(struct dumpdates)); 15446791Smckusick nddates += 1; 1551422Sroot found: 15646791Smckusick (void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name)); 15746791Smckusick dtwalk->dd_level = level; 15846791Smckusick dtwalk->dd_ddate = spcl.c_date; 1591422Sroot 16046791Smckusick ITITERATE(i, dtwalk) { 16146791Smckusick dumprecout(df, dtwalk); 1621422Sroot } 16346590Storek if (fflush(df)) 16446791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 16546590Storek if (ftruncate(fd, ftell(df))) 16646791Smckusick quit("ftruncate (%s): %s\n", dumpdates, strerror(errno)); 16712589Smckusick (void) fclose(df); 16846791Smckusick msg("level %c dump on %s", level, 16946791Smckusick spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date)); 1701422Sroot } 1711422Sroot 17246590Storek static void 17346791Smckusick dumprecout(file, what) 17446791Smckusick FILE *file; 17546791Smckusick struct dumpdates *what; 1761422Sroot { 17746590Storek 17846590Storek if (fprintf(file, DUMPOUTFMT, 17946791Smckusick what->dd_name, 18046791Smckusick what->dd_level, 18146791Smckusick ctime(&what->dd_ddate)) < 0) 18246791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 1831422Sroot } 1841422Sroot 1851422Sroot int recno; 18646590Storek int 18746791Smckusick getrecord(df, ddatep) 18846791Smckusick FILE *df; 18946791Smckusick struct dumpdates *ddatep; 1901422Sroot { 19146791Smckusick char buf[BUFSIZ]; 1921422Sroot 1931422Sroot recno = 0; 1941422Sroot if ( (fgets(buf, BUFSIZ, df)) != buf) 1951422Sroot return(-1); 1961422Sroot recno++; 19746791Smckusick if (makedumpdate(ddatep, buf) < 0) 1981422Sroot msg("Unknown intermediate format in %s, line %d\n", 19946791Smckusick dumpdates, recno); 2001422Sroot 2011422Sroot #ifdef FDEBUG 20246791Smckusick msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level, 20346791Smckusick ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate)); 2041422Sroot #endif 2051422Sroot return(0); 2061422Sroot } 2071422Sroot 2081422Sroot time_t unctime(); 2091422Sroot 21046590Storek int 21146791Smckusick makedumpdate(ddp, buf) 21246791Smckusick struct dumpdates *ddp; 21346791Smckusick char *buf; 2141422Sroot { 21546791Smckusick char un_buf[128]; 2161422Sroot 21746791Smckusick sscanf(buf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf); 21846791Smckusick ddp->dd_ddate = unctime(un_buf); 21946791Smckusick if (ddp->dd_ddate < 0) 2201422Sroot return(-1); 2211422Sroot return(0); 2221422Sroot } 223