| File: | butc/recoverDb.c |
| Location: | line 730, 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 | #include <afsconfig.h> | ||||
| 11 | #include <afs/param.h> | ||||
| 12 | |||||
| 13 | #include <roken.h> | ||||
| 14 | |||||
| 15 | #include <rx/xdr.h> | ||||
| 16 | #include <rx/rx.h> | ||||
| 17 | #include <lwp.h> | ||||
| 18 | #include <lock.h> | ||||
| 19 | #include <afs/afsutil.h> | ||||
| 20 | #include <afs/tcdata.h> | ||||
| 21 | #include <afs/bubasics.h> | ||||
| 22 | #include <afs/budb.h> | ||||
| 23 | #include <afs/budb_client.h> | ||||
| 24 | #include <afs/budb_prototypes.h> | ||||
| 25 | #include <afs/butm_prototypes.h> | ||||
| 26 | #include <afs/bucoord_prototypes.h> | ||||
| 27 | |||||
| 28 | #include "error_macros.h" | ||||
| 29 | #include "butc_internal.h" | ||||
| 30 | |||||
| 31 | #define BELLCHAR7 7 /* ascii for bell */ | ||||
| 32 | |||||
| 33 | /* GLOBAL CONFIGURATION PARAMETERS */ | ||||
| 34 | extern int autoQuery; | ||||
| 35 | extern int queryoperator; | ||||
| 36 | |||||
| 37 | /* Handle for the information read from all the tapes of a dump */ | ||||
| 38 | afs_int32 tapepos; /* when read a label, remember its position */ | ||||
| 39 | struct tapeScanInfo { | ||||
| 40 | struct butm_tapeLabel tapeLabel, dumpLabel; | ||||
| 41 | struct budb_dumpEntry dumpEntry; | ||||
| 42 | afs_int32 initialDumpId; | ||||
| 43 | int addDbFlag; | ||||
| 44 | }; | ||||
| 45 | |||||
| 46 | extern struct tapeConfig globalTapeConfig; | ||||
| 47 | extern struct deviceSyncNode *deviceLatch; | ||||
| 48 | |||||
| 49 | static int readDump(afs_uint32, struct butm_tapeInfo *, | ||||
| 50 | struct tapeScanInfo *); | ||||
| 51 | afs_int32 getScanTape(afs_int32, struct butm_tapeInfo *, char *, | ||||
| 52 | afs_int32, int prompt, struct butm_tapeLabel *); | ||||
| 53 | afs_int32 RcreateDump(struct tapeScanInfo *, struct volumeHeader *); | ||||
| 54 | void copy_ktcPrincipal_to_budbPrincipal(struct ktc_principal *, | ||||
| 55 | struct budb_principal *); | ||||
| 56 | |||||
| 57 | /* PrintDumpLabel | ||||
| 58 | * print out the tape (dump) label. | ||||
| 59 | */ | ||||
| 60 | void | ||||
| 61 | PrintDumpLabel(struct butm_tapeLabel *labelptr) | ||||
| 62 | { | ||||
| 63 | char tapeName[BU_MAXTAPELEN32 + 32]; | ||||
| 64 | time_t t; | ||||
| 65 | |||||
| 66 | printf("Dump label\n"); | ||||
| 67 | printf("----------\n"); | ||||
| 68 | TAPENAME(tapeName, labelptr->pName, labelptr->dumpid)if (!strcmp("", labelptr->pName)) sprintf(tapeName, "<NULL>" ); else if (labelptr->dumpid == 0) sprintf(tapeName, "%s", labelptr->pName); else sprintf(tapeName, "%s (%u)", labelptr ->pName, labelptr->dumpid);; | ||||
| 69 | printf("permanent tape name = %s\n", tapeName); | ||||
| 70 | TAPENAME(tapeName, labelptr->AFSName, labelptr->dumpid)if (!strcmp("", labelptr->AFSName)) sprintf(tapeName, "<NULL>" ); else if (labelptr->dumpid == 0) sprintf(tapeName, "%s", labelptr->AFSName); else sprintf(tapeName, "%s (%u)", labelptr ->AFSName, labelptr->dumpid);; | ||||
| 71 | printf("AFS tape name = %s\n", tapeName); | ||||
| 72 | t = labelptr->creationTime; | ||||
| 73 | printf("creationTime = %s", ctime(&t)); | ||||
| 74 | if (labelptr->expirationDate) { | ||||
| 75 | t = labelptr->expirationDate; | ||||
| 76 | printf("expirationDate = %s", cTIME(&t)( (*(&t) == 037777777777) ? (char *)"NEVER \n" : (char *)ctime(&t) )); | ||||
| 77 | } | ||||
| 78 | printf("cell = %s\n", labelptr->cell); | ||||
| 79 | printf("size = %u Kbytes\n", labelptr->size); | ||||
| 80 | printf("dump path = %s\n", labelptr->dumpPath); | ||||
| 81 | |||||
| 82 | if (labelptr->structVersion >= TAPE_VERSION_33) { | ||||
| 83 | printf("dump id = %u\n", labelptr->dumpid); | ||||
| 84 | printf("useCount = %d\n", labelptr->useCount); | ||||
| 85 | } | ||||
| 86 | printf("-- End of dump label --\n\n"); | ||||
| 87 | } | ||||
| 88 | |||||
| 89 | /* PrintVolumeHeader | ||||
| 90 | * print the contents of a volume header. | ||||
| 91 | */ | ||||
| 92 | static void | ||||
| 93 | PrintVolumeHeader(struct volumeHeader *volHeader) | ||||
| 94 | { | ||||
| 95 | time_t t; | ||||
| 96 | |||||
| 97 | printf("-- volume --\n"); | ||||
| 98 | printf("volume name: %s\n", volHeader->volumeName); | ||||
| 99 | printf("volume ID %d\n", volHeader->volumeID); | ||||
| 100 | /* printf("server %d\n", volHeader->server); */ | ||||
| 101 | printf("dumpSetName: %s\n", volHeader->dumpSetName); | ||||
| 102 | printf("dumpID %d\n", volHeader->dumpID); | ||||
| 103 | printf("level %d\n", volHeader->level); | ||||
| 104 | printf("parentID %d\n", volHeader->parentID); | ||||
| 105 | printf("endTime %d\n", volHeader->endTime); | ||||
| 106 | /* printf("versionflags %d\n", volHeader->versionflags); */ | ||||
| 107 | t = volHeader->cloneDate; | ||||
| 108 | printf("clonedate %s\n", ctime(&t)); | ||||
| 109 | } | ||||
| 110 | |||||
| 111 | /* Ask | ||||
| 112 | * ask a question. returns true or false | ||||
| 113 | * exit: | ||||
| 114 | * 1 - yes | ||||
| 115 | * 0 - no | ||||
| 116 | */ | ||||
| 117 | |||||
| 118 | afs_int32 | ||||
| 119 | Ask(char *st) | ||||
| 120 | { | ||||
| 121 | int response; | ||||
| 122 | |||||
| 123 | while (1) { | ||||
| 124 | FFlushInput(); | ||||
| 125 | putchar(BELLCHAR)(!__isthreaded ? __sputc(7, __stdoutp) : (putc)(7, __stdoutp) ); | ||||
| 126 | printf("%s? (y/n) ", st); | ||||
| 127 | fflush(stdout__stdoutp); | ||||
| 128 | response = getchar()(!__isthreaded ? (--(__stdinp)->_r < 0 ? __srget(__stdinp ) : (int)(*(__stdinp)->_p++)) : (getc)(__stdinp)); | ||||
| 129 | if (response == 'y') | ||||
| 130 | return (1); | ||||
| 131 | else if (response == 'n' || response == EOF(-1)) | ||||
| 132 | return (0); | ||||
| 133 | printf("please answer y/n\n"); | ||||
| 134 | } | ||||
| 135 | } | ||||
| 136 | |||||
| 137 | /* scanVolData | ||||
| 138 | * Skips the volume data on the tape. The end of the volume data is | ||||
| 139 | * detected by the presence of the volume trailer or by an EOF indication | ||||
| 140 | * from butm. This algorithm should be replaced by one that always | ||||
| 141 | * detects based on the volume trailer, returning the trailer to the | ||||
| 142 | * caller. This is of course more painful. | ||||
| 143 | * entry: | ||||
| 144 | * curTapePtr - tape info structure | ||||
| 145 | * Tape must be positioned after volume header | ||||
| 146 | * exit: | ||||
| 147 | * 0 - success | ||||
| 148 | * 3 - empty volume, requires special handling | ||||
| 149 | * | ||||
| 150 | * Tape positioned after data, but before file end marker block. | ||||
| 151 | * In case of errors, positioned after the error causing block | ||||
| 152 | */ | ||||
| 153 | #define BIGCHUNK102400 102400 | ||||
| 154 | |||||
| 155 | static int | ||||
| 156 | scanVolData(afs_int32 taskId, struct butm_tapeInfo *curTapePtr, | ||||
| 157 | afs_int32 tapeVersion, struct volumeHeader *volumeHeader, | ||||
| 158 | struct volumeHeader *volumeTrailer, afs_uint32 *bytesRead) | ||||
| 159 | { | ||||
| 160 | afs_int32 headBytes, tailBytes; | ||||
| 161 | char *block = NULL((void *)0); | ||||
| 162 | char *buffer[2]; | ||||
| 163 | int hasdata[2], curr, prev; | ||||
| 164 | afs_uint32 chunkSize = 0; | ||||
| 165 | afs_int32 nbytes; | ||||
| 166 | afs_int32 code = 0; | ||||
| 167 | afs_int32 rcode, tcode; | ||||
| 168 | |||||
| 169 | memset(volumeHeader, 0, sizeof(struct volumeHeader)); | ||||
| 170 | |||||
| 171 | block = (char *)malloc(2 * BUTM_BLOCKSIZE16384); | ||||
| 172 | if (!block) | ||||
| 173 | return (TC_NOMEMORY(156566290L)); | ||||
| 174 | buffer[0] = &block[sizeof(struct blockMark)]; | ||||
| 175 | buffer[1] = &block[BUTM_BLOCKSIZE16384 + sizeof(struct blockMark)]; | ||||
| 176 | hasdata[0] = hasdata[1] = 0; | ||||
| 177 | curr = 0; | ||||
| 178 | |||||
| 179 | tcode = NextFile(curTapePtr); /* guarantees we are at a filemark */ | ||||
| 180 | if (tcode) | ||||
| 181 | ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0); | ||||
| 182 | |||||
| 183 | /* Read the FileBegin FileMark */ | ||||
| 184 | code = butm_ReadFileBegin(curTapePtr)(*((curTapePtr)->ops.readFileBegin))(curTapePtr); | ||||
| 185 | if (code) { | ||||
| 186 | /* | ||||
| 187 | * Tapes made with 3.0 have no software EOT markers. Therefore | ||||
| 188 | * at this point, we will most likely get a read error, indicating | ||||
| 189 | * the end of this dump | ||||
| 190 | */ | ||||
| 191 | if ((tapeVersion == TAPE_VERSION_00) | ||||
| 192 | || (tapeVersion == TAPE_VERSION_11)) { | ||||
| 193 | /* | ||||
| 194 | * then a tape error is possible at this point, and it | ||||
| 195 | * signals the end of the dump. Tapes that are continued | ||||
| 196 | * have an EOT marker. | ||||
| 197 | */ | ||||
| 198 | TapeLog(0, taskId, code, curTapePtr->error, | ||||
| 199 | "Read error - end-of-dump inferred\n"); | ||||
| 200 | code = BUTM_EOD(156568847L); | ||||
| 201 | } | ||||
| 202 | |||||
| 203 | if (code != BUTM_EOD(156568847L)) | ||||
| 204 | ErrorLog(0, taskId, code, curTapePtr->error, | ||||
| 205 | "Can't read FileBegin on tape\n"); | ||||
| 206 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 207 | } | ||||
| 208 | |||||
| 209 | /* now read the volume header */ | ||||
| 210 | code = ReadVolHeader(taskId, curTapePtr, volumeHeader); | ||||
| 211 | if (code) | ||||
| 212 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 213 | |||||
| 214 | *bytesRead = 0; | ||||
| 215 | while (1) { /*w */ | ||||
| 216 | |||||
| 217 | /* Check for abort in the middle of scanning data */ | ||||
| 218 | if (*bytesRead >= chunkSize) { | ||||
| 219 | if (checkAbortByTaskId(taskId)) | ||||
| 220 | ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0); | ||||
| 221 | chunkSize += BIGCHUNK102400; | ||||
| 222 | } | ||||
| 223 | |||||
| 224 | /* | ||||
| 225 | * Read volume date - If prematurely hit the HW EOF | ||||
| 226 | * marker, check to see if data contains a volumetrailer. | ||||
| 227 | */ | ||||
| 228 | rcode = | ||||
| 229 | butm_ReadFileData(curTapePtr, buffer[curr], BUTM_BLKSIZE,(*((curTapePtr)->ops.readFileData))(curTapePtr,buffer[curr ],(16384 - ((5*sizeof(afs_int32)) + sizeof(int))),&nbytes ) | ||||
| 230 | &nbytes)(*((curTapePtr)->ops.readFileData))(curTapePtr,buffer[curr ],(16384 - ((5*sizeof(afs_int32)) + sizeof(int))),&nbytes ); | ||||
| 231 | if (rcode) { | ||||
| 232 | hasdata[curr] = 0; | ||||
| 233 | if ((rcode == BUTM_EOF(156568849L)) || (rcode == BUTM_ENDVOLUME(156568845L))) | ||||
| 234 | break; | ||||
| 235 | |||||
| 236 | ErrorLog(0, taskId, rcode, curTapePtr->error, | ||||
| 237 | "Can't read FileData on tape\n"); | ||||
| 238 | ERROR_EXIT(rcode)do { code = rcode; goto error_exit; } while (0); | ||||
| 239 | } | ||||
| 240 | hasdata[curr] = 1; | ||||
| 241 | *bytesRead += nbytes; | ||||
| 242 | |||||
| 243 | if ((nbytes != BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int)))) | ||||
| 244 | || | ||||
| 245 | (FindVolTrailer(buffer[curr], nbytes, &tailBytes, volumeTrailer))) | ||||
| 246 | break; | ||||
| 247 | |||||
| 248 | curr = ((curr == 0) ? 1 : 0); /* Switch buffers */ | ||||
| 249 | } /*w */ | ||||
| 250 | |||||
| 251 | /* Now verify that there is a volume trailer and its valid and copy it */ | ||||
| 252 | prev = ((curr == 0) ? 1 : 0); | ||||
| 253 | if (!FindVolTrailer2 | ||||
| 254 | (buffer[prev], (hasdata[prev] ? BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int))) : 0), &headBytes, | ||||
| 255 | buffer[curr], nbytes, &tailBytes, volumeTrailer)) { | ||||
| 256 | code = TC_MISSINGTRAILER(156566284L); | ||||
| 257 | ErrorLog(0, taskId, code, 0, "Missing volume trailer on tape\n"); | ||||
| 258 | } else { | ||||
| 259 | /* subtract size of the volume trailer from data read */ | ||||
| 260 | *bytesRead -= sizeof(struct volumeHeader); | ||||
| 261 | } | ||||
| 262 | |||||
| 263 | /* | ||||
| 264 | * If we didn't hit the EOF while reading data, read FileEnd marker | ||||
| 265 | * or EOF marker. | ||||
| 266 | */ | ||||
| 267 | if (!rcode) { | ||||
| 268 | tcode = butm_ReadFileEnd(curTapePtr)(*((curTapePtr)->ops.readFileEnd))(curTapePtr); | ||||
| 269 | if (tcode) { | ||||
| 270 | ErrorLog(0, taskId, tcode, curTapePtr->error, | ||||
| 271 | "Can't read EOF on tape\n"); | ||||
| 272 | ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0); | ||||
| 273 | } | ||||
| 274 | } | ||||
| 275 | |||||
| 276 | error_exit: | ||||
| 277 | if (block) | ||||
| 278 | free(block); | ||||
| 279 | return (code); | ||||
| 280 | } | ||||
| 281 | |||||
| 282 | /* nextTapeLabel | ||||
| 283 | * generate the name of the next tape label expected | ||||
| 284 | * exit: | ||||
| 285 | * ptr to static string | ||||
| 286 | */ | ||||
| 287 | |||||
| 288 | char * | ||||
| 289 | nextTapeLabel(char *prevTapeName) | ||||
| 290 | { | ||||
| 291 | char *prevdot; | ||||
| 292 | char *retval; | ||||
| 293 | int seq; | ||||
| 294 | static char buffer[BU_MAXTAPELEN32]; | ||||
| 295 | |||||
| 296 | retval = ""; | ||||
| 297 | |||||
| 298 | /* extract information from previous tape label */ | ||||
| 299 | strcpy(buffer, prevTapeName); | ||||
| 300 | prevdot = strrchr(buffer, '.'); | ||||
| 301 | if (!prevdot) | ||||
| 302 | return (retval); | ||||
| 303 | prevdot++; | ||||
| 304 | |||||
| 305 | seq = extractTapeSeq(prevTapeName); | ||||
| 306 | seq++; | ||||
| 307 | sprintf(prevdot, "%-d", seq); | ||||
| 308 | |||||
| 309 | return (&buffer[0]); | ||||
| 310 | } | ||||
| 311 | |||||
| 312 | /* readDump | ||||
| 313 | * Read all the information on a tape. If to add to the database, queue | ||||
| 314 | * onto list so another thread adds the entries to the database. | ||||
| 315 | * entry: | ||||
| 316 | * taskid - butc task number. | ||||
| 317 | * tapeInfoPtr - Tape information. | ||||
| 318 | * scanInfoPtr - Info to keep so we can add entries to the db. | ||||
| 319 | * exit: | ||||
| 320 | * 0 - tape scanned. | ||||
| 321 | * non-0 - error. Abort the scan. | ||||
| 322 | * moreTapes set to 1 if this is not the last tape in the dump, | ||||
| 323 | * 0 if the last tape, | ||||
| 324 | * -1 don't know if last tape or not. | ||||
| 325 | */ | ||||
| 326 | |||||
| 327 | static int | ||||
| 328 | readDump(afs_uint32 taskId, struct butm_tapeInfo *tapeInfoPtr, | ||||
| 329 | struct tapeScanInfo *scanInfoPtr) | ||||
| 330 | { | ||||
| 331 | int moreTapes = 1; | ||||
| 332 | afs_int32 flags, seq; | ||||
| 333 | afs_uint32 nbytes = 0; | ||||
| 334 | int newDump = 1, newTape = 1; | ||||
| 335 | afs_int32 tapePosition; | ||||
| 336 | afs_int32 code = 0, tcode; | ||||
| 337 | int badscan; | ||||
| 338 | struct volumeHeader volHeader, volTrailer; | ||||
| 339 | struct budb_tapeEntry tapeEntry; | ||||
| 340 | struct budb_volumeEntry volEntry; | ||||
| 341 | |||||
| 342 | volEntry.dump = 0; | ||||
| 343 | PrintDumpLabel(&scanInfoPtr->dumpLabel); | ||||
| 344 | |||||
| 345 | while (moreTapes) { /* While there is a tape to read *//*t */ | ||||
| 346 | badscan = 0; | ||||
| 347 | while (1) { /* Read each volume on the tape *//*w */ | ||||
| 348 | moreTapes = -1; | ||||
| 349 | tapePosition = tapeInfoPtr->position; /* remember position */ | ||||
| 350 | |||||
| 351 | /* | ||||
| 352 | * Skip the volume data | ||||
| 353 | */ | ||||
| 354 | tcode = | ||||
| 355 | scanVolData(taskId, tapeInfoPtr, | ||||
| 356 | scanInfoPtr->tapeLabel.structVersion, &volHeader, | ||||
| 357 | &volTrailer, &nbytes); | ||||
| 358 | if (tcode) { | ||||
| 359 | badscan++; | ||||
| 360 | |||||
| 361 | if (tcode == TC_ABORTEDBYREQUEST(156566278L)) { /* Aborted */ | ||||
| 362 | ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0); | ||||
| 363 | } | ||||
| 364 | |||||
| 365 | if (tcode == BUTM_EOD(156568847L)) { | ||||
| 366 | moreTapes = 0; /* the end of the dump */ | ||||
| 367 | break; | ||||
| 368 | } | ||||
| 369 | |||||
| 370 | /* Found a volume but it's incomplete. Skip over these */ | ||||
| 371 | if (volHeader.volumeID) { | ||||
| 372 | TapeLog(0, taskId, tcode, 0, | ||||
| 373 | "Warning: volume %s (%u) ignored. Incomplete\n", | ||||
| 374 | volHeader.volumeName, volHeader.volumeID); | ||||
| 375 | continue; | ||||
| 376 | } | ||||
| 377 | |||||
| 378 | /* No volume was found. We may have hit the EOT or a | ||||
| 379 | * bad-spot. Try to skip over this spot. | ||||
| 380 | */ | ||||
| 381 | if (badscan < 2) { /* allow 2 errors, then fail */ | ||||
| 382 | TapeLog(0, taskId, tcode, 0, | ||||
| 383 | "Warning: Error in scanning tape - will try skipping volume\n"); | ||||
| 384 | continue; | ||||
| 385 | } | ||||
| 386 | if (scanInfoPtr->tapeLabel.structVersion >= TAPE_VERSION_44) { | ||||
| 387 | TapeLog(0, taskId, tcode, 0, | ||||
| 388 | "Warning: Error in scanning tape - end-of-tape inferred\n"); | ||||
| 389 | moreTapes = 1; /* then assume next tape */ | ||||
| 390 | } else { | ||||
| 391 | ErrorLog(0, taskId, tcode, 0, "Error in scanning tape\n"); | ||||
| 392 | /* will ask if there is a next tape */ | ||||
| 393 | } | ||||
| 394 | break; | ||||
| 395 | } | ||||
| 396 | |||||
| 397 | PrintVolumeHeader(&volHeader); | ||||
| 398 | |||||
| 399 | /* If this is not the first volume fragment, make sure it follows | ||||
| 400 | * the last volume fragment | ||||
| 401 | */ | ||||
| 402 | if (volEntry.dump) { | ||||
| 403 | if ((volEntry.dump != volHeader.dumpID) | ||||
| 404 | || (volEntry.id != volHeader.volumeID) | ||||
| 405 | || (volEntry.seq != volHeader.frag - 2) | ||||
| 406 | || (strcmp(volEntry.name, volHeader.volumeName))) { | ||||
| 407 | TLog(taskId, | ||||
| 408 | "Warning: volume %s (%u) ignored. Incomplete - no last fragment\n", | ||||
| 409 | volEntry.name, volEntry.id); | ||||
| 410 | |||||
| 411 | if (scanInfoPtr->addDbFlag) { | ||||
| 412 | tcode = flushSavedEntries(DUMP_FAILED1); | ||||
| 413 | if (tcode) | ||||
| 414 | ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0); | ||||
| 415 | volEntry.dump = 0; | ||||
| 416 | } | ||||
| 417 | } | ||||
| 418 | } | ||||
| 419 | |||||
| 420 | /* If this is the first volume fragment, make sure says so */ | ||||
| 421 | if (scanInfoPtr->addDbFlag && !volEntry.dump | ||||
| 422 | && (volHeader.frag != 1)) { | ||||
| 423 | TLog(taskId, | ||||
| 424 | "Warning: volume %s (%u) ignored. Incomplete - no first fragment\n", | ||||
| 425 | volHeader.volumeName, volHeader.volumeID); | ||||
| 426 | } | ||||
| 427 | |||||
| 428 | /* Check that this volume belongs to the dump we are scanning */ | ||||
| 429 | else if (scanInfoPtr->dumpLabel.dumpid | ||||
| 430 | && (volHeader.dumpID != scanInfoPtr->dumpLabel.dumpid)) { | ||||
| 431 | TLog(taskId, | ||||
| 432 | "Warning: volume %s (%u) ignored. Expected DumpId %u, got %u\n", | ||||
| 433 | volHeader.volumeName, volHeader.volumeID, | ||||
| 434 | scanInfoPtr->dumpLabel.dumpid, volHeader.dumpID); | ||||
| 435 | } | ||||
| 436 | |||||
| 437 | /* Passed tests, Now add to the database (if dbadd flag is set) */ | ||||
| 438 | else if (scanInfoPtr->addDbFlag) { | ||||
| 439 | /* Have enough information to create a dump entry */ | ||||
| 440 | if (newDump) { | ||||
| 441 | tcode = RcreateDump(scanInfoPtr, &volHeader); | ||||
| 442 | if (tcode) { | ||||
| 443 | ErrorLog(0, taskId, tcode, 0, | ||||
| 444 | "Can't add dump %u to database\n", | ||||
| 445 | volHeader.dumpID); | ||||
| 446 | ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0); | ||||
| 447 | } | ||||
| 448 | newDump = 0; | ||||
| 449 | } | ||||
| 450 | |||||
| 451 | /* Have enough information to create a tape entry */ | ||||
| 452 | if (newTape) { | ||||
| 453 | seq = extractTapeSeq(scanInfoPtr->tapeLabel.AFSName); | ||||
| 454 | if (seq < 0) | ||||
| 455 | ERROR_EXIT(TC_INTERNALERROR)do { code = (156566288L); goto error_exit; } while (0); | ||||
| 456 | |||||
| 457 | tcode = | ||||
| 458 | useTape(&tapeEntry, volHeader.dumpID, | ||||
| 459 | TNAME(&scanInfoPtr->tapeLabel)( strcmp((&scanInfoPtr->tapeLabel)->pName,"") ? (& scanInfoPtr->tapeLabel)->pName : ( strcmp((&scanInfoPtr ->tapeLabel)->AFSName,"") ? (&scanInfoPtr->tapeLabel )->AFSName : "<NULL>" ) ), seq, | ||||
| 460 | scanInfoPtr->tapeLabel.useCount, | ||||
| 461 | scanInfoPtr->dumpLabel.creationTime, | ||||
| 462 | scanInfoPtr->dumpLabel.expirationDate, | ||||
| 463 | tapepos); | ||||
| 464 | if (tcode) { | ||||
| 465 | char gotName[BU_MAXTAPELEN32 + 32]; | ||||
| 466 | |||||
| 467 | LABELNAME(gotName, &scanInfoPtr->tapeLabel)if (!strcmp("", ( strcmp((&scanInfoPtr->tapeLabel)-> pName,"") ? (&scanInfoPtr->tapeLabel)->pName : ( strcmp ((&scanInfoPtr->tapeLabel)->AFSName,"") ? (&scanInfoPtr ->tapeLabel)->AFSName : "<NULL>" ) ))) sprintf(gotName , "<NULL>"); else if ((&scanInfoPtr->tapeLabel)-> dumpid == 0) sprintf(gotName, "%s", ( strcmp((&scanInfoPtr ->tapeLabel)->pName,"") ? (&scanInfoPtr->tapeLabel )->pName : ( strcmp((&scanInfoPtr->tapeLabel)->AFSName ,"") ? (&scanInfoPtr->tapeLabel)->AFSName : "<NULL>" ) )); else sprintf(gotName, "%s (%u)", ( strcmp((&scanInfoPtr ->tapeLabel)->pName,"") ? (&scanInfoPtr->tapeLabel )->pName : ( strcmp((&scanInfoPtr->tapeLabel)->AFSName ,"") ? (&scanInfoPtr->tapeLabel)->AFSName : "<NULL>" ) ), (&scanInfoPtr->tapeLabel)->dumpid);; | ||||
| 468 | ErrorLog(0, taskId, tcode, 0, | ||||
| 469 | "Can't add tape %s for dump %u to database\n", | ||||
| 470 | gotName, volHeader.dumpID); | ||||
| 471 | ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0); | ||||
| 472 | } | ||||
| 473 | newTape = 0; | ||||
| 474 | } | ||||
| 475 | |||||
| 476 | /* Create the volume entry */ | ||||
| 477 | flags = ((volHeader.frag == 1) ? BUDB_VOL_FIRSTFRAG(1<<3) : 0); | ||||
| 478 | if (!volTrailer.contd) | ||||
| 479 | flags |= BUDB_VOL_LASTFRAG(1<<4); | ||||
| 480 | tcode = | ||||
| 481 | addVolume(&volEntry, volHeader.dumpID, | ||||
| 482 | TNAME(&scanInfoPtr->tapeLabel)( strcmp((&scanInfoPtr->tapeLabel)->pName,"") ? (& scanInfoPtr->tapeLabel)->pName : ( strcmp((&scanInfoPtr ->tapeLabel)->AFSName,"") ? (&scanInfoPtr->tapeLabel )->AFSName : "<NULL>" ) ), | ||||
| 483 | volHeader.volumeName, volHeader.volumeID, | ||||
| 484 | volHeader.cloneDate, tapePosition, nbytes, | ||||
| 485 | (volHeader.frag - 1), flags); | ||||
| 486 | if (tcode) { | ||||
| 487 | ErrorLog(0, taskId, tcode, 0, | ||||
| 488 | "Can't add volume %s (%u) for dump %u to database\n", | ||||
| 489 | volHeader.volumeName, volHeader.volumeID, | ||||
| 490 | volHeader.dumpID); | ||||
| 491 | ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0); | ||||
| 492 | } | ||||
| 493 | } | ||||
| 494 | |||||
| 495 | if (volTrailer.contd) { | ||||
| 496 | /* No need to read the EOD marker, we know there is a next tape */ | ||||
| 497 | moreTapes = 1; | ||||
| 498 | break; | ||||
| 499 | } else { | ||||
| 500 | if (scanInfoPtr->addDbFlag) { | ||||
| 501 | tcode = flushSavedEntries(DUMP_SUCCESS3); | ||||
| 502 | if (tcode) | ||||
| 503 | ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0); | ||||
| 504 | volEntry.dump = 0; | ||||
| 505 | } | ||||
| 506 | } | ||||
| 507 | } /*w */ | ||||
| 508 | |||||
| 509 | if (!newTape) { | ||||
| 510 | if (scanInfoPtr->addDbFlag) { | ||||
| 511 | tcode = | ||||
| 512 | finishTape(&tapeEntry, | ||||
| 513 | (tapeInfoPtr->kBytes + | ||||
| 514 | (tapeInfoPtr->nBytes ? 1 : 0))); | ||||
| 515 | if (tcode) { | ||||
| 516 | char gotName[BU_MAXTAPELEN32 + 32]; | ||||
| 517 | |||||
| 518 | LABELNAME(gotName, &scanInfoPtr->tapeLabel)if (!strcmp("", ( strcmp((&scanInfoPtr->tapeLabel)-> pName,"") ? (&scanInfoPtr->tapeLabel)->pName : ( strcmp ((&scanInfoPtr->tapeLabel)->AFSName,"") ? (&scanInfoPtr ->tapeLabel)->AFSName : "<NULL>" ) ))) sprintf(gotName , "<NULL>"); else if ((&scanInfoPtr->tapeLabel)-> dumpid == 0) sprintf(gotName, "%s", ( strcmp((&scanInfoPtr ->tapeLabel)->pName,"") ? (&scanInfoPtr->tapeLabel )->pName : ( strcmp((&scanInfoPtr->tapeLabel)->AFSName ,"") ? (&scanInfoPtr->tapeLabel)->AFSName : "<NULL>" ) )); else sprintf(gotName, "%s (%u)", ( strcmp((&scanInfoPtr ->tapeLabel)->pName,"") ? (&scanInfoPtr->tapeLabel )->pName : ( strcmp((&scanInfoPtr->tapeLabel)->AFSName ,"") ? (&scanInfoPtr->tapeLabel)->AFSName : "<NULL>" ) ), (&scanInfoPtr->tapeLabel)->dumpid);; | ||||
| 519 | ErrorLog(0, taskId, tcode, 0, | ||||
| 520 | "Can't mark tape %s 'completed' for dump %u in database\n", | ||||
| 521 | gotName, tapeEntry.dump); | ||||
| 522 | ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0); | ||||
| 523 | } | ||||
| 524 | } | ||||
| 525 | } | ||||
| 526 | |||||
| 527 | /* Ask if there is another tape if we can't figure it out */ | ||||
| 528 | if (moreTapes == -1) | ||||
| 529 | moreTapes = (queryoperator ? Ask("Are there more tapes") : 1); | ||||
| 530 | |||||
| 531 | /* Get the next tape label */ | ||||
| 532 | if (moreTapes) { | ||||
| 533 | char *tapeName; | ||||
| 534 | afs_int32 dumpid; | ||||
| 535 | |||||
| 536 | unmountTape(taskId, tapeInfoPtr); | ||||
| 537 | |||||
| 538 | tapeName = nextTapeLabel(scanInfoPtr->tapeLabel.AFSName); | ||||
| 539 | dumpid = scanInfoPtr->tapeLabel.dumpid; | ||||
| 540 | tcode = | ||||
| 541 | getScanTape(taskId, tapeInfoPtr, tapeName, dumpid, 1, | ||||
| 542 | &scanInfoPtr->tapeLabel); | ||||
| 543 | if (tcode) | ||||
| 544 | ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0); | ||||
| 545 | newTape = 1; | ||||
| 546 | } | ||||
| 547 | } /*t */ | ||||
| 548 | |||||
| 549 | if (!newDump) { | ||||
| 550 | if (scanInfoPtr->addDbFlag) { | ||||
| 551 | tcode = finishDump(&scanInfoPtr->dumpEntry); | ||||
| 552 | if (tcode) { | ||||
| 553 | ErrorLog(0, taskId, tcode, 0, | ||||
| 554 | "Can't mark dump %u 'completed' in database\n", | ||||
| 555 | scanInfoPtr->dumpEntry.id); | ||||
| 556 | } | ||||
| 557 | |||||
| 558 | tcode = flushSavedEntries(DUMP_SUCCESS3); | ||||
| 559 | if (tcode) | ||||
| 560 | ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0); | ||||
| 561 | } | ||||
| 562 | } | ||||
| 563 | |||||
| 564 | error_exit: | ||||
| 565 | return (code); | ||||
| 566 | } | ||||
| 567 | |||||
| 568 | /* Will read a dump, then see if there is a dump following it and | ||||
| 569 | * try to read that dump too. | ||||
| 570 | * The first tape label is the first dumpLabel. | ||||
| 571 | */ | ||||
| 572 | int | ||||
| 573 | readDumps(afs_uint32 taskId, struct butm_tapeInfo *tapeInfoPtr, | ||||
| 574 | struct tapeScanInfo *scanInfoPtr) | ||||
| 575 | { | ||||
| 576 | afs_int32 code, c; | ||||
| 577 | |||||
| 578 | memcpy(&scanInfoPtr->dumpLabel, &scanInfoPtr->tapeLabel, | ||||
| 579 | sizeof(struct butm_tapeLabel)); | ||||
| 580 | |||||
| 581 | while (1) { | ||||
| 582 | code = readDump(taskId, tapeInfoPtr, scanInfoPtr); | ||||
| 583 | if (code) | ||||
| 584 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 585 | |||||
| 586 | if (scanInfoPtr->tapeLabel.structVersion < TAPE_VERSION_44) | ||||
| 587 | break; | ||||
| 588 | |||||
| 589 | /* Remember the initial dump and see if appended dump exists */ | ||||
| 590 | |||||
| 591 | if (!scanInfoPtr->initialDumpId) | ||||
| 592 | scanInfoPtr->initialDumpId = scanInfoPtr->dumpEntry.id; | ||||
| 593 | |||||
| 594 | c = butm_ReadLabel(tapeInfoPtr, &scanInfoPtr->dumpLabel, 0)(*((tapeInfoPtr)->ops.readLabel))(tapeInfoPtr,&scanInfoPtr ->dumpLabel,0); /* no rewind */ | ||||
| 595 | tapepos = tapeInfoPtr->position - 1; | ||||
| 596 | if (c) | ||||
| 597 | break; | ||||
| 598 | } | ||||
| 599 | |||||
| 600 | error_exit: | ||||
| 601 | return (code); | ||||
| 602 | } | ||||
| 603 | |||||
| 604 | afs_int32 | ||||
| 605 | getScanTape(afs_int32 taskId, struct butm_tapeInfo *tapeInfoPtr, char *tname, | ||||
| 606 | afs_int32 tapeId, int prompt, struct butm_tapeLabel *tapeLabelPtr) | ||||
| 607 | { | ||||
| 608 | afs_int32 code = 0; | ||||
| 609 | int tapecount = 1; | ||||
| 610 | afs_int32 curseq; | ||||
| 611 | char tapename[BU_MAXTAPELEN32 + 32]; | ||||
| 612 | char gotname[BU_MAXTAPELEN32 + 32]; | ||||
| 613 | |||||
| 614 | while (1) { | ||||
| 615 | /* prompt for a tape */ | ||||
| 616 | if (prompt) { | ||||
| 617 | code = | ||||
| 618 | PromptForTape(SCANOPCODE4, tname, tapeId, taskId, tapecount); | ||||
| 619 | if (code) | ||||
| 620 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 621 | } | ||||
| 622 | prompt = 1; | ||||
| 623 | tapecount++; | ||||
| 624 | |||||
| 625 | code = butm_Mount(tapeInfoPtr, "")(*((tapeInfoPtr)->ops.mount))(tapeInfoPtr,""); /* open the tape device */ | ||||
| 626 | if (code) { | ||||
| 627 | TapeLog(0, taskId, code, tapeInfoPtr->error, "Can't open tape\n"); | ||||
| 628 | goto newtape; | ||||
| 629 | } | ||||
| 630 | |||||
| 631 | /* read the label on the tape */ | ||||
| 632 | code = butm_ReadLabel(tapeInfoPtr, tapeLabelPtr, 1)(*((tapeInfoPtr)->ops.readLabel))(tapeInfoPtr,tapeLabelPtr ,1); /* rewind tape */ | ||||
| 633 | if (code) { | ||||
| 634 | ErrorLog(0, taskId, code, tapeInfoPtr->error, | ||||
| 635 | "Can't read tape label\n"); | ||||
| 636 | goto newtape; | ||||
| 637 | } | ||||
| 638 | tapepos = tapeInfoPtr->position - 1; | ||||
| 639 | |||||
| 640 | /* Now check that the tape is good */ | ||||
| 641 | TAPENAME(tapename, tname, tapeId)if (!strcmp("", tname)) sprintf(tapename, "<NULL>"); else if (tapeId == 0) sprintf(tapename, "%s", tname); else sprintf (tapename, "%s (%u)", tname, tapeId);; | ||||
| 642 | TAPENAME(gotname, tapeLabelPtr->AFSName, tapeLabelPtr->dumpid)if (!strcmp("", tapeLabelPtr->AFSName)) sprintf(gotname, "<NULL>" ); else if (tapeLabelPtr->dumpid == 0) sprintf(gotname, "%s" , tapeLabelPtr->AFSName); else sprintf(gotname, "%s (%u)", tapeLabelPtr->AFSName, tapeLabelPtr->dumpid);; | ||||
| 643 | |||||
| 644 | curseq = extractTapeSeq(tapeLabelPtr->AFSName); | ||||
| 645 | |||||
| 646 | /* Label can't be null or a bad name */ | ||||
| 647 | if (!strcmp(tapeLabelPtr->AFSName, "") || (curseq <= 0)) { | ||||
| 648 | TLog(taskId, "Expected tape with dump, label seen %s\n", gotname); | ||||
| 649 | goto newtape; | ||||
| 650 | } | ||||
| 651 | |||||
| 652 | /* Label can't be a database tape */ | ||||
| 653 | if (databaseTape(tapeLabelPtr->AFSName)) { | ||||
| 654 | TLog(taskId, | ||||
| 655 | "Expected tape with dump. Can't scan database tape %s\n", | ||||
| 656 | gotname); | ||||
| 657 | goto newtape; | ||||
| 658 | } | ||||
| 659 | |||||
| 660 | /* If no name, accept any tape */ | ||||
| 661 | if (strcmp(tname, "") == 0) { | ||||
| 662 | break; /* Start scan on any tape */ | ||||
| 663 | #ifdef notdef | ||||
| 664 | if (curseq == 1) | ||||
| 665 | break; /* The first tape */ | ||||
| 666 | else { | ||||
| 667 | TLog(taskId, "Expected first tape of dump, label seen %s\n", | ||||
| 668 | gotname); | ||||
| 669 | goto newtape; | ||||
| 670 | } | ||||
| 671 | #endif | ||||
| 672 | } | ||||
| 673 | |||||
| 674 | if (strcmp(tname, tapeLabelPtr->AFSName) | ||||
| 675 | || ((tapeLabelPtr->structVersion >= TAPE_VERSION_33) | ||||
| 676 | && (tapeLabelPtr->dumpid != tapeId))) { | ||||
| 677 | TLog(taskId, "Tape label expected %s, label seen %s\n", tapename, | ||||
| 678 | gotname); | ||||
| 679 | goto newtape; | ||||
| 680 | } | ||||
| 681 | |||||
| 682 | /* We have the correct tape */ | ||||
| 683 | break; | ||||
| 684 | |||||
| 685 | newtape: | ||||
| 686 | unmountTape(taskId, tapeInfoPtr); | ||||
| 687 | } | ||||
| 688 | |||||
| 689 | error_exit: | ||||
| 690 | return (code); | ||||
| 691 | } | ||||
| 692 | |||||
| 693 | /* ScanDumps | ||||
| 694 | * This set of code fragments read a tape, and add the information to | ||||
| 695 | * the database. Builds a literal structure. | ||||
| 696 | * | ||||
| 697 | */ | ||||
| 698 | |||||
| 699 | void * | ||||
| 700 | ScanDumps(void *param) | ||||
| 701 | { | ||||
| 702 | struct scanTapeIf *ptr = (struct scanTapeIf *)param; | ||||
| 703 | |||||
| 704 | struct butm_tapeInfo curTapeInfo; | ||||
| 705 | struct tapeScanInfo tapeScanInfo; | ||||
| 706 | afs_uint32 taskId; | ||||
| 707 | afs_int32 code = 0; | ||||
| 708 | |||||
| 709 | afs_pthread_setname_self("scandump")(void)0; | ||||
| 710 | taskId = ptr->taskId; | ||||
| 711 | setStatus(taskId, DRIVE_WAIT0x100); | ||||
| 712 | EnterDeviceQueue(deviceLatch); | ||||
| 713 | clearStatus(taskId, DRIVE_WAIT0x100); | ||||
| 714 | |||||
| 715 | printf("\n\n"); | ||||
| 716 | if (ptr->addDbFlag) | ||||
| |||||
| 717 | TLog(taskId, "ScanTape and add to the database\n"); | ||||
| 718 | else | ||||
| 719 | TLog(taskId, "Scantape\n"); | ||||
| 720 | |||||
| 721 | memset(&tapeScanInfo, 0, sizeof(tapeScanInfo)); | ||||
| 722 | tapeScanInfo.addDbFlag = ptr->addDbFlag; | ||||
| 723 | |||||
| 724 | memset(&curTapeInfo, 0, sizeof(curTapeInfo)); | ||||
| 725 | curTapeInfo.structVersion = BUTM_MAJORVERSION2; | ||||
| 726 | code = butm_file_Instantiate(&curTapeInfo, &globalTapeConfig); | ||||
| 727 | if (code) { | ||||
| |||||
| 728 | ErrorLog(0, taskId, code, curTapeInfo.error, | ||||
| 729 | "Can't initialize tape module\n"); | ||||
| 730 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| |||||
| 731 | } | ||||
| 732 | |||||
| 733 | code = | ||||
| 734 | getScanTape(taskId, &curTapeInfo, "", 0, autoQuery, | ||||
| 735 | &tapeScanInfo.tapeLabel); | ||||
| 736 | if (code) | ||||
| 737 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 738 | |||||
| 739 | code = readDumps(taskId, &curTapeInfo, &tapeScanInfo); | ||||
| 740 | if (code) | ||||
| 741 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 742 | |||||
| 743 | error_exit: | ||||
| 744 | unmountTape(taskId, &curTapeInfo); | ||||
| 745 | waitDbWatcher(); | ||||
| 746 | |||||
| 747 | if (code == TC_ABORTEDBYREQUEST(156566278L)) { | ||||
| 748 | ErrorLog(0, taskId, 0, 0, "Scantape: Aborted by request\n"); | ||||
| 749 | clearStatus(taskId, ABORT_REQUEST0x2); | ||||
| 750 | setStatus(taskId, ABORT_DONE0x8); | ||||
| 751 | } else if (code) { | ||||
| 752 | ErrorLog(0, taskId, code, 0, "Scantape: Finished with errors\n"); | ||||
| 753 | setStatus(taskId, TASK_ERROR0x80); | ||||
| 754 | } else { | ||||
| 755 | TLog(taskId, "Scantape: Finished\n"); | ||||
| 756 | } | ||||
| 757 | |||||
| 758 | free(ptr); | ||||
| 759 | setStatus(taskId, TASK_DONE0x20); | ||||
| 760 | LeaveDeviceQueue(deviceLatch); | ||||
| 761 | return (void *)(intptr_t)(code); | ||||
| 762 | } | ||||
| 763 | |||||
| 764 | |||||
| 765 | /* validatePath | ||||
| 766 | * exit: | ||||
| 767 | * 0 - not ok | ||||
| 768 | * 1 - ok | ||||
| 769 | */ | ||||
| 770 | int | ||||
| 771 | validatePath(struct butm_tapeLabel *labelptr, char *pathptr) | ||||
| 772 | { | ||||
| 773 | char *up, *tp; | ||||
| 774 | char tapeName[BU_MAXTAPELEN32]; | ||||
| 775 | |||||
| 776 | /* check length */ | ||||
| 777 | if (strlen(pathptr) > BU_MAX_DUMP_PATH256 - 1) { | ||||
| 778 | fprintf(stderr__stderrp, "Invalid pathname - too long\n"); | ||||
| 779 | return (0); | ||||
| 780 | } | ||||
| 781 | |||||
| 782 | if (!labelptr) | ||||
| 783 | return (1); | ||||
| 784 | |||||
| 785 | strcpy(tapeName, labelptr->AFSName); | ||||
| 786 | |||||
| 787 | tp = strrchr(tapeName, '.'); | ||||
| 788 | if (!tp) | ||||
| 789 | return (1); | ||||
| 790 | tp++; | ||||
| 791 | |||||
| 792 | up = strrchr(pathptr, '/'); | ||||
| 793 | if (!up) { | ||||
| 794 | fprintf(stderr__stderrp, "Invalid path name, missing /\n"); | ||||
| 795 | return (0); | ||||
| 796 | } | ||||
| 797 | up++; | ||||
| 798 | |||||
| 799 | if (strcmp(up, tp) != 0) { | ||||
| 800 | fprintf(stderr__stderrp, "Invalid path name\n"); | ||||
| 801 | fprintf(stderr__stderrp, | ||||
| 802 | "Mismatch between tape dump name '%s' and users dump name '%s'\n", | ||||
| 803 | tp, up); | ||||
| 804 | return (0); | ||||
| 805 | } | ||||
| 806 | return (1); | ||||
| 807 | } | ||||
| 808 | |||||
| 809 | /* volumesetNamePtr | ||||
| 810 | * return a pointer to a (static) volume set name string. | ||||
| 811 | * entry: | ||||
| 812 | * ptr - ptr to a dump name | ||||
| 813 | * exit: | ||||
| 814 | * 0 - error. Can't extract volumeset name. | ||||
| 815 | * ptr - to static volumeset string. | ||||
| 816 | */ | ||||
| 817 | |||||
| 818 | char * | ||||
| 819 | volumesetNamePtr(char *ptr) | ||||
| 820 | { | ||||
| 821 | static char vsname[BU_MAXUNAMELEN256]; | ||||
| 822 | char *dotPtr; | ||||
| 823 | int dotIndex; | ||||
| 824 | |||||
| 825 | dotPtr = strchr(ptr, '.'); | ||||
| 826 | if (!dotPtr) | ||||
| 827 | return (0); | ||||
| 828 | |||||
| 829 | dotIndex = dotPtr - ptr; | ||||
| 830 | if ((dotIndex + 1) > sizeof(vsname)) | ||||
| 831 | return (0); /* name too long */ | ||||
| 832 | |||||
| 833 | strncpy(&vsname[0], ptr, dotIndex); | ||||
| 834 | vsname[dotIndex] = 0; /* ensure null terminated */ | ||||
| 835 | |||||
| 836 | return (&vsname[0]); | ||||
| 837 | } | ||||
| 838 | |||||
| 839 | char * | ||||
| 840 | extractDumpName(char *ptr) | ||||
| 841 | { | ||||
| 842 | static char dname[BU_MAXTAPELEN32]; | ||||
| 843 | char *dotPtr; | ||||
| 844 | int dotIndex; | ||||
| 845 | |||||
| 846 | dotPtr = strrchr(ptr, '.'); | ||||
| 847 | if (!dotPtr) | ||||
| 848 | return (0); | ||||
| 849 | |||||
| 850 | dotIndex = dotPtr - ptr; | ||||
| 851 | if ((dotIndex + 1) > sizeof(dname)) | ||||
| 852 | return (0); /* name too long */ | ||||
| 853 | |||||
| 854 | strncpy(&dname[0], ptr, dotIndex); | ||||
| 855 | dname[dotIndex] = 0; /* ensure null terminated */ | ||||
| 856 | |||||
| 857 | return (&dname[0]); | ||||
| 858 | } | ||||
| 859 | |||||
| 860 | /* extractTapeSeq | ||||
| 861 | * The routine assumes that tape names have an embedded sequence number | ||||
| 862 | * as the trialing component. It is suggested that any tape naming | ||||
| 863 | * changes retain the trailing seq. number | ||||
| 864 | * entry: | ||||
| 865 | * tapename - ptr to tape name | ||||
| 866 | * exit: | ||||
| 867 | * 0 or positive - sequence number | ||||
| 868 | * -1 - error, couldn't extract sequence number | ||||
| 869 | */ | ||||
| 870 | |||||
| 871 | int | ||||
| 872 | extractTapeSeq(char *tapename) | ||||
| 873 | { | ||||
| 874 | char *sptr; | ||||
| 875 | |||||
| 876 | sptr = strrchr(tapename, '.'); | ||||
| 877 | if (!sptr) | ||||
| 878 | return (-1); | ||||
| 879 | sptr++; | ||||
| 880 | return (atol(sptr)); | ||||
| 881 | } | ||||
| 882 | |||||
| 883 | /* databaseTape | ||||
| 884 | * returns true or false depending on whether the tape is | ||||
| 885 | * a database tape or not. | ||||
| 886 | */ | ||||
| 887 | int | ||||
| 888 | databaseTape(char *tapeName) | ||||
| 889 | { | ||||
| 890 | char *sptr; | ||||
| 891 | int c; | ||||
| 892 | |||||
| 893 | sptr = strrchr(tapeName, '.'); | ||||
| 894 | if (!sptr) | ||||
| 895 | return (0); | ||||
| 896 | |||||
| 897 | c = (int)((char *) sptr - (char *) tapeName); | ||||
| 898 | if (strncmp(tapeName, DUMP_TAPE_NAME"Ubik_db_dump", c) == 0) | ||||
| 899 | return (1); | ||||
| 900 | |||||
| 901 | return (0); | ||||
| 902 | } | ||||
| 903 | |||||
| 904 | afs_int32 | ||||
| 905 | RcreateDump(struct tapeScanInfo *tapeScanInfoPtr, | ||||
| 906 | struct volumeHeader *volHeaderPtr) | ||||
| 907 | { | ||||
| 908 | afs_int32 code; | ||||
| 909 | struct butm_tapeLabel *dumpLabelPtr = &tapeScanInfoPtr->dumpLabel; | ||||
| 910 | struct budb_dumpEntry *dumpEntryPtr = &tapeScanInfoPtr->dumpEntry; | ||||
| 911 | |||||
| 912 | /* construct dump entry */ | ||||
| 913 | memset(dumpEntryPtr, 0, sizeof(struct budb_dumpEntry)); | ||||
| 914 | dumpEntryPtr->id = volHeaderPtr->dumpID; | ||||
| 915 | dumpEntryPtr->initialDumpID = tapeScanInfoPtr->initialDumpId; | ||||
| 916 | dumpEntryPtr->parent = volHeaderPtr->parentID; | ||||
| 917 | dumpEntryPtr->level = volHeaderPtr->level; | ||||
| 918 | dumpEntryPtr->created = volHeaderPtr->dumpID; /* time dump was created */ | ||||
| 919 | dumpEntryPtr->flags = 0; | ||||
| 920 | dumpEntryPtr->incTime = 0; | ||||
| 921 | dumpEntryPtr->nVolumes = 0; | ||||
| 922 | strcpy(dumpEntryPtr->volumeSetName, | ||||
| 923 | volumesetNamePtr(volHeaderPtr->dumpSetName)); | ||||
| 924 | strcpy(dumpEntryPtr->dumpPath, dumpLabelPtr->dumpPath); | ||||
| 925 | strcpy(dumpEntryPtr->name, volHeaderPtr->dumpSetName); | ||||
| 926 | default_tapeset(&dumpEntryPtr->tapes, volHeaderPtr->dumpSetName); | ||||
| 927 | dumpEntryPtr->tapes.b = extractTapeSeq(dumpLabelPtr->AFSName); | ||||
| 928 | copy_ktcPrincipal_to_budbPrincipal(&dumpLabelPtr->creator, | ||||
| 929 | &dumpEntryPtr->dumper); | ||||
| 930 | |||||
| 931 | code = bcdb_CreateDump(dumpEntryPtr); | ||||
| 932 | return (code); | ||||
| 933 | } |