~ubuntu-branches/ubuntu/warty/openafs/warty

« back to all changes in this revision

Viewing changes to src/butc/recoverDb.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2004-01-10 16:37:33 UTC
  • Revision ID: james.westby@ubuntu.com-20040110163733-jvr0n1uahshlb1uu
Tags: upstream-1.2.11
ImportĀ upstreamĀ versionĀ 1.2.11

Show diffs side-by-side

added added

removed removed

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