1*47082Smckusick /*- 2*47082Smckusick * Copyright (c) 1980 The Regents of the University of California. 3*47082Smckusick * All rights reserved. 4*47082Smckusick * 5*47082Smckusick * %sccs.include.redist.c% 622036Sdist */ 712589Smckusick 822036Sdist #ifndef lint 9*47082Smckusick static char sccsid[] = "@(#)itime.c 5.7 (Berkeley) 03/07/91"; 1046590Storek #endif /* not lint */ 1122036Sdist 1246795Sbostic #include <sys/param.h> 1346795Sbostic #include <ufs/dir.h> 1446795Sbostic #include <ufs/dinode.h> 1546795Sbostic #include <fcntl.h> 1646795Sbostic #include <protocols/dumprestore.h> 1746795Sbostic #include <errno.h> 1846795Sbostic #include <stdio.h> 1946795Sbostic #ifdef __STDC__ 2046795Sbostic #include <time.h> 2146795Sbostic #include <unistd.h> 2246795Sbostic #include <stdlib.h> 2346795Sbostic #include <string.h> 2446795Sbostic #endif 251422Sroot #include "dump.h" 261422Sroot 2746791Smckusick struct dumpdates **ddatev = 0; 2846791Smckusick int nddates = 0; 2946791Smckusick int ddates_in = 0; 3046791Smckusick struct dumptime *dthead = 0; 311422Sroot 3246791Smckusick void readdumptimes(); 3346590Storek int getrecord(); 3446791Smckusick int makedumpdate(); 3546590Storek 3646791Smckusick static void dumprecout(); 3746590Storek 3846590Storek void 3946791Smckusick initdumptimes() 401422Sroot { 4128858Smckusick FILE *df; 421422Sroot 4346791Smckusick if ((df = fopen(dumpdates, "r")) == NULL) { 4446590Storek if (errno == ENOENT) { 4546791Smckusick msg("WARNING: no file `%s'\n", dumpdates); 4646590Storek return; 4746590Storek } 4846791Smckusick quit("cannot read %s: %s\n", dumpdates, strerror(errno)); 4946590Storek /* NOTREACHED */ 5012589Smckusick } 5128858Smckusick (void) flock(fileno(df), LOCK_SH); 5246791Smckusick readdumptimes(df); 5328858Smckusick fclose(df); 5428858Smckusick } 5528858Smckusick 5646590Storek void 5746791Smckusick readdumptimes(df) 5828858Smckusick FILE *df; 5928858Smckusick { 6046791Smckusick register int i; 6146791Smckusick register struct dumptime *dtwalk; 6228858Smckusick 6328858Smckusick for (;;) { 6446791Smckusick dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime)); 6546791Smckusick if (getrecord(df, &(dtwalk->dt_value)) < 0) 6628858Smckusick break; 6746791Smckusick nddates++; 6846791Smckusick dtwalk->dt_next = dthead; 6946791Smckusick dthead = dtwalk; 701422Sroot } 711422Sroot 7246791Smckusick ddates_in = 1; 731422Sroot /* 741422Sroot * arrayify the list, leaving enough room for the additional 7546791Smckusick * record that we may have to add to the ddate structure 761422Sroot */ 7746791Smckusick ddatev = (struct dumpdates **) 7846791Smckusick calloc(nddates + 1, sizeof (struct dumpdates *)); 7946791Smckusick dtwalk = dthead; 8046791Smckusick for (i = nddates - 1; i >= 0; i--, dtwalk = dtwalk->dt_next) 8146791Smckusick ddatev[i] = &dtwalk->dt_value; 821422Sroot } 831422Sroot 8446590Storek void 8546791Smckusick getdumptime() 861422Sroot { 8746791Smckusick register struct dumpdates *ddp; 8846791Smckusick register int i; 8946791Smckusick char *fname; 901422Sroot 911422Sroot fname = disk; 921422Sroot #ifdef FDEBUG 9346791Smckusick msg("Looking for name %s in dumpdates = %s for level = %c\n", 9446791Smckusick fname, dumpdates, level); 951422Sroot #endif 961422Sroot spcl.c_ddate = 0; 9746791Smckusick lastlevel = '0'; 981422Sroot 9946791Smckusick initdumptimes(); 1001422Sroot /* 1011422Sroot * Go find the entry with the same name for a lower increment 1021422Sroot * and older date 1031422Sroot */ 10446791Smckusick ITITERATE(i, ddp) { 10546791Smckusick if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0) 1061422Sroot continue; 10746791Smckusick if (ddp->dd_level >= level) 1081422Sroot continue; 10946791Smckusick if (ddp->dd_ddate <= spcl.c_ddate) 1101422Sroot continue; 11146791Smckusick spcl.c_ddate = ddp->dd_ddate; 11246791Smckusick lastlevel = ddp->dd_level; 11328858Smckusick } 1141422Sroot } 1151422Sroot 11646590Storek void 11746791Smckusick putdumptime() 1181422Sroot { 11946791Smckusick FILE *df; 12046791Smckusick register struct dumpdates *dtwalk; 12146791Smckusick register int i; 12246791Smckusick int fd; 12346791Smckusick char *fname; 1241422Sroot 1251422Sroot if(uflag == 0) 1261422Sroot return; 12746791Smckusick if ((df = fopen(dumpdates, "r+")) == NULL) 12846791Smckusick quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno)); 12928858Smckusick fd = fileno(df); 13013151Ssam (void) flock(fd, LOCK_EX); 1311422Sroot fname = disk; 13246791Smckusick free(ddatev); 13346791Smckusick ddatev = 0; 13446791Smckusick nddates = 0; 13546791Smckusick dthead = 0; 13646791Smckusick ddates_in = 0; 13746791Smckusick readdumptimes(df); 13846590Storek if (fseek(df, 0L, 0) < 0) 13946590Storek quit("fseek: %s\n", strerror(errno)); 1401422Sroot spcl.c_ddate = 0; 14146791Smckusick ITITERATE(i, dtwalk) { 14246791Smckusick if (strncmp(fname, dtwalk->dd_name, 14346791Smckusick sizeof (dtwalk->dd_name)) != 0) 1441422Sroot continue; 14546791Smckusick if (dtwalk->dd_level != level) 1461422Sroot continue; 1471422Sroot goto found; 1481422Sroot } 1491422Sroot /* 1501422Sroot * construct the new upper bound; 1511422Sroot * Enough room has been allocated. 1521422Sroot */ 15346791Smckusick dtwalk = ddatev[nddates] = 15446791Smckusick (struct dumpdates *)calloc(1, sizeof(struct dumpdates)); 15546791Smckusick nddates += 1; 1561422Sroot found: 15746791Smckusick (void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name)); 15846791Smckusick dtwalk->dd_level = level; 15946791Smckusick dtwalk->dd_ddate = spcl.c_date; 1601422Sroot 16146791Smckusick ITITERATE(i, dtwalk) { 16246791Smckusick dumprecout(df, dtwalk); 1631422Sroot } 16446590Storek if (fflush(df)) 16546791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 16646590Storek if (ftruncate(fd, ftell(df))) 16746791Smckusick quit("ftruncate (%s): %s\n", dumpdates, strerror(errno)); 16812589Smckusick (void) fclose(df); 16946791Smckusick msg("level %c dump on %s", level, 17046791Smckusick spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date)); 1711422Sroot } 1721422Sroot 17346590Storek static void 17446791Smckusick dumprecout(file, what) 17546791Smckusick FILE *file; 17646791Smckusick struct dumpdates *what; 1771422Sroot { 17846590Storek 17946590Storek if (fprintf(file, DUMPOUTFMT, 18046791Smckusick what->dd_name, 18146791Smckusick what->dd_level, 18246791Smckusick ctime(&what->dd_ddate)) < 0) 18346791Smckusick quit("%s: %s\n", dumpdates, strerror(errno)); 1841422Sroot } 1851422Sroot 1861422Sroot int recno; 18746590Storek int 18846791Smckusick getrecord(df, ddatep) 18946791Smckusick FILE *df; 19046791Smckusick struct dumpdates *ddatep; 1911422Sroot { 19246791Smckusick char buf[BUFSIZ]; 1931422Sroot 1941422Sroot recno = 0; 1951422Sroot if ( (fgets(buf, BUFSIZ, df)) != buf) 1961422Sroot return(-1); 1971422Sroot recno++; 19846791Smckusick if (makedumpdate(ddatep, buf) < 0) 1991422Sroot msg("Unknown intermediate format in %s, line %d\n", 20046791Smckusick dumpdates, recno); 2011422Sroot 2021422Sroot #ifdef FDEBUG 20346791Smckusick msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level, 20446791Smckusick ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate)); 2051422Sroot #endif 2061422Sroot return(0); 2071422Sroot } 2081422Sroot 2091422Sroot time_t unctime(); 2101422Sroot 21146590Storek int 21246791Smckusick makedumpdate(ddp, buf) 21346791Smckusick struct dumpdates *ddp; 21446791Smckusick char *buf; 2151422Sroot { 21646791Smckusick char un_buf[128]; 2171422Sroot 21846791Smckusick sscanf(buf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf); 21946791Smckusick ddp->dd_ddate = unctime(un_buf); 22046791Smckusick if (ddp->dd_ddate < 0) 2211422Sroot return(-1); 2221422Sroot return(0); 2231422Sroot } 224