itime.c revision 74873
185965Sbrian/*-
277690Sbrian * Copyright (c) 1980, 1993
320365Sjkh *	The Regents of the University of California.  All rights reserved.
477690Sbrian *
577690Sbrian * Redistribution and use in source and binary forms, with or without
677690Sbrian * modification, are permitted provided that the following conditions
777690Sbrian * are met:
877690Sbrian * 1. Redistributions of source code must retain the above copyright
977690Sbrian *    notice, this list of conditions and the following disclaimer.
1077690Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1177690Sbrian *    notice, this list of conditions and the following disclaimer in the
1226031Sbrian *    documentation and/or other materials provided with the distribution.
1377690Sbrian * 3. All advertising materials mentioning features or use of this software
1477690Sbrian *    must display the following acknowledgement:
1577690Sbrian *	This product includes software developed by the University of
1677690Sbrian *	California, Berkeley and its contributors.
1777690Sbrian * 4. Neither the name of the University nor the names of its contributors
1877690Sbrian *    may be used to endorse or promote products derived from this software
1977690Sbrian *    without specific prior written permission.
2077690Sbrian *
2177690Sbrian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2277690Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2377690Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2426031Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2577690Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2677690Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2777690Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2877690Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2977690Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3077690Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3120365Sjkh * SUCH DAMAGE.
3220365Sjkh */
3320365Sjkh
3426031Sbrian#ifndef lint
3526031Sbrian#if 0
3636466Sbrianstatic char sccsid[] = "@(#)itime.c	8.1 (Berkeley) 6/5/93";
3726031Sbrian#endif
3820365Sjkhstatic const char rcsid[] =
3920365Sjkh  "$FreeBSD: head/sbin/dump/itime.c 74873 2001-03-27 19:38:34Z obrien $";
4026031Sbrian#endif /* not lint */
4120365Sjkh
4220365Sjkh#include <sys/param.h>
4377690Sbrian#include <sys/queue.h>
4477690Sbrian#include <sys/time.h>
4577690Sbrian#ifdef sunos
4677690Sbrian#include <sys/vnode.h>
4726031Sbrian
4877690Sbrian#include <ufs/fsdir.h>
4920365Sjkh#include <ufs/inode.h>
5077690Sbrian#include <ufs/fs.h>
5177690Sbrian#else
5226031Sbrian#include <ufs/ufs/dinode.h>
5326031Sbrian#endif
5426031Sbrian
5520365Sjkh#include <protocols/dumprestore.h>
5620365Sjkh
5726031Sbrian#include <errno.h>
5826031Sbrian#include <fcntl.h>
5926031Sbrian#include <stdio.h>
6026031Sbrian#ifdef __STDC__
6126031Sbrian#include <stdlib.h>
6226031Sbrian#include <string.h>
6320365Sjkh#endif
6477690Sbrian
6526031Sbrian#include "dump.h"
6626031Sbrian
6726031Sbrianstruct dumptime {
6826031Sbrian	struct	dumpdates dt_value;
6926031Sbrian	SLIST_ENTRY(dumptime) dt_list;
7020365Sjkh};
7126031SbrianSLIST_HEAD(dthead, dumptime) dthead = SLIST_HEAD_INITIALIZER(dthead);
7226031Sbrianstruct	dumpdates **ddatev = 0;
7326031Sbrianint	nddates = 0;
7426031Sbrianint	ddates_in = 0;
7526031Sbrian
7626031Sbrianstatic	void dumprecout __P((FILE *, struct dumpdates *));
7726031Sbrianstatic	int getrecord __P((FILE *, struct dumpdates *));
7820365Sjkhstatic	int makedumpdate __P((struct dumpdates *, char *));
7926031Sbrianstatic	void readdumptimes __P((FILE *));
8026031Sbrian
8136466Sbrianvoid
8226031Sbrianinitdumptimes()
8320365Sjkh{
8477690Sbrian	FILE *df;
8526031Sbrian
8620365Sjkh	if ((df = fopen(dumpdates, "r")) == NULL) {
8720365Sjkh		if (errno != ENOENT) {
8820365Sjkh			msg("WARNING: cannot read %s: %s\n", dumpdates,
8920365Sjkh			    strerror(errno));
9020365Sjkh			return;
9126031Sbrian			/* NOTREACHED */
9277690Sbrian		}
9326031Sbrian		/*
9477690Sbrian		 * Dumpdates does not exist, make an empty one.
9577690Sbrian		 */
9626031Sbrian		msg("WARNING: no file `%s', making an empty one\n", dumpdates);
9726031Sbrian		if ((df = fopen(dumpdates, "w")) == NULL) {
9820365Sjkh			msg("WARNING: cannot create %s: %s\n", dumpdates,
9977690Sbrian			    strerror(errno));
10026031Sbrian			return;
10126031Sbrian			/* NOTREACHED */
10226031Sbrian		}
10320365Sjkh		(void) fclose(df);
10426031Sbrian		if ((df = fopen(dumpdates, "r")) == NULL) {
10526031Sbrian			quit("cannot read %s even after creating it: %s\n",
10626031Sbrian			    dumpdates, strerror(errno));
10726031Sbrian			/* NOTREACHED */
10826031Sbrian		}
10926031Sbrian	}
11020365Sjkh	(void) flock(fileno(df), LOCK_SH);
11120365Sjkh	readdumptimes(df);
11220365Sjkh	(void) fclose(df);
11326031Sbrian}
11420365Sjkh
11577690Sbrianstatic void
11677690Sbrianreaddumptimes(df)
11777690Sbrian	FILE *df;
11836466Sbrian{
11977690Sbrian	register int i;
12036466Sbrian	register struct	dumptime *dtwalk;
12120365Sjkh
12226031Sbrian	for (;;) {
12377690Sbrian		dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime));
12420365Sjkh		if (getrecord(df, &(dtwalk->dt_value)) < 0)
12577690Sbrian			break;
12620365Sjkh		nddates++;
12777690Sbrian		SLIST_INSERT_HEAD(&dthead, dtwalk, dt_list);
12820365Sjkh	}
12926031Sbrian
13020365Sjkh	ddates_in = 1;
13126031Sbrian	/*
13277690Sbrian	 *	arrayify the list, leaving enough room for the additional
13326031Sbrian	 *	record that we may have to add to the ddate structure
13477690Sbrian	 */
13577690Sbrian	ddatev = (struct dumpdates **)
13626031Sbrian		calloc((unsigned) (nddates + 1), sizeof (struct dumpdates *));
13726031Sbrian	dtwalk = SLIST_FIRST(&dthead);
13877690Sbrian	for (i = nddates - 1; i >= 0; i--, dtwalk = SLIST_NEXT(dtwalk, dt_list))
13926031Sbrian		ddatev[i] = &dtwalk->dt_value;
14026031Sbrian}
14126031Sbrian
14277690Sbrianvoid
14326031Sbriangetdumptime()
14426031Sbrian{
14577690Sbrian	register struct dumpdates *ddp;
14626031Sbrian	register int i;
14777690Sbrian	char *fname;
14836466Sbrian
14926031Sbrian	fname = disk;
15026031Sbrian#ifdef FDEBUG
15126031Sbrian	msg("Looking for name %s in dumpdates = %s for level = %c\n",
15277690Sbrian		fname, dumpdates, level);
15326031Sbrian#endif
15477690Sbrian	spcl.c_ddate = 0;
15526031Sbrian	lastlevel = '0';
15677690Sbrian
15777690Sbrian	initdumptimes();
15826031Sbrian	/*
15926031Sbrian	 *	Go find the entry with the same name for a lower increment
16077690Sbrian	 *	and older date
16126031Sbrian	 */
16277690Sbrian	ITITERATE(i, ddp) {
16326031Sbrian		if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0)
16477690Sbrian			continue;
16526031Sbrian		if (ddp->dd_level >= level)
16636466Sbrian			continue;
16726031Sbrian		if (ddp->dd_ddate <= spcl.c_ddate)
16826031Sbrian			continue;
16977690Sbrian		spcl.c_ddate = ddp->dd_ddate;
17026031Sbrian		lastlevel = ddp->dd_level;
17126031Sbrian	}
17226031Sbrian}
17377690Sbrian
17426031Sbrianvoid
17577690Sbrianputdumptime()
17677690Sbrian{
17777690Sbrian	FILE *df;
17836466Sbrian	register struct dumpdates *dtwalk;
17926031Sbrian	register int i;
18026031Sbrian	int fd;
18126031Sbrian	char *fname;
18236466Sbrian
18326031Sbrian	if(uflag == 0)
18426031Sbrian		return;
18526031Sbrian	if ((df = fopen(dumpdates, "r+")) == NULL)
18626031Sbrian		quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno));
18726031Sbrian	fd = fileno(df);
18877690Sbrian	(void) flock(fd, LOCK_EX);
18926031Sbrian	fname = disk;
19077690Sbrian	free((char *)ddatev);
19126031Sbrian	ddatev = 0;
19226031Sbrian	nddates = 0;
19326031Sbrian	ddates_in = 0;
19426031Sbrian	readdumptimes(df);
19526031Sbrian	if (fseek(df, 0L, 0) < 0)
19626031Sbrian		quit("fseek: %s\n", strerror(errno));
19726031Sbrian	spcl.c_ddate = 0;
19826031Sbrian	ITITERATE(i, dtwalk) {
19926031Sbrian		if (strncmp(fname, dtwalk->dd_name,
20026031Sbrian				sizeof (dtwalk->dd_name)) != 0)
20177690Sbrian			continue;
20226031Sbrian		if (dtwalk->dd_level != level)
20326031Sbrian			continue;
20477690Sbrian		goto found;
20526031Sbrian	}
20677690Sbrian	/*
20726031Sbrian	 *	construct the new upper bound;
20826031Sbrian	 *	Enough room has been allocated.
20926031Sbrian	 */
21077690Sbrian	dtwalk = ddatev[nddates] =
21126031Sbrian		(struct dumpdates *)calloc(1, sizeof (struct dumpdates));
21236466Sbrian	nddates += 1;
21326031Sbrian  found:
21426031Sbrian	(void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name));
21526031Sbrian	dtwalk->dd_level = level;
21626031Sbrian	dtwalk->dd_ddate = spcl.c_date;
21726031Sbrian
21826031Sbrian	ITITERATE(i, dtwalk) {
21977690Sbrian		dumprecout(df, dtwalk);
22026031Sbrian	}
22126031Sbrian	if (fflush(df))
22226031Sbrian		quit("%s: %s\n", dumpdates, strerror(errno));
22326031Sbrian	if (ftruncate(fd, ftell(df)))
22426031Sbrian		quit("ftruncate (%s): %s\n", dumpdates, strerror(errno));
22526031Sbrian	(void) fclose(df);
22626031Sbrian	msg("level %c dump on %s", level,
22726031Sbrian		spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date));
22826031Sbrian}
22977690Sbrian
23026031Sbrianstatic void
23126031Sbriandumprecout(file, what)
23226031Sbrian	FILE *file;
23326031Sbrian	struct dumpdates *what;
23477690Sbrian{
23526031Sbrian
23626031Sbrian	if (fprintf(file, DUMPOUTFMT,
23777690Sbrian		    what->dd_name,
23877690Sbrian		    what->dd_level,
23977690Sbrian		    ctime(&what->dd_ddate)) < 0)
24026031Sbrian		quit("%s: %s\n", dumpdates, strerror(errno));
24136466Sbrian}
24226031Sbrian
24377690Sbrianint	recno;
24426031Sbrian
24526031Sbrianstatic int
24626031Sbriangetrecord(df, ddatep)
24726031Sbrian	FILE *df;
24826031Sbrian	struct dumpdates *ddatep;
24926031Sbrian{
25077690Sbrian	char tbuf[BUFSIZ];
25177690Sbrian
25277690Sbrian	recno = 0;
25377690Sbrian	if ( (fgets(tbuf, sizeof (tbuf), df)) != tbuf)
25477690Sbrian		return(-1);
25526031Sbrian	recno++;
25626031Sbrian	if (makedumpdate(ddatep, tbuf) < 0)
25726031Sbrian		msg("Unknown intermediate format in %s, line %d\n",
25877690Sbrian			dumpdates, recno);
25926031Sbrian
26026031Sbrian#ifdef FDEBUG
26126031Sbrian	msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level,
26226031Sbrian	    ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate));
26326031Sbrian#endif
26426031Sbrian	return(0);
26577690Sbrian}
26626031Sbrian
26726031Sbrianstatic int
26836466Sbrianmakedumpdate(ddp, tbuf)
26977690Sbrian	struct dumpdates *ddp;
27026031Sbrian	char *tbuf;
27126031Sbrian{
27226031Sbrian	char un_buf[128];
27336466Sbrian
27426031Sbrian	(void) sscanf(tbuf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf);
27586806Sbrian	ddp->dd_ddate = unctime(un_buf);
27626031Sbrian	if (ddp->dd_ddate < 0)
27726031Sbrian		return(-1);
27826031Sbrian	return(0);
27926031Sbrian}
28026031Sbrian