147082Smckusick /*-
2*61484Sbostic * Copyright (c) 1980, 1993
3*61484Sbostic * The Regents of the University of California. All rights reserved.
447082Smckusick *
547082Smckusick * %sccs.include.redist.c%
622036Sdist */
712589Smckusick
822036Sdist #ifndef lint
9*61484Sbostic static char sccsid[] = "@(#)itime.c 8.1 (Berkeley) 06/05/93";
1046590Storek #endif /* not lint */
1122036Sdist
1257725Smckusick #include <sys/param.h>
1357725Smckusick #include <sys/time.h>
1450494Smckusick #ifdef sunos
1557725Smckusick #include <sys/vnode.h>
1657725Smckusick
1757725Smckusick #include <ufs/fsdir.h>
1857725Smckusick #include <ufs/inode.h>
1950494Smckusick #include <ufs/fs.h>
2050494Smckusick #else
2157725Smckusick #include <ufs/ufs/dinode.h>
2254040Smckusick #endif
2357725Smckusick
2446795Sbostic #include <protocols/dumprestore.h>
2557725Smckusick
2646795Sbostic #include <errno.h>
2757725Smckusick #include <fcntl.h>
2846795Sbostic #include <stdio.h>
2946795Sbostic #ifdef __STDC__
3046795Sbostic #include <stdlib.h>
3146795Sbostic #include <string.h>
3257725Smckusick #include <unistd.h>
3346795Sbostic #endif
3457725Smckusick
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
4257725Smckusick static void dumprecout __P((FILE *, struct dumpdates *));
4357725Smckusick static int getrecord __P((FILE *, struct dumpdates *));
4457725Smckusick static int makedumpdate __P((struct dumpdates *, char *));
4557725Smckusick static void readdumptimes __P((FILE *));
4646590Storek
4746590Storek void
initdumptimes()4846791Smckusick initdumptimes()
491422Sroot {
5028858Smckusick FILE *df;
511422Sroot
5246791Smckusick if ((df = fopen(dumpdates, "r")) == NULL) {
5350493Smckusick if (errno != ENOENT) {
5450493Smckusick quit("cannot read %s: %s\n", dumpdates,
5550493Smckusick strerror(errno));
5650493Smckusick /* NOTREACHED */
5746590Storek }
5850493Smckusick /*
5950493Smckusick * Dumpdates does not exist, make an empty one.
6050493Smckusick */
6150493Smckusick msg("WARNING: no file `%s', making an empty one\n", dumpdates);
6250493Smckusick if ((df = fopen(dumpdates, "w")) == NULL) {
6350493Smckusick quit("cannot create %s: %s\n", dumpdates,
6450493Smckusick strerror(errno));
6550493Smckusick /* NOTREACHED */
6650493Smckusick }
6750493Smckusick (void) fclose(df);
6850493Smckusick if ((df = fopen(dumpdates, "r")) == NULL) {
6950493Smckusick quit("cannot read %s even after creating it: %s\n",
7050493Smckusick dumpdates, strerror(errno));
7150493Smckusick /* NOTREACHED */
7250493Smckusick }
7312589Smckusick }
7428858Smckusick (void) flock(fileno(df), LOCK_SH);
7546791Smckusick readdumptimes(df);
7654040Smckusick (void) fclose(df);
7728858Smckusick }
7828858Smckusick
7957725Smckusick static void
readdumptimes(df)8046791Smckusick readdumptimes(df)
8128858Smckusick FILE *df;
8228858Smckusick {
8346791Smckusick register int i;
8446791Smckusick register struct dumptime *dtwalk;
8528858Smckusick
8628858Smckusick for (;;) {
8746791Smckusick dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime));
8846791Smckusick if (getrecord(df, &(dtwalk->dt_value)) < 0)
8928858Smckusick break;
9046791Smckusick nddates++;
9146791Smckusick dtwalk->dt_next = dthead;
9246791Smckusick dthead = dtwalk;
931422Sroot }
941422Sroot
9546791Smckusick ddates_in = 1;
961422Sroot /*
971422Sroot * arrayify the list, leaving enough room for the additional
9846791Smckusick * record that we may have to add to the ddate structure
991422Sroot */
10046791Smckusick ddatev = (struct dumpdates **)
10154040Smckusick calloc((unsigned) (nddates + 1), sizeof (struct dumpdates *));
10246791Smckusick dtwalk = dthead;
10346791Smckusick for (i = nddates - 1; i >= 0; i--, dtwalk = dtwalk->dt_next)
10446791Smckusick ddatev[i] = &dtwalk->dt_value;
1051422Sroot }
1061422Sroot
10746590Storek void
getdumptime()10846791Smckusick getdumptime()
1091422Sroot {
11046791Smckusick register struct dumpdates *ddp;
11146791Smckusick register int i;
11246791Smckusick char *fname;
1131422Sroot
1141422Sroot fname = disk;
1151422Sroot #ifdef FDEBUG
11646791Smckusick msg("Looking for name %s in dumpdates = %s for level = %c\n",
11746791Smckusick fname, dumpdates, level);
1181422Sroot #endif
1191422Sroot spcl.c_ddate = 0;
12046791Smckusick lastlevel = '0';
1211422Sroot
12246791Smckusick initdumptimes();
1231422Sroot /*
1241422Sroot * Go find the entry with the same name for a lower increment
1251422Sroot * and older date
1261422Sroot */
12746791Smckusick ITITERATE(i, ddp) {
12846791Smckusick if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0)
1291422Sroot continue;
13046791Smckusick if (ddp->dd_level >= level)
1311422Sroot continue;
13246791Smckusick if (ddp->dd_ddate <= spcl.c_ddate)
1331422Sroot continue;
13446791Smckusick spcl.c_ddate = ddp->dd_ddate;
13546791Smckusick lastlevel = ddp->dd_level;
13628858Smckusick }
1371422Sroot }
1381422Sroot
13946590Storek void
putdumptime()14046791Smckusick putdumptime()
1411422Sroot {
14246791Smckusick FILE *df;
14346791Smckusick register struct dumpdates *dtwalk;
14446791Smckusick register int i;
14546791Smckusick int fd;
14646791Smckusick char *fname;
1471422Sroot
1481422Sroot if(uflag == 0)
1491422Sroot return;
15046791Smckusick if ((df = fopen(dumpdates, "r+")) == NULL)
15146791Smckusick quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno));
15228858Smckusick fd = fileno(df);
15313151Ssam (void) flock(fd, LOCK_EX);
1541422Sroot fname = disk;
15554040Smckusick free((char *)ddatev);
15646791Smckusick ddatev = 0;
15746791Smckusick nddates = 0;
15846791Smckusick dthead = 0;
15946791Smckusick ddates_in = 0;
16046791Smckusick readdumptimes(df);
16146590Storek if (fseek(df, 0L, 0) < 0)
16246590Storek quit("fseek: %s\n", strerror(errno));
1631422Sroot spcl.c_ddate = 0;
16446791Smckusick ITITERATE(i, dtwalk) {
16546791Smckusick if (strncmp(fname, dtwalk->dd_name,
16646791Smckusick sizeof (dtwalk->dd_name)) != 0)
1671422Sroot continue;
16846791Smckusick if (dtwalk->dd_level != level)
1691422Sroot continue;
1701422Sroot goto found;
1711422Sroot }
1721422Sroot /*
1731422Sroot * construct the new upper bound;
1741422Sroot * Enough room has been allocated.
1751422Sroot */
17646791Smckusick dtwalk = ddatev[nddates] =
17752847Sleres (struct dumpdates *)calloc(1, sizeof (struct dumpdates));
17846791Smckusick nddates += 1;
1791422Sroot found:
18046791Smckusick (void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name));
18146791Smckusick dtwalk->dd_level = level;
18246791Smckusick dtwalk->dd_ddate = spcl.c_date;
1831422Sroot
18446791Smckusick ITITERATE(i, dtwalk) {
18546791Smckusick dumprecout(df, dtwalk);
1861422Sroot }
18746590Storek if (fflush(df))
18846791Smckusick quit("%s: %s\n", dumpdates, strerror(errno));
18946590Storek if (ftruncate(fd, ftell(df)))
19046791Smckusick quit("ftruncate (%s): %s\n", dumpdates, strerror(errno));
19112589Smckusick (void) fclose(df);
19246791Smckusick msg("level %c dump on %s", level,
19346791Smckusick spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date));
1941422Sroot }
1951422Sroot
19646590Storek static void
dumprecout(file,what)19746791Smckusick dumprecout(file, what)
19846791Smckusick FILE *file;
19946791Smckusick struct dumpdates *what;
2001422Sroot {
20146590Storek
20246590Storek if (fprintf(file, DUMPOUTFMT,
20346791Smckusick what->dd_name,
20446791Smckusick what->dd_level,
20546791Smckusick ctime(&what->dd_ddate)) < 0)
20646791Smckusick quit("%s: %s\n", dumpdates, strerror(errno));
2071422Sroot }
2081422Sroot
2091422Sroot int recno;
21057725Smckusick
21157725Smckusick static int
getrecord(df,ddatep)21246791Smckusick getrecord(df, ddatep)
21346791Smckusick FILE *df;
21446791Smckusick struct dumpdates *ddatep;
2151422Sroot {
21652846Sleres char tbuf[BUFSIZ];
2171422Sroot
2181422Sroot recno = 0;
21952847Sleres if ( (fgets(tbuf, sizeof (tbuf), df)) != tbuf)
2201422Sroot return(-1);
2211422Sroot recno++;
22252846Sleres if (makedumpdate(ddatep, tbuf) < 0)
2231422Sroot msg("Unknown intermediate format in %s, line %d\n",
22446791Smckusick dumpdates, recno);
2251422Sroot
2261422Sroot #ifdef FDEBUG
22746791Smckusick msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level,
22846791Smckusick ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate));
2291422Sroot #endif
2301422Sroot return(0);
2311422Sroot }
2321422Sroot
23357725Smckusick static int
makedumpdate(ddp,tbuf)23452846Sleres makedumpdate(ddp, tbuf)
23546791Smckusick struct dumpdates *ddp;
23652846Sleres char *tbuf;
2371422Sroot {
23846791Smckusick char un_buf[128];
2391422Sroot
24054040Smckusick (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