Bug Summary

File:butc/lwps.c
Location:line 1772, column 5
Description:Branch condition evaluates to a garbage value

Annotated Source Code

1/*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10#include <afsconfig.h>
11#include <afs/param.h>
12
13#include <afs/procmgmt.h>
14#include <roken.h>
15
16#ifdef AFS_NT40_ENV
17#include <conio.h>
18#endif
19
20#include <rx/xdr.h>
21#include <rx/rx.h>
22#include <lwp.h>
23#include <lock.h>
24#include <afs/tcdata.h>
25#include <afs/bubasics.h> /* PA */
26#include <afs/budb_client.h>
27#include <afs/bucoord_prototypes.h>
28#include <afs/butm_prototypes.h>
29#include <afs/volser.h>
30#include <afs/volser_prototypes.h>
31#include <afs/com_err.h>
32#include <afs/afsutil.h>
33
34#include "error_macros.h"
35#include "butc_xbsa.h"
36#include "butc_internal.h"
37
38/* GLOBAL CONFIGURATION PARAMETERS */
39extern int queryoperator;
40extern int tapemounted;
41extern char *opencallout;
42extern char *closecallout;
43extern char *whoami;
44extern char *extractDumpName(char *);
45extern int BufferSize; /* Size in B stored for header info */
46FILE *restoretofilefd;
47#ifdef xbsa
48extern char *restoretofile;
49extern int forcemultiple;
50#endif
51
52/* XBSA Global Parameters */
53afs_int32 xbsaType;
54#ifdef xbsa
55struct butx_transactionInfo butxInfo;
56#endif
57
58static struct TapeBlock { /* A 16KB tapeblock */
59 char mark[BUTM_HDRSIZE((5*sizeof(afs_int32)) + sizeof(int))]; /* Header info */
60 char data[BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int)))]; /* data */
61} *bufferBlock;
62
63afs_int32 dataSize; /* Size of data to read on each xbsa_ReadObjectData() call (CONF_XBSA) */
64afs_int32 tapeblocks; /* Number of tape datablocks in buffer (!CONF_XBSA) */
65
66/* notes
67 * Need to re-write to:
68 * 1) non-interactive tape handling (optional)
69 * 2) compute tape and volume sizes for the database
70 * 3) compute and use tape id's for tape tracking (put on tape label)
71 * 4) status management
72 */
73
74/* All the relevant info shared between Restorer and restoreVolume */
75struct restoreParams {
76 struct dumpNode *nodePtr;
77 afs_int32 frag;
78 char mntTapeName[BU_MAXTAPELEN32];
79 afs_int32 tapeID;
80 struct butm_tapeInfo *tapeInfoPtr;
81};
82
83/* Abort checks are done after each BIGCHUNK of data transfer */
84#define BIGCHUNK102400 102400
85
86#define HEADER_CHECKS(vhptr, header){ afs_int32 magic, versionflags; versionflags = (__builtin_constant_p
(vhptr.versionflags) ? ((((__uint32_t)(vhptr.versionflags)) >>
24) | ((((__uint32_t)(vhptr.versionflags)) & (0xff <<
16)) >> 8) | ((((__uint32_t)(vhptr.versionflags)) &
(0xff << 8)) << 8) | (((__uint32_t)(vhptr.versionflags
)) << 24)) : __bswap32_var(vhptr.versionflags)); if ( versionflags
== 0 || versionflags == 1 || versionflags == 2 || versionflags
== 3 || versionflags == 4 ) { magic = (__builtin_constant_p(
vhptr.magic) ? ((((__uint32_t)(vhptr.magic)) >> 24) | (
(((__uint32_t)(vhptr.magic)) & (0xff << 16)) >>
8) | ((((__uint32_t)(vhptr.magic)) & (0xff << 8)) <<
8) | (((__uint32_t)(vhptr.magic)) << 24)) : __bswap32_var
(vhptr.magic)); if (magic == 0xb0258191 || magic == 0x9167345a
|| magic == 0xffffffff ) { memcpy(header, &vhptr, sizeof
(struct volumeHeader)); return (0); } } }
\
87{ \
88 afs_int32 magic, versionflags; \
89 \
90 versionflags = ntohl(vhptr.versionflags)(__builtin_constant_p(vhptr.versionflags) ? ((((__uint32_t)(vhptr
.versionflags)) >> 24) | ((((__uint32_t)(vhptr.versionflags
)) & (0xff << 16)) >> 8) | ((((__uint32_t)(vhptr
.versionflags)) & (0xff << 8)) << 8) | (((__uint32_t
)(vhptr.versionflags)) << 24)) : __bswap32_var(vhptr.versionflags
))
; \
91 if ( versionflags == TAPE_VERSION_00 || \
92 versionflags == TAPE_VERSION_11 || \
93 versionflags == TAPE_VERSION_22 || \
94 versionflags == TAPE_VERSION_33 || \
95 versionflags == TAPE_VERSION_44 ) { \
96 \
97 magic = ntohl(vhptr.magic)(__builtin_constant_p(vhptr.magic) ? ((((__uint32_t)(vhptr.magic
)) >> 24) | ((((__uint32_t)(vhptr.magic)) & (0xff <<
16)) >> 8) | ((((__uint32_t)(vhptr.magic)) & (0xff
<< 8)) << 8) | (((__uint32_t)(vhptr.magic)) <<
24)) : __bswap32_var(vhptr.magic))
; /* another sanity check */ \
98 if (magic == TC_VOLBEGINMAGIC0xb0258191 || \
99 magic == TC_VOLENDMAGIC0x9167345a || \
100 magic == TC_VOLCONTD0xffffffff ) { \
101 \
102 memcpy(header, &vhptr, sizeof(struct volumeHeader)); \
103 return (0); \
104 } /* magic */ \
105 } /* versionflags */ \
106}
107
108extern FILE *logIO;
109extern FILE *ErrorlogIO;
110extern FILE *centralLogIO;
111extern FILE *lastLogIO;
112extern afs_int32 lastPass; /* Set true during last pass of dump */
113extern int debugLevel;
114extern int autoQuery;
115extern struct tapeConfig globalTapeConfig;
116extern struct deviceSyncNode *deviceLatch;
117extern char globalCellName[];
118struct timeval tp;
119
120/* forward declaration */
121afs_int32 readVolumeHeader(char *, afs_int32, struct volumeHeader *);
122int FindVolTrailer(char *, afs_int32, afs_int32 *, struct volumeHeader *);
123int FindVolTrailer2(char *, afs_int32, afs_int32 *, char *, afs_int32,
124 afs_int32 *, struct volumeHeader *);
125int SkipVolume(struct tc_restoreDesc *, afs_int32, afs_int32, afs_int32,
126 afs_int32);
127
128
129
130/* The on-disk volume header or trailer can differ in size from platform to platform */
131static struct TapeBlock tapeBlock;
132char tapeVolumeHT[sizeof(struct volumeHeader) + 2 * sizeof(char)];
133
134void
135PrintLogStr(FILE *log, afs_int32 error1, afs_int32 error2, char *str)
136{
137 char *err1, *err2;
138
139 fprintf(log, "%s", str);
140 if (error1) {
141 err2 = "vols";
142 switch (error1) {
143 case VSALVAGE101:
144 err1 = "Volume needs to be salvaged";
145 break;
146 case VNOVNODE102:
147 err1 = "Bad vnode number quoted";
148 break;
149 case VNOVOL103:
150 err1 = "Volume not attached, does not exist, or not on line";
151 break;
152 case VVOLEXISTS104:
153 err1 = "Volume already exists";
154 break;
155 case VNOSERVICE105:
156 err1 = "Volume is not in service";
157 break;
158 case VOFFLINE106:
159 err1 = "Volume is off line";
160 break;
161 case VONLINE107:
162 err1 = "Volume is already on line";
163 break;
164 case VDISKFULL108:
165 err1 = "Partition is full";
166 break;
167 case VOVERQUOTA109:
168 err1 = "Volume max quota exceeded";
169 break;
170 case VBUSY110:
171 err1 = "Volume temporarily unavailable";
172 break;
173 case VMOVED111:
174 err1 = "Volume has moved to another server";
175 break;
176 default:
177 err1 = (char *)afs_error_message(error1);
178 err2 = (char *)afs_error_table_name(error1);
179 break;
180 }
181 if (error1 == -1)
182 fprintf(log, " Possible communication failure");
183 else
184 fprintf(log, " %s: %s", err2, err1);
185 if (error2)
186 fprintf(log, ": %s", afs_error_message(error2));
187 fprintf(log, "\n");
188 }
189 fflush(log);
190}
191
192void
193TapeLogStr(int debug, afs_int32 task, afs_int32 error1, afs_int32 error2,
194 char *str)
195{
196 time_t now;
197 char tbuffer[32];
198 struct tm tm;
199
200 now = time(0);
201 if (strftime(tbuffer, sizeof(tbuffer), "%a %b %d %T %Y",
202 localtime_r(&now, &tm)) != 0)
203 fprintf(logIO, "%s: ", tbuffer);
204
205 if (task)
206 fprintf(logIO, "Task %u: ", task);
207 PrintLogStr(logIO, error1, error2, str);
208
209 if (lastPass && lastLogIO) {
210 fprintf(lastLogIO, "%s: ", tbuffer);
211 if (task)
212 fprintf(lastLogIO, "Task %u: ", task);
213 PrintLogStr(lastLogIO, error1, error2, str);
214 }
215
216 /* Now print to the screen if debug level requires */
217 if (debug <= debugLevel)
218 PrintLogStr(stdout__stdoutp, error1, error2, str);
219}
220
221void
222TapeLog(int debug, afs_int32 task, afs_int32 error1, afs_int32 error2,
223 char *fmt, ...)
224{
225 char tmp[1024];
226 va_list ap;
227
228 va_start(ap, fmt)__builtin_va_start((ap), (fmt));
229 vsnprintf(tmp, sizeof(tmp), fmt, ap);
230 va_end(ap)__builtin_va_end(ap);
231
232 TapeLogStr(debug, task, error1, error2, tmp);
233}
234
235void
236TLog(afs_int32 task, char *fmt, ...)
237{
238 char tmp[1024];
239 va_list ap;
240
241 va_start(ap, fmt)__builtin_va_start((ap), (fmt));
242 vsnprintf(tmp, sizeof(tmp), fmt, ap);
243 va_end(ap)__builtin_va_end(ap);
244
245 /* Sends message to TapeLog and stdout */
246 TapeLogStr(0, task, 0, 0, tmp);
247}
248
249void
250ErrorLogStr(int debug, afs_int32 task, afs_int32 error1, afs_int32 error2,
251 char *errStr)
252{
253 time_t now;
254 char tbuffer[32];
255 struct tm tm;
256
257 now = time(0);
258 if (strftime(tbuffer, sizeof(tbuffer), "%a %b %d %T %Y",
259 localtime_r(&now, &tm)) != 0)
260 fprintf(ErrorlogIO, "%s: ", tbuffer);
261
262 /* Print the time and task number */
263 if (task)
264 fprintf(ErrorlogIO, "Task %u: ", task);
265
266 PrintLogStr(ErrorlogIO, error1, error2, errStr);
267 TapeLogStr(debug, task, error1, error2, errStr);
268}
269
270void
271ErrorLog(int debug, afs_int32 task, afs_int32 error1, afs_int32 error2,
272 char *fmt, ...)
273{
274 char tmp[1024];
275 va_list ap;
276
277 va_start(ap, fmt)__builtin_va_start((ap), (fmt));
278 vsnprintf(tmp, sizeof(tmp), fmt, ap);
279 va_end(ap)__builtin_va_end(ap);
280
281 ErrorLogStr(debug, task, error1, error2, tmp);
282
283}
284
285void
286ELog(afs_int32 task, char *fmt, ...)
287{
288 char tmp[1024];
289 va_list ap;
290
291 va_start(ap, fmt)__builtin_va_start((ap), (fmt));
292 vsnprintf(tmp, sizeof(tmp), fmt, ap);
293 va_end(ap)__builtin_va_end(ap);
294
295 /* Sends message to ErrorLog, TapeLog and stdout */
296 ErrorLog(0, task, 0, 0, "%s", tmp);
297}
298
299/* first proc called by anybody who intends to use the device */
300void
301EnterDeviceQueue(struct deviceSyncNode *devLatch)
302{
303 ObtainWriteLock(&(devLatch->lock))do { ; if (!(&(devLatch->lock))->excl_locked &&
!(&(devLatch->lock))->readers_reading) (&(devLatch
->lock)) -> excl_locked = 2; else Afs_Lock_Obtain(&
(devLatch->lock), 2); ; } while (0)
;
304 devLatch->flags = TC_DEVICEINUSE0x1000;
305}
306
307/* last proc called by anybody finishing using the device */
308void
309LeaveDeviceQueue(struct deviceSyncNode *devLatch)
310{
311 devLatch->flags = 0;
312 ReleaseWriteLock(&(devLatch->lock))do { ; (&(devLatch->lock))->excl_locked &= ~2; if
((&(devLatch->lock))->wait_states) Afs_Lock_ReleaseR
(&(devLatch->lock)); ; } while (0)
;
313}
314
315#define BELLTIME60 60 /* 60 seconds before a bell rings */
316#define BELLCHAR7 7 /* ascii for bell */
317
318/*
319 * FFlushInput
320 * flush all input
321 * notes:
322 * only external clients are in recoverDb.c. Was static. PA
323 */
324void
325FFlushInput(void)
326{
327 int w;
328
329 fflush(stdin__stdinp);
330
331 while (1) {
332 w = LWP_WaitForKeystroke(0);
333 if (w) {
334#ifdef AFS_NT40_ENV
335 getche();
336#else
337 getchar()(!__isthreaded ? (--(__stdinp)->_r < 0 ? __srget(__stdinp
) : (int)(*(__stdinp)->_p++)) : (getc)(__stdinp))
;
338#endif /* AFS_NT40_ENV */
339 } else {
340 return;
341 }
342 }
343}
344
345int
346callOutRoutine(afs_int32 taskId, char *tapePath, int flag, char *name,
347 afs_uint32 dbDumpId, int tapecount)
348{
349 int pid;
350
351 char StapePath[256];
352 char ScallOut[256];
353 char Scount[10];
354 char Sopcode[16];
355 char Sdumpid[16];
356 char Stape[40];
357 char *callOut;
358
359 char *CO_argv[10];
360 char *CO_envp[1];
361
362
363 callOut = opencallout;
364 switch (flag) {
365 case READOPCODE0:
366 strcpy(Sopcode, "restore");
367 break;
368 case APPENDOPCODE5:
369 strcpy(Sopcode, "appenddump");
370 break;
371 case WRITEOPCODE1:
372 strcpy(Sopcode, "dump");
373 break;
374 case LABELOPCODE2:
375 strcpy(Sopcode, "labeltape");
376 break;
377 case READLABELOPCODE3:
378 strcpy(Sopcode, "readlabel");
379 break;
380 case SCANOPCODE4:
381 strcpy(Sopcode, "scantape");
382 break;
383 case RESTOREDBOPCODE7:
384 strcpy(Sopcode, "restoredb");
385 break;
386 case SAVEDBOPCODE6:
387 strcpy(Sopcode, "savedb");
388 break;
389 case CLOSEOPCODE8:
390 strcpy(Sopcode, "unmount");
391 callOut = closecallout;
392 break;
393 default:
394 strcpy(Sopcode, "unknown");
395 break;
396 }
397
398 if (!callOut) /* no script to call */
399 return 0;
400
401 strcpy(ScallOut, callOut);
402 CO_argv[0] = ScallOut;
403
404 strcpy(StapePath, tapePath);
405 CO_argv[1] = StapePath;
406
407 CO_argv[2] = Sopcode;
408
409 if (flag == CLOSEOPCODE8) {
410 CO_argv[3] = NULL((void *)0);
411 } else {
412 sprintf(Scount, "%d", tapecount);
413 CO_argv[3] = Scount;
414
415 /* The tape label name - special case labeltape */
416 if (!name || (strcmp(name, "") == 0)) /* no label */
417 strcpy(Stape, "none");
418 else { /* labeltape */
419#ifdef AFS_NT40_ENV
420 if (!strcmp(name, TC_NULLTAPENAME"<NULL>")) /* pass "<NULL>" instead of <NULL> */
421 strcpy(Stape, TC_QUOTEDNULLTAPENAME"\"<NULL>\"");
422 else
423#endif
424 strcpy(Stape, name);
425 }
426 CO_argv[4] = Stape;
427
428 /* The tape id */
429 if (!dbDumpId)
430 strcpy(Sdumpid, "none");
431 else
432 sprintf(Sdumpid, "%u", dbDumpId);
433 CO_argv[5] = Sdumpid;
434
435 CO_argv[6] = NULL((void *)0);
436 }
437
438 CO_envp[0] = NULL((void *)0);
439
440 pid = spawnprocve(callOut, CO_argv, CO_envp, 2)pmgt_ProcessSpawnVE(callOut, CO_argv, CO_envp, 2);
441 if (pid < 0) {
442 ErrorLog(0, taskId, errno(* __error()), 0,
443 "Call to %s outside routine %s failed\n", Sopcode, callOut);
444 return 0;
445 }
446
447 return (pid);
448}
449
450/*
451 * unmountTape
452 * Unmounts a tape and prints a warning if it can't unmount it.
453 * Regardless of error, the closecallout routine will be called
454 * (unless a tape is not mounted in the first place).
455 */
456void
457unmountTape(afs_int32 taskId, struct butm_tapeInfo *tapeInfoPtr)
458{
459 afs_int32 code;
460 int cpid, status, rcpid;
461
462 code = butm_Dismount(tapeInfoPtr)(*((tapeInfoPtr)->ops.dismount))(tapeInfoPtr);
463 if (code && (code != BUTM_NOMOUNT(156568833L)))
464 ErrorLog(0, taskId, code, (tapeInfoPtr)->error,
465 "Warning: Can't close tape\n");
466
467 if (tapemounted && closecallout) {
468 setStatus(taskId, CALL_WAIT0x800);
469
470 cpid =
471 callOutRoutine(taskId, globalTapeConfig.device, CLOSEOPCODE8, "",
472 0, 1);
473 while (cpid) { /* Wait until return */
474 status = 0;
475 rcpid = waitpid(cpid, &status, WNOHANG1);
476 if (rcpid > 0) {
477 tapemounted = 0;
478 break;
479 }
480 if (rcpid == -1 && errno(* __error()) != EINTR4) {
481 tapemounted = 0;
482 afs_com_err(whoami, errno(* __error()),
483 "Error waiting for callout script to terminate.");
484 break;
485 }
486#ifdef AFS_PTHREAD_ENV
487 sleep(1);
488#else
489 IOMGR_Sleep(1);
490#endif
491
492 if (checkAbortByTaskId(taskId)) {
493 TLog(taskId, "Callout routine has been aborted\n");
494 if (kill(cpid, SIGKILL9)) /* Cancel callout */
495 ErrorLog(0, taskId, errno(* __error()), 0,
496 "Kill of callout process %d failed\n", cpid);
497 break;
498 }
499 }
500 }
501 clearStatus(taskId, CALL_WAIT0x800);
502}
503
504/* PrintPrompt
505 * print out prompt to operator
506 * calledby:
507 * PromptForTape only.
508 */
509
510void static
511PrintPrompt(int flag, char *name, int dumpid)
512{
513 char tapename[BU_MAXTAPELEN32 + 32];
514 char *dn;
515
516 TAPENAME(tapename, name, dumpid)if (!strcmp("", name)) sprintf(tapename, "<NULL>"); else
if (dumpid == 0) sprintf(tapename, "%s", name); else sprintf
(tapename, "%s (%u)", name, dumpid);
;
517
518 printf("******* OPERATOR ATTENTION *******\n");
519 printf("Device : %s \n", globalTapeConfig.device);
520
521 switch (flag) {
522 case READOPCODE0: /* mount for restore */
523 printf("Please put in tape %s for reading", tapename);
524 break;
525
526 case APPENDOPCODE5: /* mount for dump (appends) */
527
528 dn = extractDumpName(name);
529
530 if (!dn || !dumpid)
531 printf("Please put in last tape of dump set for appending dump");
532 else
533 printf
534 ("Please put in last tape of dump set for appending dump %s (DumpID %u)",
535 dn, dumpid);
536 break;
537
538 case WRITEOPCODE1: /* mount for dump */
539 if (strcmp(name, "") == 0)
540 printf("Please put in tape for writing");
541
542 /* The name is what we are going to label the tape as */
543 else
544 printf("Please put in tape %s for writing", tapename);
545 break;
546
547 case LABELOPCODE2: /* mount for labeltape */
548 printf("Please put in tape to be labelled as %s", tapename);
549 break;
550
551 case READLABELOPCODE3: /* mount for readlabel */
552 printf("Please put in tape whose label is to be read");
553 break;
554
555 case SCANOPCODE4: /* mount for scantape */
556 if (strcmp(name, "") == 0)
557 printf("Please put in tape to be scanned");
558 else
559 printf("Please put in tape %s for scanning", tapename);
560 break;
561
562 case RESTOREDBOPCODE7: /* Mount for restoredb */
563 printf("Please insert a tape %s for the database restore", tapename);
564 break;
565
566 case SAVEDBOPCODE6: /* Mount for savedb */
567 printf("Please insert a writable tape %s for the database dump",
568 tapename);
569 break;
570
571 default:
572 break;
573 }
574 printf(" and hit return when done\n");
575}
576
577/* PromptForTape
578 * Prompt the operator to change the tape.
579 * Use to be a void routine but now returns an error. Some calls
580 * don't use the error code.
581 * notes:
582 * only external clients are in recoverDb.c. Was static PA
583 */
584afs_int32
585PromptForTape(int flag, char *name, afs_uint32 dbDumpId, afs_uint32 taskId,
586 int tapecount)
587{
588 afs_int32 code = 0;
589 afs_int32 wcode;
590 afs_int32 start = 0;
591 char inchr;
592 int CallOut;
593 int cpid, status, rcpid;
594
595 if (checkAbortByTaskId(taskId))
596 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
597
598 if (dbDumpId)
599 TapeLog(2, taskId, 0, 0, "Prompt for tape %s (%u)\n", name, dbDumpId);
600 else
601 TapeLog(2, taskId, 0, 0, "Prompt for tape %s\n", name);
602
603 CallOut = (opencallout ? 1 : 0);
604 if (CallOut) {
605 setStatus(taskId, CALL_WAIT0x800);
606
607 cpid =
608 callOutRoutine(taskId, globalTapeConfig.device, flag, name,
609 dbDumpId, tapecount);
610 if (cpid == 0)
611 CallOut = 0; /* prompt at screen */
612
613 while (CallOut) { /* Check if callout routine finished */
614 status = 0;
615 rcpid = waitpid(cpid, &status, WNOHANG1);
616 if (rcpid > 0) {
617 if (rcpid != cpid)
618 wcode = -1;
619 else if (WIFEXITED(status)(((status) & 0177) == 0))
620 wcode = WEXITSTATUS(status)((status) >> 8);
621 else
622 wcode = -1;
623
624 if (wcode == 0) {
625 break; /* All done */
626 } else if (wcode == 1) {
627 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0); /* Abort */
628 } else if ((flag == READOPCODE0) && (wcode == 3)) {
629 ERROR_EXIT(TC_SKIPTAPE)do { code = (156566292L); goto error_exit; } while (0); /* Restore: skip the tape */
630 } else {
631 TLog(taskId,
632 "Callout routine has exited with code %d: will prompt\n",
633 wcode);
634 CallOut = 0; /* Switch to keyboard input */
635 break;
636 }
637 }
638 /* if waitpid experienced an error, we prompt */
639 if (rcpid == -1 && errno(* __error()) != EINTR4) {
640 afs_com_err(whoami, errno(* __error()),
641 "Error waiting for callout script to terminate.");
642 TLog(taskId,
643 "Can't get exit status from callout script. will prompt\n");
644 CallOut = 0;
645 break;
646 }
647#ifdef AFS_PTHREAD_ENV
648 sleep(1);
649#else
650 IOMGR_Sleep(1);
651#endif
652
653 if (checkAbortByTaskId(taskId)) {
654 printf
655 ("This tape operation has been aborted by the coordinator.\n");
656
657 if (kill(cpid, SIGKILL9)) /* Cancel callout */
658 ErrorLog(0, taskId, errno(* __error()), 0,
659 "Kill of callout process %d failed\n", cpid);
660
661 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
662 }
663 }
664 }
665
666 if (!CallOut) {
667 clearStatus(taskId, CALL_WAIT0x800);
668 setStatus(taskId, OPR_WAIT0x200);
669
670 PrintPrompt(flag, name, dbDumpId);
671
672 /* Loop until we get ok to go ahead (or abort) */
673 while (1) {
674 if (time(0) > start + BELLTIME60) {
675 start = time(0);
676 FFlushInput();
677 putchar(BELLCHAR)(!__isthreaded ? __sputc(7, __stdoutp) : (putc)(7, __stdoutp)
)
;
678 fflush(stdout__stdoutp);
679 }
680 wcode = LWP_GetResponseKey(5, &inchr); /* inchr stores key read */
681 if (wcode == 1) { /* keyboard input is available */
682
683 if ((inchr == 'a') || (inchr == 'A')) {
684 printf("This tape operation has been aborted.\n");
685 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0); /* Abort command */
686 } else if ((flag == READOPCODE0)
687 && ((inchr == 's') || (inchr == 'S'))) {
688 printf("This tape will be skipped.\n");
689 ERROR_EXIT(TC_SKIPTAPE)do { code = (156566292L); goto error_exit; } while (0); /* Restore: skip the tape */
690 }
691 break; /* continue */
692 }
693
694 if (checkAbortByTaskId(taskId)) {
695 printf
696 ("This tape operation has been aborted by the coordinator.\n");
697 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
698 }
699 }
700
701 }
702
703 printf("Thanks, now proceeding with tape ");
704 switch (flag) {
705 case RESTOREDBOPCODE7:
706 case READOPCODE0:
707 printf("reading");
708 break;
709
710 case APPENDOPCODE5:
711 printf("append writing");
712 break;
713
714 case SAVEDBOPCODE6:
715 case WRITEOPCODE1:
716 printf("writing");
717 break;
718
719 case LABELOPCODE2:
720 printf("labelling");
721 break;
722
723 case READLABELOPCODE3:
724 printf("label reading");
725 break;
726
727 case SCANOPCODE4:
728 printf("scanning");
729 break;
730
731 default:
732 printf("unknown");
733 break;
734 }
735
736 printf(" operation.\n");
737 if (!CallOut)
738 printf("**********************************\n");
739
740 TapeLog(2, taskId, 0, 0, "Proceeding with tape operation\n");
741 tapemounted = 1;
742
743 error_exit:
744 clearStatus(taskId, (OPR_WAIT0x200 | CALL_WAIT0x800));
745 return (code);
746}
747
748
749/* VolHeaderToHost
750 * convert the fields in the tapeVolHeader into host byte order,
751 * placing the converted copy of the structure into the hostVolHeader
752 * entry:
753 * tapeVolHeader - points to volume header read from tape
754 * hostVolHeader - pointer to struct for result
755 * exit:
756 * hostVolHeader - information in host byte order
757 */
758
759afs_int32
760VolHeaderToHost(struct volumeHeader *hostVolHeader,
761 struct volumeHeader *tapeVolHeader)
762{
763 switch (ntohl(tapeVolHeader->versionflags)(__builtin_constant_p(tapeVolHeader->versionflags) ? ((((__uint32_t
)(tapeVolHeader->versionflags)) >> 24) | ((((__uint32_t
)(tapeVolHeader->versionflags)) & (0xff << 16)) >>
8) | ((((__uint32_t)(tapeVolHeader->versionflags)) & (
0xff << 8)) << 8) | (((__uint32_t)(tapeVolHeader->
versionflags)) << 24)) : __bswap32_var(tapeVolHeader->
versionflags))
) {
764 case TAPE_VERSION_00:
765 /* sizes in bytes and fields in host order */
766 memcpy(tapeVolHeader, hostVolHeader, sizeof(struct volumeHeader));
767 break;
768
769 case TAPE_VERSION_11:
770 case TAPE_VERSION_22:
771 case TAPE_VERSION_33: /* for present */
772 case TAPE_VERSION_44:
773 /* sizes in K and fields in network order */
774 /* do the conversion field by field */
775
776 strcpy(hostVolHeader->preamble, tapeVolHeader->preamble);
777 strcpy(hostVolHeader->postamble, tapeVolHeader->postamble);
778 strcpy(hostVolHeader->volumeName, tapeVolHeader->volumeName);
779 strcpy(hostVolHeader->dumpSetName, tapeVolHeader->dumpSetName);
780 hostVolHeader->volumeID = ntohl(tapeVolHeader->volumeID)(__builtin_constant_p(tapeVolHeader->volumeID) ? ((((__uint32_t
)(tapeVolHeader->volumeID)) >> 24) | ((((__uint32_t)
(tapeVolHeader->volumeID)) & (0xff << 16)) >>
8) | ((((__uint32_t)(tapeVolHeader->volumeID)) & (0xff
<< 8)) << 8) | (((__uint32_t)(tapeVolHeader->
volumeID)) << 24)) : __bswap32_var(tapeVolHeader->volumeID
))
;
781 hostVolHeader->server = ntohl(tapeVolHeader->server)(__builtin_constant_p(tapeVolHeader->server) ? ((((__uint32_t
)(tapeVolHeader->server)) >> 24) | ((((__uint32_t)(tapeVolHeader
->server)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(tapeVolHeader->server)) & (0xff << 8)) <<
8) | (((__uint32_t)(tapeVolHeader->server)) << 24))
: __bswap32_var(tapeVolHeader->server))
;
782 hostVolHeader->part = ntohl(tapeVolHeader->part)(__builtin_constant_p(tapeVolHeader->part) ? ((((__uint32_t
)(tapeVolHeader->part)) >> 24) | ((((__uint32_t)(tapeVolHeader
->part)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(tapeVolHeader->part)) & (0xff << 8)) << 8
) | (((__uint32_t)(tapeVolHeader->part)) << 24)) : __bswap32_var
(tapeVolHeader->part))
;
783 hostVolHeader->from = ntohl(tapeVolHeader->from)(__builtin_constant_p(tapeVolHeader->from) ? ((((__uint32_t
)(tapeVolHeader->from)) >> 24) | ((((__uint32_t)(tapeVolHeader
->from)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(tapeVolHeader->from)) & (0xff << 8)) << 8
) | (((__uint32_t)(tapeVolHeader->from)) << 24)) : __bswap32_var
(tapeVolHeader->from))
;
784 hostVolHeader->frag = ntohl(tapeVolHeader->frag)(__builtin_constant_p(tapeVolHeader->frag) ? ((((__uint32_t
)(tapeVolHeader->frag)) >> 24) | ((((__uint32_t)(tapeVolHeader
->frag)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(tapeVolHeader->frag)) & (0xff << 8)) << 8
) | (((__uint32_t)(tapeVolHeader->frag)) << 24)) : __bswap32_var
(tapeVolHeader->frag))
;
785 hostVolHeader->magic = ntohl(tapeVolHeader->magic)(__builtin_constant_p(tapeVolHeader->magic) ? ((((__uint32_t
)(tapeVolHeader->magic)) >> 24) | ((((__uint32_t)(tapeVolHeader
->magic)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(tapeVolHeader->magic)) & (0xff << 8)) <<
8) | (((__uint32_t)(tapeVolHeader->magic)) << 24)) :
__bswap32_var(tapeVolHeader->magic))
;
786 hostVolHeader->contd = ntohl(tapeVolHeader->contd)(__builtin_constant_p(tapeVolHeader->contd) ? ((((__uint32_t
)(tapeVolHeader->contd)) >> 24) | ((((__uint32_t)(tapeVolHeader
->contd)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(tapeVolHeader->contd)) & (0xff << 8)) <<
8) | (((__uint32_t)(tapeVolHeader->contd)) << 24)) :
__bswap32_var(tapeVolHeader->contd))
;
787 hostVolHeader->dumpID = ntohl(tapeVolHeader->dumpID)(__builtin_constant_p(tapeVolHeader->dumpID) ? ((((__uint32_t
)(tapeVolHeader->dumpID)) >> 24) | ((((__uint32_t)(tapeVolHeader
->dumpID)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(tapeVolHeader->dumpID)) & (0xff << 8)) <<
8) | (((__uint32_t)(tapeVolHeader->dumpID)) << 24))
: __bswap32_var(tapeVolHeader->dumpID))
;
788 hostVolHeader->level = ntohl(tapeVolHeader->level)(__builtin_constant_p(tapeVolHeader->level) ? ((((__uint32_t
)(tapeVolHeader->level)) >> 24) | ((((__uint32_t)(tapeVolHeader
->level)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(tapeVolHeader->level)) & (0xff << 8)) <<
8) | (((__uint32_t)(tapeVolHeader->level)) << 24)) :
__bswap32_var(tapeVolHeader->level))
;
789 hostVolHeader->parentID = ntohl(tapeVolHeader->parentID)(__builtin_constant_p(tapeVolHeader->parentID) ? ((((__uint32_t
)(tapeVolHeader->parentID)) >> 24) | ((((__uint32_t)
(tapeVolHeader->parentID)) & (0xff << 16)) >>
8) | ((((__uint32_t)(tapeVolHeader->parentID)) & (0xff
<< 8)) << 8) | (((__uint32_t)(tapeVolHeader->
parentID)) << 24)) : __bswap32_var(tapeVolHeader->parentID
))
;
790 hostVolHeader->endTime = ntohl(tapeVolHeader->endTime)(__builtin_constant_p(tapeVolHeader->endTime) ? ((((__uint32_t
)(tapeVolHeader->endTime)) >> 24) | ((((__uint32_t)(
tapeVolHeader->endTime)) & (0xff << 16)) >>
8) | ((((__uint32_t)(tapeVolHeader->endTime)) & (0xff
<< 8)) << 8) | (((__uint32_t)(tapeVolHeader->
endTime)) << 24)) : __bswap32_var(tapeVolHeader->endTime
))
;
791 hostVolHeader->versionflags = ntohl(tapeVolHeader->versionflags)(__builtin_constant_p(tapeVolHeader->versionflags) ? ((((__uint32_t
)(tapeVolHeader->versionflags)) >> 24) | ((((__uint32_t
)(tapeVolHeader->versionflags)) & (0xff << 16)) >>
8) | ((((__uint32_t)(tapeVolHeader->versionflags)) & (
0xff << 8)) << 8) | (((__uint32_t)(tapeVolHeader->
versionflags)) << 24)) : __bswap32_var(tapeVolHeader->
versionflags))
;
792 hostVolHeader->cloneDate = ntohl(tapeVolHeader->cloneDate)(__builtin_constant_p(tapeVolHeader->cloneDate) ? ((((__uint32_t
)(tapeVolHeader->cloneDate)) >> 24) | ((((__uint32_t
)(tapeVolHeader->cloneDate)) & (0xff << 16)) >>
8) | ((((__uint32_t)(tapeVolHeader->cloneDate)) & (0xff
<< 8)) << 8) | (((__uint32_t)(tapeVolHeader->
cloneDate)) << 24)) : __bswap32_var(tapeVolHeader->cloneDate
))
;
793 break;
794
795 default:
796 return (TC_BADVOLHEADER(156566287L));
797 }
798 return (0);
799}
800
801afs_int32
802ReadVolHeader(afs_int32 taskId,
803 struct butm_tapeInfo *tapeInfoPtr,
804 struct volumeHeader *volHeaderPtr)
805{
806 afs_int32 code = 0;
807 afs_int32 nbytes;
808 struct volumeHeader volHead;
809
810 /* Read the volume header */
811 code =
812 butm_ReadFileData(tapeInfoPtr, tapeBlock.data, sizeof(tapeVolumeHT),(*((tapeInfoPtr)->ops.readFileData))(tapeInfoPtr,tapeBlock
.data,sizeof(tapeVolumeHT),&nbytes)
813 &nbytes)(*((tapeInfoPtr)->ops.readFileData))(tapeInfoPtr,tapeBlock
.data,sizeof(tapeVolumeHT),&nbytes)
;
814 if (code) {
815 ErrorLog(0, taskId, code, tapeInfoPtr->error,
816 "Can't read volume header on tape\n");
817 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
818 }
819
820 code = readVolumeHeader(tapeBlock.data, 0L, &volHead);
821 if (code) {
822 ErrorLog(0, taskId, code, 0,
823 "Can't find volume header on tape block\n");
824 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
825 }
826
827 code = VolHeaderToHost(volHeaderPtr, &volHead);
828 if (code) {
829 ErrorLog(0, taskId, code, 0, "Can't convert volume header\n");
830 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
831 }
832
833 error_exit:
834 return code;
835}
836
837afs_int32 static
838GetVolumeHead(afs_int32 taskId, struct butm_tapeInfo *tapeInfoPtr,
839 afs_int32 position, char *volName, afs_int32 volId)
840{
841 afs_int32 code = 0;
842 struct volumeHeader tapeVolHeader;
843
844 /* Position directly to the volume and read the header */
845 if (position) {
846 code = butm_Seek(tapeInfoPtr, position)(*((tapeInfoPtr)->ops.seek))(tapeInfoPtr,position);
847 if (code) {
848 ErrorLog(0, taskId, code, tapeInfoPtr->error,
849 "Can't seek to position %u on tape\n", position);
850 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
851 }
852
853 code = butm_ReadFileBegin(tapeInfoPtr)(*((tapeInfoPtr)->ops.readFileBegin))(tapeInfoPtr);
854 if (code) {
855 ErrorLog(0, taskId, code, tapeInfoPtr->error,
856 "Can't read FileBegin on tape\n");
857 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
858 }
859
860 /* Read the volume header */
861 code = ReadVolHeader(taskId, tapeInfoPtr, &tapeVolHeader);
862 if (code)
863 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
864
865 /* Check if volume header matches */
866 if (strcmp(tapeVolHeader.volumeName, volName))
867 ERROR_EXIT(TC_BADVOLHEADER)do { code = (156566287L); goto error_exit; } while (0);
868 if (volId && (tapeVolHeader.volumeID != volId))
869 ERROR_EXIT(TC_BADVOLHEADER)do { code = (156566287L); goto error_exit; } while (0);
870 if (tapeVolHeader.magic != TC_VOLBEGINMAGIC0xb0258191)
871 ERROR_EXIT(TC_BADVOLHEADER)do { code = (156566287L); goto error_exit; } while (0);
872 }
873
874 /* Do a sequential search for the volume */
875 else {
876 while (1) {
877 code = butm_ReadFileBegin(tapeInfoPtr)(*((tapeInfoPtr)->ops.readFileBegin))(tapeInfoPtr);
878 if (code) {
879 ErrorLog(0, taskId, code, tapeInfoPtr->error,
880 "Can't read FileBegin on tape\n");
881 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
882 }
883
884 code = ReadVolHeader(taskId, tapeInfoPtr, &tapeVolHeader);
885 if (code)
886 ERROR_EXIT(TC_VOLUMENOTONTAPE)do { code = (156566282L); goto error_exit; } while (0);
887
888 /* Test if we found the volume */
889 if ((strcmp(tapeVolHeader.volumeName, volName) == 0)
890 && (!volId || (volId == tapeVolHeader.volumeID)))
891 break;
892
893 /* skip to the next HW EOF marker */
894 code = SeekFile(tapeInfoPtr, 1);
895 if (code) {
896 ErrorLog(0, taskId, code, tapeInfoPtr->error,
897 "Can't seek to next EOF on tape\n");
898 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
899 }
900 }
901 }
902
903 error_exit:
904 return code;
905}
906
907afs_int32
908GetRestoreTape(afs_int32 taskId, struct butm_tapeInfo *tapeInfoPtr,
909 char *tname, afs_int32 tapeID, int prompt)
910{
911 struct butm_tapeLabel tapeLabel;
912 afs_int32 code = 0, rc;
913 int tapecount = 1;
914 struct budb_dumpEntry dumpEntry;
915
916 /* Make sure that the dump/tape is not a XBSA dump */
917 rc = bcdb_FindDumpByID(tapeID, &dumpEntry);
918 if (!rc && (dumpEntry.flags & (BUDB_DUMP_ADSM(1<<12) | BUDB_DUMP_BUTA(1<<11)))) {
919 ErrorLog(0, taskId, 0, 0,
920 "Volumes from dump %u are XBSA dumps (skipping)\n", tapeID);
921 ERROR_EXIT(TC_SKIPTAPE)do { code = (156566292L); goto error_exit; } while (0);
922 }
923
924 while (1) {
925 if (prompt) {
926 code =
927 PromptForTape(READOPCODE0, tname, tapeID, taskId, tapecount);
928 if (code)
929 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
930 }
931 prompt = 1;
932 tapecount++;
933
934 code = butm_Mount(tapeInfoPtr, tname)(*((tapeInfoPtr)->ops.mount))(tapeInfoPtr,tname);
935 if (code) {
936 TapeLog(0, taskId, code, tapeInfoPtr->error, "Can't open tape\n");
937 goto newtape;
938 }
939
940 code = butm_ReadLabel(tapeInfoPtr, &tapeLabel, 1)(*((tapeInfoPtr)->ops.readLabel))(tapeInfoPtr,&tapeLabel
,1)
;
941 if (code) {
942 ErrorLog(0, taskId, code, tapeInfoPtr->error,
943 "Can't read tape label\n");
944 goto newtape;
945 }
946
947 /* Now check the label to see if the tapename matches or tapeids match */
948 if (strcmp(TNAME(&tapeLabel)( strcmp((&tapeLabel)->pName,"") ? (&tapeLabel)->
pName : ( strcmp((&tapeLabel)->AFSName,"") ? (&tapeLabel
)->AFSName : "<NULL>" ) )
, tname)
949 || ((tapeLabel.structVersion >= TAPE_VERSION_33)
950 && (tapeLabel.dumpid != tapeID))) {
951 char expectedName[BU_MAXTAPELEN32 + 32],
952 gotName[BU_MAXTAPELEN32 + 32];
953
954 TAPENAME(expectedName, tname, tapeID)if (!strcmp("", tname)) sprintf(expectedName, "<NULL>")
; else if (tapeID == 0) sprintf(expectedName, "%s", tname); else
sprintf(expectedName, "%s (%u)", tname, tapeID);
;
955 LABELNAME(gotName, &tapeLabel)if (!strcmp("", ( strcmp((&tapeLabel)->pName,"") ? (&
tapeLabel)->pName : ( strcmp((&tapeLabel)->AFSName,
"") ? (&tapeLabel)->AFSName : "<NULL>" ) ))) sprintf
(gotName, "<NULL>"); else if ((&tapeLabel)->dumpid
== 0) sprintf(gotName, "%s", ( strcmp((&tapeLabel)->pName
,"") ? (&tapeLabel)->pName : ( strcmp((&tapeLabel)
->AFSName,"") ? (&tapeLabel)->AFSName : "<NULL>"
) )); else sprintf(gotName, "%s (%u)", ( strcmp((&tapeLabel
)->pName,"") ? (&tapeLabel)->pName : ( strcmp((&
tapeLabel)->AFSName,"") ? (&tapeLabel)->AFSName : "<NULL>"
) ), (&tapeLabel)->dumpid);
;
956
957 TapeLog(0, taskId, 0, 0,
958 "Tape label expected %s, label seen %s\n", expectedName,
959 gotName);
960 goto newtape;
961 }
962
963 break;
964
965 newtape:
966 unmountTape(taskId, tapeInfoPtr);
967 }
968
969 error_exit:
970 return code;
971}
972
973afs_int32
974xbsaRestoreVolumeData(struct rx_call *call, void *rock)
975{
976 afs_int32 code = 0;
977#ifdef xbsa
978 struct restoreParams *rparamsPtr = (struct restoreParams *)rock;
979 afs_int32 curChunk, rc;
980 afs_uint32 totalWritten;
981 afs_int32 headBytes, tailBytes, w;
982 afs_int32 taskId;
983 struct volumeHeader volTrailer;
984 afs_int32 vtsize = 0;
985 int found;
986 struct dumpNode *nodePtr;
987 struct tc_restoreDesc *Restore;
988 afs_int32 bytesRead, tbuffersize, endData = 0;
989 char *buffer = (char *)bufferBlock, tbuffer[256];
990
991 nodePtr = rparamsPtr->nodePtr;
992 Restore = nodePtr->restores;
993 taskId = nodePtr->taskID;
994
995 /* Read the volume fragment one block at a time until
996 * find a volume trailer
997 */
998 curChunk = BIGCHUNK102400 + 1;
999 tbuffersize = 0;
1000 totalWritten = 0;
1001
1002 while (!endData) {
1003 rc = xbsa_ReadObjectData(&butxInfo, buffer, dataSize, &bytesRead,
1004 &endData);
1005 if (restoretofile && (bytesRead > 0)) {
1006 fwrite(buffer, bytesRead, 1, restoretofilefd); /* Save to a file */
1007 }
1008 if (rc != XBSA_SUCCESS) {
1009 ErrorLog(0, taskId, rc, 0,
1010 "Unable to read volume data from the server\n");
1011 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
1012 }
1013
1014 /* Periodically update status structure and check if should abort */
1015 curChunk += bytesRead;
1016 if (curChunk > BIGCHUNK102400) {
1017 curChunk = 0;
1018 lock_Status();
1019 nodePtr->statusNodePtr->nKBytes = totalWritten / 1024;
1020 unlock_Status();
1021
1022 if (checkAbortByTaskId(taskId))
1023 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
1024 }
1025
1026 if (!endData && (bytesRead > 0)) {
1027 /* Fill tbuffer up with data from end of buffer and write
1028 * the remainder of buffer out.
1029 */
1030 if ((tbuffersize == 0) || (bytesRead >= sizeof(tbuffer))) {
1031 /* Write out contents of tbuffer */
1032 if (tbuffersize) {
1033 w = rx_Write(call, tbuffer, tbuffersize)rx_WriteProc(call, tbuffer, tbuffersize);
1034 if (w != tbuffersize) {
1035 ErrorLog(0, taskId, -1, 0,
1036 "Error in RX write: Wrote %d bytes\n", w);
1037 ERROR_EXIT(-1)do { code = -1; goto error_exit; } while (0);
1038 }
1039 totalWritten += w;
1040 }
1041 /* fill tbuffer with end of buffer */
1042 bytesRead -= sizeof(tbuffer);
1043 memcpy(tbuffer, buffer + bytesRead, sizeof(tbuffer));
1044 tbuffersize = sizeof(tbuffer);
1045 /* Write out whatever is left over in buffer */
1046 if (bytesRead) {
1047 w = rx_Write(call, buffer, bytesRead)rx_WriteProc(call, buffer, bytesRead);
1048 if (w != bytesRead) {
1049 ErrorLog(0, taskId, -1, 0,
1050 "Error in RX data write: Wrote %d bytes\n",
1051 w);
1052 ERROR_EXIT(-1)do { code = -1; goto error_exit; } while (0);
1053 }
1054 totalWritten += w;
1055 bytesRead = 0;
1056 }
1057 } else if ((tbuffersize + bytesRead) <= sizeof(tbuffer)) {
1058 /* Copy all of buffer into tbuffer (it will fit) */
1059 memcpy(tbuffer + tbuffersize, buffer, bytesRead);
1060 tbuffersize += bytesRead;
1061 bytesRead = 0;
1062 } else {
1063 /* We need to write some of tbuffer out and fill it with buffer */
1064 int towrite = bytesRead - (sizeof(tbuffer) - tbuffersize);
1065 w = rx_Write(call, tbuffer, towrite)rx_WriteProc(call, tbuffer, towrite);
1066 if (w != towrite) {
1067 ErrorLog(0, taskId, -1, 0,
1068 "Error in RX write: Wrote %d bytes\n", w);
1069 ERROR_EXIT(-1)do { code = -1; goto error_exit; } while (0);
1070 }
1071 totalWritten += w;
1072 tbuffersize -= w;
1073
1074 /* Move the data in tbuffer up */
1075 memcpy(tbuffer, tbuffer + towrite, tbuffersize);
1076
1077 /* Now copy buffer in */
1078 memcpy(tbuffer + tbuffersize, buffer, bytesRead);
1079 tbuffersize += bytesRead;
1080 bytesRead = 0;
1081 }
1082 }
1083 }
1084
1085 /* Pull the volume trailer from the last two buffers */
1086 found =
1087 FindVolTrailer2(tbuffer, tbuffersize, &headBytes, buffer, bytesRead,
1088 &tailBytes, &volTrailer);
1089
1090 if (!found) {
1091 ErrorLog(0, taskId, TC_MISSINGTRAILER(156566284L), 0, "Missing volume trailer\n");
1092 ERROR_EXIT(TC_MISSINGTRAILER)do { code = (156566284L); goto error_exit; } while (0);
1093 }
1094
1095 /* Now rx_write the data in the last two blocks */
1096 if (headBytes) {
1097 w = rx_Write(call, tbuffer, headBytes)rx_WriteProc(call, tbuffer, headBytes);
1098 if (w != headBytes) {
1099 ErrorLog(0, taskId, -1, 0,
1100 "Error in RX trail1 write: Wrote %d bytes\n", w);
1101 ERROR_EXIT(-1)do { code = -1; goto error_exit; } while (0);
1102 }
1103 totalWritten += w;
1104 }
1105 if (tailBytes) {
1106 w = rx_Write(call, buffer, tailBytes)rx_WriteProc(call, buffer, tailBytes);
1107 if (w != tailBytes) {
1108 ErrorLog(0, taskId, -1, 0,
1109 "Error in RX trail2 write: Wrote %d bytes\n", w);
1110 ERROR_EXIT(-1)do { code = -1; goto error_exit; } while (0);
1111 }
1112 totalWritten += w;
1113 }
1114
1115 error_exit:
1116#endif /*xbsa */
1117 return code;
1118}
1119
1120/* restoreVolume
1121 * sends the contents of volume dump to Rx Stream associated
1122 * with <call>
1123 */
1124
1125afs_int32
1126restoreVolumeData(struct rx_call *call, void *rock)
1127{
1128 struct restoreParams *rparamsPtr = (struct restoreParams *)rock;
1129 afs_int32 curChunk;
1130 afs_uint32 totalWritten = 0;
1131 afs_int32 code = 0;
1132 afs_int32 headBytes, tailBytes, w;
1133 afs_int32 taskId;
1134 afs_int32 nbytes; /* # bytes data in last tape block read */
1135 struct volumeHeader tapeVolTrailer;
1136 int found;
1137 int moretoread;
1138 afs_int32 startRbuf, endRbuf, startWbuf, endWbuf, buf, pbuf, lastbuf;
1139 struct tc_restoreDesc *Restore;
1140 struct dumpNode *nodePtr;
1141 struct butm_tapeInfo *tapeInfoPtr;
1142 char *origVolName;
1143 afs_int32 origVolID;
1144
1145 nodePtr = rparamsPtr->nodePtr;
1146 taskId = nodePtr->taskID;
1147 Restore = nodePtr->restores;
1148 tapeInfoPtr = rparamsPtr->tapeInfoPtr;
1149 origVolName = Restore[rparamsPtr->frag].oldName;
1150 origVolID = Restore[rparamsPtr->frag].origVid;
1151
1152 /* Read the volume one fragment at a time */
1153 while (rparamsPtr->frag < nodePtr->arraySize) {
1154 /*w */
1155 curChunk = BIGCHUNK102400 + 1; /* Check if should abort */
1156
1157 /* Read the volume fragment one block at a time until
1158 * find a volume trailer
1159 */
1160 moretoread = 1;
1161 startRbuf = 0;
1162 endRbuf = 0;
1163 startWbuf = 0;
1164 while (moretoread) {
1165 /* Fill the circular buffer with tape blocks
1166 * Search for volume trailer in the process.
1167 */
1168 buf = startRbuf;
1169 do {
1170 code =
1171 butm_ReadFileData(tapeInfoPtr, bufferBlock[buf].data,(*((tapeInfoPtr)->ops.readFileData))(tapeInfoPtr,bufferBlock
[buf].data,(16384 - ((5*sizeof(afs_int32)) + sizeof(int))),&
nbytes)
1172 BUTM_BLKSIZE, &nbytes)(*((tapeInfoPtr)->ops.readFileData))(tapeInfoPtr,bufferBlock
[buf].data,(16384 - ((5*sizeof(afs_int32)) + sizeof(int))),&
nbytes)
;
1173 if (code) {
1174 ErrorLog(0, taskId, code, tapeInfoPtr->error,
1175 "Can't read FileData on tape %s\n",
1176 rparamsPtr->mntTapeName);
1177 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1178 }
1179 curChunk += BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int)));
1180
1181 /* Periodically update status structure and check if should abort */
1182 if (curChunk > BIGCHUNK102400) {
1183 curChunk = 0;
1184
1185 lock_Status();
1186 nodePtr->statusNodePtr->nKBytes = totalWritten / 1024;
1187 unlock_Status();
1188
1189 if (checkAbortByTaskId(taskId))
1190 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
1191 }
1192
1193 /* step to next block in buffer */
1194 pbuf = buf;
1195 buf = ((buf + 1) == tapeblocks) ? 0 : (buf + 1);
1196
1197 /* If this is the end of the volume, the exit the loop */
1198 if ((nbytes != BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int))))
1199 ||
1200 (FindVolTrailer
1201 (bufferBlock[pbuf].data, nbytes, &tailBytes,
1202 &tapeVolTrailer)))
1203 moretoread = 0;
1204
1205 } while (moretoread && (buf != endRbuf));
1206
1207 /* Write the buffer upto (but not including) the last read block
1208 * If volume is completely read, then leave the last two blocks.
1209 */
1210 lastbuf = endWbuf = pbuf;
1211 if (!moretoread && (endWbuf != startWbuf))
1212 endWbuf = (endWbuf == 0) ? (tapeblocks - 1) : (endWbuf - 1);
1213
1214 for (buf = startWbuf; buf != endWbuf;
1215 buf = (((buf + 1) == tapeblocks) ? 0 : (buf + 1))) {
1216 w = rx_Write(call, bufferBlock[buf].data, BUTM_BLKSIZE)rx_WriteProc(call, bufferBlock[buf].data, (16384 - ((5*sizeof
(afs_int32)) + sizeof(int))))
;
1217 if (w != BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int)))) {
1218 ErrorLog(0, taskId, -1, 0, "Error in RX write\n");
1219 ERROR_EXIT(-1)do { code = -1; goto error_exit; } while (0);
1220 }
1221 totalWritten += BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int)));
1222 }
1223
1224 /* Setup pointers to refill buffer */
1225 startRbuf = ((lastbuf + 1) == tapeblocks) ? 0 : (lastbuf + 1);
1226 endRbuf = endWbuf;
1227 startWbuf = endWbuf;
1228 }
1229
1230 /* lastbuf is last block read and it has nbytes of data
1231 * startWbuf is the 2nd to last block read
1232 * Seach for the volume trailer in these two blocks.
1233 */
1234 if (lastbuf == startWbuf)
1235 found =
1236 FindVolTrailer2(NULL((void *)0), 0, &headBytes,
1237 bufferBlock[lastbuf].data, nbytes, &tailBytes,
1238 &tapeVolTrailer);
1239 else
1240 found =
1241 FindVolTrailer2(bufferBlock[startWbuf].data, BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int))),
1242 &headBytes, bufferBlock[lastbuf].data, nbytes,
1243 &tailBytes, &tapeVolTrailer);
1244 if (!found) {
1245 ErrorLog(0, taskId, TC_MISSINGTRAILER(156566284L), 0,
1246 "Missing volume trailer on tape %s\n",
1247 rparamsPtr->mntTapeName);
1248 ERROR_EXIT(TC_MISSINGTRAILER)do { code = (156566284L); goto error_exit; } while (0);
1249 }
1250
1251 /* Now rx_write the data in the last two blocks */
1252 if (headBytes) {
1253 w = rx_Write(call, bufferBlock[startWbuf].data, headBytes)rx_WriteProc(call, bufferBlock[startWbuf].data, headBytes);
1254 if (w != headBytes) {
1255 ErrorLog(0, taskId, -1, 0, "Error in RX write\n");
1256 ERROR_EXIT(-1)do { code = -1; goto error_exit; } while (0);
1257 }
1258 totalWritten += headBytes;
1259 }
1260 if (tailBytes) {
1261 w = rx_Write(call, bufferBlock[lastbuf].data, tailBytes)rx_WriteProc(call, bufferBlock[lastbuf].data, tailBytes);
1262 if (w != tailBytes) {
1263 ErrorLog(0, taskId, -1, 0, "Error in RX write\n");
1264 ERROR_EXIT(-1)do { code = -1; goto error_exit; } while (0);
1265 }
1266 totalWritten += tailBytes;
1267 }
1268
1269 /* Exit the loop if the volume is not continued on next tape */
1270 if (!tapeVolTrailer.contd)
1271 break; /* We've read the entire volume */
1272
1273 /* Volume is continued on next tape.
1274 * Step to the next volume fragment and prompt for its tape.
1275 * When a volume has multiple frags, those frags are on different
1276 * tapes. So we know that we need to prompt for a tape.
1277 */
1278 rparamsPtr->frag++;
1279 if (rparamsPtr->frag >= nodePtr->arraySize)
1280 break;
1281
1282 unmountTape(taskId, tapeInfoPtr);
1283 strcpy(rparamsPtr->mntTapeName, Restore[rparamsPtr->frag].tapeName);
1284 rparamsPtr->tapeID =
1285 (Restore[rparamsPtr->frag].
1286 initialDumpId ? Restore[rparamsPtr->frag].
1287 initialDumpId : Restore[rparamsPtr->frag].dbDumpId);
1288 code =
1289 GetRestoreTape(taskId, tapeInfoPtr, rparamsPtr->mntTapeName,
1290 rparamsPtr->tapeID, 1);
1291 if (code)
1292 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1293
1294 /* Position to the frag and read the volume header */
1295 code =
1296 GetVolumeHead(taskId, tapeInfoPtr,
1297 Restore[rparamsPtr->frag].position, origVolName,
1298 origVolID);
1299 if (code) {
1300 ErrorLog(0, taskId, code, 0,
1301 "Can't find volume %s (%u) on tape %s\n", origVolName,
1302 origVolID, rparamsPtr->mntTapeName);
1303 ERROR_EXIT(TC_VOLUMENOTONTAPE)do { code = (156566282L); goto error_exit; } while (0);
1304 }
1305 } /*w */
1306
1307 error_exit:
1308 return code;
1309}
1310
1311/* SkipTape
1312 * Find all the volumes on a specific tape and mark them to skip.
1313 */
1314int
1315SkipTape(struct tc_restoreDesc *Restore, afs_int32 size, afs_int32 index,
1316 char *tapename, afs_int32 tapeid, afs_int32 taskid)
1317{
1318 afs_int32 i, tid;
1319
1320 for (i = index; i < size; i++) {
1321 if (Restore[i].flags & RDFLAG_SKIP0x2)
1322 continue;
1323 tid =
1324 (Restore[i].initialDumpId ? Restore[i].initialDumpId : Restore[i].
1325 dbDumpId);
1326 if ((strcmp(Restore[i].tapeName, tapename) == 0) && (tid == tapeid)) {
1327 SkipVolume(Restore, size, i, Restore[i].origVid, taskid);
1328 }
1329 }
1330 return 0;
1331}
1332
1333/* SkipVolume
1334 * Find all the entries for a volume and mark them to skip.
1335 */
1336int
1337SkipVolume(struct tc_restoreDesc *Restore, afs_int32 size, afs_int32 index,
1338 afs_int32 volid, afs_int32 taskid)
1339{
1340 afs_int32 i;
1341 int report = 1;
1342
1343 for (i = index; i < size; i++) {
1344 if (Restore[i].flags & RDFLAG_SKIP0x2)
1345 continue;
1346 if (Restore[i].origVid == volid) {
1347 Restore[i].flags |= RDFLAG_SKIP0x2;
1348 if (report) {
1349 TLog(taskid, "Restore: Skipping %svolume %s (%u)\n",
1350 ((Restore[i].dumpLevel == 0) ? "" : "remainder of "),
1351 Restore[i].oldName, volid);
1352 report = 0;
1353 }
1354 }
1355 }
1356 return 0;
1357}
1358
1359int
1360xbsaRestoreVolume(afs_uint32 taskId, struct tc_restoreDesc *restoreInfo,
1361 struct restoreParams *rparamsPtr)
1362{
1363 afs_int32 code = 0;
1364#ifdef xbsa
1365 afs_int32 rc;
1366 afs_int32 newServer, newPart, newVolId;
1367 char *newVolName;
1368 int restoreflags, havetrans = 0, startread = 0;
1369 afs_int32 bytesRead, endData = 0;
1370 afs_uint32 dumpID;
1371 struct budb_dumpEntry dumpEntry;
1372 char volumeNameStr[XBSA_MAX_PATHNAME], dumpIdStr[XBSA_MAX_OSNAME];
1373 struct volumeHeader volHeader, hostVolHeader;
1374
1375 if (restoretofile) {
1376 restoretofilefd = fopen(restoretofile, "w+");
1377 }
1378
1379 dumpID = restoreInfo->dbDumpId;
1380
1381 rc = bcdb_FindDumpByID(dumpID, &dumpEntry);
1382 if (rc) {
1383 ErrorLog(0, taskId, rc, 0, "Can't read database for dump %u\n",
1384 dumpID);
1385 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
1386 }
1387
1388 /* ADSM servers restore ADSM and BUTA dumps */
1389 if ((xbsaType == XBSA_SERVER_TYPE_ADSM0x02)
1390 && !(dumpEntry.flags & (BUDB_DUMP_ADSM(1<<12) | BUDB_DUMP_BUTA(1<<11)))) {
1391 ELog(taskId,
1392 "The dump requested by this restore operation for the "
1393 "volumeset is incompatible with this instance of butc\n");
1394 /* Skip the entire dump (one dump per tape) */
1395 ERROR_EXIT(TC_SKIPTAPE)do { code = (156566292L); goto error_exit; } while (0);
1396 }
1397
1398 /* make sure we are connected to the correct server. */
1399 if ((strlen((char *)dumpEntry.tapes.tapeServer) != 0)
1400 && (strcmp((char *)dumpEntry.tapes.tapeServer, butxInfo.serverName) !=
1401 0)) {
1402 if ((dumpEntry.flags & (BUDB_DUMP_XBSA_NSS(1<<8) | BUDB_DUMP_BUTA(1<<11)))
1403 && !forcemultiple) {
1404 TLog(taskId,
1405 "Dump %d is on server %s but butc is connected "
1406 "to server %s (attempting to restore)\n", dumpID,
1407 (char *)dumpEntry.tapes.tapeServer, butxInfo.serverName);
1408 } else {
1409 TLog(taskId,
1410 "Dump %d is on server %s but butc is connected "
1411 "to server %s (switching servers)\n", dumpID,
1412 (char *)dumpEntry.tapes.tapeServer, butxInfo.serverName);
1413
1414 rc = InitToServer(taskId, &butxInfo,
1415 (char *)dumpEntry.tapes.tapeServer);
1416 if (rc != XBSA_SUCCESS)
1417 ERROR_EXIT(TC_SKIPTAPE)do { code = (156566292L); goto error_exit; } while (0);
1418 }
1419 }
1420
1421 /* Start a transaction and query the server for the correct fileset dump */
1422 rc = xbsa_BeginTrans(&butxInfo);
1423 if (rc != XBSA_SUCCESS) {
1424 ELog(taskId, "Unable to create a new transaction\n");
1425 ERROR_EXIT(TC_SKIPTAPE)do { code = (156566292L); goto error_exit; } while (0);
1426 }
1427 havetrans = 1;
1428
1429 if (dumpEntry.flags & BUDB_DUMP_BUTA(1<<11)) { /* old buta style names */
1430 sprintf(dumpIdStr, "/%d", dumpID);
1431 strcpy(volumeNameStr, "/");
1432 strcat(volumeNameStr, restoreInfo->oldName);
1433 } else { /* new butc names */
1434 extern char *butcdumpIdStr;
1435 strcpy(dumpIdStr, butcdumpIdStr);
1436 sprintf(volumeNameStr, "/%d", dumpID);
1437 strcat(volumeNameStr, "/");
1438 strcat(volumeNameStr, restoreInfo->oldName);
1439 }
1440
1441 rc = xbsa_QueryObject(&butxInfo, dumpIdStr, volumeNameStr);
1442 if (rc != XBSA_SUCCESS) {
1443 ELog(taskId,
1444 "Unable to locate object (%s) of dump (%s) on the server\n",
1445 volumeNameStr, dumpIdStr);
1446 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
1447 }
1448
1449 rc = xbsa_EndTrans(&butxInfo);
1450 havetrans = 0;
1451 if (rc != XBSA_SUCCESS) {
1452 ELog(taskId, "Unable to terminate the current transaction\n");
1453 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
1454 }
1455
1456 if (checkAbortByTaskId(taskId))
1457 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
1458
1459 /* Now start a transaction on the volume to restore and read the
1460 * volumeheader. We do this before starting a transaction on
1461 * volserver to restore the volume because the XBSA server may take
1462 * a while to mount and seek to the volume causing the volserver to
1463 * time out.
1464 */
1465 rc = xbsa_BeginTrans(&butxInfo);
1466 if (rc != XBSA_SUCCESS) {
1467 ELog(taskId, "Unable to create a new transaction\n");
1468 ERROR_EXIT(TC_SKIPTAPE)do { code = (156566292L); goto error_exit; } while (0);
1469 }
1470 havetrans = 1;
1471
1472 rc = xbsa_ReadObjectBegin(&butxInfo, (char *)&volHeader,
1473 sizeof(volHeader), &bytesRead, &endData);
1474 if (restoretofile && (bytesRead > 0)) {
1475 fwrite((char *)&volHeader, bytesRead, 1, restoretofilefd); /* Save to a file */
1476 }
1477 if (rc != XBSA_SUCCESS) {
1478 ELog(taskId,
1479 "Unable to begin reading of the volume from the server\n");
1480 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
1481 }
1482 startread = 1;
1483
1484 if ((bytesRead != sizeof(volHeader)) || endData) {
1485 ELog(taskId,
1486 "The size of data read (%d) does not equal the size of data requested (%d)\n",
1487 bytesRead, sizeof(volHeader));
1488 ERROR_EXIT(TC_BADVOLHEADER)do { code = (156566287L); goto error_exit; } while (0);
1489 }
1490
1491 /* convert and check the volume header */
1492 rc = VolHeaderToHost(&hostVolHeader, &volHeader);
1493 if (rc) {
1494 ErrorLog(0, taskId, code, 0, "Can't convert volume header\n");
1495 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
1496 }
1497
1498 if ((strcmp(hostVolHeader.volumeName, restoreInfo->oldName) != 0)
1499 || (restoreInfo->origVid
1500 && (hostVolHeader.volumeID != restoreInfo->origVid))
1501 || (hostVolHeader.magic != TC_VOLBEGINMAGIC0xb0258191))
1502 ERROR_EXIT(TC_BADVOLHEADER)do { code = (156566287L); goto error_exit; } while (0);
1503
1504 /* Set up prior restoring volume data */
1505 newVolName = restoreInfo->newName;
1506 newVolId = restoreInfo->vid;
1507 newServer = restoreInfo->hostAddr;
1508 newPart = restoreInfo->partition;
1509 restoreflags = 0;
1510 if ((restoreInfo->dumpLevel == 0)
1511 || (restoreInfo->flags & RDFLAG_FIRSTDUMP0x4))
1512 restoreflags |= RV_FULLRST0x000001;
1513 if (!(restoreInfo->flags & RDFLAG_LASTDUMP0x1))
1514 restoreflags |= RV_OFFLINE0x000002;
1515
1516 if (checkAbortByTaskId(taskId))
1517 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
1518
1519 /* Start the restore of the volume data. This is the code we want to return */
1520 code =
1521 UV_RestoreVolume(htonl(newServer)(__builtin_constant_p(newServer) ? ((((__uint32_t)(newServer)
) >> 24) | ((((__uint32_t)(newServer)) & (0xff <<
16)) >> 8) | ((((__uint32_t)(newServer)) & (0xff <<
8)) << 8) | (((__uint32_t)(newServer)) << 24)) :
__bswap32_var(newServer))
, newPart, newVolId, newVolName,
1522 restoreflags, xbsaRestoreVolumeData,
1523 (char *)rparamsPtr);
1524 error_exit:
1525 if (startread) {
1526 rc = xbsa_ReadObjectEnd(&butxInfo);
1527 if (rc != XBSA_SUCCESS) {
1528 ELog(taskId,
1529 "Unable to terminate reading of the volume from the server\n");
1530 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
1531 }
1532 }
1533
1534 if (havetrans) {
1535 rc = xbsa_EndTrans(&butxInfo);
1536 if (rc != XBSA_SUCCESS) {
1537 ELog(taskId, "Unable to terminate the current transaction\n");
1538 if (!code)
1539 code = rc;
1540 }
1541 }
1542
1543 if (restoretofile && restoretofilefd) {
1544 fclose(restoretofilefd);
1545 }
1546#endif
1547 return (code);
1548}
1549
1550int
1551restoreVolume(afs_uint32 taskId, struct tc_restoreDesc *restoreInfo,
1552 struct restoreParams *rparamsPtr)
1553{
1554 afs_int32 code = 0, rc;
1555 afs_int32 newServer, newPart, newVolId;
1556 char *newVolName;
1557 int restoreflags;
1558 afs_uint32 tapeID;
1559 struct butm_tapeInfo *tapeInfoPtr = rparamsPtr->tapeInfoPtr;
1560
1561 /* Check if we need a tape and prompt for one if so */
1562 tapeID =
1563 (restoreInfo->initialDumpId ? restoreInfo->
1564 initialDumpId : restoreInfo->dbDumpId);
1565 if ((rparamsPtr->frag == 0)
1566 || (strcmp(restoreInfo->tapeName, rparamsPtr->mntTapeName) != 0)
1567 || (tapeID != rparamsPtr->tapeID)) {
1568 /* Unmount the previous tape */
1569 unmountTape(taskId, tapeInfoPtr);
1570
1571 /* Remember this new tape */
1572 strcpy(rparamsPtr->mntTapeName, restoreInfo->tapeName);
1573 rparamsPtr->tapeID = tapeID;
1574
1575 /* Mount a new tape */
1576 rc = GetRestoreTape(taskId, tapeInfoPtr, rparamsPtr->mntTapeName,
1577 rparamsPtr->tapeID,
1578 ((rparamsPtr->frag == 0) ? autoQuery : 1));
1579 if (rc)
1580 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
1581 }
1582
1583 /* Seek to the correct spot and read the header information */
1584 rc = GetVolumeHead(taskId, tapeInfoPtr, restoreInfo->position,
1585 restoreInfo->oldName, restoreInfo->origVid);
1586 if (rc)
1587 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
1588
1589 /* Set up prior restoring volume data */
1590 newVolName = restoreInfo->newName;
1591 newVolId = restoreInfo->vid;
1592 newServer = restoreInfo->hostAddr;
1593 newPart = restoreInfo->partition;
1594 restoreflags = 0;
1595 if ((restoreInfo->dumpLevel == 0)
1596 || (restoreInfo->flags & RDFLAG_FIRSTDUMP0x4))
1597 restoreflags |= RV_FULLRST0x000001;
1598 if (!(restoreInfo->flags & RDFLAG_LASTDUMP0x1))
1599 restoreflags |= RV_OFFLINE0x000002;
1600
1601 if (checkAbortByTaskId(taskId))
1602 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
1603
1604 /* Start the restore of the volume data. This is the code we
1605 * want to return.
1606 */
1607 code =
1608 UV_RestoreVolume(htonl(newServer)(__builtin_constant_p(newServer) ? ((((__uint32_t)(newServer)
) >> 24) | ((((__uint32_t)(newServer)) & (0xff <<
16)) >> 8) | ((((__uint32_t)(newServer)) & (0xff <<
8)) << 8) | (((__uint32_t)(newServer)) << 24)) :
__bswap32_var(newServer))
, newPart, newVolId, newVolName,
1609 restoreflags, restoreVolumeData, (char *)rparamsPtr);
1610
1611 /* Read the FileEnd marker for the volume and step to next FM */
1612 rc = butm_ReadFileEnd(tapeInfoPtr)(*((tapeInfoPtr)->ops.readFileEnd))(tapeInfoPtr);
1613 if (rc) {
1614 ErrorLog(0, taskId, rc, tapeInfoPtr->error,
1615 "Can't read EOF on tape\n");
1616 }
1617
1618 error_exit:
1619 return (code);
1620}
1621
1622/* Restorer
1623 * created as a LWP by the server stub, <newNode> is a pointer to all
1624 * the parameters Restorer needs
1625 */
1626void *
1627Restorer(void *param) {
1628 struct dumpNode *newNode = (struct dumpNode *) param;
1629
1630 afs_int32 code = 0, tcode;
1631 afs_uint32 taskId;
1632 char *newVolName;
1633 struct butm_tapeInfo tapeInfo;
1634 struct tc_restoreDesc *Restore;
1635 struct tc_restoreDesc *RestoreDesc;
1636 struct restoreParams rparams;
1637 afs_int32 allocbufferSize;
1638 time_t startTime, endTime;
1639 afs_int32 goodrestore = 0;
1640
1641 afs_pthread_setname_self("restorer")(void)0;
1642 taskId = newNode->taskID;
1643 setStatus(taskId, DRIVE_WAIT0x100);
1644 EnterDeviceQueue(deviceLatch);
1645 clearStatus(taskId, DRIVE_WAIT0x100);
1646
1647 printf("\n\n");
1648 TLog(taskId, "Restore\n");
1649
1650 memset(&tapeInfo, 0, sizeof(tapeInfo));
1651 if (!CONF_XBSA0) {
1
Taking true branch
1652 tapeInfo.structVersion = BUTM_MAJORVERSION2;
1653 tcode = butm_file_Instantiate(&tapeInfo, &globalTapeConfig);
1654 if (tcode) {
2
Taking false branch
1655 ErrorLog(0, taskId, tcode, tapeInfo.error,
1656 "Can't initialize the tape module\n");
1657 ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0);
1658 }
1659 }
1660
1661 if (checkAbortByTaskId(taskId))
3
Taking true branch
1662 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
1663
1664 memset(&rparams, 0, sizeof(rparams));
1665 rparams.nodePtr = newNode;
1666 rparams.tapeInfoPtr = &tapeInfo;
1667 Restore = newNode->restores; /* Array of vol fragments to restore */
1668
1669 /* Allocate memory in which to restore the volumes data into */
1670 if (CONF_XBSA0) {
1671 allocbufferSize = dataSize = BufferSize;
1672 } else {
1673 /* Must have at least two tape blocks */
1674 tapeblocks = BufferSize / BUTM_BLOCKSIZE16384;
1675 if (tapeblocks < 2)
1676 tapeblocks = 2;
1677 allocbufferSize = tapeblocks * BUTM_BLOCKSIZE16384; /* This many full tapeblocks */
1678 }
1679 bufferBlock = NULL((void *)0);
1680 bufferBlock = (struct TapeBlock *)malloc(allocbufferSize);
1681 if (!bufferBlock)
1682 ERROR_EXIT(TC_NOMEMORY)do { code = (156566290L); goto error_exit; } while (0);
1683 memset(bufferBlock, 0, allocbufferSize);
1684
1685 startTime = time(0);
1686 for (rparams.frag = 0; (rparams.frag < newNode->arraySize);
1687 rparams.frag++) {
1688 RestoreDesc = &Restore[rparams.frag];
1689
1690 /* Skip the volume if it was requested to */
1691 if (RestoreDesc->flags & RDFLAG_SKIP0x2) {
1692 if (RestoreDesc->flags & RDFLAG_LASTDUMP0x1) {
1693 /* If the volume was restored, should bring it online */
1694 }
1695 continue;
1696 }
1697
1698 newVolName = RestoreDesc->newName;
1699
1700 /* Make sure the server to restore to is good */
1701 if (!RestoreDesc->hostAddr) {
1702 ErrorLog(0, taskId, 0, 0, "Illegal host ID 0 for volume %s\n",
1703 newVolName);
1704 ERROR_EXIT(TC_INTERNALERROR)do { code = (156566288L); goto error_exit; } while (0);
1705 }
1706
1707 if (checkAbortByTaskId(taskId))
1708 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
1709
1710 TapeLog(1, taskId, 0, 0, "Restoring volume %s\n", newVolName);
1711 lock_Status();
1712 strncpy(newNode->statusNodePtr->volumeName, newVolName,
1713 BU_MAXNAMELEN32);
1714 unlock_Status();
1715
1716 /* restoreVolume function takes care of all the related fragments
1717 * spanning various tapes. On return the complete volume has been
1718 * restored
1719 */
1720 if (CONF_XBSA0) {
1721 tcode = xbsaRestoreVolume(taskId, RestoreDesc, &rparams);
1722 } else {
1723 tcode = restoreVolume(taskId, RestoreDesc, &rparams);
1724 }
1725 if (tcode) {
1726 if (tcode == TC_ABORTEDBYREQUEST(156566278L)) {
1727 ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0);
1728 } else if (tcode == TC_SKIPTAPE(156566292L)) {
1729 afs_uint32 tapeID;
1730 tapeID =
1731 (RestoreDesc->initialDumpId ? RestoreDesc->
1732 initialDumpId : RestoreDesc->dbDumpId);
1733 SkipTape(Restore, newNode->arraySize, rparams.frag,
1734 RestoreDesc->tapeName, tapeID, taskId);
1735 } else {
1736 ErrorLog(0, taskId, tcode, 0, "Can't restore volume %s\n",
1737 newVolName);
1738 SkipVolume(Restore, newNode->arraySize, rparams.frag,
1739 RestoreDesc->origVid, taskId);
1740 }
1741 rparams.frag--;
1742 continue;
1743 }
1744
1745 goodrestore++;
1746 }
1747
1748 error_exit:
1749 endTime = time(0);
1750 if (!CONF_XBSA0) {
4
Taking true branch
1751 unmountTape(taskId, &tapeInfo);
1752 } else {
1753#ifdef xbsa
1754 code = InitToServer(taskId, &butxInfo, 0); /* Return to original server */
1755#endif
1756 }
1757
1758 if (bufferBlock)
5
Taking false branch
1759 free(bufferBlock);
1760
1761 if (code == TC_ABORTEDBYREQUEST(156566278L)) {
6
Taking true branch
1762 ErrorLog(0, taskId, 0, 0, "Restore: Aborted by request\n");
1763 clearStatus(taskId, ABORT_REQUEST0x2);
1764 setStatus(taskId, ABORT_DONE0x8);
1765 } else if (code) {
1766 TapeLog(0, taskId, code, 0, "Restore: Finished with errors\n");
1767 setStatus(taskId, TASK_ERROR0x80);
1768 } else {
1769 TLog(taskId, "Restore: Finished\n");
1770 }
1771
1772 if (centralLogIO && startTime) {
7
Branch condition evaluates to a garbage value
1773 long timediff;
1774 afs_int32 hrs, min, sec, tmp;
1775 char line[1024];
1776 struct tm tmstart, tmend;
1777
1778 localtime_r(&startTime, &tmstart);
1779 localtime_r(&endTime, &tmend);
1780 timediff = (int)endTime - (int)startTime;
1781 hrs = timediff / 3600;
1782 tmp = timediff % 3600;
1783 min = tmp / 60;
1784 sec = tmp % 60;
1785
1786 sprintf(line,
1787 "%-5d %02d/%02d/%04d %02d:%02d:%02d "
1788 "%02d/%02d/%04d %02d:%02d:%02d " "%02d:%02d:%02d "
1789 "%d of %d volume%s restored\n", taskId, tmstart.tm_mon + 1,
1790 tmstart.tm_mday, tmstart.tm_year + 1900, tmstart.tm_hour,
1791 tmstart.tm_min, tmstart.tm_sec, tmend.tm_mon + 1,
1792 tmend.tm_mday, tmend.tm_year + 1900, tmend.tm_hour,
1793 tmend.tm_min, tmend.tm_sec, hrs, min, sec, goodrestore,
1794 newNode->arraySize, ((newNode->arraySize > 1) ? "s" : ""));
1795
1796 fwrite(line, strlen(line), 1, centralLogIO);
1797 fflush(centralLogIO);
1798 }
1799
1800 setStatus(taskId, TASK_DONE0x20);
1801
1802 FreeNode(taskId);
1803 LeaveDeviceQueue(deviceLatch);
1804 return (void *)(intptr_t)(code);
1805}
1806
1807/* this is just scaffolding, creates new tape label with name <tapeName> */
1808
1809void
1810GetNewLabel(struct butm_tapeInfo *tapeInfoPtr, char *pName, char *AFSName,
1811 struct butm_tapeLabel *tapeLabel)
1812{
1813 struct timeval tp;
1814 afs_uint32 size;
1815
1816 memset(tapeLabel, 0, sizeof(struct butm_tapeLabel));
1817
1818 if (!CONF_XBSA0) {
1819 butm_GetSize(tapeInfoPtr, &size)(*((tapeInfoPtr)->ops.getSize))(tapeInfoPtr,&size);
1820 if (!size)
1821 size = globalTapeConfig.capacity;
1822 } else {
1823 size = 0; /* no tape size */
1824 }
1825 gettimeofday(&tp, NULL((void *)0));
1826
1827 tapeLabel->structVersion = CUR_TAPE_VERSION4;
1828 tapeLabel->creationTime = tp.tv_sec;
1829 tapeLabel->size = size;
1830 tapeLabel->expirationDate = 0; /* 1970 sometime */
1831 tapeLabel->dumpPath[0] = 0; /* no path name */
1832 tapeLabel->useCount = 0;
1833 strcpy(tapeLabel->AFSName, AFSName);
1834 strcpy(tapeLabel->pName, pName);
1835 strcpy(tapeLabel->cell, globalCellName);
1836 strcpy(tapeLabel->comment, "AFS Backup Software");
1837 strcpy(tapeLabel->creator.name, "AFS 3.6");
1838 strcpy(tapeLabel->creator.instance, "");
1839 strcpy(tapeLabel->creator.cell, globalCellName);
1840}
1841
1842/* extracts trailer out of buffer, nbytes is set to total data in
1843 * buffer - trailer size */
1844afs_int32
1845ExtractTrailer(char *buffer, afs_int32 size, afs_int32 *nbytes,
1846 struct volumeHeader *volTrailerPtr)
1847{
1848 afs_int32 code = 0;
1849 afs_int32 startPos;
1850 struct volumeHeader tempTrailer;
1851
1852 for (startPos = 0;
1853 startPos <=
1854 (size - sizeof(struct volumeHeader) + sizeof(tempTrailer.pad));
1855 startPos++) {
1856 code = readVolumeHeader(buffer, startPos, &tempTrailer);
1857 if (code == 0) {
1858 code = VolHeaderToHost(volTrailerPtr, &tempTrailer);
1859 if (code)
1860 break;
1861
1862 if (nbytes)
1863 *nbytes = startPos;
1864 return 1; /* saw the trailer */
1865 }
1866 }
1867
1868 if (nbytes)
1869 *nbytes = size / 2;
1870 return 0; /* did not see the trailer */
1871}
1872
1873int
1874FindVolTrailer(char *buffer, afs_int32 size, afs_int32 *dSize,
1875 struct volumeHeader *volTrailerPtr)
1876{
1877 afs_int32 offset, s;
1878 int found;
1879
1880 *dSize = size;
1881 if (!buffer)
1882 return 0;
1883
1884 s = sizeof(struct volumeHeader) + sizeof(volTrailerPtr->pad);
1885 if (s > size)
1886 s = size;
1887
1888 found = ExtractTrailer((buffer + size - s), s, &offset, volTrailerPtr);
1889 if (found)
1890 *dSize -= (s - offset);
1891 return found;
1892}
1893
1894int
1895FindVolTrailer2(char *buffera, afs_int32 sizea, afs_int32 *dataSizea,
1896 char *bufferb, afs_int32 sizeb, afs_int32 *dataSizeb,
1897 struct volumeHeader *volTrailerPtr)
1898{
1899 afs_int32 offset, s;
1900 afs_int32 headB, tailB;
1901 int found = 0;
1902
1903 if (!buffera)
1904 sizea = 0;
1905 if (!bufferb)
1906 sizeb = 0;
1907 *dataSizea = sizea;
1908 *dataSizeb = sizeb;
1909
1910 s = sizeof(struct volumeHeader) + sizeof(volTrailerPtr->pad);
1911 if (sizeb >= s) {
1912 found = FindVolTrailer(bufferb, sizeb, dataSizeb, volTrailerPtr);
1913 } else {
1914 tailB = sizeb;
1915 headB = (s - sizeb); /*(s > sizeb) */
1916 if (headB > sizea) {
1917 headB = sizea;
1918 s = headB + tailB;
1919 if (!s)
1920 return 0;
1921 }
1922
1923 memset(tapeVolumeHT, 0, sizeof(tapeVolumeHT));
1924 if (headB)
1925 memcpy(tapeVolumeHT, buffera + sizea - headB, headB);
1926 if (tailB)
1927 memcpy(tapeVolumeHT + headB, bufferb, tailB);
1928 if (ExtractTrailer(tapeVolumeHT, s, &offset, volTrailerPtr)) {
1929 found = 1;
1930 if (offset > headB) {
1931 /* *dataSizea remains unchanged */
1932 *dataSizeb = offset - headB;
1933 } else {
1934 *dataSizea -= (headB - offset); /*(headB >= offset) */
1935 *dataSizeb = 0;
1936 }
1937 }
1938 }
1939 return found;
1940}
1941
1942
1943Dateafs_uint32
1944ExpirationDate(afs_int32 dumpid)
1945{
1946 afs_int32 code;
1947 Dateafs_uint32 expiration = 0;
1948 struct budb_dumpEntry dumpEntry;
1949 struct budb_tapeEntry tapeEntry;
1950 struct budb_volumeEntry volEntry;
1951
1952 if (dumpid) {
1953 /*
1954 * Get the expiration date from DB if its there. The expiration of
1955 * any tape will be the most future expiration of any dump in the
1956 * set. Can't use bcdb_FindTape because dumpid here pertains to the
1957 * initial dump id.
1958 */
1959 code = bcdb_FindLastTape(dumpid, &dumpEntry, &tapeEntry, &volEntry);
1960 if (!code)
1961 expiration = tapeEntry.expires;
1962 }
1963 return (expiration);
1964}
1965
1966/* Returns true or false depending on whether the tape is expired or not */
1967
1968int
1969tapeExpired(struct butm_tapeLabel *tapeLabelPtr)
1970{
1971 Dateafs_uint32 expiration;
1972 struct timeval tp;
1973
1974 expiration = ExpirationDate(tapeLabelPtr->dumpid);
1975 if (!expiration)
1976 expiration = tapeLabelPtr->expirationDate;
1977
1978 gettimeofday(&tp, NULL((void *)0));
1979 return ((expiration < tp.tv_sec) ? 1 : 0);
1980}
1981
1982/* updateTapeLabel
1983 * given the label on the tape, delete any old information from the
1984 * database.
1985
1986 * Deletes all entries that match the volset.dumpnode
1987 * and the dump path.
1988 */
1989
1990int
1991updateTapeLabel(struct labelTapeIf *labelIfPtr,
1992 struct butm_tapeInfo *tapeInfoPtr,
1993 struct butm_tapeLabel *newLabelPtr)
1994{
1995 struct butm_tapeLabel oldLabel;
1996 afs_int32 i, code = 0;
1997 afs_uint32 taskId;
1998 int tapeIsLabeled = 0;
1999 int interactiveFlag;
2000 int tapecount = 1;
2001
2002 interactiveFlag = autoQuery;
2003 taskId = labelIfPtr->taskId;
2004
2005 while (1) {
2006 if (interactiveFlag) {
2007 code =
2008 PromptForTape(LABELOPCODE2, TNAME(newLabelPtr)( strcmp((newLabelPtr)->pName,"") ? (newLabelPtr)->pName
: ( strcmp((newLabelPtr)->AFSName,"") ? (newLabelPtr)->
AFSName : "<NULL>" ) )
, 0,
2009 labelIfPtr->taskId, tapecount);
2010 if (code)
2011 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
2012 }
2013 interactiveFlag = 1;
2014 tapecount++;
2015
2016 /* mount the tape */
2017 code = butm_Mount(tapeInfoPtr, newLabelPtr->AFSName)(*((tapeInfoPtr)->ops.mount))(tapeInfoPtr,newLabelPtr->
AFSName)
;
2018 if (code) {
2019 TapeLog(0, taskId, code, tapeInfoPtr->error, "Can't open tape\n");
2020 goto newtape;
2021 }
2022
2023 code = butm_ReadLabel(tapeInfoPtr, &oldLabel, 1)(*((tapeInfoPtr)->ops.readLabel))(tapeInfoPtr,&oldLabel
,1)
; /* will rewind the tape */
2024 if (!code) {
2025 tapeIsLabeled = 1;
2026
2027 if ((strcmp(newLabelPtr->AFSName, "") != 0)
2028 && (strcmp(oldLabel.pName, "") != 0)) {
2029 /* We are setting the AFS name, yet tape
2030 * has a permanent name (not allowed).
2031 */
2032 TLog(taskId, "Can't label. Tape has permanent label '%s'\n",
2033 oldLabel.pName);
2034 goto newtape;
2035 }
2036
2037 if (!tapeExpired(&oldLabel)) {
2038 if (!queryoperator) {
2039 TLog(taskId, "This tape has not expired\n");
2040 goto newtape;
2041 }
2042 if (Ask("This tape has not expired - proceed") == 0)
2043 goto newtape;
2044 }
2045
2046 /* Keep the permanent name */
2047 if (strcmp(newLabelPtr->pName, "") == 0) {
2048 strcpy(newLabelPtr->pName, oldLabel.pName);
2049 } else if (strcmp(newLabelPtr->pName, TC_NULLTAPENAME"<NULL>") == 0) {
2050 strcpy(newLabelPtr->pName, "");
2051 }
2052 }
2053
2054 /* extract useful information from the old label */
2055 if (tapeIsLabeled && oldLabel.structVersion >= TAPE_VERSION_33) {
2056 newLabelPtr->dumpid = 0;
2057 newLabelPtr->useCount = oldLabel.useCount + 1;
2058 }
2059
2060 /* now write the new label */
2061 code = butm_Create(tapeInfoPtr, newLabelPtr, 1)(*((tapeInfoPtr)->ops.create))(tapeInfoPtr,newLabelPtr,1); /* will rewind the tape */
2062 if (code) {
2063 ErrorLog(0, taskId, code, tapeInfoPtr->error,
2064 "Can't label tape\n");
2065 goto newtape;
2066 }
2067
2068 break;
2069
2070 newtape:
2071 unmountTape(taskId, tapeInfoPtr);
2072 }
2073
2074 /* delete obsolete information from the database */
2075 if (tapeIsLabeled && oldLabel.structVersion >= TAPE_VERSION_33) {
2076 /* delete based on dump id */
2077 if (oldLabel.dumpid) {
2078 i = bcdb_deleteDump(oldLabel.dumpid, 0, 0, 0);
2079 if (i && (i != BUDB_NOENT(156303877L)))
2080 ErrorLog(0, taskId, i, 0,
2081 "Warning: Can't delete old dump %u from database\n",
2082 oldLabel.dumpid);
2083 }
2084 }
2085
2086 error_exit:
2087 unmountTape(taskId, tapeInfoPtr);
2088 return (code);
2089}
2090
2091/* Labeller
2092 * LWP created by the server stub. Labels the tape with name and size
2093 * specified by <label>
2094 */
2095
2096void *
2097Labeller(void *param)
2098{
2099 struct labelTapeIf *labelIfPtr = (struct labelTapeIf *)param;
2100
2101 struct tc_tapeLabel *label = &labelIfPtr->label;
2102
2103 struct butm_tapeLabel newTapeLabel;
2104 struct butm_tapeInfo tapeInfo;
2105 afs_uint32 taskId;
2106 afs_int32 code = 0;
2107
2108 afs_pthread_setname_self("labeller")(void)0;
2109 taskId = labelIfPtr->taskId;
2110 setStatus(taskId, DRIVE_WAIT0x100);
2111 EnterDeviceQueue(deviceLatch);
2112 clearStatus(taskId, DRIVE_WAIT0x100);
2113
2114 printf("\n\n");
2115 TLog(taskId, "Labeltape\n");
2116
2117 memset(&tapeInfo, 0, sizeof(tapeInfo));
2118 tapeInfo.structVersion = BUTM_MAJORVERSION2;
2119 code = butm_file_Instantiate(&tapeInfo, &globalTapeConfig);
2120 if (code) {
2121 ErrorLog(0, taskId, code, tapeInfo.error,
2122 "Can't initialize the tape module\n");
2123 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
2124 }
2125
2126 GetNewLabel(&tapeInfo, label->pname, label->afsname, &newTapeLabel);
2127 if (label->size)
2128 newTapeLabel.size = label->size;
2129 else
2130 newTapeLabel.size = globalTapeConfig.capacity;
2131
2132 code = updateTapeLabel(labelIfPtr, &tapeInfo, &newTapeLabel);
2133 if (code)
2134 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
2135
2136 error_exit:
2137 if (code == TC_ABORTEDBYREQUEST(156566278L)) {
2138 ErrorLog(0, taskId, 0, 0, "Labeltape: Aborted by request\n");
2139 clearStatus(taskId, ABORT_REQUEST0x2);
2140 setStatus(taskId, ABORT_DONE0x8);
2141 } else if (code) {
2142 ErrorLog(0, taskId, code, 0, "Labeltape: Finished with errors\n");
2143 setStatus(taskId, TASK_ERROR0x80);
2144 } else {
2145 TLog(taskId, "Labelled tape %s size %u Kbytes\n",
2146 TNAME(&newTapeLabel)( strcmp((&newTapeLabel)->pName,"") ? (&newTapeLabel
)->pName : ( strcmp((&newTapeLabel)->AFSName,"") ? (
&newTapeLabel)->AFSName : "<NULL>" ) )
, newTapeLabel.size);
2147 }
2148 setStatus(labelIfPtr->taskId, TASK_DONE0x20);
2149
2150 free(labelIfPtr);
2151 LeaveDeviceQueue(deviceLatch);
2152 return (void *)(intptr_t)(code);
2153}
2154
2155/* PrintTapeLabel
2156 * print out the tape label.
2157 */
2158
2159void
2160PrintTapeLabel(struct butm_tapeLabel *labelptr)
2161{
2162 char tapeName[BU_MAXTAPELEN32 + 32];
2163 time_t t;
2164
2165 printf("Tape label\n");
2166 printf("----------\n");
2167 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);
;
2168 printf("permanent tape name = %s\n", tapeName);
2169 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);
;
2170 printf("AFS tape name = %s\n", tapeName);
2171 t = labelptr->creationTime;
2172 printf("creationTime = %s", ctime(&t));
2173 if (labelptr->expirationDate) {
2174 t = labelptr->expirationDate;
2175 printf("expirationDate = %s", cTIME(&t)( (*(&t) == 037777777777) ? (char *)"NEVER \n"
: (char *)ctime(&t) )
);
2176 }
2177 printf("cell = %s\n", labelptr->cell);
2178 printf("size = %u Kbytes\n", labelptr->size);
2179 printf("dump path = %s\n", labelptr->dumpPath);
2180
2181 if (labelptr->structVersion >= TAPE_VERSION_33) {
2182 printf("dump id = %u\n", labelptr->dumpid);
2183 printf("useCount = %d\n", labelptr->useCount);
2184 }
2185 printf("-- End of tape label --\n\n");
2186}
2187
2188/* ReadLabel
2189 * Read the label from a tape.
2190 * Currently prints out a "detailed" summary of the label but passes
2191 * back only selected fields.
2192 */
2193
2194int
2195ReadLabel(struct tc_tapeLabel *label)
2196{
2197 struct butm_tapeLabel newTapeLabel;
2198 struct butm_tapeInfo tapeInfo;
2199 afs_uint32 taskId;
2200 Dateafs_uint32 expir;
2201 afs_int32 code = 0;
2202 int interactiveFlag;
2203 int tapecount = 1;
2204
2205 EnterDeviceQueue(deviceLatch);
2206 taskId = allocTaskId(); /* reqd for lower level rtns */
2207
2208 printf("\n\n");
2209 TLog(taskId, "Readlabel\n");
2210
2211 memset(&tapeInfo, 0, sizeof(tapeInfo));
2212 tapeInfo.structVersion = BUTM_MAJORVERSION2;
2213 code = butm_file_Instantiate(&tapeInfo, &globalTapeConfig);
2214 if (code) {
2215 ErrorLog(0, taskId, code, tapeInfo.error,
2216 "Can't initialize the tape module\n");
2217 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
2218 }
2219 memset(&newTapeLabel, 0, sizeof(newTapeLabel));
2220
2221 interactiveFlag = autoQuery;
2222
2223 while (1) {
2224 if (interactiveFlag) {
2225 code = PromptForTape(READLABELOPCODE3, "", 0, taskId, tapecount);
2226 if (code)
2227 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
2228 }
2229 interactiveFlag = 1;
2230 tapecount++;
2231
2232 code = butm_Mount(&tapeInfo, "")(*((&tapeInfo)->ops.mount))(&tapeInfo,"");
2233 if (code) {
2234 TapeLog(0, taskId, code, tapeInfo.error, "Can't open tape\n");
2235 goto newtape;
2236 }
2237 break;
2238
2239 newtape:
2240 unmountTape(taskId, &tapeInfo);
2241 }
2242
2243 code = butm_ReadLabel(&tapeInfo, &newTapeLabel, 1)(*((&tapeInfo)->ops.readLabel))(&tapeInfo,&newTapeLabel
,1)
; /* will rewind the tape */
2244 if (code) {
2245 if (code == BUTM_NOLABEL(156568851L)) {
2246 printf("Tape is unlabelled\n");
2247 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
2248 }
2249 ErrorLog(1, taskId, code, tapeInfo.error, "Can't read tape label\n");
2250 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
2251 }
2252
2253 /* copy the fields to be passed to the caller */
2254 label->size = newTapeLabel.size;
2255 label->tapeId = newTapeLabel.dumpid;
2256 strcpy(label->afsname, newTapeLabel.AFSName);
2257 strcpy(label->pname, newTapeLabel.pName);
2258
2259
2260 expir = ExpirationDate(newTapeLabel.dumpid);
2261 if (expir)
2262 newTapeLabel.expirationDate = expir;
2263
2264 PrintTapeLabel(&newTapeLabel);
2265
2266 error_exit:
2267 unmountTape(taskId, &tapeInfo);
2268
2269 if (code == TC_ABORTEDBYREQUEST(156566278L))
2270 ErrorLog(0, taskId, 0, 0, "ReadLabel: Aborted by request\n");
2271 else if (code && (code != BUTM_NOLABEL(156568851L)))
2272 ErrorLog(0, taskId, code, 0, "ReadLabel: Finished with errors\n");
2273 else
2274 TLog(taskId, "ReadLabel: Finished\n");
2275
2276 LeaveDeviceQueue(deviceLatch);
2277 return (code);
2278}
2279
2280/* Function to read volume header and trailer structure from tape, taking
2281 into consideration, different word alignment rules.
2282*/
2283afs_int32
2284readVolumeHeader(char *buffer, /* in - buffer to read header from */
2285 afs_int32 bufloc, /* in - header's location in buffer */
2286 struct volumeHeader *header) /* out -header structure */
2287{
2288 struct volumeHeader vhptr, *tempvhptr;
2289 afs_int32 firstSplice = (afs_int32) ((char*)& vhptr.pad - (char*) & vhptr);
2290 int padLen = sizeof(vhptr.pad); /* pad to achieve 4 byte alignment */
2291 int nextSplice = sizeof(struct volumeHeader) - firstSplice - padLen;
2292
2293 /* Four cases are to be handled
2294 *
2295 * Volume Header (byte alignment)
2296 * -----------------------
2297 * Tape In Core
2298 * ---- -------
2299 * Case 1: 4 1
2300 * Case 2: 4 4
2301 * Case 3: 1 1
2302 * Case 4: 1 4
2303 * -----------------------
2304 *
2305 * Case 2 and Case 3 are identical cases and handled the same way.
2306 * Case 1 and Case 4 are separate cases. In one case the pad needs
2307 * to be removed and in the other, it needs to be spliced in. The
2308 * four cases are handled as follows
2309 */
2310 tempvhptr = (struct volumeHeader *)(buffer + bufloc);
2311 if ((strncmp(tempvhptr->preamble, "H++NAME#", 8) == 0)
2312 && (strncmp(tempvhptr->postamble, "T--NAME#", 8) == 0)) {
2313 /* Handle Cases 2 & 3 */
2314 memcpy(&vhptr, buffer + bufloc, sizeof(struct volumeHeader));
2315 HEADER_CHECKS(vhptr, header){ afs_int32 magic, versionflags; versionflags = (__builtin_constant_p
(vhptr.versionflags) ? ((((__uint32_t)(vhptr.versionflags)) >>
24) | ((((__uint32_t)(vhptr.versionflags)) & (0xff <<
16)) >> 8) | ((((__uint32_t)(vhptr.versionflags)) &
(0xff << 8)) << 8) | (((__uint32_t)(vhptr.versionflags
)) << 24)) : __bswap32_var(vhptr.versionflags)); if ( versionflags
== 0 || versionflags == 1 || versionflags == 2 || versionflags
== 3 || versionflags == 4 ) { magic = (__builtin_constant_p(
vhptr.magic) ? ((((__uint32_t)(vhptr.magic)) >> 24) | (
(((__uint32_t)(vhptr.magic)) & (0xff << 16)) >>
8) | ((((__uint32_t)(vhptr.magic)) & (0xff << 8)) <<
8) | (((__uint32_t)(vhptr.magic)) << 24)) : __bswap32_var
(vhptr.magic)); if (magic == 0xb0258191 || magic == 0x9167345a
|| magic == 0xffffffff ) { memcpy(header, &vhptr, sizeof
(struct volumeHeader)); return (0); } } }
;
2316
2317 /* Handle Case 4 */
2318 memset(&vhptr, 0, sizeof(struct volumeHeader));
2319 memcpy(&vhptr, buffer + bufloc, firstSplice);
2320 memset(&vhptr.pad, 0, padLen);
2321 memcpy(&vhptr.volumeID, buffer + bufloc + firstSplice, nextSplice);
2322 HEADER_CHECKS(vhptr, header){ afs_int32 magic, versionflags; versionflags = (__builtin_constant_p
(vhptr.versionflags) ? ((((__uint32_t)(vhptr.versionflags)) >>
24) | ((((__uint32_t)(vhptr.versionflags)) & (0xff <<
16)) >> 8) | ((((__uint32_t)(vhptr.versionflags)) &
(0xff << 8)) << 8) | (((__uint32_t)(vhptr.versionflags
)) << 24)) : __bswap32_var(vhptr.versionflags)); if ( versionflags
== 0 || versionflags == 1 || versionflags == 2 || versionflags
== 3 || versionflags == 4 ) { magic = (__builtin_constant_p(
vhptr.magic) ? ((((__uint32_t)(vhptr.magic)) >> 24) | (
(((__uint32_t)(vhptr.magic)) & (0xff << 16)) >>
8) | ((((__uint32_t)(vhptr.magic)) & (0xff << 8)) <<
8) | (((__uint32_t)(vhptr.magic)) << 24)) : __bswap32_var
(vhptr.magic)); if (magic == 0xb0258191 || magic == 0x9167345a
|| magic == 0xffffffff ) { memcpy(header, &vhptr, sizeof
(struct volumeHeader)); return (0); } } }
;
2323
2324 /* Handle Case 1 */
2325 memset(&vhptr, 0, sizeof(struct volumeHeader));
2326 memcpy(&vhptr, buffer + bufloc, firstSplice);
2327 /* probably GCC bug 37060; however, no guarantee on length of buffer */
2328 tempvhptr = (struct volumeHeader *)(buffer + firstSplice);
2329 memcpy(tempvhptr, buffer + bufloc + firstSplice + padLen,
2330 nextSplice);
2331 HEADER_CHECKS(vhptr, header){ afs_int32 magic, versionflags; versionflags = (__builtin_constant_p
(vhptr.versionflags) ? ((((__uint32_t)(vhptr.versionflags)) >>
24) | ((((__uint32_t)(vhptr.versionflags)) & (0xff <<
16)) >> 8) | ((((__uint32_t)(vhptr.versionflags)) &
(0xff << 8)) << 8) | (((__uint32_t)(vhptr.versionflags
)) << 24)) : __bswap32_var(vhptr.versionflags)); if ( versionflags
== 0 || versionflags == 1 || versionflags == 2 || versionflags
== 3 || versionflags == 4 ) { magic = (__builtin_constant_p(
vhptr.magic) ? ((((__uint32_t)(vhptr.magic)) >> 24) | (
(((__uint32_t)(vhptr.magic)) & (0xff << 16)) >>
8) | ((((__uint32_t)(vhptr.magic)) & (0xff << 8)) <<
8) | (((__uint32_t)(vhptr.magic)) << 24)) : __bswap32_var
(vhptr.magic)); if (magic == 0xb0258191 || magic == 0x9167345a
|| magic == 0xffffffff ) { memcpy(header, &vhptr, sizeof
(struct volumeHeader)); return (0); } } }
;
2332
2333 }
2334 return (TC_BADVOLHEADER(156566287L));
2335}