vol: use ffs from opr instead of inline
[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     static char tbuffer[AFSDIR_PATH_MAX];
66
67     /* construct the backup dir path */
68     strcpy(tbuffer, AFSDIR_SERVER_BACKUP_DIRPATH);
69     strcat(tbuffer, "/T");
70     strcat(tbuffer + 1, atapeName);
71     strcat(tbuffer, ".db");
72     return tbuffer;
73 }
74
75 /* return the dump file name corresponding to a particular dump ID */
76
77 static char * DumpName(afs_int32 adumpID)
78 {
79     static char tbuffer[AFSDIR_PATH_MAX];
80     char buf[AFSDIR_PATH_MAX];
81
82     /* construct the backup dir path */
83     strcpy(buf, AFSDIR_SERVER_BACKUP_DIRPATH);
84     strcat(buf, "/D%d.db");
85     sprintf(tbuffer, buf, adumpID);
86     return tbuffer;
87 }
88
89 static FILE * OpenDump(afs_int32 adumpID, char * awrite)
90 {
91     char *tp;
92     FILE *tfile;
93
94     tp = DumpName(adumpID);
95     tfile = fopen(tp, awrite);
96     return tfile;
97 }
98
99 /* OpenTape
100  * notes:
101  *      non-static for recoverDB
102  */
103
104 FILE * OpenTape(char * atapeName, char * awrite)
105 {
106     char *tp;
107     FILE *tfile;
108     tp = TapeName(atapeName);
109     tfile = fopen(tp, awrite);
110     return tfile;
111 }
112
113 /* scan for, and delete, all dumps whose parent dump ID is aparentID */
114
115 static afs_int32 ScanForChildren(afs_int32 aparentID)
116 {
117     DIR *tdir;
118     struct dirent *tde;
119     afs_int32 dumpID, parent;
120     FILE *tfile;
121     afs_int32 code;
122     afs_int32 j2, j3, j4;
123     char dname[256];
124     char dumpName[1024];
125
126     tdir = opendir(AFSDIR_SERVER_BACKUP_DIRPATH);
127     if (!tdir)
128         return -1;
129
130     for (tde = readdir(tdir); tde; tde = readdir(tdir)) {
131         code = sscanf(tde->d_name, "D%ld.db", (long int *) &dumpID);
132         if (code != 1)
133             continue;
134
135         tfile = OpenDump(dumpID, "r");
136         if (!tfile)
137             continue;           /* shouldn't happen, but should continue anyway */
138
139         code = ScanDumpHdr(tfile, dname, dumpName, &parent, &j2, &j3, &j4);
140         fclose(tfile);
141         if (code) {
142             printf("backup:dsstub: bad dump header for dump %d\n", dumpID);
143             continue;
144         }
145
146         /* if this guy's parent is the ID we're scanning for, delete it */
147         if (aparentID == parent) {
148             code = DeleteDump(dumpID);
149             if (code)
150                 printf("backup:dsstub: failed to delete child dump %d\n",
151                        dumpID);
152         }
153     }
154     closedir(tdir);
155     return 0;
156 }
157
158 static afs_int32 DeleteDump(afs_int32 adumpID)
159 {
160     char *tp;
161     afs_int32 code;
162     tp = DumpName(adumpID);
163     code = unlink(tp);
164     if (code)
165         return code;
166     code = ScanForChildren(adumpID);
167     return code;
168 }
169
170 #if 0
171 static afs_int32 DeleteTape(char * atapeName)
172 {
173     char *tp;
174     afs_int32 code;
175     tp = TapeName(atapeName);
176     code = unlink(tp);
177     return code;
178 }
179 #endif
180
181 /* tailCompPtr
182  *      name is a pathname style name, determine trailing name and return
183  *      pointer to it
184  */
185
186 char *
187 tailCompPtr(char *pathNamePtr)
188 {
189     char *ptr;
190     ptr = strrchr(pathNamePtr, '/');
191     if (ptr == 0) {
192         /* this should never happen */
193         printf("tailCompPtr: could not find / in name(%s)\n", pathNamePtr);
194         return (pathNamePtr);
195     } else
196         ptr++;                  /* skip the / */
197     return (ptr);
198 }
199
200 /* ScanDumpHdr
201  *      scan a dump header out of a dump file, leaving the file ptr set after
202  *      the header.
203  * entry:
204  *      afile - ptr to file, for reading.
205  *      various - ptrs for return values
206  * exit:
207  *      aname - string of form volume_set.dump_level
208  *      dumpName - pathname of dump schedule node
209  *      aparent - id of parent
210  *      aincTime
211  *      acreateTime - time at which dump was created
212  *      alevel - level of dump (0 = full, 1+ are incrementals)
213  */
214 afs_int32
215 ScanDumpHdr(FILE *afile, char *aname, char *dumpName, afs_int32 *aparent, afs_int32 *aincTime, afs_int32 *acreateTime, afs_int32 *alevel)
216 {
217     char tbuffer[256];
218     char *tp;
219     afs_int32 dbmagic, dbversion;
220     afs_int32 code;
221
222     tp = fgets(tbuffer, sizeof(tbuffer), afile);
223     if (!tp)
224         return -1;
225     code =
226         sscanf(tbuffer, "%d %d %s %s %ld %ld %ld %ld", &dbmagic, &dbversion,
227                aname, dumpName, (long int *) aparent, (long int *) aincTime,
228                (long int *) acreateTime, (long int *) alevel);
229     if (code != 8)
230         return -1;
231
232     /* now check the magic and version numbers */
233     if ((dbmagic != BC_DUMPDB_MAGIC) || (dbversion != BC_DUMPDB_VERSION))
234         return (-1);
235
236     return 0;
237 }
238
239 #if 0
240 /* scan a tape header out of a tape file, leaving the file ptr positioned just past the header */
241 static afs_int32 ScanTapeHdr(FILE *afile, afs_int32 *adumpID, afs_int32 *aseq, afs_int32 *adamage)
242 {
243     char tbuffer[256];
244     char *tp;
245     afs_int32 code;
246
247     tp = fgets(tbuffer, sizeof(tbuffer), afile);
248     if (!tp)
249         return -1;
250     code = sscanf(tbuffer, "%ld %ld %ld", (long int *)adumpID,
251                   (long int *)aseq, (long int *)adamage);
252     if (code != 3)
253         return -1;
254     return 0;
255 }
256 #endif
257
258 /* ScanTapeVolume
259  *      scan a tape volume record from a dump file, leaving the file ptr
260  *      positioned past the just-scanned record.
261  * exit:
262  *      0 - success
263  *      1 - EOF
264  *      -1 for error
265  */
266
267 afs_int32 ScanTapeVolume(FILE *afile, char *avolName, afs_int32 *avolID, char *atapeName, afs_int32 *apos, afs_int32 *aseq, afs_int32 *alastp, afs_int32 *cloneTime)
268 {
269     char tbuffer[256];
270     afs_int32 code;
271     char *tp;
272
273     tp = fgets(tbuffer, sizeof(tbuffer), afile);
274     if (!tp) {                  /* something went wrong, or eof hit */
275         if (ferror(afile))
276             return -1;          /* error occurred */
277         else
278             return 1;           /* eof */
279     }
280     code =
281         sscanf(tbuffer, "%s %ld %s %ld %ld %ld %ld", avolName,
282                (long int *) avolID, atapeName, (long int *)apos,
283                (long int *) aseq, (long int *) alastp,
284                (long int *) cloneTime);
285     if (code != 7)
286         return -1;              /* bad input line */
287     return 0;
288 }
289
290 /* ScanVolClone
291  *      Search the dump for the volume with name volName, and return it's
292  *      clone time.
293  * exit:
294  *      0 - clonetime set.
295  *      -1 - volume with volName not found
296  */
297
298 afs_int32 ScanVolClone(FILE *tdump, char *volName, afs_int32 *cloneTime)
299 {
300     char avolName[256], atapeName[256];
301     afs_int32 retval, avolID, apos, aseq, alastp;
302
303     retval =
304         ScanTapeVolume(tdump, &avolName[0], &avolID, &atapeName[0], &apos,
305                        &aseq, &alastp, cloneTime);
306     while (retval == 0) {
307         if (strcmp(avolName, volName) == 0)
308             return (0);
309         retval =
310             ScanTapeVolume(tdump, &avolName[0], &avolID, &atapeName[0], &apos,
311                            &aseq, &alastp, cloneTime);
312     }
313     return (-1);
314 }
315
316 #if 0
317 /* seek a dump file (after a header scan has been done) to position apos */
318 static int SeekDump(FILE *afile, afs_int32 apos)
319 {
320     afs_int32 i;
321     char *tp;
322     char tbuffer[256];
323
324     /* now skip to appropriate position */
325     for (i = 0; i < apos; i++) {
326         tp = fgets(tbuffer, sizeof(tbuffer), afile);
327         if (!tp) {
328             fclose(afile);
329             return -1;
330         }
331     }
332     return 0;
333 }
334 #endif