Allocate pathname buffers dynamically
[openafs.git] / src / bucoord / dsstub.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * ALL RIGHTS RESERVED
12  */
13
14 #include <afsconfig.h>
15 #include <afs/param.h>
16
17 #include <roken.h>
18
19 #include <afs/cmd.h>
20 #include <afs/afsutil.h>
21 #include <afs/budb.h>
22 #include <afs/bubasics.h>
23 #include <afs/afsint.h>
24 #include <afs/volser.h>
25
26 #include "bc.h"
27
28 /* protos */
29
30 static char * TapeName(char *);
31 static char * DumpName(afs_int32 adumpID);
32 static FILE * OpenDump(afs_int32 , char * );
33 FILE * OpenTape(char * , char * );
34 static afs_int32 ScanForChildren(afs_int32 );
35 static afs_int32 DeleteDump(afs_int32 );
36 char * tailCompPtr(char *);
37 afs_int32 ScanDumpHdr(FILE *, char *, char *, afs_int32 *, afs_int32 *,
38   afs_int32 *, afs_int32 *);
39 afs_int32 ScanTapeVolume(FILE *, char *, afs_int32 *, char *, afs_int32 *, afs_int32 *,
40    afs_int32 *, afs_int32 *);
41 afs_int32 ScanVolClone(FILE *, char *, afs_int32 *);
42
43
44 /* basic format of a tape file is a file, whose name is "T<tapename>.db", and
45  * which contains the fields
46  * (afs_int32) dumpID, (afs_int32) tape-sequence-within-dump, (afs_int32) damage_flag
47  * all as space-separated integers.
48  */
49
50 /* The format of a dump file is:
51  * a file whose name is "D<dump#>.db"
52  * and whose contents are a header line:
53  * (string) dumpName, (long) parent-id, (long) incTime, (long) dumpEndTime, (long) level
54  * and a bunch of bcdb_volumeEntries with this format:
55  * (string) volume name, (long) volume ID, (string) tape name, (long) position-on-tape,
56  *     (long) sequence-in-volume-dump, (long) is-this-the-last-vol-frag, (long) incTime
57  * again, all space-separated.
58  * Note that dumpEndTime is stored and returned in the dump creation time field.
59  */
60
61 /* return the tape file name corresponding to a particular tape */
62
63 static char * TapeName(char *atapeName)
64 {
65     char *tbuffer;
66
67     if (asprintf(&tbuffer, "%s/T%s.db", AFSDIR_SERVER_BACKUP_DIRPATH,
68                  atapeName) < 0)
69         return NULL;
70     return tbuffer;
71 }
72
73 /* return the dump file name corresponding to a particular dump ID */
74
75 static char * DumpName(afs_int32 adumpID)
76 {
77     char *tbuffer;
78
79     if (asprintf(&tbuffer, "%s/D%d.db", AFSDIR_SERVER_BACKUP_DIRPATH,
80                  adumpID) < 0)
81         return NULL;
82     return tbuffer;
83 }
84
85 static FILE * OpenDump(afs_int32 adumpID, char * awrite)
86 {
87     char *tp;
88     FILE *tfile;
89
90     tp = DumpName(adumpID);
91     if (tp == NULL)
92         return NULL;
93     tfile = fopen(tp, awrite);
94     free(tp);
95     return tfile;
96 }
97
98 /* OpenTape
99  * notes:
100  *      non-static for recoverDB
101  */
102
103 FILE * OpenTape(char * atapeName, char * awrite)
104 {
105     char *tp;
106     FILE *tfile;
107
108     tp = TapeName(atapeName);
109     if (tp == NULL)
110         return NULL;
111     tfile = fopen(tp, awrite);
112     free(tp);
113     return tfile;
114 }
115
116 /* scan for, and delete, all dumps whose parent dump ID is aparentID */
117
118 static afs_int32 ScanForChildren(afs_int32 aparentID)
119 {
120     DIR *tdir;
121     struct dirent *tde;
122     afs_int32 dumpID, parent;
123     FILE *tfile;
124     afs_int32 code;
125     afs_int32 j2, j3, j4;
126     char dname[256];
127     char dumpName[1024];
128
129     tdir = opendir(AFSDIR_SERVER_BACKUP_DIRPATH);
130     if (!tdir)
131         return -1;
132
133     for (tde = readdir(tdir); tde; tde = readdir(tdir)) {
134         code = sscanf(tde->d_name, "D%ld.db", (long int *) &dumpID);
135         if (code != 1)
136             continue;
137
138         tfile = OpenDump(dumpID, "r");
139         if (!tfile)
140             continue;           /* shouldn't happen, but should continue anyway */
141
142         code = ScanDumpHdr(tfile, dname, dumpName, &parent, &j2, &j3, &j4);
143         fclose(tfile);
144         if (code) {
145             printf("backup:dsstub: bad dump header for dump %d\n", dumpID);
146             continue;
147         }
148
149         /* if this guy's parent is the ID we're scanning for, delete it */
150         if (aparentID == parent) {
151             code = DeleteDump(dumpID);
152             if (code)
153                 printf("backup:dsstub: failed to delete child dump %d\n",
154                        dumpID);
155         }
156     }
157     closedir(tdir);
158     return 0;
159 }
160
161 static afs_int32 DeleteDump(afs_int32 adumpID)
162 {
163     char *tp;
164     afs_int32 code;
165
166     tp = DumpName(adumpID);
167     if (tp == NULL)
168         return ENOMEM;
169     code = unlink(tp);
170     free(tp);
171     if (code)
172         return code;
173     code = ScanForChildren(adumpID);
174     return code;
175 }
176
177 #if 0
178 static afs_int32 DeleteTape(char * atapeName)
179 {
180     char *tp;
181     afs_int32 code;
182
183     tp = TapeName(atapeName);
184     if (tp == NULL)
185         return ENOMEM;
186     code = unlink(tp);
187     free(tp);
188     return code;
189 }
190 #endif
191
192 /* tailCompPtr
193  *      name is a pathname style name, determine trailing name and return
194  *      pointer to it
195  */
196
197 char *
198 tailCompPtr(char *pathNamePtr)
199 {
200     char *ptr;
201     ptr = strrchr(pathNamePtr, '/');
202     if (ptr == 0) {
203         /* this should never happen */
204         printf("tailCompPtr: could not find / in name(%s)\n", pathNamePtr);
205         return (pathNamePtr);
206     } else
207         ptr++;                  /* skip the / */
208     return (ptr);
209 }
210
211 /* ScanDumpHdr
212  *      scan a dump header out of a dump file, leaving the file ptr set after
213  *      the header.
214  * entry:
215  *      afile - ptr to file, for reading.
216  *      various - ptrs for return values
217  * exit:
218  *      aname - string of form volume_set.dump_level
219  *      dumpName - pathname of dump schedule node
220  *      aparent - id of parent
221  *      aincTime
222  *      acreateTime - time at which dump was created
223  *      alevel - level of dump (0 = full, 1+ are incrementals)
224  */
225 afs_int32
226 ScanDumpHdr(FILE *afile, char *aname, char *dumpName, afs_int32 *aparent, afs_int32 *aincTime, afs_int32 *acreateTime, afs_int32 *alevel)
227 {
228     char tbuffer[256];
229     char *tp;
230     afs_int32 dbmagic, dbversion;
231     afs_int32 code;
232
233     tp = fgets(tbuffer, sizeof(tbuffer), afile);
234     if (!tp)
235         return -1;
236     code =
237         sscanf(tbuffer, "%d %d %s %s %ld %ld %ld %ld", &dbmagic, &dbversion,
238                aname, dumpName, (long int *) aparent, (long int *) aincTime,
239                (long int *) acreateTime, (long int *) alevel);
240     if (code != 8)
241         return -1;
242
243     /* now check the magic and version numbers */
244     if ((dbmagic != BC_DUMPDB_MAGIC) || (dbversion != BC_DUMPDB_VERSION))
245         return (-1);
246
247     return 0;
248 }
249
250 #if 0
251 /* scan a tape header out of a tape file, leaving the file ptr positioned just past the header */
252 static afs_int32 ScanTapeHdr(FILE *afile, afs_int32 *adumpID, afs_int32 *aseq, afs_int32 *adamage)
253 {
254     char tbuffer[256];
255     char *tp;
256     afs_int32 code;
257
258     tp = fgets(tbuffer, sizeof(tbuffer), afile);
259     if (!tp)
260         return -1;
261     code = sscanf(tbuffer, "%ld %ld %ld", (long int *)adumpID,
262                   (long int *)aseq, (long int *)adamage);
263     if (code != 3)
264         return -1;
265     return 0;
266 }
267 #endif
268
269 /* ScanTapeVolume
270  *      scan a tape volume record from a dump file, leaving the file ptr
271  *      positioned past the just-scanned record.
272  * exit:
273  *      0 - success
274  *      1 - EOF
275  *      -1 for error
276  */
277
278 afs_int32 ScanTapeVolume(FILE *afile, char *avolName, afs_int32 *avolID, char *atapeName, afs_int32 *apos, afs_int32 *aseq, afs_int32 *alastp, afs_int32 *cloneTime)
279 {
280     char tbuffer[256];
281     afs_int32 code;
282     char *tp;
283
284     tp = fgets(tbuffer, sizeof(tbuffer), afile);
285     if (!tp) {                  /* something went wrong, or eof hit */
286         if (ferror(afile))
287             return -1;          /* error occurred */
288         else
289             return 1;           /* eof */
290     }
291     code =
292         sscanf(tbuffer, "%s %ld %s %ld %ld %ld %ld", avolName,
293                (long int *) avolID, atapeName, (long int *)apos,
294                (long int *) aseq, (long int *) alastp,
295                (long int *) cloneTime);
296     if (code != 7)
297         return -1;              /* bad input line */
298     return 0;
299 }
300
301 /* ScanVolClone
302  *      Search the dump for the volume with name volName, and return it's
303  *      clone time.
304  * exit:
305  *      0 - clonetime set.
306  *      -1 - volume with volName not found
307  */
308
309 afs_int32 ScanVolClone(FILE *tdump, char *volName, afs_int32 *cloneTime)
310 {
311     char avolName[256], atapeName[256];
312     afs_int32 retval, avolID, apos, aseq, alastp;
313
314     retval =
315         ScanTapeVolume(tdump, &avolName[0], &avolID, &atapeName[0], &apos,
316                        &aseq, &alastp, cloneTime);
317     while (retval == 0) {
318         if (strcmp(avolName, volName) == 0)
319             return (0);
320         retval =
321             ScanTapeVolume(tdump, &avolName[0], &avolID, &atapeName[0], &apos,
322                            &aseq, &alastp, cloneTime);
323     }
324     return (-1);
325 }
326
327 #if 0
328 /* seek a dump file (after a header scan has been done) to position apos */
329 static int SeekDump(FILE *afile, afs_int32 apos)
330 {
331     afs_int32 i;
332     char *tp;
333     char tbuffer[256];
334
335     /* now skip to appropriate position */
336     for (i = 0; i < apos; i++) {
337         tp = fgets(tbuffer, sizeof(tbuffer), afile);
338         if (!tp) {
339             fclose(afile);
340             return -1;
341         }
342     }
343     return 0;
344 }
345 #endif