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 <afs/param.h>
15 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
27 #include <afs/afsutil.h>
29 #include <afs/bubasics.h>
30 #include <afs/volser.h>
32 #define dprintf /* debug */
34 /* basic format of a tape file is a file, whose name is "T<tapename>.db", and
35 * which contains the fields
36 * (afs_int32) dumpID, (afs_int32) tape-sequence-within-dump, (afs_int32) damage_flag
37 * all as space-separated integers.
40 /* The format of a dump file is:
41 * a file whose name is "D<dump#>.db"
42 * and whose contents are a header line:
43 * (string) dumpName, (long) parent-id, (long) incTime, (long) dumpEndTime, (long) level
44 * and a bunch of bcdb_volumeEntries with this format:
45 * (string) volume name, (long) volume ID, (string) tape name, (long) position-on-tape,
46 * (long) sequence-in-volume-dump, (long) is-this-the-last-vol-frag, (long) incTime
47 * again, all space-separated.
48 * Note that dumpEndTime is stored and returned in the dump creation time field.
51 afs_int32 DeleteDump();
52 afs_int32 ScanDumpHdr();
54 /* return the tape file name corresponding to a particular tape */
55 static char *TapeName(atapeName)
56 register char *atapeName; {
57 static char tbuffer[AFSDIR_PATH_MAX];
59 /* construct the backup dir path */
60 strcpy(tbuffer, AFSDIR_SERVER_BACKUP_DIRPATH);
61 strcat(tbuffer, "/T");
62 strcat(tbuffer+1, atapeName);
63 strcat(tbuffer, ".db");
67 /* return the dump file name corresponding to a particular dump ID */
68 static char *DumpName(adumpID)
69 register afs_int32 adumpID;
71 static char tbuffer[AFSDIR_PATH_MAX];
72 char buf[AFSDIR_PATH_MAX];
74 /* construct the backup dir path */
75 strcpy(buf, AFSDIR_SERVER_BACKUP_DIRPATH);
76 strcat(buf, "/D%d.db");
77 sprintf(tbuffer, buf, adumpID);
81 static FILE *OpenDump(adumpID, awrite)
87 tp = DumpName(adumpID);
88 tfile = fopen(tp, awrite);
94 * non-static for recoverDB
97 FILE *OpenTape(atapeName, awrite)
101 register FILE *tfile;
102 tp = TapeName(atapeName);
103 tfile = fopen(tp, awrite);
107 /* scan for, and delete, all dumps whose parent dump ID is aparentID */
108 static afs_int32 ScanForChildren(aparentID)
109 afs_int32 aparentID; {
111 register struct dirent *tde;
112 afs_int32 dumpID, parent;
113 register FILE *tfile;
114 register afs_int32 code;
115 afs_int32 j2, j3, j4;
119 tdir = opendir(AFSDIR_SERVER_BACKUP_DIRPATH);
120 if (!tdir) return -1;
122 for(tde=readdir(tdir); tde; tde=readdir(tdir)) {
123 code = sscanf(tde->d_name, "D%ld.db", &dumpID);
124 if (code != 1) continue;
126 tfile = OpenDump(dumpID, "r");
127 if (!tfile) continue; /* shouldn't happen, but should continue anyway */
129 code = ScanDumpHdr(tfile, dname, dumpName, &parent, &j2, &j3, &j4);
132 printf("backup:dsstub: bad dump header for dump %d\n", dumpID);
136 /* if this guy's parent is the ID we're scanning for, delete it */
137 if (aparentID == parent) {
138 code = DeleteDump(dumpID);
139 if (code) printf("backup:dsstub: failed to delete child dump %d\n", dumpID);
146 static afs_int32 DeleteDump(adumpID)
149 register afs_int32 code;
150 tp = DumpName(adumpID);
152 if (code) return code;
153 code = ScanForChildren(adumpID);
157 static afs_int32 DeleteTape(atapeName)
160 register afs_int32 code;
161 tp = TapeName(atapeName);
167 * name is a pathname style name, determine trailing name and return
172 tailCompPtr(pathNamePtr)
176 ptr = rindex(pathNamePtr, '/');
179 /* this should never happen */
180 printf("tailCompPtr: could not find / in name(%s)\n",
185 ptr++; /* skip the / */
190 * scan a dump header out of a dump file, leaving the file ptr set after
193 * afile - ptr to file, for reading.
194 * various - ptrs for return values
196 * aname - string of form volume_set.dump_level
197 * dumpName - pathname of dump schedule node
198 * aparent - id of parent
200 * acreateTime - time at which dump was created
201 * alevel - level of dump (0 = full, 1+ are incrementals)
204 ScanDumpHdr(afile, aname, dumpName, aparent, aincTime, acreateTime, alevel)
205 register FILE *afile;
209 afs_int32 *acreateTime;
215 afs_int32 dbmagic, dbversion;
216 register afs_int32 code;
218 tp = fgets(tbuffer, sizeof(tbuffer), afile);
220 code = sscanf(tbuffer, "%d %d %s %s %ld %ld %ld %ld",
221 &dbmagic, &dbversion,
222 aname, dumpName, aparent, aincTime, acreateTime, alevel);
223 if (code != 8) return -1;
225 /* now check the magic and version numbers */
226 if ( (dbmagic != BC_DUMPDB_MAGIC) || (dbversion != BC_DUMPDB_VERSION) )
232 /* scan a tape header out of a tape file, leaving the file ptr positioned just past the header */
233 static afs_int32 ScanTapeHdr(afile, adumpID, aseq, adamage)
234 register FILE *afile;
237 afs_int32 *adamage; {
240 register afs_int32 code;
242 tp = fgets(tbuffer, sizeof(tbuffer), afile);
244 code = sscanf(tbuffer, "%ld %ld %ld", adumpID, aseq, adamage);
245 if (code != 3) return -1;
250 * scan a tape volume record from a dump file, leaving the file ptr
251 * positioned past the just-scanned record.
259 ScanTapeVolume(afile, avolName, avolID, atapeName, apos, aseq, alastp,
265 afs_int32 *apos, *aseq, *alastp, *cloneTime; {
267 register afs_int32 code;
270 tp = fgets(tbuffer, sizeof(tbuffer), afile);
271 if (!tp) { /* something went wrong, or eof hit */
272 if (ferror(afile)) return -1; /* error occurred */
273 else return 1; /* eof */
275 code = sscanf(tbuffer, "%s %ld %s %ld %ld %ld %ld", avolName, avolID,
276 atapeName, apos, aseq, alastp, cloneTime);
277 if (code != 7) return -1; /* bad input line */
282 * Search the dump for the volume with name volName, and return it's
286 * -1 - volume with volName not found
290 ScanVolClone(tdump, volName, cloneTime)
293 afs_int32 *cloneTime;
295 char avolName[256], atapeName[256];
296 afs_int32 retval, avolID, apos, aseq, alastp;
298 retval = ScanTapeVolume(tdump, &avolName[0], &avolID, &atapeName[0],
299 &apos, &aseq, &alastp, cloneTime);
300 while ( retval == 0 )
302 if ( strcmp(avolName, volName) == 0 )
304 retval = ScanTapeVolume(tdump, &avolName[0], &avolID, &atapeName[0],
305 &apos, &aseq, &alastp, cloneTime);
310 /* seek a dump file (after a header scan has been done) to position apos */
311 static SeekDump(afile, apos)
312 register FILE *afile;
314 register afs_int32 i;
318 /* now skip to appropriate position */
319 for(i=0;i<apos; i++) {
320 tp = fgets(tbuffer, sizeof(tbuffer), afile);