Bug Summary

File:bucoord/ubik_db_if.c
Location:line 497, column 5
Description:Value stored to 'offset' is never read

Annotated Source Code

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/* Interface and supporting routines for the backup system's ubik database */
11
12#include <afsconfig.h>
13#include <afs/stds.h>
14
15#include <roken.h>
16
17#ifdef IGNORE_SOME_GCC_WARNINGS
18# pragma GCC diagnostic warning "-Wstrict-prototypes"
19#endif
20
21#include <afs/auth.h>
22#include <afs/cellconfig.h>
23#include <ubik.h>
24#include <afs/volser.h>
25#include <afs/volser_prototypes.h>
26#include <afs/afsutil.h>
27#include <afs/bubasics.h>
28#include <afs/budb_client.h>
29#include <afs/budb.h>
30#include <afs/com_err.h>
31
32#include "bc.h"
33#include "error_macros.h"
34#include "bucoord_internal.h"
35#include "bucoord_prototypes.h"
36
37extern char *whoami;
38
39/* -------------------------------------
40 * Globals
41 * -------------------------------------
42 */
43
44struct udbHandleS udbHandle;
45
46/* -------------------------------------
47 * interface routines (alphabetic)
48 * -------------------------------------
49 */
50
51afs_int32 bcdb_AddVolume(struct budb_volumeEntry *veptr)
52{
53 afs_int32 code;
54
55 code = ubik_BUDB_AddVolume(udbHandle.uh_client, 0, veptr);
56 return (code);
57}
58
59afs_int32 bcdb_AddVolumes(struct budb_volumeEntry *veptr, afs_int32 count)
60{
61 struct budb_volumeList volumeList;
62 afs_int32 code;
63
64 volumeList.budb_volumeList_len = count;
65 volumeList.budb_volumeList_val = veptr;
66 code = ubik_BUDB_AddVolumes(udbHandle.uh_client, 0, &volumeList);
67 return (code);
68}
69
70
71afs_int32 bcdb_CreateDump(struct budb_dumpEntry *deptr)
72{
73 afs_int32 code;
74
75 code = ubik_BUDB_CreateDump(udbHandle.uh_client, 0, deptr);
76 return (code);
77}
78
79afs_int32 bcdb_deleteDump(afs_int32 dumpID, afs_int32 fromTime, afs_int32 toTime,
80 budb_dumpsList *dumps)
81{
82 afs_int32 code;
83 budb_dumpsList dumpsList, *dumpsPtr;
84
85 dumpsList.budb_dumpsList_len = 0;
86 dumpsList.budb_dumpsList_val = 0;
87 dumpsPtr = (dumps ? dumps : &dumpsList);
88
89 code =
90 ubik_BUDB_DeleteDump(udbHandle.uh_client, 0, dumpID, fromTime,
91 toTime, dumpsPtr);
92 if (dumpsList.budb_dumpsList_val)
93 free(dumpsList.budb_dumpsList_val);
94 return (code);
95}
96
97afs_int32 bcdb_listDumps (afs_int32 sflags, afs_int32 groupId,
98 afs_int32 fromTime, afs_int32 toTime,
99 budb_dumpsList *dumps, budb_dumpsList *flags)
100{
101 afs_int32 code;
102 budb_dumpsList dumpsList, *dumpsPtr;
103 budb_dumpsList flagsList, *flagsPtr;
104
105 dumpsList.budb_dumpsList_len = 0;
106 dumpsList.budb_dumpsList_val = 0;
107 dumpsPtr = (dumps ? dumps : &dumpsList);
108
109 flagsList.budb_dumpsList_len = 0;
110 flagsList.budb_dumpsList_val = 0;
111 flagsPtr = (flags ? flags : &flagsList);
112
113 code =
114 ubik_BUDB_ListDumps(udbHandle.uh_client, 0, sflags, "", groupId,
115 fromTime, toTime, dumpsPtr, flagsPtr);
116
117 if (dumpsList.budb_dumpsList_val)
118 free(dumpsList.budb_dumpsList_val);
119 if (flagsList.budb_dumpsList_val)
120 free(flagsList.budb_dumpsList_val);
121 return (code);
122}
123
124
125afs_int32 bcdb_DeleteVDP(char *dumpSetName, char *dumpPath, afs_int32 dumpID)
126{
127 afs_int32 code;
128
129 code =
130 ubik_BUDB_DeleteVDP(udbHandle.uh_client, 0, dumpSetName,
131 dumpPath, dumpID);
132 return (code);
133}
134
135/* bcdb_FindClone
136 * Returns the clone time of a volume by going up the parent chain.
137 * If no clone time is found, a clone time of 0 is returned, forcing
138 * a full dump.
139 * entry:
140 * dumpID - of the first dump to examine.
141 * volName - name of the volume for whom a clone time is required
142 * clonetime - ptr to vbl for returning result
143 * exit:
144 * 0 - clonetime set appropriately
145 * -1 - error occured in traversing chain, clone time set to 0.
146 * -2 - no clone times found, clone time set to 0
147 */
148
149afs_int32 bcdb_FindClone(afs_int32 dumpID, char *volName, afs_int32 *clonetime)
150{
151 afs_int32 code;
152 code =
153 ubik_BUDB_FindClone(udbHandle.uh_client, 0, dumpID, volName,
154 clonetime);
155 return (code);
156}
157
158/* bcdb_FindDump
159 * scan entire database for latest volume dump before adate. Optimize
160 * further by reading only the first line of the dump and if it is older
161 * than the oldest acceptable dump we've found so far, we don't bother
162 * scanning the dump file we've just opened
163 *
164 * Used by restore code when restoring a user requested volume(s)
165 * entry:
166 * volumeName - name of volume to match on
167 * beforeDate - look for dumps older than this date
168 * exit:
169 * deptr - desciptor of most recent dump
170 * notes:
171 * should be able to implement this in a single call rather than
172 * the current multiple bcdb_ call algorithm.
173 */
174
175int
176bcdb_FindDump(char *volumeName, afs_int32 beforeDate,
177 struct budb_dumpEntry *deptr)
178{
179 afs_int32 code;
180 code =
181 ubik_BUDB_FindDump(udbHandle.uh_client, 0, volumeName,
182 beforeDate, deptr);
183 return (code);
184}
185
186/* bcdb_FindDumpByID
187 * find a dump by id. Currently insists on a single return value.
188 * entry:
189 * dumpID - id to lookup
190 * exit:
191 */
192int
193bcdb_FindDumpByID(afs_int32 dumpID, struct budb_dumpEntry *deptr)
194{
195 afs_int32 code;
196 afs_int32 nextindex;
197 afs_int32 dbTime;
198 budb_dumpList dl;
199
200 /* initialize the dump list */
201 dl.budb_dumpList_len = 0;
202 dl.budb_dumpList_val = 0;
203
204 /* outline algorithm */
205 code = ubik_BUDB_GetDumps(udbHandle.uh_client, 0, BUDB_MAJORVERSION2, BUDB_OP_DUMPID(2<<3), "", /* no name */
206 dumpID, /* start */
207 0, /* end */
208 0, /* index */
209 &nextindex, &dbTime, &dl);
210
211 if ((code != 0)
212 || (dl.budb_dumpList_len != 1) /* single retn val expected */
213 ) {
214/* printf("bcdb_FindDumpByID: code %d, nvalues %d\n",
215 code, dl.budb_dumpList_len); */
216 if (code == 0)
217 code = 1; /* multiple id's */
218 goto error;
219 }
220
221 memcpy(deptr, dl.budb_dumpList_val, sizeof(*deptr));
222
223 exit:
224 if (dl.budb_dumpList_val) {
225 /* free any allocated structures */
226 free(dl.budb_dumpList_val);
227 }
228 return (code);
229
230 error:
231 memset(deptr, 0, sizeof(*deptr));
232 goto exit;
233}
234
235/* bcdb_FindLastVolClone
236 * Returns the clone time, from the most recent dump of volName, when
237 * dumped in the volume set volSetName, with dump schedule dumpName.
238 * The clone time can be used to check if the volume has been correctly
239 * re-cloned, and also is used as the time from which to do the current
240 * incremental dump.
241 * entry:
242 * volSetName - name of volume set
243 * dumpName - full path of dump node
244 * volName - name of volume for whom a clone time is required
245 * clonetime - ptr to vbl for result
246 * exit:
247 * 0 - clonetime set appropriately
248 * notes:
249 * used only for warning generation. Suggest that this be omitted.
250 */
251
252afs_int32
253bcdb_FindLastVolClone(char *volSetName, char *dumpName, char *volName,
254 afs_int32 *clonetime)
255{
256 /* server notes
257 * search by dumpName
258 * match on volumeset and dump path
259 * search for the volume name
260 */
261 return (0);
262}
263
264/* bcdb_FindLatestDump
265 * find the latest dump with volume set component avname and the
266 * specified dump pathname. Used to find a dump, relative to which an
267 * incremental dump can be done. Defines the parent <-> child relations
268 * for restores.
269 * entry:
270 * avname: volume set name
271 * dumpPath: full path of dump node
272 * exit:
273 * 0: adentry: dump entry structure filled in.
274 * -1: probably an internal error
275 * 2: no such entry
276 * Notes for 4.0:
277 * Need to store volumeset name in dump in order to implement this.
278 * Need new routine since params are two strings
279 */
280
281int
282bcdb_FindLatestDump(char *volSetName, char *dumpPath,
283 struct budb_dumpEntry *deptr)
284{
285 afs_int32 code;
286 code =
287 ubik_BUDB_FindLatestDump(udbHandle.uh_client, 0, volSetName,
288 dumpPath, deptr);
289 return (code);
290}
291
292
293/* bcdb_FindTape
294 * find a tape
295 * entry:
296 * dumpid: dump id to which tape beint32s
297 * tapeName: name of tape
298 */
299
300int
301bcdb_FindTape(afs_int32 dumpid, char *tapeName,
302 struct budb_tapeEntry *teptr)
303{
304 budb_tapeList tl;
305 afs_int32 next;
306 afs_int32 dbTime;
307 afs_int32 code = 0;
308
309 memset(teptr, 0, sizeof(*teptr));
310 tl.budb_tapeList_len = 0;
311 tl.budb_tapeList_val = 0;
312
313 code =
314 ubik_BUDB_GetTapes(udbHandle.uh_client, 0, BUDB_MAJORVERSION2,
315 BUDB_OP_TAPENAME(3<<0) | BUDB_OP_DUMPID(2<<3), tapeName, dumpid, 0, 0,
316 &next, &dbTime, &tl);
317
318 if (code)
319 ERROR(code)do { code = code; goto error_exit; } while (0);
320
321 if (tl.budb_tapeList_len != 1)
322 ERROR(BC_NOTUNIQUE)do { code = (156288002L); goto error_exit; } while (0); /* expecting a single descriptor */
323
324 memcpy(teptr, tl.budb_tapeList_val, sizeof(*teptr));
325
326 error_exit:
327 if (tl.budb_tapeList_val)
328 free(tl.budb_tapeList_val);
329 return (code);
330}
331
332int
333bcdb_FindTapeSeq(afs_int32 dumpid, afs_int32 tapeSeq,
334 struct budb_tapeEntry *teptr)
335{
336 budb_tapeList tl;
337 afs_int32 next;
338 afs_int32 dbTime;
339 afs_int32 code = 0;
340
341 memset(teptr, 0, sizeof(*teptr));
342 tl.budb_tapeList_len = 0;
343 tl.budb_tapeList_val = 0;
344
345 code =
346 ubik_BUDB_GetTapes(udbHandle.uh_client, 0, BUDB_MAJORVERSION2,
347 BUDB_OP_TAPESEQ(4<<0) | BUDB_OP_DUMPID(2<<3), "", dumpid, tapeSeq, 0,
348 &next, &dbTime, &tl);
349 if (code)
350 ERROR(code)do { code = code; goto error_exit; } while (0);
351
352 if (tl.budb_tapeList_len != 1)
353 ERROR(BC_NOTUNIQUE)do { code = (156288002L); goto error_exit; } while (0); /* expecting a single descriptor */
354
355 memcpy(teptr, tl.budb_tapeList_val, sizeof(*teptr));
356
357 error_exit:
358 if (tl.budb_tapeList_val)
359 free(tl.budb_tapeList_val);
360 return (code);
361}
362
363/* bcdb_FindVolumes
364 * notes:
365 * - this is part of dblookup. The existing semantics will not work since
366 * they do lookups based on dump id.
367 * - in the restore code, it uses this to extract information about
368 * the volume. Need current semantics. Could filter the output, selecting
369 * on the dumpid.
370 * - Suggest that the lookup be based on volume name only, with optional
371 * match on backup, and readonly volumes.
372 * - Further, need to check if the volume structure returns enough
373 * information
374 */
375
376afs_int32
377bcdb_FindVolumes(afs_int32 dumpID, char *volumeName,
378 struct budb_volumeEntry *returnArray,
379 afs_int32 last, afs_int32 *next, afs_int32 maxa,
380 afs_int32 *nEntries)
381{
382 budb_volumeList vl;
383 afs_int32 dbTime;
384 afs_int32 code;
385
386 vl.budb_volumeList_len = maxa;
387 vl.budb_volumeList_val = returnArray;
388
389 /* outline algorithm */
390 code = ubik_BUDB_GetVolumes(udbHandle.uh_client, 0, BUDB_MAJORVERSION2, BUDB_OP_VOLUMENAME(2<<0) | BUDB_OP_DUMPID(2<<3), volumeName, /* name */
391 dumpID, /* start */
392 0, /* end */
393 last, /* index */
394 next, /* nextindex */
395 &dbTime, &vl);
396
397 *nEntries = vl.budb_volumeList_len;
398 return (code);
399}
400
401int
402bcdb_FinishDump(struct budb_dumpEntry *deptr)
403{
404 afs_int32 code;
405 code = ubik_BUDB_FinishDump(udbHandle.uh_client, 0, deptr);
406 return (code);
407}
408
409int
410bcdb_FinishTape(struct budb_tapeEntry *teptr)
411{
412 afs_int32 code;
413 code = ubik_BUDB_FinishTape(udbHandle.uh_client, 0, teptr);
414 return (code);
415
416}
417
418/* bcdb_LookupVolumes
419 */
420
421afs_int32
422bcdb_LookupVolume(char *volumeName, struct budb_volumeEntry *returnArray,
423 afs_int32 last, afs_int32 *next, afs_int32 maxa,
424 afs_int32 *nEntries)
425{
426 budb_volumeList vl;
427 afs_int32 dbTime;
428 afs_int32 code;
429
430 vl.budb_volumeList_len = maxa;
431 vl.budb_volumeList_val = returnArray;
432
433 /* outline algorithm */
434 code = ubik_BUDB_GetVolumes(udbHandle.uh_client, 0, BUDB_MAJORVERSION2, BUDB_OP_VOLUMENAME(2<<0), volumeName, /* name */
435 0, /* start */
436 0, /* end */
437 last, /* index */
438 next, /* nextindex */
439 &dbTime, &vl);
440 if (code) {
441 *nEntries = 0;
442 return (code);
443 }
444 *nEntries = vl.budb_volumeList_len;
445 return (0);
446}
447
448int
449bcdb_UseTape(struct budb_tapeEntry *teptr, afs_int32 *newFlag)
450{
451 afs_int32 code;
452 code = ubik_BUDB_UseTape(udbHandle.uh_client, 0, teptr, newFlag);
453 return (code);
454}
455
456
457/* ---- text configuration handling routines ----
458 *
459 * notes:
460 * The caller should pass in/out a fid for an unlinked, open file to prevent
461 * tampering with the files contents;
462 */
463
464/* bcdb_GetTextFile
465 * extract the specified textType and put it in a temporary, local
466 * file.
467 * entry:
468 * ctPtr - ptr to client structure with all the required information
469 */
470
471int
472bcdb_GetTextFile(udbClientTextP ctPtr)
473{
474 afs_int32 bufferSize;
475 afs_int32 offset, nextOffset;
476 charListT charList;
477 afs_int32 code = 0;
478
479 /* Initialize charlistT_val. We try to deallocate this structure based on
480 * this */
481 memset((void *)&charList, 0, sizeof(charList));
482
483 /* check params and cleanup any previous state */
484 if (ctPtr->lockHandle == 0)
485 ERROR(BUDB_INTERNALERROR)do { code = (156303895L); goto error_exit; } while (0);
486
487 if (ctPtr->textStream == NULL((void *)0)) /* Should have an open stream */
488 ERROR(BUDB_INTERNALERROR)do { code = (156303895L); goto error_exit; } while (0);
489
490 /* allocate a buffer */
491 bufferSize = 1024;
492 charList.charListT_val = (char *)malloc(bufferSize);
493 if (charList.charListT_val == 0)
494 ERROR(BUDB_INTERNALERROR)do { code = (156303895L); goto error_exit; } while (0);
495 charList.charListT_len = bufferSize;
496
497 offset = 0;
Value stored to 'offset' is never read
498 nextOffset = 0;
499 ctPtr->textSize = 0;
500 while (nextOffset != -1) {
501 offset = nextOffset;
502 charList.charListT_len = bufferSize;
503 code =
504 ubik_BUDB_GetText(udbHandle.uh_client, 0, ctPtr->lockHandle,
505 ctPtr->textType, bufferSize, offset, &nextOffset,
506 &charList);
507
508 if (code)
509 ERROR(code)do { code = code; goto error_exit; } while (0);
510
511 code =
512 fwrite(charList.charListT_val, sizeof(char),
513 charList.charListT_len, ctPtr->textStream);
514 if (ferror(ctPtr->textStream)(!__isthreaded ? (((ctPtr->textStream)->_flags & 0x0040
) != 0) : (ferror)(ctPtr->textStream))
)
515 ERROR(BUDB_INTERNALERROR)do { code = (156303895L); goto error_exit; } while (0);
516
517 ctPtr->textSize += charList.charListT_len;
518 }
519
520 /* get text version */
521 code =
522 ubik_BUDB_GetTextVersion(udbHandle.uh_client, 0,
523 ctPtr->textType, &ctPtr->textVersion);
524 if (code)
525 ERROR(code)do { code = code; goto error_exit; } while (0);
526
527 normal_exit:
528 fflush(ctPtr->textStream); /* debug */
529
530 /* exit, leaving the configuration text file open */
531 if (charList.charListT_val)
532 free(charList.charListT_val);
533 return (code);
534
535 error_exit:
536 if (ctPtr->textStream != NULL((void *)0)) {
537 fclose(ctPtr->textStream);
538 ctPtr->textStream = NULL((void *)0);
539 }
540 goto normal_exit;
541}
542
543
544/* bcdb_SaveTextFile
545 * save the text file in ubik database
546 * entry:
547 * textType - identifies type of configuration file
548 * filename - where to get the text from
549 */
550
551int
552bcdb_SaveTextFile(udbClientTextP ctPtr)
553{
554 afs_int32 bufferSize;
555 afs_int32 offset, chunkSize, fileSize;
556 charListT charList;
557 afs_int32 code = 0;
558
559 /* allocate a buffer */
560 bufferSize = 1024;
561 charList.charListT_val = (char *)malloc(bufferSize);
562 if (charList.charListT_val == 0)
563 ERROR(BUDB_INTERNALERROR)do { code = (156303895L); goto error_exit; } while (0);
564 charList.charListT_len = bufferSize;
565
566 if (ctPtr->textStream == NULL((void *)0))
567 ERROR(BUDB_INTERNALERROR)do { code = (156303895L); goto error_exit; } while (0);
568 rewind(ctPtr->textStream);
569
570 fileSize = (afs_int32) filesize(ctPtr->textStream);
571
572 afs_dprintf(("filesize is %d\n", fileSize));
573
574 rewind(ctPtr->textStream);
575
576 /* special case empty files */
577 if (fileSize == 0) {
578 charList.charListT_len = 0;
579 code =
580 ubik_BUDB_SaveText(udbHandle.uh_client, 0,
581 ctPtr->lockHandle, ctPtr->textType, 0,
582 BUDB_TEXT_COMPLETE1, &charList);
583 goto error_exit;
584 }
585
586 offset = 0;
587 while (fileSize != 0) {
588 chunkSize = MIN(fileSize, bufferSize)(((fileSize)<(bufferSize))?(fileSize):(bufferSize));
589 code =
590 fread(charList.charListT_val, sizeof(char), chunkSize,
591 ctPtr->textStream);
592
593 if (code != chunkSize)
594 printf("code = %d\n", code);
595 if (ferror(ctPtr->textStream)(!__isthreaded ? (((ctPtr->textStream)->_flags & 0x0040
) != 0) : (ferror)(ctPtr->textStream))
)
596 ERROR(BUDB_INTERNALERROR)do { code = (156303895L); goto error_exit; } while (0);
597
598 charList.charListT_len = chunkSize;
599 code =
600 ubik_BUDB_SaveText(udbHandle.uh_client, 0,
601 ctPtr->lockHandle, ctPtr->textType, offset,
602 (chunkSize == fileSize) ? BUDB_TEXT_COMPLETE1 : 0,
603 &charList);
604 if (code)
605 ERROR(code)do { code = code; goto error_exit; } while (0);
606
607 fileSize -= chunkSize;
608 offset += chunkSize;
609 }
610
611 error_exit:
612 /* if ( ctPtr->textStream >= 0 )
613 * close(ctPtr->textStream); */
614 if (charList.charListT_val)
615 free(charList.charListT_val);
616 return (code);
617}
618
619int
620bcdb_FindLastTape(afs_int32 dumpID, struct budb_dumpEntry *dumpEntry,
621 struct budb_tapeEntry *tapeEntry,
622 struct budb_volumeEntry *volEntry)
623{
624 return (ubik_BUDB_FindLastTape(udbHandle.uh_client, 0, dumpID, dumpEntry,
625 tapeEntry, volEntry));
626}
627
628int
629bcdb_MakeDumpAppended(afs_int32 appendedDumpID, afs_int32 initialDumpID,
630 afs_int32 startTapeSeq)
631{
632 return (ubik_BUDB_MakeDumpAppended(udbHandle.uh_client, 0, appendedDumpID,
633 initialDumpID, startTapeSeq));
634}
635
636
637/* -------------------------------------
638 * misc. support routines
639 * -------------------------------------
640 */
641
642afs_int32
643filesize(FILE *stream)
644{
645 afs_int32 offset;
646 afs_int32 size;
647
648 offset = ftell(stream);
649 fseek(stream, (afs_int32) 0, 2); /* end of file */
650 size = ftell(stream);
651 fseek(stream, offset, 0);
652 return (size);
653}
654
655
656/* ------------------------------------
657 * misc. support routines - general text management
658 * ------------------------------------
659 */
660
661
662/* bc_LockText
663 * locks the text described by the ctPtr
664 * entry:
665 * ctptr - client text ptr
666 * exit:
667 * 0 - success
668 * n - fail
669 */
670
671int
672bc_LockText(udbClientTextP ctPtr)
673{
674 afs_int32 code;
675 afs_int32 timeout, j = 0;
676
677 if (ctPtr->lockHandle != 0)
678 return (1); /* already locked */
679
680 timeout =
681 ((ctPtr->textSize == 0) ? 30 : ((ctPtr->textSize / 50000) + 10));
682
683 while (1) {
684 code =
685 ubik_BUDB_GetLock(udbHandle.uh_client, 0,
686 udbHandle.uh_instanceId, ctPtr->textType, timeout,
687 &ctPtr->lockHandle);
688 if ((code != BUDB_LOCKED(156303889L)) && (code != BUDB_SELFLOCKED(156303890L))) {
689 break;
690 }
691
692 /* Mention something every 30 seconds */
693 if (++j >= 30) {
694 afs_com_err(whoami, code,
695 "; Waiting for db configuration text unlock");
696 j = 0;
697 }
698#ifdef AFS_PTHREAD_ENV
699 sleep(1);
700#else
701 IOMGR_Sleep(1);
702#endif
703 }
704
705 /* cleanup */
706 if (code)
707 ctPtr->lockHandle = 0;
708 return (code);
709}
710
711/* bc_UnlockText
712 * unlocks the text described by the ctPtr
713 * entry:
714 * ctptr - client text ptr
715 * exit:
716 * 0 - success
717 * n - fail
718 */
719
720int
721bc_UnlockText(udbClientTextP ctPtr)
722{
723 afs_int32 code = 0;
724
725 if (ctPtr->lockHandle == 0)
726 return (0);
727
728 code =
729 ubik_BUDB_FreeLock(udbHandle.uh_client, 0, ctPtr->lockHandle);
730 ctPtr->lockHandle = 0;
731
732 /* Don't try to analyse the error. Let the lock timeout */
733 return (code);
734}
735
736/* bc_CheckTextVersion
737 * exit:
738 * 0 - version # ok
739 * n - out of date or error
740 */
741
742int
743bc_CheckTextVersion(udbClientTextP ctPtr)
744{
745 afs_int32 code;
746 afs_uint32 tversion;
747
748 if (ctPtr->textVersion == -1)
749 return (BC_VERSIONMISMATCH(156288001L));
750
751 code =
752 ubik_BUDB_GetTextVersion(udbHandle.uh_client, 0,
753 ctPtr->textType, &tversion);
754 if (code)
755 return (code);
756 if (tversion != ctPtr->textVersion)
757 return (BC_VERSIONMISMATCH(156288001L));
758 return (0);
759}
760
761/* -------------------------------------
762 * initialization routines
763 * -------------------------------------
764 */
765
766static afsconf_secflags
767parseSecFlags(int noAuthFlag, int localauth, const char **confdir) {
768 afsconf_secflags secFlags;
769
770 secFlags = 0;
771 if (noAuthFlag)
772 secFlags |= AFSCONF_SECOPTS_NOAUTH0x1;
773
774 if (localauth) {
775 secFlags |= AFSCONF_SECOPTS_LOCALAUTH0x2;
776 *confdir = AFSDIR_SERVER_ETC_DIRPATHgetDirPath(AFSDIR_SERVER_ETC_DIRPATH_ID);
777 } else {
778 *confdir = AFSDIR_CLIENT_ETC_DIRPATHgetDirPath(AFSDIR_CLIENT_ETC_DIRPATH_ID);
779 }
780 return secFlags;
781}
782
783/* vldbClientInit
784 * Initialize a client for the vl ubik database.
785 */
786int
787vldbClientInit(int noAuthFlag, int localauth, char *cellName,
788 struct ubik_client **cstruct,
789 time_t *expires)
790{
791 afs_int32 code = 0;
792 struct afsconf_dir *acdir;
793 struct rx_securityClass *sc;
794 afs_int32 i, scIndex = RX_SECIDX_NULL;
795 struct afsconf_cell info;
796 struct rx_connection *serverconns[VLDB_MAXSERVERS10];
797 afsconf_secflags secFlags;
798 const char *confdir;
799
800 secFlags = parseSecFlags(noAuthFlag, localauth, &confdir);
801 secFlags |= AFSCONF_SECOPTS_FALLBACK_NULL0x8;
802
803 /* This just preserves old behaviour of using the default cell when
804 * passed an empty string */
805 if (cellName && cellName[0] == '\0')
806 cellName = NULL((void *)0);
807
808 /* Find out about the given cell */
809 acdir = afsconf_Open(confdir);
810 if (!acdir) {
811 afs_com_err(whoami, 0, "Can't open configuration directory '%s'", confdir);
812 ERROR(BC_NOCELLCONFIG)do { code = (156288004L); goto error_exit; } while (0);
813 }
814
815 code = afsconf_GetCellInfo(acdir, cellName, AFSCONF_VLDBSERVICE"afsvldb", &info);
816 if (code) {
817 afs_com_err(whoami, code, "; Can't find cell %s's hosts in %s/%s",
818 cellName, confdir, AFSDIR_CELLSERVDB_FILE"CellServDB");
819 ERROR(BC_NOCELLCONFIG)do { code = (156288004L); goto error_exit; } while (0);
820 }
821
822 code = afsconf_PickClientSecObj(acdir, secFlags, &info, cellName,
823 &sc, &scIndex, expires);
824 if (code) {
825 afs_com_err(whoami, code, "(configuring connection security)");
826 ERROR(BC_NOCELLCONFIG)do { code = (156288004L); goto error_exit; } while (0);
827 }
828 if (scIndex == RX_SECIDX_NULL && !noAuthFlag)
829 afs_com_err(whoami, 0, "Can't get tokens - running unauthenticated");
830
831 /* tell UV module about default authentication */
832 UV_SetSecurity(sc, scIndex);
833
834 if (info.numServers > VLDB_MAXSERVERS10) {
835 afs_com_err(whoami, 0,
836 "Warning: %d VLDB servers exist for cell '%s', can only remember the first %d",
837 info.numServers, cellName, VLDB_MAXSERVERS10);
838 info.numServers = VLDB_MAXSERVERS10;
839 }
840
841 for (i = 0; i < info.numServers; i++)
842 serverconns[i] =
843 rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
844 info.hostAddr[i].sin_port, USER_SERVICE_ID52, sc,
845 scIndex);
846 serverconns[i] = 0;
847
848 *cstruct = 0;
849 code = ubik_ClientInit(serverconns, cstruct);
850 if (code) {
851 afs_com_err(whoami, code, "; Can't initialize ubik connection to vldb");
852 ERROR(code)do { code = code; goto error_exit; } while (0);
853 }
854
855 error_exit:
856 if (acdir)
857 afsconf_Close(acdir);
858 return (code);
859}
860
861/* udbClientInit
862 * initialize a client for the backup systems ubik database.
863 */
864
865afs_int32
866udbClientInit(int noAuthFlag, int localauth, char *cellName)
867{
868 struct afsconf_cell info;
869 struct afsconf_dir *acdir;
870 const char *confdir;
871 int i;
872 afs_int32 secFlags;
873 afs_int32 code = 0;
874
875 secFlags = parseSecFlags(noAuthFlag, localauth, &confdir);
876 secFlags |= AFSCONF_SECOPTS_FALLBACK_NULL0x8;
877
878 if (cellName && cellName[0] == '\0')
879 cellName = NULL((void *)0);
880
881 acdir = afsconf_Open(confdir);
882 if (!acdir) {
883 afs_com_err(whoami, 0, "Can't open configuration directory '%s'",
884 confdir);
885 ERROR(BC_NOCELLCONFIG)do { code = (156288004L); goto error_exit; } while (0);
886 }
887
888 code = afsconf_GetCellInfo(acdir, cellName, 0, &info);
889 if (code) {
890 afs_com_err(whoami, code, "; Can't find cell %s's hosts in %s/%s",
891 cellName, confdir, AFSDIR_CELLSERVDB_FILE"CellServDB");
892 ERROR(BC_NOCELLCONFIG)do { code = (156288004L); goto error_exit; } while (0);
893 }
894
895 code = afsconf_PickClientSecObj(acdir, secFlags, &info, cellName,
896 &udbHandle.uh_secobj,
897 &udbHandle.uh_scIndex, NULL((void *)0));
898 if (code) {
899 afs_com_err(whoami, code, "(configuring connection security)");
900 ERROR(BC_NOCELLCONFIG)do { code = (156288004L); goto error_exit; } while (0);
901 }
902 if (&udbHandle.uh_scIndex == RX_SECIDX_NULL && !noAuthFlag)
903 afs_com_err(whoami, 0, "Can't get tokens - running unauthenticated");
904
905 if (info.numServers > MAXSERVERS20) {
906 afs_com_err(whoami, 0,
907 "Warning: %d BDB servers exist for cell '%s', can only remember the first %d",
908 info.numServers, cellName, MAXSERVERS20);
909 info.numServers = MAXSERVERS20;
910 }
911
912 /* establish connections to the servers. Check for failed connections? */
913 for (i = 0; i < info.numServers; i++) {
914 udbHandle.uh_serverConn[i] =
915 rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
916 htons(AFSCONF_BUDBPORT)(__builtin_constant_p(7021) ? (__uint16_t)(((__uint16_t)(7021
)) << 8 | ((__uint16_t)(7021)) >> 8) : __bswap16_var
(7021))
, BUDB_SERVICE22314,
917 udbHandle.uh_secobj, udbHandle.uh_scIndex);
918 }
919 udbHandle.uh_serverConn[i] = 0;
920
921 code = ubik_ClientInit(udbHandle.uh_serverConn, &udbHandle.uh_client);
922 if (code) {
923 afs_com_err(whoami, code,
924 "; Can't initialize ubik connection to backup database");
925 ERROR(code)do { code = code; goto error_exit; } while (0);
926 }
927
928 /* Try to quickly find a good site by setting deadtime low */
929 for (i = 0; i < info.numServers; i++)
930 rx_SetConnDeadTime(udbHandle.uh_client->conns[i], 1);
931 code =
932 ubik_BUDB_GetInstanceId(udbHandle.uh_client, 0,
933 &udbHandle.uh_instanceId);
934
935 /* Reset dead time back up to default */
936 for (i = 0; i < info.numServers; i++)
937 rx_SetConnDeadTime(udbHandle.uh_client->conns[i], 60);
938
939 /* If did not find a site on first quick pass, try again */
940 if (code == -1)
941 code =
942 ubik_BUDB_GetInstanceId(udbHandle.uh_client, 0,
943 &udbHandle.uh_instanceId);
944 if (code) {
945 afs_com_err(whoami, code, "; Can't access backup database");
946 ERROR(code)do { code = code; goto error_exit; } while (0);
947 }
948
949 error_exit:
950 if (acdir)
951 afsconf_Close(acdir);
952 return (code);
953}
954
955/* -------------------------------------
956 * specialized ubik support
957 * -------------------------------------
958 */
959
960#include <rx/xdr.h>
961#include <rx/rx.h>
962#include <lock.h>
963
964/* notes
965 * 1) first call with SINGLESERVER set, record the server to be used.
966 * 2) subsequent calls use that server. If a failure is encountered,
967 * the state is cleaned up and the error returned back to the caller.
968 * 3) upon completion, the user must make a dummy call with
969 * END_SINGLESERVER set, to clean up state.
970 * 4) if the vanilla ubik_Call is ever modified, the END_SINGLESERVER
971 * flag can be discarded. The first call without SINGLESERVER set
972 * can clean up the state.
973 */
974
975struct ubikCallState {
976 afs_int32 ucs_flags; /* state flags */
977 afs_int32 ucs_selectedServer; /* which server selected */
978};
979
980static struct ubikCallState uServer;
981
982/* ubik_Call_SingleServer
983 * variant of ubik_Call. This is used by the backup system to initiate
984 * a series of calls to a single ubik server. The first call sets up
985 * process state (not recorded in ubik) that requires all further calls
986 * of that group to be made to the same server process.
987 *
988 * call this instead of stub and we'll guarantee to find a host that's up.
989 * in the future, we should also put in a protocol to find the sync site
990 */
991
992afs_int32
993ubik_Call_SingleServer(int (*aproc) (), struct ubik_client *aclient,
994 afs_int32 aflags, char *p1, char *p2, char *p3,
995 char *p4, char *p5, char *p6, char *p7, char *p8,
996 char *p9, char *p10, char *p11, char *p12, char *p13,
997 char *p14, char *p15, char *p16)
998{
999 afs_int32 code;
1000 afs_int32 someCode, newHost, thisHost;
1001 afs_int32 i;
1002 afs_int32 count;
1003 int chaseCount;
1004 int pass;
1005 struct rx_connection *tc;
1006 struct rx_peer *rxp;
1007
1008 if ((aflags & (UF_SINGLESERVER1 | UF_END_SINGLESERVER2)) != 0) {
1009 if (((aflags & UF_SINGLESERVER1) != 0)
1010 && ((uServer.ucs_flags & UF_SINGLESERVER1) != 0)
1011 ) {
1012
1013 /* have a selected server */
1014 tc = aclient->conns[uServer.ucs_selectedServer];
1015
1016 code =
1017 (*aproc) (tc, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
1018 p12, p13, p14, p15, p16);
1019 if (code) {
1020 /* error. Clean up single server state */
1021 memset(&uServer, 0, sizeof(uServer));
1022 }
1023 return (code);
1024 } else if ((aflags & UF_END_SINGLESERVER2) != 0) {
1025 memset(&uServer, 0, sizeof(uServer));
1026 return (0);
1027 }
1028 }
1029
1030 someCode = UNOSERVERS(5389L);
1031 chaseCount = 0;
1032 pass = 0;
1033 count = 0;
1034 while (1) { /*w */
1035
1036 /* tc is the next conn to try */
1037 tc = aclient->conns[count];
1038 if (tc == 0) {
1039 if (pass == 0) {
1040 pass = 1; /* in pass 1, we look at down hosts, too */
1041 count = 0;
1042 continue;
1043 } else
1044 break; /* nothing left to try */
1045 }
1046 if (pass == 0 && (aclient->states[count] & CFLastFailed1)) {
1047 count++;
1048 continue; /* this guy's down, try someone else first */
1049 }
1050
1051 code =
1052 (*aproc) (tc, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12,
1053 p13, p14, p15, p16);
1054
1055 /* note that getting a UNOTSYNC error code back does *not* guarantee
1056 * that there is a sync site yet elected. However, if there is a
1057 * sync site out there somewhere, and you're trying an operation that
1058 * requires a sync site, ubik will return UNOTSYNC, indicating the
1059 * operation won't work until you find a sync site
1060 */
1061 if (code == UNOTSYNC(5377L)) { /*ns */
1062 /* means that this requires a sync site to work */
1063 someCode = code; /* remember an error, if this fails */
1064
1065 /* now see if we can find the sync site host */
1066 code = VOTE_GetSyncSite(tc, &newHost);
1067 if (code == 0 && newHost != 0) {
1068 newHost = htonl(newHost)(__builtin_constant_p(newHost) ? ((((__uint32_t)(newHost)) >>
24) | ((((__uint32_t)(newHost)) & (0xff << 16)) >>
8) | ((((__uint32_t)(newHost)) & (0xff << 8)) <<
8) | (((__uint32_t)(newHost)) << 24)) : __bswap32_var(
newHost))
; /* convert back to network order */
1069
1070 /* position count at the appropriate slot in the client
1071 * structure and retry. If we can't find in slot, we'll just
1072 * continue through the whole list
1073 */
1074 for (i = 0; i < MAXSERVERS20; i++) { /*f */
1075 rxp = rx_PeerOf(aclient->conns[i])((aclient->conns[i])->peer);
1076 if (!(thisHost = rx_HostOf(rxp)((rxp)->host))) {
1077 count++; /* host not found, try the next dude */
1078 break;
1079 }
1080 if (thisHost == newHost) {
1081 /* avoid asking in a loop */
1082 if (chaseCount++ > 2)
1083 break;
1084 count = i; /* we were told to use this one */
1085 break;
1086 }
1087 } /*f */
1088 } else
1089 count++; /* not directed, keep looking for a sync site */
1090 continue;
1091 } /*ns */
1092 else if (code == UNOQUORUM(5376L)) { /* this guy is still recovering */
1093 someCode = code;
1094 count++;
1095 continue;
1096 } else if (code < 0) { /* network errors */
1097 someCode = code;
1098 aclient->states[count] |= CFLastFailed1;
1099 count++;
1100 continue;
1101 } else {
1102 /* ok, operation worked */
1103 aclient->states[count] &= ~CFLastFailed1;
1104 /* either misc ubik code, or misc application code (incl success)
1105 */
1106
1107 /* if the call succeeded, setup connection state for subsequent
1108 * calls
1109 */
1110 if ((code == 0)
1111 && ((aflags & UF_SINGLESERVER1) != 0)
1112 ) {
1113 /* need to save state */
1114 uServer.ucs_flags = UF_SINGLESERVER1;
1115 uServer.ucs_selectedServer = count;
1116 }
1117
1118 return code;
1119 }
1120 } /*w */
1121 return someCode;
1122}
1123
1124
1125/* -------------------------------------
1126 * debug and test routines
1127 * -------------------------------------
1128 */
1129
1130/* udbLocalInit
1131 * For testing only. Open a connect to the database server running on
1132 * the local host
1133 * exit:
1134 * 0 - ubik connection established in the global udbHandle structure
1135 * n - error.
1136 */
1137
1138int
1139udbLocalInit(void)
1140{
1141 afs_uint32 serverList[MAXSERVERS20];
1142 char hostname[256];
1143 char *args[3];
1144 int i;
1145 afs_int32 code;
1146
1147 /* get our host name */
1148 gethostname(hostname, sizeof(hostname));
1149 /* strcpy(hostname, "hops"); */
1150
1151 args[0] = "";
1152 args[1] = "-servers";
1153 args[2] = hostname;
1154
1155 code = ubik_ParseClientList(3, args, serverList);
1156 if (code) {
1157 afs_com_err(whoami, code, "; udbLocalInit: parsing ubik server list");
1158 return (-1);
1159 }
1160
1161 udbHandle.uh_scIndex = RX_SECIDX_NULL;
1162 udbHandle.uh_secobj = (struct rx_securityClass *)
1163 rxnull_NewClientSecurityObject();
1164
1165 for (i = 0; serverList[i] != 0; i++) {
1166 udbHandle.uh_serverConn[i] =
1167 rx_NewConnection(serverList[i], htons(AFSCONF_BUDBPORT)(__builtin_constant_p(7021) ? (__uint16_t)(((__uint16_t)(7021
)) << 8 | ((__uint16_t)(7021)) >> 8) : __bswap16_var
(7021))
,
1168 BUDB_SERVICE22314, udbHandle.uh_secobj,
1169 udbHandle.uh_scIndex);
1170 if (udbHandle.uh_serverConn[i] == 0) {
1171 afs_com_err(whoami, 0, "connection %d failed", i);
1172 continue;
1173 }
1174 }
1175 udbHandle.uh_serverConn[i] = 0;
1176 code = ubik_ClientInit(udbHandle.uh_serverConn, &udbHandle.uh_client);
1177 if (code) {
1178 afs_com_err(whoami, code, "; in ubik_ClientInit");
1179 return (code);
1180 }
1181
1182 code =
1183 ubik_BUDB_GetInstanceId(udbHandle.uh_client, 0,
1184 &udbHandle.uh_instanceId);
1185 if (code) {
1186 afs_com_err(whoami, code, "; Can't estblish instance Id");
1187 return (code);
1188 }
1189
1190 /* abort: */
1191 return (0);
1192}
1193
1194/* bc_openTextFile - This function opens a temp file to read in the
1195 * config text recd from the bu server. On Unix, an unlink() is done on
1196 * the file as soon as it is opened, so when the program exits, the file will
1197 * be removed automatically, while being invisible while in use.
1198 * On NT, however, the file must be explicitly deleted after use with an unlink()
1199 * Input:
1200 * Pointer to a udhClientTextP struct. The open stream ptr is stored in
1201 * the udbClientTextP.textStream member.
1202 * Output: The temp file name is returned in tmpFileName. This should be used
1203 * to delete the file when done with it.
1204 * Return Values:
1205 * !0: error code
1206 * 0: Success.
1207 */
1208int
1209bc_openTextFile(udbClientTextP ctPtr, char *tmpFileName)
1210{
1211 int code = 0;
1212 int fd;
1213
1214 if (ctPtr->textStream != NULL((void *)0)) {
1215 fclose(ctPtr->textStream);
1216 ctPtr->textStream = NULL((void *)0);
1217 }
1218
1219 sprintf(tmpFileName, "%s/bu_XXXXXX", gettmpdir());
1220 fd = mkstemp(tmpFileName);
1221 if (fd == -1)
1222 ERROR(BUDB_INTERNALERROR)do { code = (156303895L); goto error_exit; } while (0);
1223 ctPtr->textStream = fdopen(fd, "w+");
1224 if (ctPtr->textStream == NULL((void *)0))
1225 ERROR(BUDB_INTERNALERROR)do { code = (156303895L); goto error_exit; } while (0);
1226
1227#ifndef AFS_NT40_ENV /* This can't be done on NT */
1228 /* make the file invisible to others */
1229 code = unlink(tmpFileName);
1230 if (code)
1231 ERROR(errno)do { code = (* __error()); goto error_exit; } while (0);
1232#endif
1233
1234 afs_dprintf(("file is %s\n", tmpFileName));
1235
1236 normal_exit:
1237 return code;
1238
1239 error_exit:
1240 if (ctPtr->textStream != NULL((void *)0)) {
1241 fclose(ctPtr->textStream);
1242 ctPtr->textStream = NULL((void *)0);
1243 }
1244 goto normal_exit;
1245}
1246
1247
1248/* bc_closeTextFile: This function closes any actual temp files associated with
1249 * a udbClientText structure.
1250 * Input: ctPtr->textStream - stream to close
1251 * tmpFileName - temp file name to delete
1252 * RetVal:
1253 * 0 - Success
1254 * !0 - error code
1255 */
1256int
1257bc_closeTextFile(udbClientTextP ctPtr, char *tmpFileName)
1258{
1259 int code = 0;
1260
1261 if (ctPtr->textStream)
1262 fclose(ctPtr->textStream);
1263
1264 if (*tmpFileName) { /* we have a valid name */
1265 code = unlink(tmpFileName);
1266 if (code < 0)
1267 code = errno(* __error());
1268 }
1269 return code;
1270}