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