| File: | bucoord/ubik_db_if.c |
| Location: | line 319, column 2 |
| Description: | Assigned value is always the same as the existing value |
| 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 | |||||
| 37 | extern char *whoami; | ||||
| 38 | |||||
| 39 | /* ------------------------------------- | ||||
| 40 | * Globals | ||||
| 41 | * ------------------------------------- | ||||
| 42 | */ | ||||
| 43 | |||||
| 44 | struct udbHandleS udbHandle; | ||||
| 45 | |||||
| 46 | /* ------------------------------------- | ||||
| 47 | * interface routines (alphabetic) | ||||
| 48 | * ------------------------------------- | ||||
| 49 | */ | ||||
| 50 | |||||
| 51 | afs_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 | |||||
| 59 | afs_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 | |||||
| 71 | afs_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 | |||||
| 79 | afs_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 | |||||
| 97 | afs_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 | |||||
| 125 | afs_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 | |||||
| 149 | afs_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 | |||||
| 175 | int | ||||
| 176 | bcdb_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 | */ | ||||
| 192 | int | ||||
| 193 | bcdb_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 | |||||
| 252 | afs_int32 | ||||
| 253 | bcdb_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 | |||||
| 281 | int | ||||
| 282 | bcdb_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 | |||||
| 300 | int | ||||
| 301 | bcdb_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 | |||||
| 332 | int | ||||
| 333 | bcdb_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 | |||||
| 376 | afs_int32 | ||||
| 377 | bcdb_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 | |||||
| 401 | int | ||||
| 402 | bcdb_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 | |||||
| 409 | int | ||||
| 410 | bcdb_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 | |||||
| 421 | afs_int32 | ||||
| 422 | bcdb_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 | |||||
| 448 | int | ||||
| 449 | bcdb_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 | |||||
| 471 | int | ||||
| 472 | bcdb_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; | ||||
| 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 | |||||
| 551 | int | ||||
| 552 | bcdb_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 | |||||
| 619 | int | ||||
| 620 | bcdb_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 | |||||
| 628 | int | ||||
| 629 | bcdb_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 | |||||
| 642 | afs_int32 | ||||
| 643 | filesize(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 | |||||
| 671 | int | ||||
| 672 | bc_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 | |||||
| 720 | int | ||||
| 721 | bc_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 | |||||
| 742 | int | ||||
| 743 | bc_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 | |||||
| 766 | static afsconf_secflags | ||||
| 767 | parseSecFlags(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 | */ | ||||
| 786 | int | ||||
| 787 | vldbClientInit(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 | |||||
| 865 | afs_int32 | ||||
| 866 | udbClientInit(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 | |||||
| 975 | struct ubikCallState { | ||||
| 976 | afs_int32 ucs_flags; /* state flags */ | ||||
| 977 | afs_int32 ucs_selectedServer; /* which server selected */ | ||||
| 978 | }; | ||||
| 979 | |||||
| 980 | static 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 | |||||
| 992 | afs_int32 | ||||
| 993 | ubik_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 | |||||
| 1138 | int | ||||
| 1139 | udbLocalInit(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 | */ | ||||
| 1208 | int | ||||
| 1209 | bc_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 | */ | ||||
| 1256 | int | ||||
| 1257 | bc_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 | } |