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