Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / bucoord / dsstub.c
CommitLineData
805e021f
CE
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
30static char * TapeName(char *);
31static char * DumpName(afs_int32 adumpID);
32static FILE * OpenDump(afs_int32 , char * );
33FILE * OpenTape(char * , char * );
34static afs_int32 ScanForChildren(afs_int32 );
35static afs_int32 DeleteDump(afs_int32 );
36char * tailCompPtr(char *);
37afs_int32 ScanDumpHdr(FILE *, char *, char *, afs_int32 *, afs_int32 *,
38 afs_int32 *, afs_int32 *);
39afs_int32 ScanTapeVolume(FILE *, char *, afs_int32 *, char *, afs_int32 *, afs_int32 *,
40 afs_int32 *, afs_int32 *);
41afs_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
63static 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
75static 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
85static 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
103FILE * 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
118static 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
161static 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
178static 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
197char *
198tailCompPtr(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 */
225afs_int32
226ScanDumpHdr(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 */
252static 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
278afs_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
309afs_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 */
329static 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