xref: /original-bsd/sbin/dump/itime.c (revision d652179b)
1 /*-
2  * Copyright (c) 1980 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)itime.c	5.15 (Berkeley) 06/18/92";
10 #endif /* not lint */
11 
12 #ifdef sunos
13 #include <stdio.h>
14 #include <ctype.h>
15 #include <sys/param.h>
16 #include <sys/stat.h>
17 #include <ufs/fs.h>
18 #else
19 #include <sys/param.h>
20 #include <sys/time.h>
21 #endif
22 #include <ufs/ufs/dinode.h>
23 #include <fcntl.h>
24 #include <protocols/dumprestore.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #ifdef __STDC__
28 #include <time.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #endif
33 #include "dump.h"
34 
35 struct	dumpdates **ddatev = 0;
36 int	nddates = 0;
37 int	ddates_in = 0;
38 struct	dumptime *dthead = 0;
39 
40 void	readdumptimes();
41 int	getrecord();
42 int	makedumpdate();
43 
44 static void dumprecout();
45 
46 void
47 initdumptimes()
48 {
49 	FILE *df;
50 
51 	if ((df = fopen(dumpdates, "r")) == NULL) {
52 		if (errno != ENOENT) {
53 			quit("cannot read %s: %s\n", dumpdates,
54 			    strerror(errno));
55 			/* NOTREACHED */
56 		}
57 		/*
58 		 * Dumpdates does not exist, make an empty one.
59 		 */
60 		msg("WARNING: no file `%s', making an empty one\n", dumpdates);
61 		if ((df = fopen(dumpdates, "w")) == NULL) {
62 			quit("cannot create %s: %s\n", dumpdates,
63 			    strerror(errno));
64 			/* NOTREACHED */
65 		}
66 		(void) fclose(df);
67 		if ((df = fopen(dumpdates, "r")) == NULL) {
68 			quit("cannot read %s even after creating it: %s\n",
69 			    dumpdates, strerror(errno));
70 			/* NOTREACHED */
71 		}
72 	}
73 	(void) flock(fileno(df), LOCK_SH);
74 	readdumptimes(df);
75 	(void) fclose(df);
76 }
77 
78 void
79 readdumptimes(df)
80 	FILE *df;
81 {
82 	register int i;
83 	register struct	dumptime *dtwalk;
84 
85 	for (;;) {
86 		dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime));
87 		if (getrecord(df, &(dtwalk->dt_value)) < 0)
88 			break;
89 		nddates++;
90 		dtwalk->dt_next = dthead;
91 		dthead = dtwalk;
92 	}
93 
94 	ddates_in = 1;
95 	/*
96 	 *	arrayify the list, leaving enough room for the additional
97 	 *	record that we may have to add to the ddate structure
98 	 */
99 	ddatev = (struct dumpdates **)
100 		calloc((unsigned) (nddates + 1), sizeof (struct dumpdates *));
101 	dtwalk = dthead;
102 	for (i = nddates - 1; i >= 0; i--, dtwalk = dtwalk->dt_next)
103 		ddatev[i] = &dtwalk->dt_value;
104 }
105 
106 void
107 getdumptime()
108 {
109 	register struct dumpdates *ddp;
110 	register int i;
111 	char *fname;
112 
113 	fname = disk;
114 #ifdef FDEBUG
115 	msg("Looking for name %s in dumpdates = %s for level = %c\n",
116 		fname, dumpdates, level);
117 #endif
118 	spcl.c_ddate = 0;
119 	lastlevel = '0';
120 
121 	initdumptimes();
122 	/*
123 	 *	Go find the entry with the same name for a lower increment
124 	 *	and older date
125 	 */
126 	ITITERATE(i, ddp) {
127 		if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0)
128 			continue;
129 		if (ddp->dd_level >= level)
130 			continue;
131 		if (ddp->dd_ddate <= spcl.c_ddate)
132 			continue;
133 		spcl.c_ddate = ddp->dd_ddate;
134 		lastlevel = ddp->dd_level;
135 	}
136 }
137 
138 void
139 putdumptime()
140 {
141 	FILE *df;
142 	register struct dumpdates *dtwalk;
143 	register int i;
144 	int fd;
145 	char *fname;
146 
147 	if(uflag == 0)
148 		return;
149 	if ((df = fopen(dumpdates, "r+")) == NULL)
150 		quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno));
151 	fd = fileno(df);
152 	(void) flock(fd, LOCK_EX);
153 	fname = disk;
154 	free((char *)ddatev);
155 	ddatev = 0;
156 	nddates = 0;
157 	dthead = 0;
158 	ddates_in = 0;
159 	readdumptimes(df);
160 	if (fseek(df, 0L, 0) < 0)
161 		quit("fseek: %s\n", strerror(errno));
162 	spcl.c_ddate = 0;
163 	ITITERATE(i, dtwalk) {
164 		if (strncmp(fname, dtwalk->dd_name,
165 				sizeof (dtwalk->dd_name)) != 0)
166 			continue;
167 		if (dtwalk->dd_level != level)
168 			continue;
169 		goto found;
170 	}
171 	/*
172 	 *	construct the new upper bound;
173 	 *	Enough room has been allocated.
174 	 */
175 	dtwalk = ddatev[nddates] =
176 		(struct dumpdates *)calloc(1, sizeof (struct dumpdates));
177 	nddates += 1;
178   found:
179 	(void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name));
180 	dtwalk->dd_level = level;
181 	dtwalk->dd_ddate = spcl.c_date;
182 
183 	ITITERATE(i, dtwalk) {
184 		dumprecout(df, dtwalk);
185 	}
186 	if (fflush(df))
187 		quit("%s: %s\n", dumpdates, strerror(errno));
188 	if (ftruncate(fd, ftell(df)))
189 		quit("ftruncate (%s): %s\n", dumpdates, strerror(errno));
190 	(void) fclose(df);
191 	msg("level %c dump on %s", level,
192 		spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date));
193 }
194 
195 static void
196 dumprecout(file, what)
197 	FILE *file;
198 	struct dumpdates *what;
199 {
200 
201 	if (fprintf(file, DUMPOUTFMT,
202 		    what->dd_name,
203 		    what->dd_level,
204 		    ctime(&what->dd_ddate)) < 0)
205 		quit("%s: %s\n", dumpdates, strerror(errno));
206 }
207 
208 int	recno;
209 int
210 getrecord(df, ddatep)
211 	FILE *df;
212 	struct dumpdates *ddatep;
213 {
214 	char tbuf[BUFSIZ];
215 
216 	recno = 0;
217 	if ( (fgets(tbuf, sizeof (tbuf), df)) != tbuf)
218 		return(-1);
219 	recno++;
220 	if (makedumpdate(ddatep, tbuf) < 0)
221 		msg("Unknown intermediate format in %s, line %d\n",
222 			dumpdates, recno);
223 
224 #ifdef FDEBUG
225 	msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level,
226 	    ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate));
227 #endif
228 	return(0);
229 }
230 
231 int
232 makedumpdate(ddp, tbuf)
233 	struct dumpdates *ddp;
234 	char *tbuf;
235 {
236 	char un_buf[128];
237 
238 	(void) sscanf(tbuf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf);
239 	ddp->dd_ddate = unctime(un_buf);
240 	if (ddp->dd_ddate < 0)
241 		return(-1);
242 	return(0);
243 }
244