Add -n option to print major and minor version, e.g. 5.99 on -current.
[netbsd-mini2440.git] / sbin / dump / itime.c
blob3bb2e0cae10030bb69a675f9966b95687976d6a3
1 /* $NetBSD: itime.c,v 1.15 2003/08/07 10:04:14 agc Exp $ */
3 /*-
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)itime.c 8.1 (Berkeley) 6/5/93";
36 #else
37 __RCSID("$NetBSD: itime.c,v 1.15 2003/08/07 10:04:14 agc Exp $");
38 #endif
39 #endif /* not lint */
41 #include <sys/param.h>
42 #include <sys/queue.h>
43 #include <sys/time.h>
44 #include <ufs/ufs/dinode.h>
46 #include <protocols/dumprestore.h>
48 #include <errno.h>
49 #include <fcntl.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <time.h>
54 #include <unistd.h>
56 #include "dump.h"
58 struct dumptime {
59 struct dumpdates dt_value;
60 SLIST_ENTRY(dumptime) dt_list;
62 SLIST_HEAD(dthead, dumptime) dthead = SLIST_HEAD_INITIALIZER(dthead);
63 struct dumpdates **ddatev = 0;
64 int nddates = 0;
66 static void dumprecout(FILE *, struct dumpdates *);
67 static int getrecord(FILE *, struct dumpdates *);
68 static int makedumpdate(struct dumpdates *, char *);
69 static void readdumptimes(FILE *);
71 void
72 initdumptimes(void)
74 FILE *df;
76 if ((df = fopen(dumpdates, "r")) == NULL) {
77 if (errno != ENOENT) {
78 msg("WARNING: cannot read %s: %s\n", dumpdates,
79 strerror(errno));
80 return;
83 * Dumpdates does not exist, make an empty one.
85 msg("WARNING: no file `%s', making an empty one\n", dumpdates);
86 if ((df = fopen(dumpdates, "w")) == NULL) {
87 msg("WARNING: cannot create %s: %s\n", dumpdates,
88 strerror(errno));
89 return;
91 (void) fclose(df);
92 if ((df = fopen(dumpdates, "r")) == NULL) {
93 quit("cannot read %s even after creating it: %s\n",
94 dumpdates, strerror(errno));
95 /* NOTREACHED */
98 (void) flock(fileno(df), LOCK_SH);
99 readdumptimes(df);
100 (void) fclose(df);
103 static void
104 readdumptimes(FILE *df)
106 int i;
107 struct dumptime *dtwalk;
109 for (;;) {
110 dtwalk = (struct dumptime *)xcalloc(1, sizeof(struct dumptime));
111 if (getrecord(df, &(dtwalk->dt_value)) < 0) {
112 free(dtwalk);
113 break;
115 nddates++;
116 SLIST_INSERT_HEAD(&dthead, dtwalk, dt_list);
120 * arrayify the list, leaving enough room for the additional
121 * record that we may have to add to the ddate structure
123 ddatev = (struct dumpdates **)
124 xcalloc((unsigned) (nddates + 1), sizeof(struct dumpdates *));
125 dtwalk = SLIST_FIRST(&dthead);
126 for (i = nddates - 1; i >= 0; i--, dtwalk = SLIST_NEXT(dtwalk, dt_list))
127 ddatev[i] = &dtwalk->dt_value;
130 void
131 getdumptime(void)
133 struct dumpdates *ddp;
134 int i;
135 char *fname;
137 fname = disk;
138 #ifdef FDEBUG
139 msg("Looking for name %s in dumpdates = %s for level = %c\n",
140 fname, dumpdates, level);
141 #endif
142 spcl.c_ddate = 0;
143 lastlevel = '0';
145 initdumptimes();
147 * Go find the entry with the same name for a lower increment
148 * and older date
150 ITITERATE(i, ddp) {
151 if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0)
152 continue;
153 if (ddp->dd_level >= level)
154 continue;
155 if (ddp->dd_ddate <= iswap32(spcl.c_ddate))
156 continue;
157 spcl.c_ddate = iswap32(ddp->dd_ddate);
158 lastlevel = ddp->dd_level;
162 void
163 putdumptime(void)
165 FILE *df;
166 struct dumpdates *dtwalk, *dtfound;
167 int i;
168 int fd;
169 char *fname;
171 if(uflag == 0)
172 return;
173 if ((df = fopen(dumpdates, "r+")) == NULL)
174 quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno));
175 fd = fileno(df);
176 (void) flock(fd, LOCK_EX);
177 fname = disk;
178 free((char *)ddatev);
179 ddatev = 0;
180 nddates = 0;
181 readdumptimes(df);
182 if (fseek(df, 0L, 0) < 0)
183 quit("fseek: %s\n", strerror(errno));
184 spcl.c_ddate = 0;
185 ITITERATE(i, dtwalk) {
186 if (strncmp(fname, dtwalk->dd_name,
187 sizeof (dtwalk->dd_name)) != 0)
188 continue;
189 if (dtwalk->dd_level != level)
190 continue;
191 goto found;
194 * construct the new upper bound;
195 * Enough room has been allocated.
197 dtwalk = ddatev[nddates] =
198 (struct dumpdates *)xcalloc(1, sizeof (struct dumpdates));
199 nddates += 1;
200 found:
201 (void) strlcpy(dtwalk->dd_name, fname, sizeof(dtwalk->dd_name));
202 dtwalk->dd_level = level;
203 dtwalk->dd_ddate = iswap32(spcl.c_date);
204 dtfound = dtwalk;
206 ITITERATE(i, dtwalk) {
207 dumprecout(df, dtwalk);
209 if (fflush(df))
210 quit("%s: %s\n", dumpdates, strerror(errno));
211 if (ftruncate(fd, ftell(df)))
212 quit("ftruncate (%s): %s\n", dumpdates, strerror(errno));
213 (void) fclose(df);
214 msg("level %c dump on %s", level,
215 spcl.c_date == 0 ? "the epoch\n" : ctime(&dtfound->dd_ddate));
218 static void
219 dumprecout(FILE *file, struct dumpdates *what)
222 if (fprintf(file, DUMPOUTFMT,
223 what->dd_name,
224 what->dd_level,
225 ctime(&what->dd_ddate)) < 0)
226 quit("%s: %s\n", dumpdates, strerror(errno));
229 int recno;
231 static int
232 getrecord(FILE *df, struct dumpdates *ddatep)
234 char tbuf[BUFSIZ];
236 recno = 0;
237 if ( (fgets(tbuf, sizeof (tbuf), df)) != tbuf)
238 return(-1);
239 recno++;
240 if (makedumpdate(ddatep, tbuf) < 0)
241 msg("Unknown intermediate format in %s, line %d\n",
242 dumpdates, recno);
244 #ifdef FDEBUG
245 msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level,
246 ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate));
247 #endif
248 return(0);
251 static int
252 makedumpdate(struct dumpdates *ddp, char *tbuf)
254 char un_buf[128];
256 (void) sscanf(tbuf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf);
257 ddp->dd_ddate = unctime(un_buf);
258 if (ddp->dd_ddate < 0)
259 return(-1);
260 return(0);