xref: /netbsd-src/sbin/dump/itime.c (revision eeb96f8c806686155344a4ad9c8535d6b850e06f)
1*eeb96f8cSmanu /*	$NetBSD: itime.c,v 1.22 2019/03/25 02:13:01 manu Exp $	*/
20114e805Scgd 
3108d8947Scgd /*-
4ccfa3742Smycroft  * Copyright (c) 1980, 1993
5ccfa3742Smycroft  *	The Regents of the University of California.  All rights reserved.
6108d8947Scgd  *
7108d8947Scgd  * Redistribution and use in source and binary forms, with or without
8108d8947Scgd  * modification, are permitted provided that the following conditions
9108d8947Scgd  * are met:
10108d8947Scgd  * 1. Redistributions of source code must retain the above copyright
11108d8947Scgd  *    notice, this list of conditions and the following disclaimer.
12108d8947Scgd  * 2. Redistributions in binary form must reproduce the above copyright
13108d8947Scgd  *    notice, this list of conditions and the following disclaimer in the
14108d8947Scgd  *    documentation and/or other materials provided with the distribution.
15bf07c871Sagc  * 3. Neither the name of the University nor the names of its contributors
16108d8947Scgd  *    may be used to endorse or promote products derived from this software
17108d8947Scgd  *    without specific prior written permission.
18108d8947Scgd  *
19108d8947Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20108d8947Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21108d8947Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22108d8947Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23108d8947Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24108d8947Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25108d8947Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26108d8947Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27108d8947Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28108d8947Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29108d8947Scgd  * SUCH DAMAGE.
30108d8947Scgd  */
31108d8947Scgd 
32a84bab53Slukem #include <sys/cdefs.h>
33108d8947Scgd #ifndef lint
340114e805Scgd #if 0
350114e805Scgd static char sccsid[] = "@(#)itime.c	8.1 (Berkeley) 6/5/93";
360114e805Scgd #else
37*eeb96f8cSmanu __RCSID("$NetBSD: itime.c,v 1.22 2019/03/25 02:13:01 manu Exp $");
380114e805Scgd #endif
39108d8947Scgd #endif /* not lint */
40108d8947Scgd 
41108d8947Scgd #include <sys/param.h>
428975510aSlukem #include <sys/queue.h>
43108d8947Scgd #include <sys/time.h>
44ccfa3742Smycroft 
45108d8947Scgd #include <errno.h>
46ccfa3742Smycroft #include <fcntl.h>
47108d8947Scgd #include <stdio.h>
48108d8947Scgd #include <stdlib.h>
49108d8947Scgd #include <string.h>
5022821b35Skleink #include <time.h>
51ccfa3742Smycroft #include <unistd.h>
52ccfa3742Smycroft 
53108d8947Scgd #include "dump.h"
54108d8947Scgd 
558975510aSlukem struct dumptime {
568975510aSlukem 	struct	dumpdates dt_value;
578975510aSlukem 	SLIST_ENTRY(dumptime) dt_list;
588975510aSlukem };
598975510aSlukem SLIST_HEAD(dthead, dumptime) dthead = SLIST_HEAD_INITIALIZER(dthead);
60108d8947Scgd struct	dumpdates **ddatev = 0;
61108d8947Scgd int	nddates = 0;
62108d8947Scgd 
6399feaf5bSlukem static	void dumprecout(FILE *, struct dumpdates *);
6499feaf5bSlukem static	int getrecord(FILE *, struct dumpdates *);
659c53e91bSdholland static	int makedumpdate(struct dumpdates *, const char *);
6699feaf5bSlukem static	void readdumptimes(FILE *);
67108d8947Scgd 
68108d8947Scgd void
initdumptimes(void)6999feaf5bSlukem initdumptimes(void)
70108d8947Scgd {
71108d8947Scgd 	FILE *df;
72108d8947Scgd 
73108d8947Scgd 	if ((df = fopen(dumpdates, "r")) == NULL) {
74108d8947Scgd 		if (errno != ENOENT) {
758975510aSlukem 			msg("WARNING: cannot read %s: %s\n", dumpdates,
76108d8947Scgd 			    strerror(errno));
778975510aSlukem 			return;
78108d8947Scgd 		}
79108d8947Scgd 		/*
80108d8947Scgd 		 * Dumpdates does not exist, make an empty one.
81108d8947Scgd 		 */
82108d8947Scgd 		msg("WARNING: no file `%s', making an empty one\n", dumpdates);
83108d8947Scgd 		if ((df = fopen(dumpdates, "w")) == NULL) {
848975510aSlukem 			msg("WARNING: cannot create %s: %s\n", dumpdates,
85108d8947Scgd 			    strerror(errno));
868975510aSlukem 			return;
87108d8947Scgd 		}
88108d8947Scgd 		(void) fclose(df);
89108d8947Scgd 		if ((df = fopen(dumpdates, "r")) == NULL) {
90c8d11eb8Schristos 			quite(errno, "cannot read %s even after creating it",
91c8d11eb8Schristos 			    dumpdates);
92108d8947Scgd 			/* NOTREACHED */
93108d8947Scgd 		}
94108d8947Scgd 	}
95108d8947Scgd 	(void) flock(fileno(df), LOCK_SH);
96108d8947Scgd 	readdumptimes(df);
97108d8947Scgd 	(void) fclose(df);
98108d8947Scgd }
99108d8947Scgd 
100ccfa3742Smycroft static void
readdumptimes(FILE * df)10199feaf5bSlukem readdumptimes(FILE *df)
102108d8947Scgd {
10393da79deSlukem 	int i;
10493da79deSlukem 	struct	dumptime *dtwalk;
105108d8947Scgd 
106108d8947Scgd 	for (;;) {
1079af1692eSlukem 		dtwalk = (struct dumptime *)xcalloc(1, sizeof(struct dumptime));
108326dc9f0Schristos 		if (getrecord(df, &(dtwalk->dt_value)) < 0) {
109326dc9f0Schristos 			free(dtwalk);
110108d8947Scgd 			break;
111326dc9f0Schristos 		}
112108d8947Scgd 		nddates++;
1138975510aSlukem 		SLIST_INSERT_HEAD(&dthead, dtwalk, dt_list);
114108d8947Scgd 	}
115108d8947Scgd 
116108d8947Scgd 	/*
117108d8947Scgd 	 *	arrayify the list, leaving enough room for the additional
118108d8947Scgd 	 *	record that we may have to add to the ddate structure
119108d8947Scgd 	 */
120108d8947Scgd 	ddatev = (struct dumpdates **)
1219af1692eSlukem 		xcalloc((unsigned) (nddates + 1), sizeof(struct dumpdates *));
1228975510aSlukem 	dtwalk = SLIST_FIRST(&dthead);
1238975510aSlukem 	for (i = nddates - 1; i >= 0; i--, dtwalk = SLIST_NEXT(dtwalk, dt_list))
124108d8947Scgd 		ddatev[i] = &dtwalk->dt_value;
125108d8947Scgd }
126108d8947Scgd 
127108d8947Scgd void
getdumptime(void)12899feaf5bSlukem getdumptime(void)
129108d8947Scgd {
13093da79deSlukem 	struct dumpdates *ddp;
13193da79deSlukem 	int i;
132*eeb96f8cSmanu 	const char *fname;
133108d8947Scgd 
134*eeb96f8cSmanu 	fname = dumpdev ? dumpdev : disk;
135108d8947Scgd #ifdef FDEBUG
136108d8947Scgd 	msg("Looking for name %s in dumpdates = %s for level = %c\n",
137108d8947Scgd 		fname, dumpdates, level);
138108d8947Scgd #endif
139108d8947Scgd 	spcl.c_ddate = 0;
140108d8947Scgd 	lastlevel = '0';
141108d8947Scgd 
142108d8947Scgd 	initdumptimes();
143108d8947Scgd 	/*
144108d8947Scgd 	 *	Go find the entry with the same name for a lower increment
145c40eb1e7Schristos 	 *	and older date.  If we are doing a true incremental, then
14620ebd2a4Schristos 	 *	we can use any level as a ref point.
147108d8947Scgd 	 */
148108d8947Scgd 	ITITERATE(i, ddp) {
149108d8947Scgd 		if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0)
150108d8947Scgd 			continue;
15120ebd2a4Schristos 		/* trueinc: ostensibly could omit the second clause
15220ebd2a4Schristos 		 * since if trueinc is set, we don't care about the level
15320ebd2a4Schristos 		 * at all.
15420ebd2a4Schristos 		 */
15520ebd2a4Schristos 		/* if ((!trueinc && (ddp->dd_level >= level)) ||
15620ebd2a4Schristos 		    (trueinc && (ddp->dd_level > level))) */
15720ebd2a4Schristos 		if (!trueinc && (ddp->dd_level >= level))
158108d8947Scgd 			continue;
15934ccbd43Sbouyer 		if (ddp->dd_ddate <= iswap32(spcl.c_ddate))
160108d8947Scgd 			continue;
16134ccbd43Sbouyer 		spcl.c_ddate = iswap32(ddp->dd_ddate);
162108d8947Scgd 		lastlevel = ddp->dd_level;
163108d8947Scgd 	}
164108d8947Scgd }
165108d8947Scgd 
166108d8947Scgd void
putdumptime(void)16799feaf5bSlukem putdumptime(void)
168108d8947Scgd {
169108d8947Scgd 	FILE *df;
170d90a3686Sbouyer 	struct dumpdates *dtwalk, *dtfound;
17193da79deSlukem 	int i;
172108d8947Scgd 	int fd;
173*eeb96f8cSmanu 	const char *fname;
174108d8947Scgd 
175*eeb96f8cSmanu 	if (uflag == 0 && dumpdev == NULL)
176108d8947Scgd 		return;
177108d8947Scgd 	if ((df = fopen(dumpdates, "r+")) == NULL)
178c8d11eb8Schristos 		quite(errno, "cannot rewrite %s", dumpdates);
179108d8947Scgd 	fd = fileno(df);
180108d8947Scgd 	(void) flock(fd, LOCK_EX);
181*eeb96f8cSmanu 	fname = dumpdev ? dumpdev : disk;
182108d8947Scgd 	free((char *)ddatev);
183108d8947Scgd 	ddatev = 0;
184108d8947Scgd 	nddates = 0;
185108d8947Scgd 	readdumptimes(df);
186108d8947Scgd 	if (fseek(df, 0L, 0) < 0)
187c8d11eb8Schristos 		quite(errno, "can't fseek %s", dumpdates);
188108d8947Scgd 	spcl.c_ddate = 0;
189108d8947Scgd 	ITITERATE(i, dtwalk) {
190108d8947Scgd 		if (strncmp(fname, dtwalk->dd_name,
191108d8947Scgd 				sizeof (dtwalk->dd_name)) != 0)
192108d8947Scgd 			continue;
193108d8947Scgd 		if (dtwalk->dd_level != level)
194108d8947Scgd 			continue;
195108d8947Scgd 		goto found;
196108d8947Scgd 	}
197108d8947Scgd 	/*
198108d8947Scgd 	 *	construct the new upper bound;
199108d8947Scgd 	 *	Enough room has been allocated.
200108d8947Scgd 	 */
201108d8947Scgd 	dtwalk = ddatev[nddates] =
2029af1692eSlukem 		(struct dumpdates *)xcalloc(1, sizeof (struct dumpdates));
203108d8947Scgd 	nddates += 1;
204108d8947Scgd   found:
20594ccb14aSitojun 	(void) strlcpy(dtwalk->dd_name, fname, sizeof(dtwalk->dd_name));
206108d8947Scgd 	dtwalk->dd_level = level;
20734ccbd43Sbouyer 	dtwalk->dd_ddate = iswap32(spcl.c_date);
208d90a3686Sbouyer 	dtfound = dtwalk;
209108d8947Scgd 
210108d8947Scgd 	ITITERATE(i, dtwalk) {
211108d8947Scgd 		dumprecout(df, dtwalk);
212108d8947Scgd 	}
213108d8947Scgd 	if (fflush(df))
214c8d11eb8Schristos 		quite(errno, "can't flush %s", dumpdates);
215108d8947Scgd 	if (ftruncate(fd, ftell(df)))
216c8d11eb8Schristos 		quite(errno, "can't ftruncate %s", dumpdates);
217108d8947Scgd 	(void) fclose(df);
218108d8947Scgd 	msg("level %c dump on %s", level,
219d90a3686Sbouyer 		spcl.c_date == 0 ? "the epoch\n" : ctime(&dtfound->dd_ddate));
220108d8947Scgd }
221108d8947Scgd 
222108d8947Scgd static void
dumprecout(FILE * file,struct dumpdates * what)22399feaf5bSlukem dumprecout(FILE *file, struct dumpdates *what)
224108d8947Scgd {
225108d8947Scgd 
226108d8947Scgd 	if (fprintf(file, DUMPOUTFMT,
227108d8947Scgd 		    what->dd_name,
228108d8947Scgd 		    what->dd_level,
229108d8947Scgd 		    ctime(&what->dd_ddate)) < 0)
230c8d11eb8Schristos 		quite(errno, "can't write %s", dumpdates);
231108d8947Scgd }
232108d8947Scgd 
233108d8947Scgd int	recno;
234ccfa3742Smycroft 
235ccfa3742Smycroft static int
getrecord(FILE * df,struct dumpdates * ddatep)23699feaf5bSlukem getrecord(FILE *df, struct dumpdates *ddatep)
237108d8947Scgd {
238108d8947Scgd 	char tbuf[BUFSIZ];
239108d8947Scgd 
240108d8947Scgd 	recno = 0;
241108d8947Scgd 	if ( (fgets(tbuf, sizeof (tbuf), df)) != tbuf)
242108d8947Scgd 		return(-1);
243108d8947Scgd 	recno++;
244108d8947Scgd 	if (makedumpdate(ddatep, tbuf) < 0)
245108d8947Scgd 		msg("Unknown intermediate format in %s, line %d\n",
246108d8947Scgd 			dumpdates, recno);
247108d8947Scgd 
248108d8947Scgd #ifdef FDEBUG
249108d8947Scgd 	msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level,
250108d8947Scgd 	    ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate));
251108d8947Scgd #endif
252108d8947Scgd 	return(0);
253108d8947Scgd }
254108d8947Scgd 
255ccfa3742Smycroft static int
makedumpdate(struct dumpdates * ddp,const char * tbuf)2569c53e91bSdholland makedumpdate(struct dumpdates *ddp, const char *tbuf)
257108d8947Scgd {
258ccfa3742Smycroft 	char un_buf[128];
259108d8947Scgd 
260108d8947Scgd 	(void) sscanf(tbuf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf);
261108d8947Scgd 	ddp->dd_ddate = unctime(un_buf);
262108d8947Scgd 	if (ddp->dd_ddate < 0)
263108d8947Scgd 		return(-1);
264108d8947Scgd 	return(0);
265108d8947Scgd }
266