xref: /freebsd/sbin/dump/itime.c (revision 5b3817c60b5d4e7ac21b4576f820cad7e853b5d9)
18fae3551SRodney W. Grimes /*-
28fae3551SRodney W. Grimes  * Copyright (c) 1980, 1993
38fae3551SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
48fae3551SRodney W. Grimes  *
58fae3551SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
68fae3551SRodney W. Grimes  * modification, are permitted provided that the following conditions
78fae3551SRodney W. Grimes  * are met:
88fae3551SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
98fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
108fae3551SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
118fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
128fae3551SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
138fae3551SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
148fae3551SRodney W. Grimes  *    must display the following acknowledgement:
158fae3551SRodney W. Grimes  *	This product includes software developed by the University of
168fae3551SRodney W. Grimes  *	California, Berkeley and its contributors.
178fae3551SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
188fae3551SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
198fae3551SRodney W. Grimes  *    without specific prior written permission.
208fae3551SRodney W. Grimes  *
218fae3551SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
228fae3551SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
238fae3551SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
248fae3551SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
258fae3551SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
268fae3551SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
278fae3551SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
288fae3551SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
298fae3551SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
308fae3551SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
318fae3551SRodney W. Grimes  * SUCH DAMAGE.
328fae3551SRodney W. Grimes  */
338fae3551SRodney W. Grimes 
348fae3551SRodney W. Grimes #ifndef lint
357580ffbbSPhilippe Charnier #if 0
368fae3551SRodney W. Grimes static char sccsid[] = "@(#)itime.c	8.1 (Berkeley) 6/5/93";
377580ffbbSPhilippe Charnier #endif
387580ffbbSPhilippe Charnier static const char rcsid[] =
397f3dea24SPeter Wemm   "$FreeBSD$";
408fae3551SRodney W. Grimes #endif /* not lint */
418fae3551SRodney W. Grimes 
428fae3551SRodney W. Grimes #include <sys/param.h>
43941ee632SPoul-Henning Kamp #include <sys/queue.h>
448fae3551SRodney W. Grimes #include <sys/time.h>
458fae3551SRodney W. Grimes #ifdef sunos
468fae3551SRodney W. Grimes #include <sys/vnode.h>
478fae3551SRodney W. Grimes 
488fae3551SRodney W. Grimes #include <ufs/fsdir.h>
498fae3551SRodney W. Grimes #include <ufs/inode.h>
508fae3551SRodney W. Grimes #include <ufs/fs.h>
518fae3551SRodney W. Grimes #else
528fae3551SRodney W. Grimes #include <ufs/ufs/dinode.h>
538fae3551SRodney W. Grimes #endif
548fae3551SRodney W. Grimes 
558fae3551SRodney W. Grimes #include <protocols/dumprestore.h>
568fae3551SRodney W. Grimes 
578fae3551SRodney W. Grimes #include <errno.h>
588fae3551SRodney W. Grimes #include <fcntl.h>
598fae3551SRodney W. Grimes #include <stdio.h>
608fae3551SRodney W. Grimes #ifdef __STDC__
618fae3551SRodney W. Grimes #include <stdlib.h>
628fae3551SRodney W. Grimes #include <string.h>
638fae3551SRodney W. Grimes #endif
648fae3551SRodney W. Grimes 
658fae3551SRodney W. Grimes #include "dump.h"
668fae3551SRodney W. Grimes 
67941ee632SPoul-Henning Kamp struct dumptime {
68941ee632SPoul-Henning Kamp 	struct	dumpdates dt_value;
69941ee632SPoul-Henning Kamp 	SLIST_ENTRY(dumptime) dt_list;
70941ee632SPoul-Henning Kamp };
71941ee632SPoul-Henning Kamp SLIST_HEAD(dthead, dumptime) dthead = SLIST_HEAD_INITIALIZER(dthead);
728fae3551SRodney W. Grimes struct	dumpdates **ddatev = 0;
738fae3551SRodney W. Grimes int	nddates = 0;
748fae3551SRodney W. Grimes int	ddates_in = 0;
758fae3551SRodney W. Grimes 
768fae3551SRodney W. Grimes static	void dumprecout __P((FILE *, struct dumpdates *));
778fae3551SRodney W. Grimes static	int getrecord __P((FILE *, struct dumpdates *));
788fae3551SRodney W. Grimes static	int makedumpdate __P((struct dumpdates *, char *));
798fae3551SRodney W. Grimes static	void readdumptimes __P((FILE *));
808fae3551SRodney W. Grimes 
818fae3551SRodney W. Grimes void
828fae3551SRodney W. Grimes initdumptimes()
838fae3551SRodney W. Grimes {
848fae3551SRodney W. Grimes 	FILE *df;
858fae3551SRodney W. Grimes 
868fae3551SRodney W. Grimes 	if ((df = fopen(dumpdates, "r")) == NULL) {
878fae3551SRodney W. Grimes 		if (errno != ENOENT) {
88b2f6bdeeSDavid E. O'Brien 			msg("WARNING: cannot read %s: %s\n", dumpdates,
898fae3551SRodney W. Grimes 			    strerror(errno));
908cc6e4d8SDavid E. O'Brien 			return;
918fae3551SRodney W. Grimes 		}
928fae3551SRodney W. Grimes 		/*
938fae3551SRodney W. Grimes 		 * Dumpdates does not exist, make an empty one.
948fae3551SRodney W. Grimes 		 */
958fae3551SRodney W. Grimes 		msg("WARNING: no file `%s', making an empty one\n", dumpdates);
968fae3551SRodney W. Grimes 		if ((df = fopen(dumpdates, "w")) == NULL) {
97b2f6bdeeSDavid E. O'Brien 			msg("WARNING: cannot create %s: %s\n", dumpdates,
988fae3551SRodney W. Grimes 			    strerror(errno));
998cc6e4d8SDavid E. O'Brien 			return;
1008fae3551SRodney W. Grimes 		}
1018fae3551SRodney W. Grimes 		(void) fclose(df);
1028fae3551SRodney W. Grimes 		if ((df = fopen(dumpdates, "r")) == NULL) {
1038fae3551SRodney W. Grimes 			quit("cannot read %s even after creating it: %s\n",
1048fae3551SRodney W. Grimes 			    dumpdates, strerror(errno));
1058fae3551SRodney W. Grimes 			/* NOTREACHED */
1068fae3551SRodney W. Grimes 		}
1078fae3551SRodney W. Grimes 	}
1088fae3551SRodney W. Grimes 	(void) flock(fileno(df), LOCK_SH);
1098fae3551SRodney W. Grimes 	readdumptimes(df);
1108fae3551SRodney W. Grimes 	(void) fclose(df);
1118fae3551SRodney W. Grimes }
1128fae3551SRodney W. Grimes 
1138fae3551SRodney W. Grimes static void
1148fae3551SRodney W. Grimes readdumptimes(df)
1158fae3551SRodney W. Grimes 	FILE *df;
1168fae3551SRodney W. Grimes {
1178fae3551SRodney W. Grimes 	register int i;
1188fae3551SRodney W. Grimes 	register struct	dumptime *dtwalk;
1198fae3551SRodney W. Grimes 
1208fae3551SRodney W. Grimes 	for (;;) {
1218fae3551SRodney W. Grimes 		dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime));
1228fae3551SRodney W. Grimes 		if (getrecord(df, &(dtwalk->dt_value)) < 0)
1238fae3551SRodney W. Grimes 			break;
1248fae3551SRodney W. Grimes 		nddates++;
125941ee632SPoul-Henning Kamp 		SLIST_INSERT_HEAD(&dthead, dtwalk, dt_list);
1268fae3551SRodney W. Grimes 	}
1278fae3551SRodney W. Grimes 
1288fae3551SRodney W. Grimes 	ddates_in = 1;
1298fae3551SRodney W. Grimes 	/*
1308fae3551SRodney W. Grimes 	 *	arrayify the list, leaving enough room for the additional
1318fae3551SRodney W. Grimes 	 *	record that we may have to add to the ddate structure
1328fae3551SRodney W. Grimes 	 */
1338fae3551SRodney W. Grimes 	ddatev = (struct dumpdates **)
1348fae3551SRodney W. Grimes 		calloc((unsigned) (nddates + 1), sizeof (struct dumpdates *));
135941ee632SPoul-Henning Kamp 	dtwalk = SLIST_FIRST(&dthead);
136941ee632SPoul-Henning Kamp 	for (i = nddates - 1; i >= 0; i--, dtwalk = SLIST_NEXT(dtwalk, dt_list))
1378fae3551SRodney W. Grimes 		ddatev[i] = &dtwalk->dt_value;
1388fae3551SRodney W. Grimes }
1398fae3551SRodney W. Grimes 
1408fae3551SRodney W. Grimes void
1418fae3551SRodney W. Grimes getdumptime()
1428fae3551SRodney W. Grimes {
1438fae3551SRodney W. Grimes 	register struct dumpdates *ddp;
1448fae3551SRodney W. Grimes 	register int i;
1458fae3551SRodney W. Grimes 	char *fname;
1468fae3551SRodney W. Grimes 
1478fae3551SRodney W. Grimes 	fname = disk;
1488fae3551SRodney W. Grimes #ifdef FDEBUG
1498fae3551SRodney W. Grimes 	msg("Looking for name %s in dumpdates = %s for level = %c\n",
1508fae3551SRodney W. Grimes 		fname, dumpdates, level);
1518fae3551SRodney W. Grimes #endif
1528fae3551SRodney W. Grimes 	spcl.c_ddate = 0;
1538fae3551SRodney W. Grimes 	lastlevel = '0';
1548fae3551SRodney W. Grimes 
1558fae3551SRodney W. Grimes 	initdumptimes();
1568fae3551SRodney W. Grimes 	/*
1578fae3551SRodney W. Grimes 	 *	Go find the entry with the same name for a lower increment
1588fae3551SRodney W. Grimes 	 *	and older date
1598fae3551SRodney W. Grimes 	 */
1608fae3551SRodney W. Grimes 	ITITERATE(i, ddp) {
1618fae3551SRodney W. Grimes 		if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0)
1628fae3551SRodney W. Grimes 			continue;
1638fae3551SRodney W. Grimes 		if (ddp->dd_level >= level)
1648fae3551SRodney W. Grimes 			continue;
1655b3817c6SMatthew Dillon 		if (ddp->dd_ddate <= time32_to_time(spcl.c_ddate))
1668fae3551SRodney W. Grimes 			continue;
1675b3817c6SMatthew Dillon 		spcl.c_ddate = time_to_time32(ddp->dd_ddate);
1688fae3551SRodney W. Grimes 		lastlevel = ddp->dd_level;
1698fae3551SRodney W. Grimes 	}
1708fae3551SRodney W. Grimes }
1718fae3551SRodney W. Grimes 
1728fae3551SRodney W. Grimes void
1738fae3551SRodney W. Grimes putdumptime()
1748fae3551SRodney W. Grimes {
1758fae3551SRodney W. Grimes 	FILE *df;
1768fae3551SRodney W. Grimes 	register struct dumpdates *dtwalk;
1778fae3551SRodney W. Grimes 	register int i;
1788fae3551SRodney W. Grimes 	int fd;
1798fae3551SRodney W. Grimes 	char *fname;
1805b3817c6SMatthew Dillon 	char *tmsg;
1818fae3551SRodney W. Grimes 
1828fae3551SRodney W. Grimes 	if(uflag == 0)
1838fae3551SRodney W. Grimes 		return;
1848fae3551SRodney W. Grimes 	if ((df = fopen(dumpdates, "r+")) == NULL)
1858fae3551SRodney W. Grimes 		quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno));
1868fae3551SRodney W. Grimes 	fd = fileno(df);
1878fae3551SRodney W. Grimes 	(void) flock(fd, LOCK_EX);
1888fae3551SRodney W. Grimes 	fname = disk;
1898fae3551SRodney W. Grimes 	free((char *)ddatev);
1908fae3551SRodney W. Grimes 	ddatev = 0;
1918fae3551SRodney W. Grimes 	nddates = 0;
1928fae3551SRodney W. Grimes 	ddates_in = 0;
1938fae3551SRodney W. Grimes 	readdumptimes(df);
1948fae3551SRodney W. Grimes 	if (fseek(df, 0L, 0) < 0)
1958fae3551SRodney W. Grimes 		quit("fseek: %s\n", strerror(errno));
1968fae3551SRodney W. Grimes 	spcl.c_ddate = 0;
1978fae3551SRodney W. Grimes 	ITITERATE(i, dtwalk) {
1988fae3551SRodney W. Grimes 		if (strncmp(fname, dtwalk->dd_name,
1998fae3551SRodney W. Grimes 				sizeof (dtwalk->dd_name)) != 0)
2008fae3551SRodney W. Grimes 			continue;
2018fae3551SRodney W. Grimes 		if (dtwalk->dd_level != level)
2028fae3551SRodney W. Grimes 			continue;
2038fae3551SRodney W. Grimes 		goto found;
2048fae3551SRodney W. Grimes 	}
2058fae3551SRodney W. Grimes 	/*
2068fae3551SRodney W. Grimes 	 *	construct the new upper bound;
2078fae3551SRodney W. Grimes 	 *	Enough room has been allocated.
2088fae3551SRodney W. Grimes 	 */
2098fae3551SRodney W. Grimes 	dtwalk = ddatev[nddates] =
2108fae3551SRodney W. Grimes 		(struct dumpdates *)calloc(1, sizeof (struct dumpdates));
2118fae3551SRodney W. Grimes 	nddates += 1;
2128fae3551SRodney W. Grimes   found:
2138fae3551SRodney W. Grimes 	(void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name));
2148fae3551SRodney W. Grimes 	dtwalk->dd_level = level;
2155b3817c6SMatthew Dillon 	dtwalk->dd_ddate = time32_to_time(spcl.c_date);
2168fae3551SRodney W. Grimes 
2178fae3551SRodney W. Grimes 	ITITERATE(i, dtwalk) {
2188fae3551SRodney W. Grimes 		dumprecout(df, dtwalk);
2198fae3551SRodney W. Grimes 	}
2208fae3551SRodney W. Grimes 	if (fflush(df))
2218fae3551SRodney W. Grimes 		quit("%s: %s\n", dumpdates, strerror(errno));
2228fae3551SRodney W. Grimes 	if (ftruncate(fd, ftell(df)))
2238fae3551SRodney W. Grimes 		quit("ftruncate (%s): %s\n", dumpdates, strerror(errno));
2248fae3551SRodney W. Grimes 	(void) fclose(df);
2255b3817c6SMatthew Dillon 	if (spcl.c_date == 0) {
2265b3817c6SMatthew Dillon 		tmsg = "the epoch\n";
2275b3817c6SMatthew Dillon 	} else {
2285b3817c6SMatthew Dillon 		time_t t = time32_to_time(spcl.c_date);
2295b3817c6SMatthew Dillon 		tmsg = ctime(&t);
2305b3817c6SMatthew Dillon 	}
2315b3817c6SMatthew Dillon 	msg("level %c dump on %s", level, tmsg);
2328fae3551SRodney W. Grimes }
2338fae3551SRodney W. Grimes 
2348fae3551SRodney W. Grimes static void
2358fae3551SRodney W. Grimes dumprecout(file, what)
2368fae3551SRodney W. Grimes 	FILE *file;
2378fae3551SRodney W. Grimes 	struct dumpdates *what;
2388fae3551SRodney W. Grimes {
2398fae3551SRodney W. Grimes 
2408fae3551SRodney W. Grimes 	if (fprintf(file, DUMPOUTFMT,
2418fae3551SRodney W. Grimes 		    what->dd_name,
2428fae3551SRodney W. Grimes 		    what->dd_level,
2438fae3551SRodney W. Grimes 		    ctime(&what->dd_ddate)) < 0)
2448fae3551SRodney W. Grimes 		quit("%s: %s\n", dumpdates, strerror(errno));
2458fae3551SRodney W. Grimes }
2468fae3551SRodney W. Grimes 
2478fae3551SRodney W. Grimes int	recno;
2488fae3551SRodney W. Grimes 
2498fae3551SRodney W. Grimes static int
2508fae3551SRodney W. Grimes getrecord(df, ddatep)
2518fae3551SRodney W. Grimes 	FILE *df;
2528fae3551SRodney W. Grimes 	struct dumpdates *ddatep;
2538fae3551SRodney W. Grimes {
2548fae3551SRodney W. Grimes 	char tbuf[BUFSIZ];
2558fae3551SRodney W. Grimes 
2568fae3551SRodney W. Grimes 	recno = 0;
2578fae3551SRodney W. Grimes 	if ( (fgets(tbuf, sizeof (tbuf), df)) != tbuf)
2588fae3551SRodney W. Grimes 		return(-1);
2598fae3551SRodney W. Grimes 	recno++;
2608fae3551SRodney W. Grimes 	if (makedumpdate(ddatep, tbuf) < 0)
2618fae3551SRodney W. Grimes 		msg("Unknown intermediate format in %s, line %d\n",
2628fae3551SRodney W. Grimes 			dumpdates, recno);
2638fae3551SRodney W. Grimes 
2648fae3551SRodney W. Grimes #ifdef FDEBUG
2658fae3551SRodney W. Grimes 	msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level,
2668fae3551SRodney W. Grimes 	    ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate));
2678fae3551SRodney W. Grimes #endif
2688fae3551SRodney W. Grimes 	return(0);
2698fae3551SRodney W. Grimes }
2708fae3551SRodney W. Grimes 
2718fae3551SRodney W. Grimes static int
2728fae3551SRodney W. Grimes makedumpdate(ddp, tbuf)
2738fae3551SRodney W. Grimes 	struct dumpdates *ddp;
2748fae3551SRodney W. Grimes 	char *tbuf;
2758fae3551SRodney W. Grimes {
2768fae3551SRodney W. Grimes 	char un_buf[128];
2778fae3551SRodney W. Grimes 
2788fae3551SRodney W. Grimes 	(void) sscanf(tbuf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf);
2798fae3551SRodney W. Grimes 	ddp->dd_ddate = unctime(un_buf);
2808fae3551SRodney W. Grimes 	if (ddp->dd_ddate < 0)
2818fae3551SRodney W. Grimes 		return(-1);
2828fae3551SRodney W. Grimes 	return(0);
2838fae3551SRodney W. Grimes }
284