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