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