itime.c revision 1.4 1 /* $NetBSD: itime.c,v 1.4 1997/04/15 01:09:50 lukem Exp $ */
2
3 /*-
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)itime.c 8.1 (Berkeley) 6/5/93";
39 #else
40 static char rcsid[] = "$NetBSD: itime.c,v 1.4 1997/04/15 01:09:50 lukem Exp $";
41 #endif
42 #endif /* not lint */
43
44 #include <sys/param.h>
45 #include <sys/time.h>
46 #ifdef sunos
47 #include <sys/vnode.h>
48
49 #include <ufs/fsdir.h>
50 #include <ufs/inode.h>
51 #include <ufs/fs.h>
52 #else
53 #include <ufs/ufs/dinode.h>
54 #endif
55
56 #include <protocols/dumprestore.h>
57
58 #include <errno.h>
59 #include <fcntl.h>
60 #include <stdio.h>
61 #ifdef __STDC__
62 #include <stdlib.h>
63 #include <string.h>
64 #include <unistd.h>
65 #endif
66
67 #include "dump.h"
68
69 struct dumpdates **ddatev = 0;
70 int nddates = 0;
71 int ddates_in = 0;
72 struct dumptime *dthead = 0;
73
74 static void dumprecout __P((FILE *, struct dumpdates *));
75 static int getrecord __P((FILE *, struct dumpdates *));
76 static int makedumpdate __P((struct dumpdates *, char *));
77 static void readdumptimes __P((FILE *));
78
79 void
80 initdumptimes()
81 {
82 FILE *df;
83
84 if ((df = fopen(dumpdates, "r")) == NULL) {
85 if (errno != ENOENT) {
86 quit("cannot read %s: %s\n", dumpdates,
87 strerror(errno));
88 /* NOTREACHED */
89 }
90 /*
91 * Dumpdates does not exist, make an empty one.
92 */
93 msg("WARNING: no file `%s', making an empty one\n", dumpdates);
94 if ((df = fopen(dumpdates, "w")) == NULL) {
95 quit("cannot create %s: %s\n", dumpdates,
96 strerror(errno));
97 /* NOTREACHED */
98 }
99 (void) fclose(df);
100 if ((df = fopen(dumpdates, "r")) == NULL) {
101 quit("cannot read %s even after creating it: %s\n",
102 dumpdates, strerror(errno));
103 /* NOTREACHED */
104 }
105 }
106 (void) flock(fileno(df), LOCK_SH);
107 readdumptimes(df);
108 (void) fclose(df);
109 }
110
111 static void
112 readdumptimes(df)
113 FILE *df;
114 {
115 int i;
116 struct dumptime *dtwalk;
117
118 for (;;) {
119 dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime));
120 if (getrecord(df, &(dtwalk->dt_value)) < 0)
121 break;
122 nddates++;
123 dtwalk->dt_next = dthead;
124 dthead = dtwalk;
125 }
126
127 ddates_in = 1;
128 /*
129 * arrayify the list, leaving enough room for the additional
130 * record that we may have to add to the ddate structure
131 */
132 ddatev = (struct dumpdates **)
133 calloc((unsigned) (nddates + 1), sizeof (struct dumpdates *));
134 dtwalk = dthead;
135 for (i = nddates - 1; i >= 0; i--, dtwalk = dtwalk->dt_next)
136 ddatev[i] = &dtwalk->dt_value;
137 }
138
139 void
140 getdumptime()
141 {
142 struct dumpdates *ddp;
143 int i;
144 char *fname;
145
146 fname = disk;
147 #ifdef FDEBUG
148 msg("Looking for name %s in dumpdates = %s for level = %c\n",
149 fname, dumpdates, level);
150 #endif
151 spcl.c_ddate = 0;
152 lastlevel = '0';
153
154 initdumptimes();
155 /*
156 * Go find the entry with the same name for a lower increment
157 * and older date
158 */
159 ITITERATE(i, ddp) {
160 if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0)
161 continue;
162 if (ddp->dd_level >= level)
163 continue;
164 if (ddp->dd_ddate <= spcl.c_ddate)
165 continue;
166 spcl.c_ddate = ddp->dd_ddate;
167 lastlevel = ddp->dd_level;
168 }
169 }
170
171 void
172 putdumptime()
173 {
174 FILE *df;
175 struct dumpdates *dtwalk;
176 int i;
177 int fd;
178 char *fname;
179
180 if(uflag == 0)
181 return;
182 if ((df = fopen(dumpdates, "r+")) == NULL)
183 quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno));
184 fd = fileno(df);
185 (void) flock(fd, LOCK_EX);
186 fname = disk;
187 free((char *)ddatev);
188 ddatev = 0;
189 nddates = 0;
190 dthead = 0;
191 ddates_in = 0;
192 readdumptimes(df);
193 if (fseek(df, 0L, 0) < 0)
194 quit("fseek: %s\n", strerror(errno));
195 spcl.c_ddate = 0;
196 ITITERATE(i, dtwalk) {
197 if (strncmp(fname, dtwalk->dd_name,
198 sizeof (dtwalk->dd_name)) != 0)
199 continue;
200 if (dtwalk->dd_level != level)
201 continue;
202 goto found;
203 }
204 /*
205 * construct the new upper bound;
206 * Enough room has been allocated.
207 */
208 dtwalk = ddatev[nddates] =
209 (struct dumpdates *)calloc(1, sizeof (struct dumpdates));
210 nddates += 1;
211 found:
212 (void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name));
213 dtwalk->dd_level = level;
214 dtwalk->dd_ddate = spcl.c_date;
215
216 ITITERATE(i, dtwalk) {
217 dumprecout(df, dtwalk);
218 }
219 if (fflush(df))
220 quit("%s: %s\n", dumpdates, strerror(errno));
221 if (ftruncate(fd, ftell(df)))
222 quit("ftruncate (%s): %s\n", dumpdates, strerror(errno));
223 (void) fclose(df);
224 msg("level %c dump on %s", level,
225 spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date));
226 }
227
228 static void
229 dumprecout(file, what)
230 FILE *file;
231 struct dumpdates *what;
232 {
233
234 if (fprintf(file, DUMPOUTFMT,
235 what->dd_name,
236 what->dd_level,
237 ctime(&what->dd_ddate)) < 0)
238 quit("%s: %s\n", dumpdates, strerror(errno));
239 }
240
241 int recno;
242
243 static int
244 getrecord(df, ddatep)
245 FILE *df;
246 struct dumpdates *ddatep;
247 {
248 char tbuf[BUFSIZ];
249
250 recno = 0;
251 if ( (fgets(tbuf, sizeof (tbuf), df)) != tbuf)
252 return(-1);
253 recno++;
254 if (makedumpdate(ddatep, tbuf) < 0)
255 msg("Unknown intermediate format in %s, line %d\n",
256 dumpdates, recno);
257
258 #ifdef FDEBUG
259 msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level,
260 ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate));
261 #endif
262 return(0);
263 }
264
265 static int
266 makedumpdate(ddp, tbuf)
267 struct dumpdates *ddp;
268 char *tbuf;
269 {
270 char un_buf[128];
271
272 (void) sscanf(tbuf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf);
273 ddp->dd_ddate = unctime(un_buf);
274 if (ddp->dd_ddate < 0)
275 return(-1);
276 return(0);
277 }
278