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