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