| File: | butm/file_tm.c |
| Location: | line 1272, column 2 |
| Description: | Assigned value is always the same as the existing value |
| 1 | /* | ||||
| 2 | * Copyright 2000, International Business Machines Corporation and others. | ||||
| 3 | * All Rights Reserved. | ||||
| 4 | * | ||||
| 5 | * This software has been released under the terms of the IBM Public | ||||
| 6 | * License. For details, see the LICENSE file in the top-level source | ||||
| 7 | * directory or online at http://www.openafs.org/dl/license10.html | ||||
| 8 | */ | ||||
| 9 | |||||
| 10 | #include <afsconfig.h> | ||||
| 11 | #include <afs/param.h> | ||||
| 12 | |||||
| 13 | #include <roken.h> | ||||
| 14 | |||||
| 15 | #ifdef HAVE_SYS_WAIT_H1 | ||||
| 16 | #include <sys/wait.h> | ||||
| 17 | #endif | ||||
| 18 | |||||
| 19 | #include <limits.h> | ||||
| 20 | #include <ctype.h> | ||||
| 21 | |||||
| 22 | #include <lwp.h> | ||||
| 23 | #include <afs/com_err.h> | ||||
| 24 | #include <afs/butm.h> | ||||
| 25 | #include <afs/usd.h> | ||||
| 26 | |||||
| 27 | #include "error_macros.h" | ||||
| 28 | #include "butm_prototypes.h" | ||||
| 29 | |||||
| 30 | #ifdef O_LARGEFILE | ||||
| 31 | typedef off64_t osi_lloff_t; | ||||
| 32 | #else /* O_LARGEFILE */ | ||||
| 33 | #ifdef AFS_HAVE_LLSEEK | ||||
| 34 | typedef offset_t osi_lloff_t; | ||||
| 35 | #else /* AFS_HAVE_LLSEEK */ | ||||
| 36 | typedef off_t osi_lloff_t; | ||||
| 37 | #endif /* AFS_HAVE_LLSEEK */ | ||||
| 38 | #endif /* O_LARGEFILE */ | ||||
| 39 | |||||
| 40 | extern int isafile; | ||||
| 41 | |||||
| 42 | #define FILE_MAGIC1000000007 1000000007 /* s/w file mark */ | ||||
| 43 | #define FILE_BEGIN0 0 /* byte field in file mark */ | ||||
| 44 | #define FILE_FMEND1 1 /* byte field in file mark */ | ||||
| 45 | #define FILE_EOD-1 -1 /* byte field in file mark */ | ||||
| 46 | #define TAPE_MAGIC1100000009 1100000009 /* tape label block */ | ||||
| 47 | #define BLOCK_MAGIC1100000005 1100000005 /* file data block */ | ||||
| 48 | #ifdef AFS_PTHREAD_ENV | ||||
| 49 | #define POLL()IOMGR_Poll() | ||||
| 50 | #define SLEEP(s)IOMGR_Sleep(s) sleep(s) | ||||
| 51 | #else | ||||
| 52 | #define POLL()IOMGR_Poll() IOMGR_Poll() | ||||
| 53 | #define SLEEP(s)IOMGR_Sleep(s) IOMGR_Sleep(s) | ||||
| 54 | #endif | ||||
| 55 | |||||
| 56 | /* Notes: (PA) | ||||
| 57 | * | ||||
| 58 | * 1) filemarks and block marks have the magic,bytes fields reversed. This | ||||
| 59 | * is undoubtedly a bug. Also note that the two structures have | ||||
| 60 | * inconsistent types, overlaying int and afs_int32. | ||||
| 61 | * 2) When a volume is dumped, if the volume is locked, the dump will produce | ||||
| 62 | * an anomalous tape format of the form: | ||||
| 63 | * s/w file begin mark | ||||
| 64 | * volume header | ||||
| 65 | * s/w file end mark | ||||
| 66 | * The design of the original butm code means that this cannot be | ||||
| 67 | * handled correctly. The code is modified so that ReadFileData | ||||
| 68 | * returns BUTM_ENDVOLUME if it encounters the s/w filemark. | ||||
| 69 | */ | ||||
| 70 | |||||
| 71 | /* data organization on tape: | ||||
| 72 | * all writes are in blocks of BUTM_BLOCKSIZE (= sizeof(blockMark) + BUTM_BLKSIZE) | ||||
| 73 | * blockMark contains a magic number and counts of real data bytes | ||||
| 74 | * written out in the block. | ||||
| 75 | * | ||||
| 76 | * each file is preceeded by a fileMark, which acts as the file | ||||
| 77 | * delimiter. A file consists of contigous data blocks. TM does | ||||
| 78 | * understand or interrpet the data in data blocks. | ||||
| 79 | * | ||||
| 80 | * The tape begins with a tape label and ends with EOF file markers | ||||
| 81 | * in succession (2 or 4 of them ). | ||||
| 82 | */ | ||||
| 83 | |||||
| 84 | |||||
| 85 | struct fileMark { /* in network byte order */ | ||||
| 86 | afs_int32 magic; | ||||
| 87 | afs_uint32 nBytes; | ||||
| 88 | }; | ||||
| 89 | |||||
| 90 | struct tapeLabel { | ||||
| 91 | afs_int32 magic; | ||||
| 92 | struct butm_tapeLabel label; | ||||
| 93 | }; | ||||
| 94 | |||||
| 95 | struct progress { | ||||
| 96 | usd_handle_t fid; /* file id of simulated tape */ | ||||
| 97 | afs_int32 mountId; /* current mountId */ | ||||
| 98 | afs_int32 reading; /* read file operation in progress */ | ||||
| 99 | afs_int32 writing; /* write file operation in progress */ | ||||
| 100 | }; | ||||
| 101 | |||||
| 102 | static struct configuration { | ||||
| 103 | char tapedir[64]; /* directory to create "tapes" */ | ||||
| 104 | afs_int32 mountId; /* for detecting simultaneous mounts */ | ||||
| 105 | afs_uint32 tapeSize; /* size of simulated tapes */ | ||||
| 106 | afs_uint32 fileMarkSize; /* size of file mark, bytes */ | ||||
| 107 | afs_int32 portOffset; /* port + portOffset is used by TC to listen */ | ||||
| 108 | } config; | ||||
| 109 | |||||
| 110 | static char *whoami = "file_tm"; | ||||
| 111 | char tapeBlock[BUTM_BLOCKSIZE16384]; /* Tape buffer for reads and writes */ | ||||
| 112 | |||||
| 113 | #define BLOCK_LABEL0 0 /* read/write a tape label */ | ||||
| 114 | #define BLOCK_FMBEGIN1 1 /* read/write a begin FileMark */ | ||||
| 115 | #define BLOCK_DATA2 2 /* read/write a data block */ | ||||
| 116 | #define BLOCK_FMEND3 3 /* read/write an end FileMark */ | ||||
| 117 | #define BLOCK_EOD4 4 /* read/write an EOD FileMark */ | ||||
| 118 | #define BLOCK_EOF5 5 /* tape block is a HW EOF mark (usually error) */ | ||||
| 119 | #define BLOCK_UNKNOWN6 6 /* tape block is unknwon (error) */ | ||||
| 120 | |||||
| 121 | #define WRITE_OP1 1 | ||||
| 122 | #define READ_OP0 0 | ||||
| 123 | |||||
| 124 | #define READS(((struct progress *)(info->tmRock))->reading) (((struct progress *)(info->tmRock))->reading) | ||||
| 125 | #define WRITES(((struct progress *)(info->tmRock))->writing) (((struct progress *)(info->tmRock))->writing) | ||||
| 126 | |||||
| 127 | /* ---------------------------------------------------------------------- | ||||
| 128 | * These routines use the usd library to perform tape operations. | ||||
| 129 | * ForkIoctl, ForkOpen, ForkClose, ForwardSpace, BackwardSpace, WriteEOF, | ||||
| 130 | * PrepareAccess(nt), ShutdownAccess(nt) | ||||
| 131 | * | ||||
| 132 | * Return Values: USD functions return 0 if successful or errno if failed. | ||||
| 133 | */ | ||||
| 134 | /* ------------------ USD Interface Functions Begin ------------------------ */ | ||||
| 135 | |||||
| 136 | /* | ||||
| 137 | * On Unix, fork a child process to perform an IOCTL call. This avoids | ||||
| 138 | * blocking the entire process during a tape operation | ||||
| 139 | */ | ||||
| 140 | |||||
| 141 | #ifndef AFS_NT40_ENV | ||||
| 142 | /* Unix version of function */ | ||||
| 143 | |||||
| 144 | static int | ||||
| 145 | ForkIoctl(usd_handle_t fd, int op, int count) | ||||
| 146 | { | ||||
| 147 | int rc; /* return code from system calls */ | ||||
| 148 | int i; /* loop index */ | ||||
| 149 | int pid; /* process ID of child process */ | ||||
| 150 | int status; /* exit status of child process */ | ||||
| 151 | int ioctl_rc; /* return code from ioctl call */ | ||||
| 152 | int pipefd[2]; /* pipe for child return status */ | ||||
| 153 | int forkflag; /* flag set when ready to fork */ | ||||
| 154 | usd_tapeop_t tapeop; /* tape operation specification */ | ||||
| 155 | int unixfd; | ||||
| 156 | |||||
| 157 | #ifdef AFS_PTHREAD_ENV | ||||
| 158 | forkflag = 0; /* No need to fork if using pthreads */ | ||||
| 159 | #else | ||||
| 160 | forkflag = 1; | ||||
| 161 | #endif | ||||
| 162 | |||||
| 163 | /* initialize tape command structure */ | ||||
| 164 | tapeop.tp_op = op; | ||||
| 165 | tapeop.tp_count = count; | ||||
| 166 | |||||
| 167 | /* create pipe for getting return code from child */ | ||||
| 168 | if (forkflag) { | ||||
| 169 | rc = pipe(pipefd); | ||||
| 170 | if (rc < 0) { | ||||
| 171 | printf("butm: Can't open pipe for IOCTL process. Error %d\n", | ||||
| 172 | errno(* __error())); | ||||
| 173 | forkflag = 0; | ||||
| 174 | } | ||||
| 175 | } | ||||
| 176 | |||||
| 177 | if (forkflag) { | ||||
| 178 | pid = fork(); | ||||
| 179 | if (pid < 0) { | ||||
| 180 | close(pipefd[0]); | ||||
| 181 | close(pipefd[1]); | ||||
| 182 | printf("butm: Can't fork IOCTL process. Error %d\n", errno(* __error())); | ||||
| 183 | forkflag = 0; | ||||
| 184 | |||||
| 185 | } | ||||
| 186 | } | ||||
| 187 | |||||
| 188 | if (!forkflag) { /* problem starting child process */ | ||||
| 189 | /* do the ioctl anyway, it will probably work */ | ||||
| 190 | ioctl_rc = USD_IOCTL(fd, USD_IOCTL_TAPEOPERATION, (void *)&tapeop)((*(fd)->ioctl)(fd, 8, (void *)&tapeop)); | ||||
| 191 | } else if (pid == 0) { /* child process */ | ||||
| 192 | /* close all unneccessary file descriptors */ | ||||
| 193 | /* note: as painful as it is, we have to reach under the covers of | ||||
| 194 | * the usd package to implement this functionality. | ||||
| 195 | */ | ||||
| 196 | unixfd = (intptr_t)(fd->handle); | ||||
| 197 | |||||
| 198 | for (i = 3; i < _POSIX_OPEN_MAX20; i++) { | ||||
| 199 | if (i != unixfd && i != pipefd[1]) { | ||||
| 200 | close(i); | ||||
| 201 | } | ||||
| 202 | } | ||||
| 203 | |||||
| 204 | /* do the ioctl call */ | ||||
| 205 | ioctl_rc = USD_IOCTL(fd, USD_IOCTL_TAPEOPERATION, (void *)&tapeop)((*(fd)->ioctl)(fd, 8, (void *)&tapeop)); | ||||
| 206 | |||||
| 207 | /* send the return code back to the parent */ | ||||
| 208 | write(pipefd[1], &ioctl_rc, sizeof(int)); | ||||
| 209 | |||||
| 210 | exit(0); | ||||
| 211 | } else { /* parent process */ | ||||
| 212 | |||||
| 213 | close(pipefd[1]); | ||||
| 214 | POLL()IOMGR_Poll(); | ||||
| 215 | /* read the result from the child process */ | ||||
| 216 | rc = read(pipefd[0], &ioctl_rc, sizeof(int)); | ||||
| 217 | if (rc != sizeof(int)) { | ||||
| 218 | /* tape is now in unknown state */ | ||||
| 219 | printf("butm: Can't determine IOCTL child status. Error %d\n", | ||||
| 220 | errno(* __error())); | ||||
| 221 | ioctl_rc = EFAULT14; | ||||
| 222 | } | ||||
| 223 | |||||
| 224 | close(pipefd[0]); | ||||
| 225 | |||||
| 226 | /* get the completion status from the child process */ | ||||
| 227 | rc = waitpid(pid, &status, 0); | ||||
| 228 | while (rc < 0 && errno(* __error()) == EINTR4) { | ||||
| 229 | rc = waitpid(pid, &status, 0); | ||||
| 230 | } | ||||
| 231 | if (rc < 0) { | ||||
| 232 | printf("butm: Can't determine IOCTL child status. Error %d\n", | ||||
| 233 | errno(* __error())); | ||||
| 234 | } else if (status != 0) { | ||||
| 235 | printf | ||||
| 236 | ("butm: Unexpected IOCTL process status 0x%04x . Error %d\n", | ||||
| 237 | status, errno(* __error())); | ||||
| 238 | } | ||||
| 239 | SLEEP(1)IOMGR_Sleep(1); | ||||
| 240 | } | ||||
| 241 | |||||
| 242 | return (ioctl_rc); | ||||
| 243 | } | ||||
| 244 | #else | ||||
| 245 | /* NT version of function */ | ||||
| 246 | |||||
| 247 | static int | ||||
| 248 | ForkIoctl(usd_handle_t fd, int op, int count) | ||||
| 249 | { | ||||
| 250 | usd_tapeop_t tapeop; | ||||
| 251 | |||||
| 252 | /* Issue requested tape control */ | ||||
| 253 | tapeop.tp_op = op; | ||||
| 254 | tapeop.tp_count = count; | ||||
| 255 | |||||
| 256 | return (USD_IOCTL(fd, USD_IOCTL_TAPEOPERATION, (void *)&tapeop)((*(fd)->ioctl)(fd, 8, (void *)&tapeop))); | ||||
| 257 | } | ||||
| 258 | #endif /* !AFS_NT40_ENV */ | ||||
| 259 | |||||
| 260 | |||||
| 261 | /* | ||||
| 262 | * On Unix, fork a child process to attempt to open the drive. We want to make | ||||
| 263 | * certain there is tape in the drive before trying to open the device | ||||
| 264 | * in the main process | ||||
| 265 | */ | ||||
| 266 | |||||
| 267 | #ifndef AFS_NT40_ENV | ||||
| 268 | /* Unix version of function. */ | ||||
| 269 | |||||
| 270 | static int | ||||
| 271 | ForkOpen(char *device) | ||||
| 272 | { | ||||
| 273 | int rc; /* return code from system calls */ | ||||
| 274 | int i; /* loop index */ | ||||
| 275 | int pid; /* process ID of child process */ | ||||
| 276 | int status; /* exit status of child process */ | ||||
| 277 | int open_rc; /* return code from open */ | ||||
| 278 | int pipefd[2]; /* pipe for child return status */ | ||||
| 279 | int forkflag; /* flag set when ready to fork */ | ||||
| 280 | usd_handle_t fd; /* handle returned from open */ | ||||
| 281 | |||||
| 282 | #ifdef AFS_PTHREAD_ENV | ||||
| 283 | forkflag = 0; /* No need to fork if using pthreads */ | ||||
| 284 | #else | ||||
| 285 | forkflag = 1; | ||||
| 286 | #endif | ||||
| 287 | |||||
| 288 | /* create pipe for getting return code from child */ | ||||
| 289 | if (forkflag) { | ||||
| 290 | rc = pipe(pipefd); | ||||
| 291 | if (rc < 0) { | ||||
| 292 | printf("butm: Cannot create pipe for OPEN process. Error %d\n", | ||||
| 293 | errno(* __error())); | ||||
| 294 | forkflag = 0; | ||||
| 295 | } | ||||
| 296 | } | ||||
| 297 | |||||
| 298 | if (forkflag) { | ||||
| 299 | pid = fork(); | ||||
| 300 | if (pid < 0) { | ||||
| 301 | close(pipefd[0]); | ||||
| 302 | close(pipefd[1]); | ||||
| 303 | printf("butm: Cannot create child process for OPEN. Error %d\n", | ||||
| 304 | errno(* __error())); | ||||
| 305 | forkflag = 0; | ||||
| 306 | } | ||||
| 307 | } | ||||
| 308 | |||||
| 309 | if (!forkflag) { /* problem starting child process */ | ||||
| 310 | /* | ||||
| 311 | *return success, the caller will discover any problems | ||||
| 312 | * when it opens the device. | ||||
| 313 | */ | ||||
| 314 | open_rc = 0; | ||||
| 315 | } else if (pid == 0) { /* child process */ | ||||
| 316 | /* close all unneccessary file descriptors */ | ||||
| 317 | for (i = 3; i < _POSIX_OPEN_MAX20; i++) { | ||||
| 318 | if (i != pipefd[1]) { | ||||
| 319 | close(i); | ||||
| 320 | } | ||||
| 321 | } | ||||
| 322 | |||||
| 323 | /* try the open */ | ||||
| 324 | open_rc = usd_Open(device, USD_OPEN_RDONLY0, 0, &fd); | ||||
| 325 | |||||
| 326 | if (open_rc == 0) { | ||||
| 327 | USD_CLOSE(fd)((*(fd)->close)(fd)); | ||||
| 328 | } | ||||
| 329 | |||||
| 330 | /* send the return code back to the parent */ | ||||
| 331 | write(pipefd[1], &open_rc, sizeof(open_rc)); | ||||
| 332 | |||||
| 333 | exit(0); | ||||
| 334 | } else { /* parent process */ | ||||
| 335 | |||||
| 336 | close(pipefd[1]); | ||||
| 337 | |||||
| 338 | POLL()IOMGR_Poll(); | ||||
| 339 | /* read the result from the child process */ | ||||
| 340 | rc = read(pipefd[0], &open_rc, sizeof(open_rc)); | ||||
| 341 | if (rc != sizeof(open_rc)) { | ||||
| 342 | /* this is not a problem since we will reopen the device anyway */ | ||||
| 343 | printf("butm: No response from OPEN process. Error %d\n", errno(* __error())); | ||||
| 344 | open_rc = 0; | ||||
| 345 | } | ||||
| 346 | |||||
| 347 | close(pipefd[0]); | ||||
| 348 | |||||
| 349 | /* get the completion status from the child process */ | ||||
| 350 | rc = waitpid(pid, &status, 0); | ||||
| 351 | while (rc < 0 && errno(* __error()) == EINTR4) { | ||||
| 352 | rc = waitpid(pid, &status, 0); | ||||
| 353 | } | ||||
| 354 | if (rc < 0) { | ||||
| 355 | printf("butm: Cannot get status of OPEN process. Error %d\n", | ||||
| 356 | errno(* __error())); | ||||
| 357 | } else if (status != 0) { | ||||
| 358 | printf | ||||
| 359 | ("butm: Unexpected OPEN process exit status 0x%04x. Error %d \n", | ||||
| 360 | status, errno(* __error())); | ||||
| 361 | } | ||||
| 362 | SLEEP(1)IOMGR_Sleep(1); | ||||
| 363 | } | ||||
| 364 | |||||
| 365 | return (open_rc); | ||||
| 366 | } | ||||
| 367 | #else | ||||
| 368 | /* NT version of function. */ | ||||
| 369 | |||||
| 370 | static int | ||||
| 371 | ForkOpen(char *device) | ||||
| 372 | { | ||||
| 373 | return (0); | ||||
| 374 | } | ||||
| 375 | #endif /* AFS_NT40_ENV */ | ||||
| 376 | |||||
| 377 | /* | ||||
| 378 | * On Unix, fork a child process to close the drive. If the drive rewinds | ||||
| 379 | * on close it could cause the process to block. | ||||
| 380 | */ | ||||
| 381 | |||||
| 382 | #ifndef AFS_NT40_ENV | ||||
| 383 | /* Unix version of function */ | ||||
| 384 | |||||
| 385 | static int | ||||
| 386 | ForkClose(usd_handle_t fd) | ||||
| 387 | { | ||||
| 388 | int rc; /* return code from system calls */ | ||||
| 389 | int i; /* loop index */ | ||||
| 390 | int pid; /* process ID of child process */ | ||||
| 391 | int status; /* exit status of child process */ | ||||
| 392 | int close_rc, parent_close_rc; /* return codes from close */ | ||||
| 393 | int pipefd[2]; /* pipe for child return status */ | ||||
| 394 | int ctlpipe[2]; /* pipe for message to child */ | ||||
| 395 | int forkflag; /* flag set when ready to fork */ | ||||
| 396 | int unixfd; | ||||
| 397 | |||||
| 398 | #ifdef AFS_PTHREAD_ENV | ||||
| 399 | forkflag = 0; /* No need to fork if using pthreads */ | ||||
| 400 | #else | ||||
| 401 | forkflag = 1; | ||||
| 402 | #endif | ||||
| 403 | |||||
| 404 | /* create pipe for getting return code from child */ | ||||
| 405 | if (forkflag) { | ||||
| 406 | rc = pipe(pipefd); | ||||
| 407 | if (rc < 0) { | ||||
| 408 | printf("butm: Cannot create pipe for CLOSE process. Error %d\n", | ||||
| 409 | errno(* __error())); | ||||
| 410 | forkflag = 0; | ||||
| 411 | } | ||||
| 412 | } | ||||
| 413 | |||||
| 414 | /* create pipe for notifying child when to close */ | ||||
| 415 | if (forkflag) { | ||||
| 416 | rc = pipe(ctlpipe); | ||||
| 417 | if (rc < 0) { | ||||
| 418 | close(pipefd[0]); | ||||
| 419 | close(pipefd[1]); | ||||
| 420 | printf("butm: Cannot create pipe for CLOSE process. Error %d\n", | ||||
| 421 | errno(* __error())); | ||||
| 422 | forkflag = 0; | ||||
| 423 | } | ||||
| 424 | } | ||||
| 425 | |||||
| 426 | if (forkflag) { | ||||
| 427 | pid = fork(); | ||||
| 428 | if (pid < 0) { | ||||
| 429 | close(pipefd[0]); | ||||
| 430 | close(pipefd[1]); | ||||
| 431 | close(ctlpipe[0]); | ||||
| 432 | close(ctlpipe[1]); | ||||
| 433 | printf("butm: Cannot create CLOSE child process. Error %d\n", | ||||
| 434 | errno(* __error())); | ||||
| 435 | forkflag = 0; | ||||
| 436 | } | ||||
| 437 | } | ||||
| 438 | |||||
| 439 | if (!forkflag) { /* problem starting child process */ | ||||
| 440 | close_rc = USD_CLOSE(fd)((*(fd)->close)(fd)); | ||||
| 441 | parent_close_rc = close_rc; | ||||
| 442 | } else if (pid == 0) { /* child process */ | ||||
| 443 | /* close all unneccessary file descriptors */ | ||||
| 444 | /* note: as painful as it is, we have to reach under the covers of | ||||
| 445 | * the usd package to implement this functionality. | ||||
| 446 | */ | ||||
| 447 | unixfd = (intptr_t)(fd->handle); | ||||
| 448 | |||||
| 449 | for (i = 3; i < _POSIX_OPEN_MAX20; i++) { | ||||
| 450 | if (i != unixfd && i != ctlpipe[0] && i != pipefd[1]) { | ||||
| 451 | close(i); | ||||
| 452 | } | ||||
| 453 | } | ||||
| 454 | |||||
| 455 | /* the parent writes the control pipe after it closes the device */ | ||||
| 456 | read(ctlpipe[0], &close_rc, sizeof(int)); | ||||
| 457 | close(ctlpipe[0]); | ||||
| 458 | |||||
| 459 | /* do the close */ | ||||
| 460 | close_rc = USD_CLOSE(fd)((*(fd)->close)(fd)); | ||||
| 461 | |||||
| 462 | /* send the return code back to the parent */ | ||||
| 463 | write(pipefd[1], &close_rc, sizeof(int)); | ||||
| 464 | |||||
| 465 | exit(0); | ||||
| 466 | } else { /* parent process */ | ||||
| 467 | |||||
| 468 | close(pipefd[1]); | ||||
| 469 | close(ctlpipe[0]); | ||||
| 470 | |||||
| 471 | POLL()IOMGR_Poll(); | ||||
| 472 | /* | ||||
| 473 | * close the device, this should have no effect as long as the | ||||
| 474 | * child has not closed | ||||
| 475 | */ | ||||
| 476 | |||||
| 477 | parent_close_rc = USD_CLOSE(fd)((*(fd)->close)(fd)); | ||||
| 478 | |||||
| 479 | /* notify the child to do its close */ | ||||
| 480 | rc = write(ctlpipe[1], &close_rc, sizeof(int)); /* just send garbage */ | ||||
| 481 | if (rc != sizeof(int)) { | ||||
| 482 | printf("butm: Error communicating with CLOSE process. Error %d\n", | ||||
| 483 | errno(* __error())); | ||||
| 484 | } | ||||
| 485 | close(ctlpipe[1]); | ||||
| 486 | |||||
| 487 | /* read the result from the child process */ | ||||
| 488 | rc = read(pipefd[0], &close_rc, sizeof(int)); | ||||
| 489 | if (rc != sizeof(int)) { | ||||
| 490 | /* logging is enough, since we wrote a file mark the */ | ||||
| 491 | /* return code from the close doesn't really matter */ | ||||
| 492 | printf("butm: No response from CLOSE process. Error %d\n", | ||||
| 493 | errno(* __error())); | ||||
| 494 | close_rc = 0; | ||||
| 495 | } | ||||
| 496 | |||||
| 497 | close(pipefd[0]); | ||||
| 498 | |||||
| 499 | /* get the completion status from the child process */ | ||||
| 500 | rc = waitpid(pid, &status, 0); | ||||
| 501 | while (rc < 0 && errno(* __error()) == EINTR4) { | ||||
| 502 | rc = waitpid(pid, &status, 0); | ||||
| 503 | } | ||||
| 504 | if (rc < 0) { | ||||
| 505 | printf("butm: Cannot get status of CLOSE process. Error %d\n", | ||||
| 506 | errno(* __error())); | ||||
| 507 | } else if (status != 0) { | ||||
| 508 | printf | ||||
| 509 | ("butm: Unexpected exit status 0x%04x from CLOSE process. Error %d\n", | ||||
| 510 | status, errno(* __error())); | ||||
| 511 | } | ||||
| 512 | |||||
| 513 | /* if either process received an error, then return an error */ | ||||
| 514 | if (parent_close_rc < 0) { | ||||
| 515 | close_rc = parent_close_rc; | ||||
| 516 | } | ||||
| 517 | SLEEP(1)IOMGR_Sleep(1); | ||||
| 518 | } | ||||
| 519 | |||||
| 520 | return (close_rc); | ||||
| 521 | } | ||||
| 522 | #else | ||||
| 523 | /* NT version of function */ | ||||
| 524 | |||||
| 525 | static int | ||||
| 526 | ForkClose(usd_handle_t fd) | ||||
| 527 | { | ||||
| 528 | return (USD_CLOSE(fd)((*(fd)->close)(fd))); | ||||
| 529 | } | ||||
| 530 | #endif /* AFS_NT40_ENV */ | ||||
| 531 | |||||
| 532 | /* Forward space file */ | ||||
| 533 | static int | ||||
| 534 | ForwardSpace(usd_handle_t fid, int count) | ||||
| 535 | { | ||||
| 536 | POLL()IOMGR_Poll(); | ||||
| 537 | |||||
| 538 | if (isafile) { | ||||
| 539 | return (0); | ||||
| 540 | } else { | ||||
| 541 | return (ForkIoctl(fid, USDTAPE_FSF2, count)); | ||||
| 542 | } | ||||
| 543 | } | ||||
| 544 | |||||
| 545 | /* Backward space file */ | ||||
| 546 | static int | ||||
| 547 | BackwardSpace(usd_handle_t fid, int count) | ||||
| 548 | { | ||||
| 549 | POLL()IOMGR_Poll(); | ||||
| 550 | |||||
| 551 | if (isafile) { | ||||
| 552 | return (0); | ||||
| 553 | } else { | ||||
| 554 | return (ForkIoctl(fid, USDTAPE_BSF3, count)); | ||||
| 555 | } | ||||
| 556 | } | ||||
| 557 | |||||
| 558 | /* write end of file mark */ | ||||
| 559 | static int | ||||
| 560 | WriteEOF(usd_handle_t fid, int count) | ||||
| 561 | { | ||||
| 562 | POLL()IOMGR_Poll(); | ||||
| 563 | |||||
| 564 | if (isafile) { | ||||
| 565 | return (0); | ||||
| 566 | } else { | ||||
| 567 | return (ForkIoctl(fid, USDTAPE_WEOF0, count)); | ||||
| 568 | } | ||||
| 569 | } | ||||
| 570 | |||||
| 571 | /* rewind tape */ | ||||
| 572 | static int | ||||
| 573 | Rewind(usd_handle_t fid) | ||||
| 574 | { | ||||
| 575 | if (isafile) { | ||||
| 576 | afs_int64 stopOff; | ||||
| 577 | |||||
| 578 | return (USD_SEEK(fid, 0, SEEK_SET, &stopOff)((*(fid)->seek)(fid, 0, 0, &stopOff))); | ||||
| 579 | } else { | ||||
| 580 | return (ForkIoctl(fid, USDTAPE_REW1, 0)); | ||||
| 581 | } | ||||
| 582 | } | ||||
| 583 | |||||
| 584 | /* prepare tape drive for access */ | ||||
| 585 | static int | ||||
| 586 | PrepareAccess(usd_handle_t fid) | ||||
| 587 | { | ||||
| 588 | int code = 0; | ||||
| 589 | #ifdef AFS_NT40_ENV | ||||
| 590 | if (!isafile) { | ||||
| 591 | (void)ForkIoctl(fid, USDTAPE_PREPARE4, 0); | ||||
| 592 | } | ||||
| 593 | /* NT won't rewind tape when it is opened */ | ||||
| 594 | code = Rewind(fid); | ||||
| 595 | #endif /* AFS_NT40_ENV */ | ||||
| 596 | return code; | ||||
| 597 | } | ||||
| 598 | |||||
| 599 | /* decommission tape drive after all accesses complete */ | ||||
| 600 | static int | ||||
| 601 | ShutdownAccess(usd_handle_t fid) | ||||
| 602 | { | ||||
| 603 | #ifdef AFS_NT40_ENV | ||||
| 604 | if (!isafile) { | ||||
| 605 | (void)ForkIoctl(fid, USDTAPE_SHUTDOWN5, 0); | ||||
| 606 | } | ||||
| 607 | #endif /* AFS_NT40_ENV */ | ||||
| 608 | return 0; | ||||
| 609 | } | ||||
| 610 | |||||
| 611 | /* -------------------- USD Interface Functions End ----------------------- */ | ||||
| 612 | |||||
| 613 | /* ===================================================================== | ||||
| 614 | * Support routines | ||||
| 615 | * ===================================================================== */ | ||||
| 616 | |||||
| 617 | /* incSize | ||||
| 618 | * add the supplied no. of bytes to the byte count of information placed | ||||
| 619 | * on the tape. | ||||
| 620 | * entry: | ||||
| 621 | * dataSize - bytes used on the tape | ||||
| 622 | */ | ||||
| 623 | |||||
| 624 | void | ||||
| 625 | incSize(struct butm_tapeInfo *info, afs_uint32 dataSize) | ||||
| 626 | { | ||||
| 627 | info->nBytes += dataSize; | ||||
| 628 | info->kBytes += (info->nBytes / 1024); | ||||
| 629 | info->nBytes %= 1024; | ||||
| 630 | } | ||||
| 631 | |||||
| 632 | /* incPosition | ||||
| 633 | * IF YOU ADD/CHANGE THE ifdefs, BE SURE | ||||
| 634 | * TO ALSO MAKE THE SAME CHANGES IN bu_utils/fms.c. | ||||
| 635 | * | ||||
| 636 | * add the supplied no. of bytes to the byte count of data placed | ||||
| 637 | * on the tape. Also check for reaching 2GB limit and reset the | ||||
| 638 | * pointer if necessary. This allows us to use >2GB tapes. | ||||
| 639 | * entry: | ||||
| 640 | * fid - file id for the tape. | ||||
| 641 | * dataSize - bytes used on the tape | ||||
| 642 | */ | ||||
| 643 | |||||
| 644 | void | ||||
| 645 | incPosition(struct butm_tapeInfo *info, usd_handle_t fid, afs_uint32 dataSize) | ||||
| 646 | { | ||||
| 647 | /* Add this to the amount of data written to the tape */ | ||||
| 648 | incSize(info, dataSize); | ||||
| 649 | |||||
| 650 | info->posCount += dataSize; | ||||
| 651 | |||||
| 652 | if (info->posCount >= 2147467264) { /* 2GB - 16K */ | ||||
| 653 | info->posCount = 0; | ||||
| 654 | #if (defined(AFS_SUN_ENV) || defined(AFS_LINUX24_ENV)) | ||||
| 655 | if (!isafile) { | ||||
| 656 | afs_int64 off; | ||||
| 657 | |||||
| 658 | off = 0; | ||||
| 659 | USD_IOCTL(fid, USD_IOCTL_SETSIZE, &off)((*(fid)->ioctl)(fid, 7, &off)); | ||||
| 660 | } | ||||
| 661 | #endif | ||||
| 662 | } | ||||
| 663 | } | ||||
| 664 | |||||
| 665 | /* | ||||
| 666 | * This accounts for tape drives with a block size different from variable or 16K | ||||
| 667 | * blocks and only reads that block size. | ||||
| 668 | */ | ||||
| 669 | afs_int32 TapeBlockSize; | ||||
| 670 | afs_int32 | ||||
| 671 | readData(usd_handle_t fid, char *data, afs_uint32 totalSize, afs_int32 *errorP) | ||||
| 672 | { | ||||
| 673 | afs_int32 toread; /* Number of bytes to read */ | ||||
| 674 | afs_uint32 rSize; /* Total bytes read so far */ | ||||
| 675 | afs_uint32 tSize; /* Temporary size */ | ||||
| 676 | afs_int32 rc; /* return code */ | ||||
| 677 | |||||
| 678 | toread = totalSize; /* First, try to read all the data */ | ||||
| 679 | |||||
| 680 | rc = USD_READ(fid, &data[0], toread, &rSize)((*(fid)->read)(fid, &data[0], toread, &rSize)); | ||||
| 681 | if (rc != 0) { | ||||
| 682 | *errorP = rc; | ||||
| 683 | return -1; | ||||
| 684 | } | ||||
| 685 | if (rSize == 0) /* reached EOF */ | ||||
| 686 | return rSize; | ||||
| 687 | |||||
| 688 | if (rSize != TapeBlockSize) { /* Tape block size has changed */ | ||||
| 689 | TapeBlockSize = rSize; | ||||
| 690 | printf("Tape blocks read in %d Byte chunks.\n", TapeBlockSize); | ||||
| 691 | } | ||||
| 692 | |||||
| 693 | /* Read the rest of the data in */ | ||||
| 694 | while (rSize < totalSize) { | ||||
| 695 | toread = | ||||
| 696 | ((totalSize - rSize) < | ||||
| 697 | TapeBlockSize ? (totalSize - rSize) : TapeBlockSize); | ||||
| 698 | rc = USD_READ(fid, &data[rSize], toread, &tSize)((*(fid)->read)(fid, &data[rSize], toread, &tSize) ); | ||||
| 699 | if (rc) | ||||
| 700 | *errorP = rc; | ||||
| 701 | else | ||||
| 702 | rSize += tSize; | ||||
| 703 | if (tSize != toread) | ||||
| 704 | break; | ||||
| 705 | } | ||||
| 706 | |||||
| 707 | if (rSize > totalSize) | ||||
| 708 | printf("readData - Read > 16K data block - continuing.\n"); | ||||
| 709 | |||||
| 710 | return (rSize); | ||||
| 711 | } | ||||
| 712 | |||||
| 713 | afs_int32 | ||||
| 714 | SeekFile(struct butm_tapeInfo *info, int count) | ||||
| 715 | { | ||||
| 716 | afs_int32 code = 0; | ||||
| 717 | struct progress *p; | ||||
| 718 | afs_int32 error = 0; | ||||
| 719 | |||||
| 720 | if (count == 0) | ||||
| 721 | ERROR_EXIT(0)do { code = 0; goto error_exit; } while (0); | ||||
| 722 | p = (struct progress *)info->tmRock; | ||||
| 723 | |||||
| 724 | if (isafile) { /* no reason for seeking through a file */ | ||||
| 725 | p->reading = p->writing = 0; | ||||
| 726 | return (0); | ||||
| 727 | } | ||||
| 728 | |||||
| 729 | POLL()IOMGR_Poll(); | ||||
| 730 | |||||
| 731 | if (count > 0) | ||||
| 732 | error = ForwardSpace(p->fid, count); | ||||
| 733 | else | ||||
| 734 | error = BackwardSpace(p->fid, -count); | ||||
| 735 | |||||
| 736 | POLL()IOMGR_Poll(); | ||||
| 737 | |||||
| 738 | if (error) { | ||||
| 739 | info->status |= BUTM_STATUS_SEEKERROR(1<<4); | ||||
| 740 | ERROR_EXIT(BUTM_IOCTL)do { code = (156568848L); goto error_exit; } while (0); | ||||
| 741 | } | ||||
| 742 | |||||
| 743 | info->position += count; | ||||
| 744 | incSize(info, (count * config.fileMarkSize)); | ||||
| 745 | p = (struct progress *)info->tmRock; | ||||
| 746 | p->reading = p->writing = 0; | ||||
| 747 | |||||
| 748 | error_exit: | ||||
| 749 | if (error) | ||||
| 750 | info->error = error; | ||||
| 751 | return (code); | ||||
| 752 | } | ||||
| 753 | |||||
| 754 | /* Step to the next filemark if we are not at one already */ | ||||
| 755 | afs_int32 | ||||
| 756 | NextFile(struct butm_tapeInfo *info) | ||||
| 757 | { | ||||
| 758 | afs_int32 code; | ||||
| 759 | |||||
| 760 | if (!READS(((struct progress *)(info->tmRock))->reading) && !WRITES(((struct progress *)(info->tmRock))->writing)) | ||||
| 761 | return 0; | ||||
| 762 | |||||
| 763 | code = SeekFile(info, 1); | ||||
| 764 | return (code); | ||||
| 765 | } | ||||
| 766 | |||||
| 767 | static afs_int32 | ||||
| 768 | WriteTapeBlock(struct butm_tapeInfo *info, | ||||
| 769 | char *buffer, /* assumed to be 16384 bytes with data in it */ | ||||
| 770 | afs_int32 length, /* amount data in buffer */ | ||||
| 771 | afs_int32 blockType) | ||||
| 772 | { | ||||
| 773 | afs_int32 code = 0, rc = 0; | ||||
| 774 | afs_uint32 wsize; | ||||
| 775 | struct tapeLabel *label; | ||||
| 776 | struct fileMark *fmark; | ||||
| 777 | struct blockMark *bmark; | ||||
| 778 | struct progress *p; | ||||
| 779 | afs_int32 error = 0; | ||||
| 780 | |||||
| 781 | p = (struct progress *)info->tmRock; | ||||
| 782 | |||||
| 783 | if (blockType == BLOCK_DATA2) { /* Data Block */ | ||||
| 784 | if (length == 0) | ||||
| 785 | ERROR_EXIT(0)do { code = 0; goto error_exit; } while (0); | ||||
| 786 | bmark = (struct blockMark *)buffer; | ||||
| 787 | memset(bmark, 0, sizeof(struct blockMark)); | ||||
| 788 | bmark->magic = htonl(BLOCK_MAGIC)(__builtin_constant_p(1100000005) ? ((((__uint32_t)(1100000005 )) >> 24) | ((((__uint32_t)(1100000005)) & (0xff << 16)) >> 8) | ((((__uint32_t)(1100000005)) & (0xff << 8)) << 8) | (((__uint32_t)(1100000005)) << 24)) : __bswap32_var(1100000005)); | ||||
| 789 | bmark->count = htonl(length)(__builtin_constant_p(length) ? ((((__uint32_t)(length)) >> 24) | ((((__uint32_t)(length)) & (0xff << 16)) >> 8) | ((((__uint32_t)(length)) & (0xff << 8)) << 8) | (((__uint32_t)(length)) << 24)) : __bswap32_var(length )); | ||||
| 790 | } else if (blockType == BLOCK_FMBEGIN1) { /* Filemark - begin */ | ||||
| 791 | fmark = (struct fileMark *)buffer; | ||||
| 792 | fmark->magic = htonl(FILE_MAGIC)(__builtin_constant_p(1000000007) ? ((((__uint32_t)(1000000007 )) >> 24) | ((((__uint32_t)(1000000007)) & (0xff << 16)) >> 8) | ((((__uint32_t)(1000000007)) & (0xff << 8)) << 8) | (((__uint32_t)(1000000007)) << 24)) : __bswap32_var(1000000007)); | ||||
| 793 | fmark->nBytes = htonl(FILE_BEGIN)(__builtin_constant_p(0) ? ((((__uint32_t)(0)) >> 24) | ((((__uint32_t)(0)) & (0xff << 16)) >> 8) | ( (((__uint32_t)(0)) & (0xff << 8)) << 8) | ((( __uint32_t)(0)) << 24)) : __bswap32_var(0)); | ||||
| 794 | } else if (blockType == BLOCK_FMEND3) { /* Filemark - end */ | ||||
| 795 | fmark = (struct fileMark *)buffer; | ||||
| 796 | fmark->magic = htonl(FILE_MAGIC)(__builtin_constant_p(1000000007) ? ((((__uint32_t)(1000000007 )) >> 24) | ((((__uint32_t)(1000000007)) & (0xff << 16)) >> 8) | ((((__uint32_t)(1000000007)) & (0xff << 8)) << 8) | (((__uint32_t)(1000000007)) << 24)) : __bswap32_var(1000000007)); | ||||
| 797 | fmark->nBytes = htonl(FILE_FMEND)(__builtin_constant_p(1) ? ((((__uint32_t)(1)) >> 24) | ((((__uint32_t)(1)) & (0xff << 16)) >> 8) | ( (((__uint32_t)(1)) & (0xff << 8)) << 8) | ((( __uint32_t)(1)) << 24)) : __bswap32_var(1)); | ||||
| 798 | } else if (blockType == BLOCK_LABEL0) { /* Label */ | ||||
| 799 | label = (struct tapeLabel *)buffer; | ||||
| 800 | label->magic = htonl(TAPE_MAGIC)(__builtin_constant_p(1100000009) ? ((((__uint32_t)(1100000009 )) >> 24) | ((((__uint32_t)(1100000009)) & (0xff << 16)) >> 8) | ((((__uint32_t)(1100000009)) & (0xff << 8)) << 8) | (((__uint32_t)(1100000009)) << 24)) : __bswap32_var(1100000009)); | ||||
| 801 | } else if (blockType == BLOCK_EOD4) { /* Filemark - EOD mark */ | ||||
| 802 | fmark = (struct fileMark *)buffer; | ||||
| 803 | fmark->magic = htonl(FILE_MAGIC)(__builtin_constant_p(1000000007) ? ((((__uint32_t)(1000000007 )) >> 24) | ((((__uint32_t)(1000000007)) & (0xff << 16)) >> 8) | ((((__uint32_t)(1000000007)) & (0xff << 8)) << 8) | (((__uint32_t)(1000000007)) << 24)) : __bswap32_var(1000000007)); | ||||
| 804 | fmark->nBytes = htonl(FILE_EOD)(__builtin_constant_p(-1) ? ((((__uint32_t)(-1)) >> 24) | ((((__uint32_t)(-1)) & (0xff << 16)) >> 8) | ((((__uint32_t)(-1)) & (0xff << 8)) << 8) | (((__uint32_t)(-1)) << 24)) : __bswap32_var(-1)); | ||||
| 805 | } | ||||
| 806 | |||||
| 807 | /* Write the tape block */ | ||||
| 808 | /* -------------------- */ | ||||
| 809 | rc = USD_WRITE(p->fid, buffer, BUTM_BLOCKSIZE, &wsize)((*(p->fid)->write)(p->fid, buffer, 16384, &wsize )); | ||||
| 810 | if ((rc == 0) && (wsize > 0)) { | ||||
| 811 | incPosition(info, p->fid, wsize); /* record whats written */ | ||||
| 812 | p->writing++; | ||||
| 813 | } | ||||
| 814 | |||||
| 815 | if (wsize != BUTM_BLOCKSIZE16384) { | ||||
| 816 | info->status |= BUTM_STATUS_WRITEERROR(1<<2); | ||||
| 817 | if (rc != 0) { | ||||
| 818 | error = rc; | ||||
| 819 | ERROR_EXIT(BUTM_IO)do { code = (156568837L); goto error_exit; } while (0); | ||||
| 820 | } else | ||||
| 821 | ERROR_EXIT(BUTM_EOT)do { code = (156568842L); goto error_exit; } while (0); | ||||
| 822 | } | ||||
| 823 | if (isafile) | ||||
| 824 | info->position++; | ||||
| 825 | |||||
| 826 | /* Write trailing EOF marker for some block types */ | ||||
| 827 | /* ---------------------------------------------- */ | ||||
| 828 | if ((blockType == BLOCK_FMEND3) || (blockType == BLOCK_LABEL0) | ||||
| 829 | || (blockType == BLOCK_EOD4)) { | ||||
| 830 | |||||
| 831 | POLL()IOMGR_Poll(); | ||||
| 832 | error = WriteEOF(p->fid, 1); | ||||
| 833 | POLL()IOMGR_Poll(); | ||||
| 834 | if (error) { | ||||
| 835 | info->status |= BUTM_STATUS_WRITEERROR(1<<2); | ||||
| 836 | ERROR_EXIT(BUTM_IOCTL)do { code = (156568848L); goto error_exit; } while (0); | ||||
| 837 | } | ||||
| 838 | |||||
| 839 | incSize(info, config.fileMarkSize); | ||||
| 840 | if (!isafile) | ||||
| 841 | info->position++; | ||||
| 842 | p->writing = 0; | ||||
| 843 | } | ||||
| 844 | |||||
| 845 | error_exit: | ||||
| 846 | if (error) | ||||
| 847 | info->error = error; | ||||
| 848 | return (code); | ||||
| 849 | } | ||||
| 850 | |||||
| 851 | static afs_int32 | ||||
| 852 | ReadTapeBlock(struct butm_tapeInfo *info, | ||||
| 853 | char *buffer, /* assumed to be 16384 bytes */ | ||||
| 854 | afs_int32 *blockType) | ||||
| 855 | { | ||||
| 856 | afs_int32 code = 0; | ||||
| 857 | afs_int32 rsize, fmtype; | ||||
| 858 | struct tapeLabel *label; | ||||
| 859 | struct fileMark *fmark; | ||||
| 860 | struct blockMark *bmark; | ||||
| 861 | struct progress *p; | ||||
| 862 | |||||
| 863 | *blockType = BLOCK_UNKNOWN6; | ||||
| 864 | |||||
| 865 | p = (struct progress *)info->tmRock; | ||||
| 866 | |||||
| 867 | memset(buffer, 0, BUTM_BLOCKSIZE16384); | ||||
| 868 | label = (struct tapeLabel *)buffer; | ||||
| 869 | fmark = (struct fileMark *)buffer; | ||||
| 870 | bmark = (struct blockMark *)buffer; | ||||
| 871 | |||||
| 872 | rsize = readData(p->fid, buffer, BUTM_BLOCKSIZE16384, &info->error); | ||||
| 873 | if (rsize > 0) { | ||||
| 874 | incPosition(info, p->fid, rsize); | ||||
| 875 | p->reading++; | ||||
| 876 | } | ||||
| 877 | |||||
| 878 | if (rsize == 0) { /* Read a HW EOF Marker? OK */ | ||||
| 879 | *blockType = BLOCK_EOF5; | ||||
| 880 | incSize(info, config.fileMarkSize); /* Size of filemark */ | ||||
| 881 | if (!isafile) | ||||
| 882 | info->position++; /* bump position */ | ||||
| 883 | p->reading = 0; /* No reads since EOF */ | ||||
| 884 | } | ||||
| 885 | |||||
| 886 | else if (rsize != BUTM_BLOCKSIZE16384) { /* Didn't Read a full block */ | ||||
| 887 | info->status |= BUTM_STATUS_READERROR(1<<3); | ||||
| 888 | ERROR_EXIT((rsize < 0) ? BUTM_IO : BUTM_EOT)do { code = (rsize < 0) ? (156568837L) : (156568842L); goto error_exit; } while (0); | ||||
| 889 | } | ||||
| 890 | |||||
| 891 | else if (ntohl(bmark->magic)(__builtin_constant_p(bmark->magic) ? ((((__uint32_t)(bmark ->magic)) >> 24) | ((((__uint32_t)(bmark->magic)) & (0xff << 16)) >> 8) | ((((__uint32_t)(bmark ->magic)) & (0xff << 8)) << 8) | (((__uint32_t )(bmark->magic)) << 24)) : __bswap32_var(bmark->magic )) == BLOCK_MAGIC1100000005) { /* Data block? */ | ||||
| 892 | *blockType = BLOCK_DATA2; | ||||
| 893 | } | ||||
| 894 | |||||
| 895 | else if (ntohl(fmark->magic)(__builtin_constant_p(fmark->magic) ? ((((__uint32_t)(fmark ->magic)) >> 24) | ((((__uint32_t)(fmark->magic)) & (0xff << 16)) >> 8) | ((((__uint32_t)(fmark ->magic)) & (0xff << 8)) << 8) | (((__uint32_t )(fmark->magic)) << 24)) : __bswap32_var(fmark->magic )) == FILE_MAGIC1000000007) { /* Read a filemark? */ | ||||
| 896 | fmtype = ntohl(fmark->nBytes)(__builtin_constant_p(fmark->nBytes) ? ((((__uint32_t)(fmark ->nBytes)) >> 24) | ((((__uint32_t)(fmark->nBytes )) & (0xff << 16)) >> 8) | ((((__uint32_t)(fmark ->nBytes)) & (0xff << 8)) << 8) | (((__uint32_t )(fmark->nBytes)) << 24)) : __bswap32_var(fmark-> nBytes)); | ||||
| 897 | |||||
| 898 | if (fmtype == FILE_BEGIN0) { /* filemark begin */ | ||||
| 899 | *blockType = BLOCK_FMBEGIN1; | ||||
| 900 | } else if (fmtype == FILE_FMEND1) { /* filemark end */ | ||||
| 901 | *blockType = BLOCK_FMEND3; | ||||
| 902 | code = SeekFile(info, 1); | ||||
| 903 | } else if (fmtype == FILE_EOD-1) { /* EOD mark */ | ||||
| 904 | *blockType = BLOCK_EOD4; | ||||
| 905 | info->status |= BUTM_STATUS_EOD(1<<6); | ||||
| 906 | code = SeekFile(info, 1); | ||||
| 907 | } | ||||
| 908 | } | ||||
| 909 | |||||
| 910 | else if (ntohl(label->magic)(__builtin_constant_p(label->magic) ? ((((__uint32_t)(label ->magic)) >> 24) | ((((__uint32_t)(label->magic)) & (0xff << 16)) >> 8) | ((((__uint32_t)(label ->magic)) & (0xff << 8)) << 8) | (((__uint32_t )(label->magic)) << 24)) : __bswap32_var(label->magic )) == TAPE_MAGIC1100000009) { /* Read a tape label? */ | ||||
| 911 | *blockType = BLOCK_LABEL0; | ||||
| 912 | code = SeekFile(info, 1); | ||||
| 913 | } | ||||
| 914 | |||||
| 915 | if (isafile) | ||||
| 916 | info->position++; | ||||
| 917 | |||||
| 918 | error_exit: | ||||
| 919 | return (code); | ||||
| 920 | } | ||||
| 921 | |||||
| 922 | /* check | ||||
| 923 | * check version numbers and permissions in the info structure | ||||
| 924 | */ | ||||
| 925 | |||||
| 926 | static afs_int32 | ||||
| 927 | check(struct butm_tapeInfo *info, | ||||
| 928 | int write) /* write operation requested */ | ||||
| 929 | { | ||||
| 930 | struct progress *p; | ||||
| 931 | |||||
| 932 | if (!info) | ||||
| 933 | return (BUTM_BADARGUMENT(156568844L)); | ||||
| 934 | |||||
| 935 | /* Check version number in info structure */ | ||||
| 936 | if (info->structVersion != BUTM_MAJORVERSION2) | ||||
| 937 | return BUTM_OLDINTERFACE(156568832L); | ||||
| 938 | |||||
| 939 | /* Check if a tape is mounted */ | ||||
| 940 | if (((p = (struct progress *)info->tmRock) == 0) || (p->fid == 0)) | ||||
| 941 | return BUTM_NOMOUNT(156568833L); | ||||
| 942 | |||||
| 943 | /* If writing check if there is write access */ | ||||
| 944 | if (write && (info->flags & BUTM_FLAGS_READONLY(1<<0))) | ||||
| 945 | return BUTM_READONLY(156568838L); | ||||
| 946 | |||||
| 947 | return 0; | ||||
| 948 | } | ||||
| 949 | |||||
| 950 | static afs_int32 | ||||
| 951 | rewindFile(struct butm_tapeInfo *info) | ||||
| 952 | { | ||||
| 953 | struct progress *p; | ||||
| 954 | afs_int32 code = 0; | ||||
| 955 | afs_int32 error; | ||||
| 956 | |||||
| 957 | p = (struct progress *)info->tmRock; | ||||
| 958 | |||||
| 959 | POLL()IOMGR_Poll(); | ||||
| 960 | |||||
| 961 | error = Rewind(p->fid); | ||||
| 962 | |||||
| 963 | POLL()IOMGR_Poll(); | ||||
| 964 | |||||
| 965 | if (error) { | ||||
| 966 | info->status |= BUTM_STATUS_SEEKERROR(1<<4); | ||||
| 967 | ERROR_EXIT(BUTM_IOCTL)do { code = (156568848L); goto error_exit; } while (0); | ||||
| 968 | } | ||||
| 969 | |||||
| 970 | info->position = (isafile ? 0 : 1); | ||||
| 971 | info->kBytes = info->nBytes = 0; | ||||
| 972 | info->nFiles = info->nRecords = 0; | ||||
| 973 | p->reading = p->writing = 0; | ||||
| 974 | |||||
| 975 | error_exit: | ||||
| 976 | if (error) | ||||
| 977 | info->error = error; | ||||
| 978 | return (code); | ||||
| 979 | } | ||||
| 980 | |||||
| 981 | /* ===================================================================== | ||||
| 982 | * butm routines | ||||
| 983 | * ===================================================================== */ | ||||
| 984 | |||||
| 985 | static afs_int32 | ||||
| 986 | file_Mount(struct butm_tapeInfo *info, char *tape) | ||||
| 987 | { | ||||
| 988 | struct progress *p; | ||||
| 989 | char filename[64]; | ||||
| 990 | usd_handle_t fid; | ||||
| 991 | int xflags; | ||||
| 992 | afs_int32 code = 0, error = 0, rc = 0; | ||||
| 993 | |||||
| 994 | if (info->debug) | ||||
| 995 | printf("butm: Mount tape drive\n"); | ||||
| 996 | |||||
| 997 | POLL()IOMGR_Poll(); | ||||
| 998 | info->error = 0; | ||||
| 999 | |||||
| 1000 | if (!info || !tape) | ||||
| 1001 | ERROR_EXIT(BUTM_BADARGUMENT)do { code = (156568844L); goto error_exit; } while (0); | ||||
| 1002 | if (info->structVersion != BUTM_MAJORVERSION2) | ||||
| 1003 | ERROR_EXIT(BUTM_OLDINTERFACE)do { code = (156568832L); goto error_exit; } while (0); | ||||
| 1004 | if (info->tmRock) | ||||
| 1005 | ERROR_EXIT(BUTM_PARALLELMOUNTS)do { code = (156568834L); goto error_exit; } while (0); | ||||
| 1006 | if (strlen(tape) >= sizeof(info->name)) | ||||
| 1007 | ERROR_EXIT(BUTM_BADARGUMENT)do { code = (156568844L); goto error_exit; } while (0); | ||||
| 1008 | |||||
| 1009 | strcpy(info->name, tape); | ||||
| 1010 | |||||
| 1011 | strcpy(filename, config.tapedir); /* the name of the tape device */ | ||||
| 1012 | info->position = (isafile ? 0 : 1); | ||||
| 1013 | info->kBytes = info->nBytes = 0; | ||||
| 1014 | info->nRecords = info->nFiles = 0; | ||||
| 1015 | info->recordSize = 0; | ||||
| 1016 | info->tapeSize = config.tapeSize; | ||||
| 1017 | info->coefBytes = 1; | ||||
| 1018 | info->coefRecords = 0; | ||||
| 1019 | info->coefFiles = sizeof(struct fileMark); | ||||
| 1020 | info->simultaneousTapes = 1; | ||||
| 1021 | info->status = 0; | ||||
| 1022 | info->error = 0; | ||||
| 1023 | info->flags = BUTM_FLAGS_SEQUENTIAL(1<<1); | ||||
| 1024 | |||||
| 1025 | xflags = 0; | ||||
| 1026 | if (isafile) { | ||||
| 1027 | xflags |= USD_OPEN_CREATE0x10; | ||||
| 1028 | } else { | ||||
| 1029 | /* | ||||
| 1030 | * try to open in a child process first so nothing will | ||||
| 1031 | * time out should the process block because the device | ||||
| 1032 | * isn't ready. | ||||
| 1033 | */ | ||||
| 1034 | |||||
| 1035 | if (ForkOpen(filename)) { | ||||
| 1036 | ERROR_EXIT(BUTM_MOUNTFAIL)do { code = (156568835L); goto error_exit; } while (0); | ||||
| 1037 | } | ||||
| 1038 | } | ||||
| 1039 | |||||
| 1040 | /* Now go ahead and open the tape drive for real */ | ||||
| 1041 | rc = usd_Open(filename, (USD_OPEN_RDWR1 | USD_OPEN_WLOCK8 | xflags), 0777, | ||||
| 1042 | &fid); | ||||
| 1043 | if (rc != 0) { /* try for lesser access */ | ||||
| 1044 | rc = usd_Open(filename, (USD_OPEN_RDONLY0 | USD_OPEN_RLOCK4), 0, &fid); | ||||
| 1045 | |||||
| 1046 | if (rc) { | ||||
| 1047 | error = rc; | ||||
| 1048 | ERROR_EXIT(BUTM_MOUNTFAIL)do { code = (156568835L); goto error_exit; } while (0); | ||||
| 1049 | } | ||||
| 1050 | info->flags |= BUTM_FLAGS_READONLY(1<<0); | ||||
| 1051 | } | ||||
| 1052 | |||||
| 1053 | (void)PrepareAccess(fid); /* for NT */ | ||||
| 1054 | |||||
| 1055 | p = (struct progress *)malloc(sizeof(*p)); | ||||
| 1056 | info->tmRock = (char *)p; | ||||
| 1057 | p->fid = fid; | ||||
| 1058 | p->mountId = config.mountId = time(0); | ||||
| 1059 | p->reading = p->writing = 0; | ||||
| 1060 | |||||
| 1061 | TapeBlockSize = BUTM_BLOCKSIZE16384; /* Initialize */ | ||||
| 1062 | |||||
| 1063 | error_exit: | ||||
| 1064 | if (error) | ||||
| 1065 | info->error = error; | ||||
| 1066 | return (code); | ||||
| 1067 | } | ||||
| 1068 | |||||
| 1069 | static afs_int32 | ||||
| 1070 | file_Dismount(struct butm_tapeInfo *info) | ||||
| 1071 | { | ||||
| 1072 | struct progress *p; | ||||
| 1073 | afs_int32 code = 0, error = 0; | ||||
| 1074 | |||||
| 1075 | if (info->debug) | ||||
| 1076 | printf("butm: Unmount tape drive\n"); | ||||
| 1077 | |||||
| 1078 | POLL()IOMGR_Poll(); | ||||
| 1079 | info->error = 0; | ||||
| 1080 | |||||
| 1081 | code = check(info, READ_OP0); | ||||
| 1082 | if (code) | ||||
| 1083 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1084 | |||||
| 1085 | p = (struct progress *)info->tmRock; | ||||
| 1086 | |||||
| 1087 | (void)ShutdownAccess(p->fid); /* for NT */ | ||||
| 1088 | |||||
| 1089 | /* close the device */ | ||||
| 1090 | if ((error = ForkClose(p->fid))) { | ||||
| 1091 | printf("butm: Tape close failed. Error %d\n", errno(* __error())); | ||||
| 1092 | } | ||||
| 1093 | |||||
| 1094 | POLL()IOMGR_Poll(); | ||||
| 1095 | |||||
| 1096 | if (error) { | ||||
| 1097 | code = BUTM_DISMOUNTFAIL(156568836L); | ||||
| 1098 | info->status |= BUTM_STATUS_TAPEERROR(1<<1); | ||||
| 1099 | } | ||||
| 1100 | |||||
| 1101 | config.mountId = 0; | ||||
| 1102 | info->tmRock = 0; /* mark it as closed - even if error on close */ | ||||
| 1103 | if (p) | ||||
| 1104 | free(p); | ||||
| 1105 | |||||
| 1106 | error_exit: | ||||
| 1107 | if (error) | ||||
| 1108 | info->error = error; | ||||
| 1109 | return (code); | ||||
| 1110 | } | ||||
| 1111 | |||||
| 1112 | /* file_WriteLabel | ||||
| 1113 | * write the header on a tape | ||||
| 1114 | * entry: | ||||
| 1115 | * info - handle on tape unit | ||||
| 1116 | * label - label information. This label is not copied onto the tape. | ||||
| 1117 | * If supplied, various fields are copied from this label to | ||||
| 1118 | * the actual tape label written on the tape. | ||||
| 1119 | */ | ||||
| 1120 | |||||
| 1121 | static afs_int32 | ||||
| 1122 | file_WriteLabel(struct butm_tapeInfo *info, struct butm_tapeLabel *label, | ||||
| 1123 | afs_int32 rewind) | ||||
| 1124 | { | ||||
| 1125 | afs_int32 code = 0; | ||||
| 1126 | afs_int32 fcode; | ||||
| 1127 | struct tapeLabel *tlabel; | ||||
| 1128 | struct progress *p; | ||||
| 1129 | afs_int64 off; /* offset */ | ||||
| 1130 | |||||
| 1131 | if (info->debug) | ||||
| 1132 | printf("butm: Write tape label\n"); | ||||
| 1133 | |||||
| 1134 | POLL()IOMGR_Poll(); | ||||
| 1135 | info->error = 0; | ||||
| 1136 | |||||
| 1137 | code = check(info, WRITE_OP1); | ||||
| 1138 | if (code) | ||||
| 1139 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1140 | if (!label) | ||||
| 1141 | ERROR_EXIT(BUTM_BADARGUMENT)do { code = (156568844L); goto error_exit; } while (0); | ||||
| 1142 | if (label->structVersion != CUR_TAPE_VERSION4) | ||||
| 1143 | ERROR_EXIT(BUTM_OLDINTERFACE)do { code = (156568832L); goto error_exit; } while (0); | ||||
| 1144 | |||||
| 1145 | if (rewind) { /* Not appending, so rewind */ | ||||
| 1146 | code = rewindFile(info); | ||||
| 1147 | if (code) | ||||
| 1148 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1149 | |||||
| 1150 | if (isafile) { | ||||
| 1151 | p = (struct progress *)info->tmRock; | ||||
| 1152 | off = 0; | ||||
| 1153 | code = USD_IOCTL(p->fid, USD_IOCTL_SETSIZE, &off)((*(p->fid)->ioctl)(p->fid, 7, &off)); | ||||
| 1154 | if (code) | ||||
| 1155 | ERROR_EXIT(BUTM_POSITION)do { code = (156568852L); goto error_exit; } while (0); | ||||
| 1156 | } | ||||
| 1157 | } else { | ||||
| 1158 | if (READS(((struct progress *)(info->tmRock))->reading) || WRITES(((struct progress *)(info->tmRock))->writing)) | ||||
| 1159 | ERROR_EXIT(BUTM_BADOP)do { code = (156568839L); goto error_exit; } while (0); | ||||
| 1160 | } | ||||
| 1161 | |||||
| 1162 | /* Copy the label into the tape block | ||||
| 1163 | * ---------------------------------- */ | ||||
| 1164 | memset(tapeBlock, 0, BUTM_BLOCKSIZE16384); | ||||
| 1165 | |||||
| 1166 | if (!label->creationTime) | ||||
| 1167 | label->creationTime = time(0); | ||||
| 1168 | |||||
| 1169 | tlabel = (struct tapeLabel *)tapeBlock; | ||||
| 1170 | memcpy(&tlabel->label, label, sizeof(struct butm_tapeLabel)); | ||||
| 1171 | tlabel->label.structVersion = htonl(CUR_TAPE_VERSION)(__builtin_constant_p(4) ? ((((__uint32_t)(4)) >> 24) | ((((__uint32_t)(4)) & (0xff << 16)) >> 8) | ( (((__uint32_t)(4)) & (0xff << 8)) << 8) | ((( __uint32_t)(4)) << 24)) : __bswap32_var(4)); | ||||
| 1172 | tlabel->label.creationTime = htonl(tlabel->label.creationTime)(__builtin_constant_p(tlabel->label.creationTime) ? ((((__uint32_t )(tlabel->label.creationTime)) >> 24) | ((((__uint32_t )(tlabel->label.creationTime)) & (0xff << 16)) >> 8) | ((((__uint32_t)(tlabel->label.creationTime)) & ( 0xff << 8)) << 8) | (((__uint32_t)(tlabel->label .creationTime)) << 24)) : __bswap32_var(tlabel->label .creationTime)); | ||||
| 1173 | tlabel->label.expirationDate = htonl(tlabel->label.expirationDate)(__builtin_constant_p(tlabel->label.expirationDate) ? (((( __uint32_t)(tlabel->label.expirationDate)) >> 24) | ( (((__uint32_t)(tlabel->label.expirationDate)) & (0xff << 16)) >> 8) | ((((__uint32_t)(tlabel->label.expirationDate )) & (0xff << 8)) << 8) | (((__uint32_t)(tlabel ->label.expirationDate)) << 24)) : __bswap32_var(tlabel ->label.expirationDate)); | ||||
| 1174 | tlabel->label.size = htonl(tlabel->label.size)(__builtin_constant_p(tlabel->label.size) ? ((((__uint32_t )(tlabel->label.size)) >> 24) | ((((__uint32_t)(tlabel ->label.size)) & (0xff << 16)) >> 8) | ((( (__uint32_t)(tlabel->label.size)) & (0xff << 8)) << 8) | (((__uint32_t)(tlabel->label.size)) << 24)) : __bswap32_var(tlabel->label.size)); | ||||
| 1175 | tlabel->label.useCount = htonl(tlabel->label.useCount)(__builtin_constant_p(tlabel->label.useCount) ? ((((__uint32_t )(tlabel->label.useCount)) >> 24) | ((((__uint32_t)( tlabel->label.useCount)) & (0xff << 16)) >> 8) | ((((__uint32_t)(tlabel->label.useCount)) & (0xff << 8)) << 8) | (((__uint32_t)(tlabel->label.useCount )) << 24)) : __bswap32_var(tlabel->label.useCount)); | ||||
| 1176 | tlabel->label.dumpid = htonl(tlabel->label.dumpid)(__builtin_constant_p(tlabel->label.dumpid) ? ((((__uint32_t )(tlabel->label.dumpid)) >> 24) | ((((__uint32_t)(tlabel ->label.dumpid)) & (0xff << 16)) >> 8) | ( (((__uint32_t)(tlabel->label.dumpid)) & (0xff << 8)) << 8) | (((__uint32_t)(tlabel->label.dumpid)) << 24)) : __bswap32_var(tlabel->label.dumpid)); | ||||
| 1177 | |||||
| 1178 | /* | ||||
| 1179 | * write the tape label - For appends, the write may need to skip | ||||
| 1180 | * over 1 or 2 EOF marks that were written when tape was closed after | ||||
| 1181 | * the last dump. Plus, some AIX tape drives require we try forwarding | ||||
| 1182 | * over the last EOF and take an error before we can write the new label. | ||||
| 1183 | * ---------------------------------------------------------------------- */ | ||||
| 1184 | code = WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE16384, BLOCK_LABEL0); | ||||
| 1185 | if (!isafile && !rewind && (code == BUTM_IO(156568837L))) | ||||
| 1186 | do { /* do if write failed */ | ||||
| 1187 | fcode = SeekFile(info, 1); /* skip over the EOF */ | ||||
| 1188 | if (fcode) | ||||
| 1189 | break; /* leave if error */ | ||||
| 1190 | |||||
| 1191 | code = | ||||
| 1192 | WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE16384, BLOCK_LABEL0); | ||||
| 1193 | if (code != BUTM_IO(156568837L)) | ||||
| 1194 | break; /* continue if write failed */ | ||||
| 1195 | |||||
| 1196 | fcode = SeekFile(info, 1); /* skip over the EOF */ | ||||
| 1197 | if (fcode) { /* retry 1 write if couldn't skip */ | ||||
| 1198 | code = | ||||
| 1199 | WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE16384, | ||||
| 1200 | BLOCK_LABEL0); | ||||
| 1201 | break; | ||||
| 1202 | } | ||||
| 1203 | |||||
| 1204 | code = | ||||
| 1205 | WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE16384, BLOCK_LABEL0); | ||||
| 1206 | if (code != BUTM_IO(156568837L)) | ||||
| 1207 | break; /* continue if write failed */ | ||||
| 1208 | |||||
| 1209 | fcode = SeekFile(info, 1); /* skip over the EOF */ | ||||
| 1210 | if (fcode) { /* retry 1 write if couldn't skip */ | ||||
| 1211 | code = | ||||
| 1212 | WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE16384, | ||||
| 1213 | BLOCK_LABEL0); | ||||
| 1214 | break; | ||||
| 1215 | } | ||||
| 1216 | break; | ||||
| 1217 | } while (0); | ||||
| 1218 | |||||
| 1219 | /* clear the write error status a failed WriteTapeBlock may have produced */ | ||||
| 1220 | if (!code) | ||||
| 1221 | info->status &= ~BUTM_STATUS_WRITEERROR(1<<2); | ||||
| 1222 | |||||
| 1223 | error_exit: | ||||
| 1224 | return code; | ||||
| 1225 | } | ||||
| 1226 | |||||
| 1227 | static afs_int32 | ||||
| 1228 | file_ReadLabel(struct butm_tapeInfo *info, struct butm_tapeLabel *label, | ||||
| 1229 | afs_int32 rewind) | ||||
| 1230 | { | ||||
| 1231 | struct tapeLabel *tlabel; | ||||
| 1232 | afs_int32 code = 0; | ||||
| 1233 | afs_int32 blockType; | ||||
| 1234 | |||||
| 1235 | if (info->debug) | ||||
| |||||
| 1236 | printf("butm: Read tape label\n"); | ||||
| 1237 | |||||
| 1238 | POLL()IOMGR_Poll(); | ||||
| 1239 | info->error = 0; | ||||
| 1240 | |||||
| 1241 | code = check(info, READ_OP0); | ||||
| 1242 | if (code) | ||||
| |||||
| 1243 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1244 | if (READS(((struct progress *)(info->tmRock))->reading) || WRITES(((struct progress *)(info->tmRock))->writing)) | ||||
| |||||
| 1245 | ERROR_EXIT(BUTM_BADOP)do { code = (156568839L); goto error_exit; } while (0); | ||||
| 1246 | |||||
| 1247 | if (rewind) { | ||||
| |||||
| 1248 | code = rewindFile(info); | ||||
| 1249 | if (code) | ||||
| 1250 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); /* status is set so return */ | ||||
| 1251 | } | ||||
| 1252 | |||||
| 1253 | /* | ||||
| 1254 | * When appended labels were written, either 1 or 2 EOF marks may | ||||
| 1255 | * have had to be skipped. When reading a label, these EOF marks | ||||
| 1256 | * must also be skipped. When an EOF is read, 0 bytes are returned | ||||
| 1257 | * (refer to the write calls in file_WriteLabel routine). | ||||
| 1258 | * ---------------------------------------------------------------- */ | ||||
| 1259 | code = ReadTapeBlock(info, tapeBlock, &blockType); | ||||
| 1260 | if (!isafile && !rewind && (blockType == BLOCK_EOF5)) | ||||
| |||||
| 1261 | do { | ||||
| 1262 | code = ReadTapeBlock(info, tapeBlock, &blockType); | ||||
| 1263 | if (blockType != BLOCK_EOF5) | ||||
| 1264 | break; /* didn't read an EOF */ | ||||
| 1265 | |||||
| 1266 | code = ReadTapeBlock(info, tapeBlock, &blockType); | ||||
| 1267 | } while (0); | ||||
| 1268 | |||||
| 1269 | if (blockType == BLOCK_UNKNOWN6) | ||||
| |||||
| 1270 | ERROR_EXIT(BUTM_NOLABEL)do { code = (156568851L); goto error_exit; } while (0); | ||||
| 1271 | if (code) | ||||
| |||||
| 1272 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| |||||
| 1273 | if (blockType != BLOCK_LABEL0) | ||||
| 1274 | ERROR_EXIT(BUTM_BADBLOCK)do { code = (156568850L); goto error_exit; } while (0); | ||||
| 1275 | |||||
| 1276 | /* Copy label out | ||||
| 1277 | * -------------- */ | ||||
| 1278 | if (label) { | ||||
| 1279 | tlabel = (struct tapeLabel *)tapeBlock; | ||||
| 1280 | memcpy(label, &tlabel->label, sizeof(struct butm_tapeLabel)); | ||||
| 1281 | label->structVersion = ntohl(label->structVersion)(__builtin_constant_p(label->structVersion) ? ((((__uint32_t )(label->structVersion)) >> 24) | ((((__uint32_t)(label ->structVersion)) & (0xff << 16)) >> 8) | ( (((__uint32_t)(label->structVersion)) & (0xff << 8)) << 8) | (((__uint32_t)(label->structVersion)) << 24)) : __bswap32_var(label->structVersion)); | ||||
| 1282 | label->creationTime = ntohl(label->creationTime)(__builtin_constant_p(label->creationTime) ? ((((__uint32_t )(label->creationTime)) >> 24) | ((((__uint32_t)(label ->creationTime)) & (0xff << 16)) >> 8) | ( (((__uint32_t)(label->creationTime)) & (0xff << 8 )) << 8) | (((__uint32_t)(label->creationTime)) << 24)) : __bswap32_var(label->creationTime)); | ||||
| 1283 | label->expirationDate = ntohl(label->expirationDate)(__builtin_constant_p(label->expirationDate) ? ((((__uint32_t )(label->expirationDate)) >> 24) | ((((__uint32_t)(label ->expirationDate)) & (0xff << 16)) >> 8) | ((((__uint32_t)(label->expirationDate)) & (0xff << 8)) << 8) | (((__uint32_t)(label->expirationDate)) << 24)) : __bswap32_var(label->expirationDate)); | ||||
| 1284 | label->size = ntohl(label->size)(__builtin_constant_p(label->size) ? ((((__uint32_t)(label ->size)) >> 24) | ((((__uint32_t)(label->size)) & (0xff << 16)) >> 8) | ((((__uint32_t)(label-> size)) & (0xff << 8)) << 8) | (((__uint32_t)( label->size)) << 24)) : __bswap32_var(label->size )); | ||||
| 1285 | label->dumpid = ntohl(label->dumpid)(__builtin_constant_p(label->dumpid) ? ((((__uint32_t)(label ->dumpid)) >> 24) | ((((__uint32_t)(label->dumpid )) & (0xff << 16)) >> 8) | ((((__uint32_t)(label ->dumpid)) & (0xff << 8)) << 8) | (((__uint32_t )(label->dumpid)) << 24)) : __bswap32_var(label-> dumpid)); | ||||
| 1286 | label->useCount = ntohl(label->useCount)(__builtin_constant_p(label->useCount) ? ((((__uint32_t)(label ->useCount)) >> 24) | ((((__uint32_t)(label->useCount )) & (0xff << 16)) >> 8) | ((((__uint32_t)(label ->useCount)) & (0xff << 8)) << 8) | (((__uint32_t )(label->useCount)) << 24)) : __bswap32_var(label-> useCount)); | ||||
| 1287 | |||||
| 1288 | info->tapeSize = label->size; /* use size from label */ | ||||
| 1289 | } | ||||
| 1290 | |||||
| 1291 | error_exit: | ||||
| 1292 | return (code); | ||||
| 1293 | } | ||||
| 1294 | |||||
| 1295 | static afs_int32 | ||||
| 1296 | file_WriteFileBegin(struct butm_tapeInfo *info) | ||||
| 1297 | { | ||||
| 1298 | afs_int32 code = 0; | ||||
| 1299 | |||||
| 1300 | if (info->debug) | ||||
| 1301 | printf("butm: Write filemark begin\n"); | ||||
| 1302 | |||||
| 1303 | POLL()IOMGR_Poll(); | ||||
| 1304 | |||||
| 1305 | code = check(info, WRITE_OP1); | ||||
| 1306 | if (code) | ||||
| 1307 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1308 | |||||
| 1309 | code = WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE16384, BLOCK_FMBEGIN1); | ||||
| 1310 | if (code) | ||||
| 1311 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1312 | |||||
| 1313 | info->nFiles++; | ||||
| 1314 | |||||
| 1315 | error_exit: | ||||
| 1316 | return (code); | ||||
| 1317 | } | ||||
| 1318 | |||||
| 1319 | static afs_int32 | ||||
| 1320 | file_ReadFileBegin(struct butm_tapeInfo *info) | ||||
| 1321 | { | ||||
| 1322 | afs_int32 code = 0; | ||||
| 1323 | afs_int32 blockType; | ||||
| 1324 | |||||
| 1325 | if (info->debug) | ||||
| 1326 | printf("butm: Read filemark begin\n"); | ||||
| 1327 | |||||
| 1328 | POLL()IOMGR_Poll(); | ||||
| 1329 | info->error = 0; | ||||
| 1330 | |||||
| 1331 | code = check(info, READ_OP0); | ||||
| 1332 | if (code) | ||||
| 1333 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1334 | if (READS(((struct progress *)(info->tmRock))->reading) || WRITES(((struct progress *)(info->tmRock))->writing)) | ||||
| 1335 | ERROR_EXIT(BUTM_BADOP)do { code = (156568839L); goto error_exit; } while (0); | ||||
| 1336 | |||||
| 1337 | code = ReadTapeBlock(info, tapeBlock, &blockType); | ||||
| 1338 | if (code) | ||||
| 1339 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1340 | |||||
| 1341 | if (blockType != BLOCK_FMBEGIN1) { | ||||
| 1342 | if (blockType == BLOCK_EOD4) | ||||
| 1343 | ERROR_EXIT(BUTM_EOD)do { code = (156568847L); goto error_exit; } while (0); /* EODump label */ | ||||
| 1344 | if (blockType == BLOCK_LABEL0) | ||||
| 1345 | ERROR_EXIT(BUTM_LABEL)do { code = (156568846L); goto error_exit; } while (0); /* Tape label */ | ||||
| 1346 | ERROR_EXIT(BUTM_BADBLOCK)do { code = (156568850L); goto error_exit; } while (0); /* Other */ | ||||
| 1347 | } | ||||
| 1348 | |||||
| 1349 | error_exit: | ||||
| 1350 | return (code); | ||||
| 1351 | } | ||||
| 1352 | |||||
| 1353 | /* Writes data out in block sizes of 16KB. Does destroy the data. | ||||
| 1354 | * Assumes the data buffer has a space reserved at beginning for a blockMark. | ||||
| 1355 | */ | ||||
| 1356 | static afs_int32 | ||||
| 1357 | file_WriteFileData(struct butm_tapeInfo *info, char *data, afs_int32 blocks, afs_int32 len) | ||||
| 1358 | { | ||||
| 1359 | afs_int32 code = 0; | ||||
| 1360 | int length; | ||||
| 1361 | afs_int32 b; | ||||
| 1362 | char *bstart; /* Where block starts for a 16K block */ | ||||
| 1363 | char *dstart; /* Where data starts for a 16K block */ | ||||
| 1364 | |||||
| 1365 | if (info->debug) | ||||
| 1366 | printf("butm: Write tape data - %u bytes\n", len); | ||||
| 1367 | |||||
| 1368 | POLL()IOMGR_Poll(); | ||||
| 1369 | info->error = 0; | ||||
| 1370 | |||||
| 1371 | code = check(info, WRITE_OP1); | ||||
| 1372 | if (code) | ||||
| 1373 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1374 | if (!data || (len < 0)) | ||||
| 1375 | ERROR_EXIT(BUTM_BADARGUMENT)do { code = (156568844L); goto error_exit; } while (0); | ||||
| 1376 | if (READS(((struct progress *)(info->tmRock))->reading) || !WRITES(((struct progress *)(info->tmRock))->writing)) | ||||
| 1377 | ERROR_EXIT(BUTM_BADOP)do { code = (156568839L); goto error_exit; } while (0); | ||||
| 1378 | |||||
| 1379 | b = 0; /* start at block 0 */ | ||||
| 1380 | while (len > 0) { | ||||
| 1381 | dstart = &data[b * BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int)))]; | ||||
| 1382 | bstart = dstart - sizeof(struct blockMark); | ||||
| 1383 | |||||
| 1384 | if (len < BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int)))) { | ||||
| 1385 | memset(&dstart[len], 0, BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int))) - len); | ||||
| 1386 | length = len; | ||||
| 1387 | } else { | ||||
| 1388 | length = BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int))); | ||||
| 1389 | } | ||||
| 1390 | |||||
| 1391 | code = WriteTapeBlock(info, bstart, length, BLOCK_DATA2); | ||||
| 1392 | |||||
| 1393 | len -= length; | ||||
| 1394 | |||||
| 1395 | /* If there are more blocks, step to next block */ | ||||
| 1396 | /* Otherwise, copy the data to beginning of last block */ | ||||
| 1397 | |||||
| 1398 | if (b < (blocks - 1)) | ||||
| 1399 | b++; | ||||
| 1400 | else if (len) | ||||
| 1401 | memcpy(&dstart[0], &dstart[BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int)))], len); | ||||
| 1402 | } | ||||
| 1403 | |||||
| 1404 | error_exit: | ||||
| 1405 | return (code); | ||||
| 1406 | } | ||||
| 1407 | |||||
| 1408 | /* file_ReadFileData | ||||
| 1409 | * Read a data block from tape. | ||||
| 1410 | * entry: | ||||
| 1411 | * info - tape info structure, c.f. fid | ||||
| 1412 | * data - ptr to buffer for data | ||||
| 1413 | * len - size of data buffer | ||||
| 1414 | * exit: | ||||
| 1415 | * nBytes - no. of data bytes read. | ||||
| 1416 | */ | ||||
| 1417 | |||||
| 1418 | static afs_int32 | ||||
| 1419 | file_ReadFileData(struct butm_tapeInfo *info, char *data, int len, int *nBytes) | ||||
| 1420 | { | ||||
| 1421 | struct blockMark *bmark; | ||||
| 1422 | afs_int32 code = 0; | ||||
| 1423 | afs_int32 blockType; | ||||
| 1424 | |||||
| 1425 | if (info->debug) | ||||
| 1426 | printf("butm: Read tape data - %u bytes\n", len); | ||||
| 1427 | |||||
| 1428 | POLL()IOMGR_Poll(); | ||||
| 1429 | info->error = 0; | ||||
| 1430 | |||||
| 1431 | if (!nBytes) | ||||
| 1432 | ERROR_EXIT(BUTM_BADARGUMENT)do { code = (156568844L); goto error_exit; } while (0); | ||||
| 1433 | *nBytes = 0; | ||||
| 1434 | |||||
| 1435 | code = check(info, READ_OP0); | ||||
| 1436 | if (code) | ||||
| 1437 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1438 | if (!data || (len < 0) || (len > BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int))))) | ||||
| 1439 | ERROR_EXIT(BUTM_BADARGUMENT)do { code = (156568844L); goto error_exit; } while (0); | ||||
| 1440 | if (!READS(((struct progress *)(info->tmRock))->reading) || WRITES(((struct progress *)(info->tmRock))->writing)) | ||||
| 1441 | ERROR_EXIT(BUTM_BADOP)do { code = (156568839L); goto error_exit; } while (0); | ||||
| 1442 | |||||
| 1443 | data -= sizeof(struct blockMark); | ||||
| 1444 | code = ReadTapeBlock(info, data, &blockType); | ||||
| 1445 | if (code) | ||||
| 1446 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1447 | |||||
| 1448 | if (blockType != BLOCK_DATA2) { | ||||
| 1449 | if (blockType == BLOCK_EOF5) | ||||
| 1450 | ERROR_EXIT(BUTM_EOF)do { code = (156568849L); goto error_exit; } while (0); | ||||
| 1451 | if (blockType == BLOCK_FMEND3) | ||||
| 1452 | ERROR_EXIT(BUTM_ENDVOLUME)do { code = (156568845L); goto error_exit; } while (0); | ||||
| 1453 | ERROR_EXIT(BUTM_BADBLOCK)do { code = (156568850L); goto error_exit; } while (0); | ||||
| 1454 | } | ||||
| 1455 | |||||
| 1456 | bmark = (struct blockMark *)data; | ||||
| 1457 | *nBytes = ntohl(bmark->count)(__builtin_constant_p(bmark->count) ? ((((__uint32_t)(bmark ->count)) >> 24) | ((((__uint32_t)(bmark->count)) & (0xff << 16)) >> 8) | ((((__uint32_t)(bmark ->count)) & (0xff << 8)) << 8) | (((__uint32_t )(bmark->count)) << 24)) : __bswap32_var(bmark->count )); /* Size of data in buf */ | ||||
| 1458 | |||||
| 1459 | error_exit: | ||||
| 1460 | return (code); | ||||
| 1461 | } | ||||
| 1462 | |||||
| 1463 | static afs_int32 | ||||
| 1464 | file_WriteFileEnd(struct butm_tapeInfo *info) | ||||
| 1465 | { | ||||
| 1466 | afs_int32 code = 0; | ||||
| 1467 | |||||
| 1468 | if (info->debug) | ||||
| 1469 | printf("butm: Write filemark end\n"); | ||||
| 1470 | |||||
| 1471 | POLL()IOMGR_Poll(); | ||||
| 1472 | info->error = 0; | ||||
| 1473 | |||||
| 1474 | code = check(info, WRITE_OP1); | ||||
| 1475 | if (code) | ||||
| 1476 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1477 | if (READS(((struct progress *)(info->tmRock))->reading) || !WRITES(((struct progress *)(info->tmRock))->writing)) | ||||
| 1478 | ERROR_EXIT(BUTM_BADOP)do { code = (156568839L); goto error_exit; } while (0); | ||||
| 1479 | |||||
| 1480 | code = WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE16384, BLOCK_FMEND3); | ||||
| 1481 | |||||
| 1482 | error_exit: | ||||
| 1483 | return (code); | ||||
| 1484 | } | ||||
| 1485 | |||||
| 1486 | /* Read a SW filemark, verify that it is a SW filemark, then skip to the next | ||||
| 1487 | * HW filemark. If the read of the SW filemark shows it's an EOF, then | ||||
| 1488 | * ignore that the SW filemark is not there and return 0 (found the SW filemark | ||||
| 1489 | * missing with some 3.1 dumps). | ||||
| 1490 | */ | ||||
| 1491 | static afs_int32 | ||||
| 1492 | file_ReadFileEnd(struct butm_tapeInfo *info) | ||||
| 1493 | { | ||||
| 1494 | afs_int32 code = 0; | ||||
| 1495 | afs_int32 blockType; | ||||
| 1496 | |||||
| 1497 | if (info->debug) | ||||
| 1498 | printf("butm: Read filemark end\n"); | ||||
| 1499 | |||||
| 1500 | POLL()IOMGR_Poll(); | ||||
| 1501 | info->error = 0; | ||||
| 1502 | |||||
| 1503 | code = check(info, READ_OP0); | ||||
| 1504 | if (code) | ||||
| 1505 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1506 | if (!READS(((struct progress *)(info->tmRock))->reading) || WRITES(((struct progress *)(info->tmRock))->writing)) | ||||
| 1507 | ERROR_EXIT(BUTM_BADOP)do { code = (156568839L); goto error_exit; } while (0); | ||||
| 1508 | |||||
| 1509 | info->status &= ~BUTM_STATUS_EOF(1<<5); | ||||
| 1510 | |||||
| 1511 | code = ReadTapeBlock(info, tapeBlock, &blockType); | ||||
| 1512 | if (code) | ||||
| 1513 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1514 | |||||
| 1515 | if ((blockType != BLOCK_FMEND3) && (blockType != BLOCK_EOF5)) | ||||
| 1516 | ERROR_EXIT(BUTM_BADBLOCK)do { code = (156568850L); goto error_exit; } while (0); | ||||
| 1517 | |||||
| 1518 | error_exit: | ||||
| 1519 | return code; | ||||
| 1520 | } | ||||
| 1521 | |||||
| 1522 | /* | ||||
| 1523 | * Write the end-of-dump marker. | ||||
| 1524 | */ | ||||
| 1525 | static afs_int32 | ||||
| 1526 | file_WriteEODump(struct butm_tapeInfo *info) | ||||
| 1527 | { | ||||
| 1528 | afs_int32 code = 0; | ||||
| 1529 | |||||
| 1530 | if (info->debug) | ||||
| 1531 | printf("butm: Write filemark EOD\n"); | ||||
| 1532 | |||||
| 1533 | POLL()IOMGR_Poll(); | ||||
| 1534 | info->error = 0; | ||||
| 1535 | |||||
| 1536 | code = check(info, WRITE_OP1); | ||||
| 1537 | if (code) | ||||
| 1538 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1539 | if (READS(((struct progress *)(info->tmRock))->reading) || WRITES(((struct progress *)(info->tmRock))->writing)) | ||||
| 1540 | ERROR_EXIT(BUTM_BADOP)do { code = (156568839L); goto error_exit; } while (0); | ||||
| 1541 | |||||
| 1542 | code = WriteTapeBlock(info, tapeBlock, BUTM_BLOCKSIZE16384, BLOCK_EOD4); | ||||
| 1543 | if (code) | ||||
| 1544 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1545 | |||||
| 1546 | info->status |= BUTM_STATUS_EOD(1<<6); | ||||
| 1547 | |||||
| 1548 | error_exit: | ||||
| 1549 | return (code); | ||||
| 1550 | } | ||||
| 1551 | |||||
| 1552 | static afs_int32 | ||||
| 1553 | file_Seek(struct butm_tapeInfo *info, afs_int32 position) | ||||
| 1554 | { | ||||
| 1555 | afs_int32 code = 0; | ||||
| 1556 | afs_int32 w; | ||||
| 1557 | osi_lloff_t posit; | ||||
| 1558 | struct progress *p; | ||||
| 1559 | afs_int64 stopOff; /* for normal file(non-tape) seeks */ | ||||
| 1560 | |||||
| 1561 | if (info->debug) | ||||
| 1562 | printf("butm: Seek to the tape position %d\n", position); | ||||
| 1563 | |||||
| 1564 | info->error = 0; | ||||
| 1565 | |||||
| 1566 | code = check(info, READ_OP0); | ||||
| 1567 | if (code) | ||||
| 1568 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1569 | |||||
| 1570 | if (isafile) { | ||||
| 1571 | p = (struct progress *)info->tmRock; | ||||
| 1572 | posit = (osi_lloff_t) position *(osi_lloff_t) BUTM_BLOCKSIZE16384; | ||||
| 1573 | |||||
| 1574 | w = USD_SEEK(p->fid, posit, SEEK_SET, &stopOff)((*(p->fid)->seek)(p->fid, posit, 0, &stopOff)); | ||||
| 1575 | if (w) | ||||
| 1576 | info->error = w; | ||||
| 1577 | if (posit != stopOff) | ||||
| 1578 | ERROR_EXIT(BUTM_POSITION)do { code = (156568852L); goto error_exit; } while (0); | ||||
| 1579 | |||||
| 1580 | p->reading = p->writing = 0; | ||||
| 1581 | info->position = position; | ||||
| 1582 | } else { | ||||
| 1583 | /* Don't position backwards if we are in-between FMs */ | ||||
| 1584 | if ((READS(((struct progress *)(info->tmRock))->reading) || WRITES(((struct progress *)(info->tmRock))->writing)) && ((position - info->position) <= 0)) | ||||
| 1585 | ERROR_EXIT(BUTM_BADOP)do { code = (156568839L); goto error_exit; } while (0); | ||||
| 1586 | |||||
| 1587 | code = SeekFile(info, (position - info->position)); | ||||
| 1588 | if (code) | ||||
| 1589 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1590 | } | ||||
| 1591 | |||||
| 1592 | error_exit: | ||||
| 1593 | return (code); | ||||
| 1594 | } | ||||
| 1595 | |||||
| 1596 | /* | ||||
| 1597 | * Seek to the EODump (end-of-dump) after the given position. This is | ||||
| 1598 | * the position after the EOF filemark immediately after the EODump mark. | ||||
| 1599 | * This is for tapes of version 4 or greater. | ||||
| 1600 | */ | ||||
| 1601 | static afs_int32 | ||||
| 1602 | file_SeekEODump(struct butm_tapeInfo *info, afs_int32 position) | ||||
| 1603 | { | ||||
| 1604 | afs_int32 code = 0; | ||||
| 1605 | afs_int32 blockType; | ||||
| 1606 | afs_int32 w; | ||||
| 1607 | struct progress *p; | ||||
| 1608 | afs_int64 stopOff; /* file seek offsets */ | ||||
| 1609 | |||||
| 1610 | if (info->debug) | ||||
| 1611 | printf("butm: Seek to end-of-dump\n"); | ||||
| 1612 | info->error = 0; | ||||
| 1613 | |||||
| 1614 | code = check(info, READ_OP0); | ||||
| 1615 | if (code) | ||||
| 1616 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1617 | if (READS(((struct progress *)(info->tmRock))->reading) || WRITES(((struct progress *)(info->tmRock))->writing)) | ||||
| 1618 | ERROR_EXIT(BUTM_BADOP)do { code = (156568839L); goto error_exit; } while (0); | ||||
| 1619 | |||||
| 1620 | if (isafile) { | ||||
| 1621 | p = (struct progress *)info->tmRock; | ||||
| 1622 | w = USD_SEEK(p->fid, 0, SEEK_END, &stopOff)((*(p->fid)->seek)(p->fid, 0, 2, &stopOff)); | ||||
| 1623 | if (w) { | ||||
| 1624 | info->error = w; | ||||
| 1625 | ERROR_EXIT(BUTM_POSITION)do { code = (156568852L); goto error_exit; } while (0); | ||||
| 1626 | } | ||||
| 1627 | |||||
| 1628 | if (stopOff % BUTM_BLOCKSIZE16384) | ||||
| 1629 | ERROR_EXIT(BUTM_POSITION)do { code = (156568852L); goto error_exit; } while (0); | ||||
| 1630 | info->position = (stopOff / BUTM_BLOCKSIZE16384); | ||||
| 1631 | } else { | ||||
| 1632 | /* Seek to the desired position */ | ||||
| 1633 | code = SeekFile(info, (position - info->position) + 1); | ||||
| 1634 | if (code) | ||||
| 1635 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1636 | |||||
| 1637 | /* | ||||
| 1638 | * Search until the filemark is an EODump filemark. | ||||
| 1639 | * Skip over volumes only. | ||||
| 1640 | */ | ||||
| 1641 | while (1) { | ||||
| 1642 | code = ReadTapeBlock(info, tapeBlock, &blockType); | ||||
| 1643 | if (code) | ||||
| 1644 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1645 | |||||
| 1646 | if (blockType == BLOCK_EOD4) | ||||
| 1647 | break; | ||||
| 1648 | if (blockType != BLOCK_FMBEGIN1) | ||||
| 1649 | ERROR_EXIT(BUTM_BADBLOCK)do { code = (156568850L); goto error_exit; } while (0); | ||||
| 1650 | |||||
| 1651 | code = SeekFile(info, 1); /* Step forward to next volume */ | ||||
| 1652 | if (code) | ||||
| 1653 | ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); | ||||
| 1654 | } | ||||
| 1655 | code = 0; | ||||
| 1656 | } | ||||
| 1657 | |||||
| 1658 | error_exit: | ||||
| 1659 | return (code); | ||||
| 1660 | } | ||||
| 1661 | |||||
| 1662 | static afs_int32 | ||||
| 1663 | file_SetSize(struct butm_tapeInfo *info, afs_uint32 size) | ||||
| 1664 | { | ||||
| 1665 | if (info->debug) | ||||
| 1666 | printf("butm: Set size of tape\n"); | ||||
| 1667 | info->error = 0; | ||||
| 1668 | |||||
| 1669 | if (size <= 0) | ||||
| 1670 | info->tapeSize = config.tapeSize; | ||||
| 1671 | else | ||||
| 1672 | info->tapeSize = size; | ||||
| 1673 | return 0; | ||||
| 1674 | } | ||||
| 1675 | |||||
| 1676 | static afs_int32 | ||||
| 1677 | file_GetSize(struct butm_tapeInfo *info, afs_uint32 *size) | ||||
| 1678 | { | ||||
| 1679 | if (info->debug) | ||||
| 1680 | printf("butm: Get size of tape\n"); | ||||
| 1681 | info->error = 0; | ||||
| 1682 | |||||
| 1683 | *size = info->tapeSize; | ||||
| 1684 | return 0; | ||||
| 1685 | } | ||||
| 1686 | |||||
| 1687 | /* ===================================================================== | ||||
| 1688 | * Startup/configuration routines. | ||||
| 1689 | * ===================================================================== */ | ||||
| 1690 | |||||
| 1691 | static afs_int32 | ||||
| 1692 | file_Configure(struct tapeConfig *file) | ||||
| 1693 | { | ||||
| 1694 | if (!file) { | ||||
| 1695 | afs_com_err(whoami, BUTM_BADCONFIG(156568843L), "device not specified"); | ||||
| 1696 | return BUTM_BADCONFIG(156568843L); | ||||
| 1697 | } | ||||
| 1698 | |||||
| 1699 | config.tapeSize = file->capacity; | ||||
| 1700 | config.fileMarkSize = file->fileMarkSize; | ||||
| 1701 | config.portOffset = file->portOffset; | ||||
| 1702 | strcpy(config.tapedir, file->device); | ||||
| 1703 | |||||
| 1704 | /* Tape must be large enough to at least fit a label */ | ||||
| 1705 | if (config.tapeSize <= 0) { | ||||
| 1706 | afs_com_err(whoami, BUTM_BADCONFIG(156568843L), "Tape size bogus: %d Kbytes", | ||||
| 1707 | config.tapeSize); | ||||
| 1708 | return BUTM_BADCONFIG(156568843L); | ||||
| 1709 | } | ||||
| 1710 | |||||
| 1711 | if (strlen(config.tapedir) == 0) { | ||||
| 1712 | afs_com_err(whoami, BUTM_BADCONFIG(156568843L), "no tape device specified"); | ||||
| 1713 | return BUTM_BADCONFIG(156568843L); | ||||
| 1714 | } | ||||
| 1715 | |||||
| 1716 | config.mountId = 0; | ||||
| 1717 | return 0; | ||||
| 1718 | } | ||||
| 1719 | |||||
| 1720 | /* This procedure instantiates a tape module of type file_tm. */ | ||||
| 1721 | afs_int32 | ||||
| 1722 | butm_file_Instantiate(struct butm_tapeInfo *info, struct tapeConfig *file) | ||||
| 1723 | { | ||||
| 1724 | extern int debugLevel; | ||||
| 1725 | afs_int32 code = 0; | ||||
| 1726 | |||||
| 1727 | if (debugLevel > 98) | ||||
| 1728 | printf("butm: Instantiate butc\n"); | ||||
| 1729 | |||||
| 1730 | if (!info) | ||||
| 1731 | ERROR_EXIT(BUTM_BADARGUMENT)do { code = (156568844L); goto error_exit; } while (0); | ||||
| 1732 | if (info->structVersion != BUTM_MAJORVERSION2) | ||||
| 1733 | ERROR_EXIT(BUTM_OLDINTERFACE)do { code = (156568832L); goto error_exit; } while (0); | ||||
| 1734 | |||||
| 1735 | memset(info, 0, sizeof(struct butm_tapeInfo)); | ||||
| 1736 | info->structVersion = BUTM_MAJORVERSION2; | ||||
| 1737 | info->ops.mount = file_Mount; | ||||
| 1738 | info->ops.dismount = file_Dismount; | ||||
| 1739 | info->ops.create = file_WriteLabel; | ||||
| 1740 | info->ops.readLabel = file_ReadLabel; | ||||
| 1741 | info->ops.seek = file_Seek; | ||||
| 1742 | info->ops.seekEODump = file_SeekEODump; | ||||
| 1743 | info->ops.readFileBegin = file_ReadFileBegin; | ||||
| 1744 | info->ops.readFileData = file_ReadFileData; | ||||
| 1745 | info->ops.readFileEnd = file_ReadFileEnd; | ||||
| 1746 | info->ops.writeFileBegin = file_WriteFileBegin; | ||||
| 1747 | info->ops.writeFileData = file_WriteFileData; | ||||
| 1748 | info->ops.writeFileEnd = file_WriteFileEnd; | ||||
| 1749 | info->ops.writeEOT = file_WriteEODump; | ||||
| 1750 | info->ops.setSize = file_SetSize; | ||||
| 1751 | info->ops.getSize = file_GetSize; | ||||
| 1752 | info->debug = ((debugLevel > 98) ? 1 : 0); | ||||
| 1753 | |||||
| 1754 | code = file_Configure(file); | ||||
| 1755 | |||||
| 1756 | error_exit: | ||||
| 1757 | return code; | ||||
| 1758 | } |