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 <afsconfig.h>
19 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
31 #include <afs/afsutil.h>
33 #include <afs/bubasics.h>
34 #include <afs/volser.h>
36 #define dprintf /* debug */
38 /* basic format of a tape file is a file, whose name is "T<tapename>.db", and
39 * which contains the fields
40 * (afs_int32) dumpID, (afs_int32) tape-sequence-within-dump, (afs_int32) damage_flag
41 * all as space-separated integers.
44 /* The format of a dump file is:
45 * a file whose name is "D<dump#>.db"
46 * and whose contents are a header line:
47 * (string) dumpName, (long) parent-id, (long) incTime, (long) dumpEndTime, (long) level
48 * and a bunch of bcdb_volumeEntries with this format:
49 * (string) volume name, (long) volume ID, (string) tape name, (long) position-on-tape,
50 * (long) sequence-in-volume-dump, (long) is-this-the-last-vol-frag, (long) incTime
51 * again, all space-separated.
52 * Note that dumpEndTime is stored and returned in the dump creation time field.
55 afs_int32 DeleteDump();
56 afs_int32 ScanDumpHdr();
58 /* return the tape file name corresponding to a particular tape */
59 static char *TapeName(atapeName)
60 register char *atapeName; {
61 static char tbuffer[AFSDIR_PATH_MAX];
63 /* construct the backup dir path */
64 strcpy(tbuffer, AFSDIR_SERVER_BACKUP_DIRPATH);
65 strcat(tbuffer, "/T");
66 strcat(tbuffer+1, atapeName);
67 strcat(tbuffer, ".db");
71 /* return the dump file name corresponding to a particular dump ID */
72 static char *DumpName(adumpID)
73 register afs_int32 adumpID;
75 static char tbuffer[AFSDIR_PATH_MAX];
76 char buf[AFSDIR_PATH_MAX];
78 /* construct the backup dir path */
79 strcpy(buf, AFSDIR_SERVER_BACKUP_DIRPATH);
80 strcat(buf, "/D%d.db");
81 sprintf(tbuffer, buf, adumpID);
85 static FILE *OpenDump(adumpID, awrite)
91 tp = DumpName(adumpID);
92 tfile = fopen(tp, awrite);
98 * non-static for recoverDB
101 FILE *OpenTape(atapeName, awrite)
105 register FILE *tfile;
106 tp = TapeName(atapeName);
107 tfile = fopen(tp, awrite);
111 /* scan for, and delete, all dumps whose parent dump ID is aparentID */
112 static afs_int32 ScanForChildren(aparentID)
113 afs_int32 aparentID; {
115 register struct dirent *tde;
116 afs_int32 dumpID, parent;
117 register FILE *tfile;
118 register afs_int32 code;
119 afs_int32 j2, j3, j4;
123 tdir = opendir(AFSDIR_SERVER_BACKUP_DIRPATH);
124 if (!tdir) return -1;
126 for(tde=readdir(tdir); tde; tde=readdir(tdir)) {
127 code = sscanf(tde->d_name, "D%ld.db", &dumpID);
128 if (code != 1) continue;
130 tfile = OpenDump(dumpID, "r");
131 if (!tfile) continue; /* shouldn't happen, but should continue anyway */
133 code = ScanDumpHdr(tfile, dname, dumpName, &parent, &j2, &j3, &j4);
136 printf("backup:dsstub: bad dump header for dump %d\n", dumpID);
140 /* if this guy's parent is the ID we're scanning for, delete it */
141 if (aparentID == parent) {
142 code = DeleteDump(dumpID);
143 if (code) printf("backup:dsstub: failed to delete child dump %d\n", dumpID);
150 static afs_int32 DeleteDump(adumpID)
153 register afs_int32 code;
154 tp = DumpName(adumpID);
156 if (code) return code;
157 code = ScanForChildren(adumpID);
161 static afs_int32 DeleteTape(atapeName)
164 register afs_int32 code;
165 tp = TapeName(atapeName);
171 * name is a pathname style name, determine trailing name and return
176 tailCompPtr(pathNamePtr)
180 ptr = rindex(pathNamePtr, '/');
183 /* this should never happen */
184 printf("tailCompPtr: could not find / in name(%s)\n",
189 ptr++; /* skip the / */
194 * scan a dump header out of a dump file, leaving the file ptr set after
197 * afile - ptr to file, for reading.
198 * various - ptrs for return values
200 * aname - string of form volume_set.dump_level
201 * dumpName - pathname of dump schedule node
202 * aparent - id of parent
204 * acreateTime - time at which dump was created
205 * alevel - level of dump (0 = full, 1+ are incrementals)
208 ScanDumpHdr(afile, aname, dumpName, aparent, aincTime, acreateTime, alevel)
209 register FILE *afile;
213 afs_int32 *acreateTime;
219 afs_int32 dbmagic, dbversion;
220 register afs_int32 code;
222 tp = fgets(tbuffer, sizeof(tbuffer), afile);
224 code = sscanf(tbuffer, "%d %d %s %s %ld %ld %ld %ld",
225 &dbmagic, &dbversion,
226 aname, dumpName, aparent, aincTime, acreateTime, alevel);
227 if (code != 8) return -1;
229 /* now check the magic and version numbers */
230 if ( (dbmagic != BC_DUMPDB_MAGIC) || (dbversion != BC_DUMPDB_VERSION) )
236 /* scan a tape header out of a tape file, leaving the file ptr positioned just past the header */
237 static afs_int32 ScanTapeHdr(afile, adumpID, aseq, adamage)
238 register FILE *afile;
241 afs_int32 *adamage; {
244 register afs_int32 code;
246 tp = fgets(tbuffer, sizeof(tbuffer), afile);
248 code = sscanf(tbuffer, "%ld %ld %ld", adumpID, aseq, adamage);
249 if (code != 3) return -1;
254 * scan a tape volume record from a dump file, leaving the file ptr
255 * positioned past the just-scanned record.
263 ScanTapeVolume(afile, avolName, avolID, atapeName, apos, aseq, alastp,
269 afs_int32 *apos, *aseq, *alastp, *cloneTime; {
271 register afs_int32 code;
274 tp = fgets(tbuffer, sizeof(tbuffer), afile);
275 if (!tp) { /* something went wrong, or eof hit */
276 if (ferror(afile)) return -1; /* error occurred */
277 else return 1; /* eof */
279 code = sscanf(tbuffer, "%s %ld %s %ld %ld %ld %ld", avolName, avolID,
280 atapeName, apos, aseq, alastp, cloneTime);
281 if (code != 7) return -1; /* bad input line */
286 * Search the dump for the volume with name volName, and return it's
290 * -1 - volume with volName not found
294 ScanVolClone(tdump, volName, cloneTime)
297 afs_int32 *cloneTime;
299 char avolName[256], atapeName[256];
300 afs_int32 retval, avolID, apos, aseq, alastp;
302 retval = ScanTapeVolume(tdump, &avolName[0], &avolID, &atapeName[0],
303 &apos, &aseq, &alastp, cloneTime);
304 while ( retval == 0 )
306 if ( strcmp(avolName, volName) == 0 )
308 retval = ScanTapeVolume(tdump, &avolName[0], &avolID, &atapeName[0],
309 &apos, &aseq, &alastp, cloneTime);
314 /* seek a dump file (after a header scan has been done) to position apos */
315 static SeekDump(afile, apos)
316 register FILE *afile;
318 register afs_int32 i;
322 /* now skip to appropriate position */
323 for(i=0;i<apos; i++) {
324 tp = fgets(tbuffer, sizeof(tbuffer), afile);