bucoord-protoize-20070104
[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 RCSID
18     ("$Header$");
19
20 #include <sys/types.h>
21 #include <afs/cmd.h>
22 #ifdef AFS_NT40_ENV
23 #include <winsock2.h>
24 #else
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <netdb.h>
28 #endif
29 #include <dirent.h>
30 #include <afs/afsutil.h>
31 #include <afs/budb.h>
32 #include <afs/bubasics.h>
33 #include <afs/volser.h>
34 #include "bc.h"
35
36 /* protos */
37
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 static afs_int32 DeleteTape(char * );
45 char * tailCompPtr(char *);
46 afs_int32 ScanDumpHdr(register FILE *, char *, char *, afs_int32 *, afs_int32 *,
47   afs_int32 *, afs_int32 *);
48 static afs_int32 ScanTapeHdr(register FILE *, afs_int32 *, afs_int32 *, afs_int32 *);
49 afs_int32 ScanTapeVolume(FILE *, char *, afs_int32 *, char *, afs_int32 *, afs_int32 *,
50    afs_int32 *, afs_int32 *);
51 afs_int32 ScanVolClone(FILE *, char *, afs_int32 *);
52 static int SeekDump(register FILE *afile, afs_int32 apos);
53
54
55 /* basic format of a tape file is a file, whose name is "T<tapename>.db", and
56  * which contains the fields
57  * (afs_int32) dumpID, (afs_int32) tape-sequence-within-dump, (afs_int32) damage_flag
58  * all as space-separated integers.
59  */
60
61 /* The format of a dump file is:
62  * a file whose name is "D<dump#>.db"
63  * and whose contents are a header line:
64  * (string) dumpName, (long) parent-id, (long) incTime, (long) dumpEndTime, (long) level
65  * and a bunch of bcdb_volumeEntries with this format:
66  * (string) volume name, (long) volume ID, (string) tape name, (long) position-on-tape,
67  *     (long) sequence-in-volume-dump, (long) is-this-the-last-vol-frag, (long) incTime
68  * again, all space-separated.
69  * Note that dumpEndTime is stored and returned in the dump creation time field.
70  */
71
72 static afs_int32 DeleteDump();
73 afs_int32 ScanDumpHdr();
74
75 /* return the tape file name corresponding to a particular tape */
76
77 static char * TapeName(register char *atapeName)
78 {
79     static char tbuffer[AFSDIR_PATH_MAX];
80
81     /* construct the backup dir path */
82     strcpy(tbuffer, AFSDIR_SERVER_BACKUP_DIRPATH);
83     strcat(tbuffer, "/T");
84     strcat(tbuffer + 1, atapeName);
85     strcat(tbuffer, ".db");
86     return tbuffer;
87 }
88
89 /* return the dump file name corresponding to a particular dump ID */
90
91 static char * DumpName(register afs_int32 adumpID)
92 {
93     static char tbuffer[AFSDIR_PATH_MAX];
94     char buf[AFSDIR_PATH_MAX];
95
96     /* construct the backup dir path */
97     strcpy(buf, AFSDIR_SERVER_BACKUP_DIRPATH);
98     strcat(buf, "/D%d.db");
99     sprintf(tbuffer, buf, adumpID);
100     return tbuffer;
101 }
102
103 static FILE * OpenDump(afs_int32 adumpID, char * awrite)
104 {
105     register char *tp;
106     register FILE *tfile;
107
108     tp = DumpName(adumpID);
109     tfile = fopen(tp, awrite);
110     return tfile;
111 }
112
113 /* OpenTape
114  * notes: 
115  *      non-static for recoverDB
116  */
117
118 FILE * OpenTape(char * atapeName, char * awrite)
119 {
120     register char *tp;
121     register FILE *tfile;
122     tp = TapeName(atapeName);
123     tfile = fopen(tp, awrite);
124     return tfile;
125 }
126
127 /* scan for, and delete, all dumps whose parent dump ID is aparentID */
128
129 static afs_int32 ScanForChildren(afs_int32 aparentID)
130 {
131     DIR *tdir;
132     register struct dirent *tde;
133     afs_int32 dumpID, parent;
134     register FILE *tfile;
135     register afs_int32 code;
136     afs_int32 j2, j3, j4;
137     char dname[256];
138     char dumpName[1024];
139
140     tdir = opendir(AFSDIR_SERVER_BACKUP_DIRPATH);
141     if (!tdir)
142         return -1;
143
144     for (tde = readdir(tdir); tde; tde = readdir(tdir)) {
145         code = sscanf(tde->d_name, "D%ld.db", &dumpID);
146         if (code != 1)
147             continue;
148
149         tfile = OpenDump(dumpID, "r");
150         if (!tfile)
151             continue;           /* shouldn't happen, but should continue anyway */
152
153         code = ScanDumpHdr(tfile, dname, dumpName, &parent, &j2, &j3, &j4);
154         fclose(tfile);
155         if (code) {
156             printf("backup:dsstub: bad dump header for dump %d\n", dumpID);
157             continue;
158         }
159
160         /* if this guy's parent is the ID we're scanning for, delete it */
161         if (aparentID == parent) {
162             code = DeleteDump(dumpID);
163             if (code)
164                 printf("backup:dsstub: failed to delete child dump %d\n",
165                        dumpID);
166         }
167     }
168     closedir(tdir);
169     return 0;
170 }
171
172 static afs_int32 DeleteDump(afs_int32 adumpID)
173 {
174     register char *tp;
175     register afs_int32 code;
176     tp = DumpName(adumpID);
177     code = unlink(tp);
178     if (code)
179         return code;
180     code = ScanForChildren(adumpID);
181     return code;
182 }
183
184 static afs_int32 DeleteTape(char * atapeName)
185 {
186     register char *tp;
187     register afs_int32 code;
188     tp = TapeName(atapeName);
189     code = unlink(tp);
190     return code;
191 }
192
193 /* tailCompPtr
194  *      name is a pathname style name, determine trailing name and return
195  *      pointer to it
196  */
197
198 char * tailCompPtr(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  */
225 afs_int32
226 ScanDumpHdr(register 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     register 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, aparent, aincTime, acreateTime, alevel);
239     if (code != 8)
240         return -1;
241
242     /* now check the magic and version numbers */
243     if ((dbmagic != BC_DUMPDB_MAGIC) || (dbversion != BC_DUMPDB_VERSION))
244         return (-1);
245
246     return 0;
247 }
248
249 /* scan a tape header out of a tape file, leaving the file ptr positioned just past the header */
250 static afs_int32 ScanTapeHdr(register FILE *afile, afs_int32 *adumpID, afs_int32 *aseq, afs_int32 *adamage)
251 {
252     char tbuffer[256];
253     char *tp;
254     register afs_int32 code;
255
256     tp = fgets(tbuffer, sizeof(tbuffer), afile);
257     if (!tp)
258         return -1;
259     code = sscanf(tbuffer, "%ld %ld %ld", adumpID, aseq, adamage);
260     if (code != 3)
261         return -1;
262     return 0;
263 }
264
265 /* ScanTapeVolume
266  *      scan a tape volume record from a dump file, leaving the file ptr
267  *      positioned past the just-scanned record.
268  * exit:
269  *      0 - success
270  *      1 - EOF
271  *      -1 for error
272  */
273
274 afs_int32 ScanTapeVolume(FILE *afile, char *avolName, afs_int32 *avolID, char *atapeName, afs_int32 *apos, afs_int32 *aseq, afs_int32 *alastp, afs_int32 *cloneTime)
275 {
276     char tbuffer[256];
277     register afs_int32 code;
278     register char *tp;
279
280     tp = fgets(tbuffer, sizeof(tbuffer), afile);
281     if (!tp) {                  /* something went wrong, or eof hit */
282         if (ferror(afile))
283             return -1;          /* error occurred */
284         else
285             return 1;           /* eof */
286     }
287     code =
288         sscanf(tbuffer, "%s %ld %s %ld %ld %ld %ld", avolName, avolID,
289                atapeName, apos, aseq, alastp, cloneTime);
290     if (code != 7)
291         return -1;              /* bad input line */
292     return 0;
293 }
294
295 /* ScanVolClone
296  *      Search the dump for the volume with name volName, and return it's
297  *      clone time.
298  * exit:
299  *      0 - clonetime set.
300  *      -1 - volume with volName not found
301  */
302
303 afs_int32 ScanVolClone(FILE *tdump, char *volName, afs_int32 *cloneTime)
304 {
305     char avolName[256], atapeName[256];
306     afs_int32 retval, avolID, apos, aseq, alastp;
307
308     retval =
309         ScanTapeVolume(tdump, &avolName[0], &avolID, &atapeName[0], &apos,
310                        &aseq, &alastp, cloneTime);
311     while (retval == 0) {
312         if (strcmp(avolName, volName) == 0)
313             return (0);
314         retval =
315             ScanTapeVolume(tdump, &avolName[0], &avolID, &atapeName[0], &apos,
316                            &aseq, &alastp, cloneTime);
317     }
318     return (-1);
319 }
320
321 /* seek a dump file (after a header scan has been done) to position apos */
322 static int SeekDump(register FILE *afile, afs_int32 apos)
323 {
324     register afs_int32 i;
325     register char *tp;
326     char tbuffer[256];
327
328     /* now skip to appropriate position */
329     for (i = 0; i < apos; i++) {
330         tp = fgets(tbuffer, sizeof(tbuffer), afile);
331         if (!tp) {
332             fclose(afile);
333             return -1;
334         }
335     }
336     return 0;
337 }