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