2 * Copyright 2000, International Business Machines Corporation and others.
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
14 #include <afsconfig.h>
15 #include <afs/param.h>
18 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
30 #include <afs/afsutil.h>
32 #include <afs/bubasics.h>
33 #include <afs/volser.h>
38 static char * TapeName(register char *);
39 static char * DumpName(register afs_int32 adumpID);
40 static FILE * OpenDump(afs_int32 , char * );
41 FILE * OpenTape(char * , char * );
42 static afs_int32 ScanForChildren(afs_int32 );
43 static afs_int32 DeleteDump(afs_int32 );
44 char * tailCompPtr(char *);
45 afs_int32 ScanDumpHdr(register FILE *, char *, char *, afs_int32 *, afs_int32 *,
46 afs_int32 *, afs_int32 *);
47 afs_int32 ScanTapeVolume(FILE *, char *, afs_int32 *, char *, afs_int32 *, afs_int32 *,
48 afs_int32 *, afs_int32 *);
49 afs_int32 ScanVolClone(FILE *, char *, afs_int32 *);
52 /* basic format of a tape file is a file, whose name is "T<tapename>.db", and
53 * which contains the fields
54 * (afs_int32) dumpID, (afs_int32) tape-sequence-within-dump, (afs_int32) damage_flag
55 * all as space-separated integers.
58 /* The format of a dump file is:
59 * a file whose name is "D<dump#>.db"
60 * and whose contents are a header line:
61 * (string) dumpName, (long) parent-id, (long) incTime, (long) dumpEndTime, (long) level
62 * and a bunch of bcdb_volumeEntries with this format:
63 * (string) volume name, (long) volume ID, (string) tape name, (long) position-on-tape,
64 * (long) sequence-in-volume-dump, (long) is-this-the-last-vol-frag, (long) incTime
65 * again, all space-separated.
66 * Note that dumpEndTime is stored and returned in the dump creation time field.
69 /* return the tape file name corresponding to a particular tape */
71 static char * TapeName(register char *atapeName)
73 static char tbuffer[AFSDIR_PATH_MAX];
75 /* construct the backup dir path */
76 strcpy(tbuffer, AFSDIR_SERVER_BACKUP_DIRPATH);
77 strcat(tbuffer, "/T");
78 strcat(tbuffer + 1, atapeName);
79 strcat(tbuffer, ".db");
83 /* return the dump file name corresponding to a particular dump ID */
85 static char * DumpName(register afs_int32 adumpID)
87 static char tbuffer[AFSDIR_PATH_MAX];
88 char buf[AFSDIR_PATH_MAX];
90 /* construct the backup dir path */
91 strcpy(buf, AFSDIR_SERVER_BACKUP_DIRPATH);
92 strcat(buf, "/D%d.db");
93 sprintf(tbuffer, buf, adumpID);
97 static FILE * OpenDump(afs_int32 adumpID, char * awrite)
100 register FILE *tfile;
102 tp = DumpName(adumpID);
103 tfile = fopen(tp, awrite);
109 * non-static for recoverDB
112 FILE * OpenTape(char * atapeName, char * awrite)
115 register FILE *tfile;
116 tp = TapeName(atapeName);
117 tfile = fopen(tp, awrite);
121 /* scan for, and delete, all dumps whose parent dump ID is aparentID */
123 static afs_int32 ScanForChildren(afs_int32 aparentID)
126 register struct dirent *tde;
127 afs_int32 dumpID, parent;
128 register FILE *tfile;
129 register afs_int32 code;
130 afs_int32 j2, j3, j4;
134 tdir = opendir(AFSDIR_SERVER_BACKUP_DIRPATH);
138 for (tde = readdir(tdir); tde; tde = readdir(tdir)) {
139 code = sscanf(tde->d_name, "D%ld.db", (long int *) &dumpID);
143 tfile = OpenDump(dumpID, "r");
145 continue; /* shouldn't happen, but should continue anyway */
147 code = ScanDumpHdr(tfile, dname, dumpName, &parent, &j2, &j3, &j4);
150 printf("backup:dsstub: bad dump header for dump %d\n", dumpID);
154 /* if this guy's parent is the ID we're scanning for, delete it */
155 if (aparentID == parent) {
156 code = DeleteDump(dumpID);
158 printf("backup:dsstub: failed to delete child dump %d\n",
166 static afs_int32 DeleteDump(afs_int32 adumpID)
169 register afs_int32 code;
170 tp = DumpName(adumpID);
174 code = ScanForChildren(adumpID);
179 static afs_int32 DeleteTape(char * atapeName)
182 register afs_int32 code;
183 tp = TapeName(atapeName);
190 * name is a pathname style name, determine trailing name and return
195 tailCompPtr(char *pathNamePtr)
198 ptr = strrchr(pathNamePtr, '/');
200 /* this should never happen */
201 printf("tailCompPtr: could not find / in name(%s)\n", pathNamePtr);
202 return (pathNamePtr);
204 ptr++; /* skip the / */
209 * scan a dump header out of a dump file, leaving the file ptr set after
212 * afile - ptr to file, for reading.
213 * various - ptrs for return values
215 * aname - string of form volume_set.dump_level
216 * dumpName - pathname of dump schedule node
217 * aparent - id of parent
219 * acreateTime - time at which dump was created
220 * alevel - level of dump (0 = full, 1+ are incrementals)
223 ScanDumpHdr(register FILE *afile, char *aname, char *dumpName, afs_int32 *aparent, afs_int32 *aincTime, afs_int32 *acreateTime, afs_int32 *alevel)
227 afs_int32 dbmagic, dbversion;
228 register afs_int32 code;
230 tp = fgets(tbuffer, sizeof(tbuffer), afile);
234 sscanf(tbuffer, "%d %d %s %s %ld %ld %ld %ld", &dbmagic, &dbversion,
235 aname, dumpName, (long int *) aparent, (long int *) aincTime,
236 (long int *) acreateTime, (long int *) alevel);
240 /* now check the magic and version numbers */
241 if ((dbmagic != BC_DUMPDB_MAGIC) || (dbversion != BC_DUMPDB_VERSION))
248 /* scan a tape header out of a tape file, leaving the file ptr positioned just past the header */
249 static afs_int32 ScanTapeHdr(register FILE *afile, afs_int32 *adumpID, afs_int32 *aseq, afs_int32 *adamage)
253 register afs_int32 code;
255 tp = fgets(tbuffer, sizeof(tbuffer), afile);
258 code = sscanf(tbuffer, "%ld %ld %ld", (long int *)adumpID,
259 (long int *)aseq, (long int *)adamage);
267 * scan a tape volume record from a dump file, leaving the file ptr
268 * positioned past the just-scanned record.
275 afs_int32 ScanTapeVolume(FILE *afile, char *avolName, afs_int32 *avolID, char *atapeName, afs_int32 *apos, afs_int32 *aseq, afs_int32 *alastp, afs_int32 *cloneTime)
278 register afs_int32 code;
281 tp = fgets(tbuffer, sizeof(tbuffer), afile);
282 if (!tp) { /* something went wrong, or eof hit */
284 return -1; /* error occurred */
289 sscanf(tbuffer, "%s %ld %s %ld %ld %ld %ld", avolName,
290 (long int *) avolID, atapeName, (long int *)apos,
291 (long int *) aseq, (long int *) alastp,
292 (long int *) cloneTime);
294 return -1; /* bad input line */
299 * Search the dump for the volume with name volName, and return it's
303 * -1 - volume with volName not found
306 afs_int32 ScanVolClone(FILE *tdump, char *volName, afs_int32 *cloneTime)
308 char avolName[256], atapeName[256];
309 afs_int32 retval, avolID, apos, aseq, alastp;
312 ScanTapeVolume(tdump, &avolName[0], &avolID, &atapeName[0], &apos,
313 &aseq, &alastp, cloneTime);
314 while (retval == 0) {
315 if (strcmp(avolName, volName) == 0)
318 ScanTapeVolume(tdump, &avolName[0], &avolID, &atapeName[0], &apos,
319 &aseq, &alastp, cloneTime);
325 /* seek a dump file (after a header scan has been done) to position apos */
326 static int SeekDump(register FILE *afile, afs_int32 apos)
328 register afs_int32 i;
332 /* now skip to appropriate position */
333 for (i = 0; i < apos; i++) {
334 tp = fgets(tbuffer, sizeof(tbuffer), afile);