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