1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 22 * Use is subject to license terms. 23 */ 24 25 26 #include <thread.h> 27 #include <ctype.h> 28 #include <sys/types.h> 29 #include <sys/mkdev.h> 30 #include <sys/file.h> 31 #include <synch.h> 32 #include <unistd.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <time.h> 36 #include <stropts.h> 37 #include <errno.h> 38 #include <string.h> 39 #include <syslog.h> 40 #include <fcntl.h> 41 #include <sys/stat.h> 42 #include <pthread.h> 43 #include <sys/scsi/generic/sense.h> 44 #include <sys/scsi/impl/uscsi.h> 45 #include <mms_list.h> 46 #include <dmd_impl.h> 47 #include <dm_impl.h> 48 #include <dm_msg.h> 49 #include <mms_trace.h> 50 #include <mms_dmd.h> 51 #include <dm_proto.h> 52 #include <mms_strapp.h> 53 54 static char *_SrcFile = __FILE__; 55 56 void 57 dm_get_request(void) 58 { 59 /* 60 * Get request from driver 61 */ 62 if (ioctl(wka->dm_drm_fd, DRM_REQUEST, &wka->dm_reqbuf)) { 63 /* 64 * No request, process error 65 */ 66 TRACE((MMS_DEBUG, "dm_get_request: " 67 "No request: %s", strerror(errno))); 68 return; 69 } 70 wka->dm_request = &wka->dm_reqbuf; 71 } 72 73 void 74 dm_proc_request(void) 75 { 76 int rc = 0; 77 drm_request_t *req; 78 drm_reply_t rep; 79 tapepos_t pos; 80 char dbuf[4096]; 81 82 dm_msg_destroy(); /* cleanup any left over msg */ 83 84 if (DRV_CALL(drv_get_pos, (&pos)) == 0) { 85 TRACE((MMS_DEBUG, "dm_proc_request: Entered at position %lld", 86 pos.lgclblkno)); 87 } 88 89 memset(&rep, 0, sizeof (rep)); 90 req = wka->dm_request; 91 (void) mms_trace_dump((char *)req, sizeof (drm_request_t), dbuf, 92 sizeof (dbuf)); 93 TRACE((MMS_DEBUG, "dm_proc_request: Request:\n%s", dbuf)); 94 95 /* 96 * Save I/O counts 97 */ 98 drv->drv_rdbytes += req->drm_req_rdbytes; 99 drv->drv_wrbytes += req->drm_req_wrbytes; 100 101 if (req->drm_req_type != DRM_REQ_OPEN && 102 req->drm_req_type != DRM_REQ_CLOSE) { 103 /* 104 * If not an open or close request and not in user data, 105 * then allow only status requests. 106 */ 107 if ((drv->drv_flags & DRV_UDATA) == 0 && 108 req->drm_req_type != DRM_REQ_MTGET) { 109 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 110 "file not positioned correctly")); 111 rc = EACCES; 112 goto done; 113 } 114 } 115 116 if (req->drm_req_flags & DRM_REQ_MOVED) { 117 TRACE((MMS_DEBUG, "dm_get_request: Tape Moved")); 118 drv->drv_flags &= ~(DRV_VALID_STAT | DRV_MOVE_FLAGS); 119 } 120 121 memset(&rep, 0, sizeof (drm_reply_t)); 122 switch (req->drm_req_type) { 123 case DRM_REQ_MTIOCTOP: 124 TRACE((MMS_INFO, "dm_get_request: " 125 "Got request DRM_REQ_MTIOCTOP")); 126 rc = dm_ioctl_mtiocltop(req, &rep); 127 break; 128 case DRM_REQ_MTIOCLTOP: 129 TRACE((MMS_INFO, "dm_get_request: " 130 "Got request DRM_REQ_MTIOCLTOP")); 131 rc = dm_ioctl_mtiocltop(req, &rep); 132 break; 133 case DRM_REQ_OPEN: 134 TRACE((MMS_INFO, "dm_get_request: " 135 "Got open request DRM_REQ_OPEN")); 136 rc = dm_open(req, &rep); 137 break; 138 case DRM_REQ_CLOSE: 139 TRACE((MMS_INFO, "dm_get_request: " 140 "Got close request DRM_REQ_CLOSE")); 141 rc = dm_close(); 142 break; 143 case DRM_REQ_READ: 144 TRACE((MMS_INFO, "dm_get_request: " 145 "Got read request DRM_REQ_READ")); 146 rc = dm_read(&rep); 147 break; 148 case DRM_REQ_READ_TM: 149 TRACE((MMS_INFO, "dm_get_request: " 150 "Got read FM request DRM_REQ_READ_TM")); 151 rc = dm_read_tm(req); 152 break; 153 case DRM_REQ_READ_ERR: 154 TRACE((MMS_INFO, "dm_get_request: " 155 "Got read ERR request DRM_REQ_READ_ERR")); 156 rc = dm_read_err(req, &rep); 157 break; 158 case DRM_REQ_WRITE: 159 TRACE((MMS_INFO, "dm_get_request: " 160 "Got write request DRM_REQ_WRITE")); 161 rc = dm_write(&rep); 162 break; 163 case DRM_REQ_WRITE0: 164 TRACE((MMS_INFO, "dm_get_request: " 165 "Got write0 request DRM_REQ_WRITE0")); 166 rc = dm_write_0(req, &rep); 167 break; 168 case DRM_REQ_WRITE_ERR: 169 TRACE((MMS_INFO, "dm_get_request: " 170 "Got write err request DRM_REQ_WRITE_ERR")); 171 rc = dm_write_err(req, &rep); 172 break; 173 case DRM_REQ_MTGET: 174 TRACE((MMS_INFO, "dm_get_request: " 175 "Got request DRM_REQ_MTGET")); 176 rc = dm_ioctl_mtget(req, &rep); 177 break; 178 case DRM_REQ_CLRERR: 179 TRACE((MMS_INFO, "dm_get_request: " 180 "Got request DRM_REQ_CLRERR")); 181 rc = dm_ioctl_clrerr(&rep); 182 break; 183 case DRM_REQ_BLK_LIMIT: 184 TRACE((MMS_INFO, "dm_get_request: " 185 "Got request MMS_REQ_BLK_LIMIT")); 186 if (drv->drv_flags & DRV_FATAL) { 187 rc = EIO; 188 break; 189 } 190 rc = DRV_CALL(drv_blk_limit, (&rep.drm_blk_limit_rep)); 191 break; 192 case DRM_REQ_GET_POS: 193 TRACE((MMS_INFO, "dm_get_request: " 194 "Got request MMS_REQ_GET_POS")); 195 rc = dm_ioctl_getpos(&rep); 196 break; 197 case DRM_REQ_MTGETPOS: 198 TRACE((MMS_INFO, "dm_get_request: " 199 "Got request MMS_REQ_GET_POS")); 200 rc = dm_ioctl_mtgetpos(&rep); 201 break; 202 case DRM_REQ_MTRESTPOS: 203 TRACE((MMS_INFO, "dm_get_request: " 204 "Got request MMS_REQ_GET_POS")); 205 rc = dm_ioctl_mtrestpos(req); 206 break; 207 case DRM_REQ_LOCATE: 208 TRACE((MMS_INFO, "dm_get_request: " 209 "Got request MMS_REQ_LOCATE")); 210 rc = dm_ioctl_locate(req); 211 break; 212 case DRM_REQ_GET_CAPACITY: 213 TRACE((MMS_INFO, "dm_get_request: " 214 "Got request MMS_REQ_GET_CAPACITY")); 215 rc = dm_ioctl_get_capacity(&rep); 216 break; 217 case DRM_REQ_UPT_CAPACITY: 218 TRACE((MMS_INFO, "dm_get_request: " 219 "Got request MMS_REQ_UPT_CAPACITY")); 220 rc = dm_ioctl_upt_capacity(); 221 break; 222 case DRM_REQ_SET_DENSITY: 223 TRACE((MMS_INFO, "dm_get_request: " 224 "Got request MMS_REQ_SET_DENSITY")); 225 rc = dm_ioctl_set_density(); 226 break; 227 case DRM_REQ_GET_DENSITY: 228 TRACE((MMS_INFO, "dm_get_request: " 229 "Got request MMS_REQ_GET_DENSITY")); 230 rc = dm_ioctl_get_density(&rep); 231 break; 232 233 default: 234 rc = EINVAL; 235 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 236 "invalid request from driver %lld", req->drm_req_type)); 237 rc = EINVAL; 238 break; 239 } 240 241 done: 242 dm_msg_destroy(); /* clean up left over msg */ 243 /* 244 * If at EOF and don't have a valid EOF position, then get it. 245 */ 246 if (drv->drv_flags & DRV_EOF) { 247 (void) dm_get_eof_pos(); 248 } 249 250 rep.drm_rep_rc = rc; 251 if (drv->drv_flags & DRV_EOF) { 252 TRACE((MMS_DEBUG, "dm_get_request: " 253 "At EOF")); 254 rep.drm_rep_flags |= DRM_REP_EOF; 255 } 256 257 if (drv->drv_flags & DRV_FATAL) { 258 TRACE((MMS_DEBUG, "dm_get_request: " 259 "Fatal error occured")); 260 rep.drm_rep_flags |= DRM_REP_FATAL; 261 } 262 if (drv->drv_flags & DRV_TERM_FILE) { 263 TRACE((MMS_DEBUG, "dm_get_request: " 264 "Catch next read")); 265 rep.drm_rep_flags |= DRM_REP_NOTIFY_READ; 266 } else { 267 TRACE((MMS_DEBUG, "dm_get_request: " 268 "Catch next write")); 269 rep.drm_rep_flags |= DRM_REP_NOTIFY_WRITE; 270 } 271 if (req->drm_req_flags & DRM_REQ_NOTIFY_READ) { 272 TRACE((MMS_DEBUG, "dm_get_request: " 273 "Notify read in effect")); 274 rep.drm_rep_flags |= DRM_REP_NOTIFY_READ; 275 } 276 if (req->drm_req_flags & DRM_REQ_NOTIFY_WRITE) { 277 TRACE((MMS_DEBUG, "dm_get_request: " 278 "Notify write in effect")); 279 rep.drm_rep_flags |= DRM_REP_NOTIFY_WRITE; 280 } 281 282 if (DRV_CALL(drv_get_pos, (&pos)) == 0) { 283 TRACE((MMS_DEBUG, "dm_proc_request: Resumed at position %lld", 284 pos.lgclblkno)); 285 } 286 287 wka->dm_request = NULL; /* request done */ 288 ioctl(wka->dm_drm_fd, DRM_RESUME, &rep); 289 TRACE((MMS_DEBUG, "Resume with rc = %lld", rep.drm_rep_rc)); 290 291 if (req->drm_req_type == DRM_REQ_OPEN) { 292 if (rep.drm_rep_rc == 0) { 293 /* Opened successfully */ 294 wka->dm_flags |= DM_OPENED; 295 } 296 297 } 298 299 } 300 301 int 302 dm_ioctl_mtiocltop(drm_request_t *req, drm_reply_t *rep) 303 { 304 drm_mtop_t *op = &req->drm_mtop_req; 305 int rc = 0; 306 307 rep->drm_mtop_rep.drm_op = op->drm_op; 308 rep->drm_mtop_rep.drm_count = op->drm_count; 309 310 switch (op->drm_op) { 311 case MTREW: 312 case MTRETEN: 313 TRACE((MMS_INFO, "dm_ioctl_mtiocltop: MTREW/MTRETEN")); 314 rc = dm_ioctl_rewind(); 315 break; 316 case MTSEEK: 317 TRACE((MMS_INFO, "dm_ioctl_mtiocltop: MTSEEK")); 318 rc = dm_ioctl_seek(op->drm_count); 319 break; 320 case MTTELL: 321 TRACE((MMS_INFO, "dm_ioctl_mtiocltop: MTTELL")); 322 drv->drv_flags &= ~DRV_VALID_STAT; 323 rc = DRV_CALL(drv_tell, 324 ((uint64_t *)&rep->drm_mtop_rep.drm_count)); 325 if (rc) { 326 DM_MSG_SEND((DM_ADM_ERR, DM_6523_MSG, DM_MSG_REASON)); 327 } 328 break; 329 case MTFSF: 330 TRACE((MMS_INFO, "dm_ioctl_mtiocltop: MTFSF")); 331 rc = dm_ioctl_fsf(op->drm_count); 332 break; 333 case MTFSR: 334 TRACE((MMS_INFO, "dm_ioctl_mtiocltop: MTFSR")); 335 rc = dm_ioctl_fsb(op->drm_count); 336 break; 337 case MTBSF: 338 TRACE((MMS_INFO, "dm_ioctl_mtiocltop: MTBSF")); 339 rc = dm_ioctl_bsf(op->drm_count); 340 break; 341 case MTBSR: 342 TRACE((MMS_INFO, "dm_ioctl_mtiocltop: MTBSR")); 343 rc = dm_ioctl_bsb(op->drm_count); 344 break; 345 case MTWEOF: 346 TRACE((MMS_INFO, "dm_ioctl_mtiocltop: MTWEOF")); 347 rc = dm_ioctl_wtm(op->drm_count); 348 break; 349 case MTEOM: 350 TRACE((MMS_INFO, "dm_ioctl_mtiocltop: MTEOM")); 351 rc = dm_goto_eof(); 352 break; 353 case MTSRSZ: 354 TRACE((MMS_INFO, "dm_ioctl_mtiocltop: MTSRSZ")); 355 /* 356 * You're allowed to set any record size any time. 357 */ 358 rc = dm_ioctl_set_blksize(op->drm_count); 359 break; 360 case MTGRSZ: 361 TRACE((MMS_INFO, "dm_ioctl_mtiocltop: MTGRSZ")); 362 if (drv->drv_flags & DRV_FATAL) { 363 rc = EIO; 364 break; 365 } 366 rc = DRV_CALL(drv_get_blksize, 367 ((uint64_t *)&rep->drm_mtop_rep.drm_count)); 368 if (rc) { 369 DM_MSG_SEND((DM_ADM_ERR, DM_6514_MSG, DM_MSG_REASON)); 370 } 371 rep->drm_mtop_rep.drm_op = MTGRSZ; 372 break; 373 374 default: 375 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 376 "0x%x", (int)op->drm_op)); 377 DM_MSG_SEND((DM_ADM_ERR, DM_6515_MSG, DM_MSG_REASON)); 378 rc = EINVAL; 379 break; 380 } 381 382 return (rc); 383 } 384 385 386 int 387 dm_open(drm_request_t *req, drm_reply_t *rep) 388 { 389 int newfile = 0; 390 drm_open_t *oreq = &req->drm_open_req; 391 tapepos_t pos; 392 int rc = 0; 393 char *user; 394 395 TRACE((MMS_DEBUG, "dm_open: Enter dm_open")); 396 397 /* 398 * Must be attached to open 399 */ 400 if ((drv->drv_flags & DRV_ATTACHED) == 0) { 401 /* Not attached */ 402 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 403 "Drive not attached")); 404 rc = ENODEV; 405 goto fatal; 406 } 407 408 if (wka->dm_hdl_minor != oreq->drm_open_minor) { 409 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 410 "Target ID mismatch, requested %lld, have %d", 411 oreq->drm_open_minor, wka->dm_hdl_minor)); 412 rc = ENODEV; 413 goto fatal; 414 } 415 416 /* Return EBUSY if already opened */ 417 if (wka->dm_app_pid) { 418 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 419 "Already opened by pid = %d", wka->dm_app_pid)); 420 rc = EBUSY; 421 goto fatal; 422 } 423 424 /* 425 * Save application's pid and user name 426 */ 427 wka->dm_app_pid = req->drm_req_pid; 428 user = dm_get_user(req->drm_req_pid); 429 if (user == NULL) { 430 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 431 "Unable to get user from uid %lld", req->drm_req_uid)); 432 rc = EPERM; 433 goto fatal; 434 } 435 436 /* 437 * Check user authentication 438 */ 439 if (dm_chk_dev_auth(user) != 0) { 440 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 441 "User %s is not authorized to use MMS", 442 user)); 443 rc = EPERM; 444 goto fatal; 445 } 446 447 448 if ((drv->drv_flags & DRV_LOADED) == 0) { 449 /* Cartridge is not loaded */ 450 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 451 "Cartridge %s, Volume %s not loaded", 452 mnt->mnt_pcl, mnt->mnt_volumename)); 453 rc = ENOTTY; 454 goto fatal; 455 } 456 457 /* 458 * Check MMS mode 459 */ 460 if ((mnt->mnt_flags & MNT_MMS) == 0) { 461 /* In raw mode */ 462 TRACE((MMS_DEBUG, "dm_open: RAW mode")); 463 rc = ioctl(wka->dm_drm_fd, DRM_MMS_MODE, 0); 464 if (rc < 0) { 465 rc = errno; 466 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 467 "Cannot set raw mode: %s", strerror(rc))); 468 goto fatal; 469 } 470 471 if (DRV_CALL(drv_bind_raw_dev, 472 (req->drm_open_req.drm_open_flags | FNDELAY)) != 0) { 473 rc = errno; 474 DM_MSG_PREPEND(("Cannot set raw mode: %s: ", 475 strerror(rc))); 476 goto fatal; 477 } 478 /* The entire tape is user data in non MMS mode */ 479 drv->drv_flags |= DRV_UDATA; 480 drv->drv_numopens++; /* 1 more open */ 481 drv->drv_flags |= DRV_OPENED; 482 /* 483 * Set the bit format 484 */ 485 if (dm_update_bitformat()) { 486 DM_MSG_PREPEND(("update bit format error: ")); 487 rc = EIO; 488 goto fatal; 489 } 490 491 return (0); 492 } 493 494 /* 495 * MMS mode 496 */ 497 498 /* 499 * Save open flags 500 */ 501 drv->drv_oflags = oreq->drm_open_flags; 502 503 /* 504 * Set readonly/readwrite flags 505 */ 506 if ((drv->drv_oflags & O_RDONLY) || 507 (mnt->mnt_flags & MNT_READONLY)) { 508 TRACE((MMS_DEBUG, "readonly open option")); 509 drv->drv_flags |= DRV_READONLY; 510 } 511 512 if (mnt->mnt_flags & MNT_READWRITE) { 513 if (drv->drv_flags & DRV_READONLY) { 514 TRACE((MMS_DEBUG, "dm_open: explicit readwrite " 515 "on mount command overrides readonly option")); 516 drv->drv_flags &= ~DRV_READONLY; 517 } 518 } 519 520 if (drv->drv_flags & DRV_WRITEPROTECTED) { 521 TRACE((MMS_DEBUG, "dm_open: cartridge writeprotected")); 522 drv->drv_flags |= DRV_READONLY; 523 } 524 525 /* 526 * Set disposition of file 527 */ 528 if ((drv->drv_oflags & FCREAT) || (mnt->mnt_flags & MNT_CREAT)) { 529 drv->drv_flags |= DRV_CREAT; 530 } 531 532 if (drv->drv_oflags & FAPPEND) { 533 drv->drv_flags |= DRV_APPEND; 534 } 535 536 /* 537 * Save current tape position before validation. We may have to 538 * return to this position if the rest of open fails. 539 */ 540 if (DRV_CALL(drv_get_pos, (&pos)) != 0) { 541 DM_MSG_PREPEND(("unable to get current position: ")); 542 rc = EIO; 543 goto fatal; 544 } 545 drv->drv_cur_pos = pos; 546 547 /* 548 * Determine if a new file should be created 549 */ 550 if (drv->drv_lbl_type != DRV_NL) { 551 rc = dm_open_labeled(&newfile); 552 } else { 553 rc = dm_open_nonlabeled(&newfile); 554 } 555 if (rc != 0) { 556 goto fatal; 557 } 558 559 if (newfile && 560 (drv->drv_flags & DRV_READONLY)) { 561 /* Readonly is for old only */ 562 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 563 "cannot write to readonly")); 564 rc = EACCES; 565 goto fatal; 566 } 567 568 /* 569 * Set record format 570 */ 571 if (mnt->mnt_flags & MNT_FIXED) { 572 drv->drv_flags |= DRV_FIXED; 573 drv->drv_flags &= ~DRV_VARIABLE; 574 } else { 575 drv->drv_flags &= ~DRV_FIXED; 576 drv->drv_flags |= DRV_VARIABLE; 577 } 578 579 TRACE((MMS_DEBUG, "dm_open: %s, %s, %s, %s", 580 drv->drv_flags & DRV_CREAT ? "CREAT" : "OLD", 581 drv->drv_flags & DRV_READONLY ? "READONLY" : "READWRITE", 582 drv->drv_flags & DRV_APPEND ? "APPEND" : "NOT_APPEND", 583 drv->drv_flags & DRV_FIXED ? "FIXED" : "VARIABLE")); 584 585 if (newfile) { 586 /* Turn off append */ 587 drv->drv_flags &= ~DRV_APPEND; 588 589 /* 590 * Check expiration date. 591 */ 592 if (drv->drv_lbl_type != DRV_NL) { 593 if (dm_validate_xdate() != 0) { 594 DM_MSG_PREPEND(("Existing file not expired: ")); 595 /* Existing file not expired */ 596 rc = EACCES; 597 goto fatal; 598 } 599 } 600 601 if (dm_set_label_blksize() != 0) { 602 DM_MSG_PREPEND(("Set label blksize error: ")); 603 rc = EIO; 604 goto fatal; 605 } 606 if (mnt->mnt_fseq == 1) { 607 /* 608 * If mounted tape is NL, then decide whether to 609 * write new label to AL. 610 */ 611 if (drv->drv_lbl_type == DRV_NL) { 612 if (dm_ask_write_lbl("NL", "AL", 613 mnt->mnt_pcl) != 0) { 614 /* Don't write new label */ 615 rc = EACCES; 616 goto fatal; 617 } 618 } 619 /* 620 * If creating the first file, rewind 621 * to BOM and set density and create 622 * VOL1 again 623 */ 624 if (DRV_CALL(drv_rewind, ())) { 625 rc = EIO; 626 goto fatal; 627 } 628 if ((mnt->mnt_flags & MNT_AUTO_DEN) == 0) { 629 if (DRV_CALL(drv_set_density, (mnt-> 630 mnt_density->sym_code)) != 0) { 631 rc = EIO; 632 goto fatal; 633 } 634 } 635 if (dm_create_vol1() != 0) { 636 rc = EIO; 637 goto fatal; 638 } 639 } else { 640 /* fseq != 1 */ 641 if (DRV_CALL(drv_locate, (&pos)) != 0) { 642 rc = EIO; 643 goto fatal; 644 } 645 } 646 /* Create file, write hdr label */ 647 if (dm_create_hdr1() != 0) { 648 rc = EIO; 649 goto fatal; 650 } 651 if (dm_create_hdr2() != 0) { 652 rc = EIO; 653 goto fatal; 654 } 655 if (DRV_CALL(drv_wtm, (1)) != 0) { 656 rc = EIO; 657 goto fatal; 658 } 659 drv->drv_flags &= ~DRV_TM; 660 drv->drv_flags |= 661 (DRV_TERM_FILE | DRV_BOF | DRV_UDATA | 662 DRV_VALIDATED_FNAME); 663 if (dm_get_bof_pos() != 0) { 664 rc = EIO; 665 goto fatal; 666 } 667 } 668 669 if ((drv->drv_flags & DRV_VALIDATED_FNAME) == 0) { 670 /* 671 * File must be validated by now 672 */ 673 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 674 "Unable to validate filename")); 675 rc = EACCES; 676 goto fatal; 677 } 678 679 if ((drv->drv_flags & DRV_UDATA) == 0) { 680 /* 681 * Validated and not in user data, then 682 * position file to BOF 683 */ 684 if (DRV_CALL(drv_fsf, (1)) != 0) { 685 DM_MSG_PREPEND(("spacing to user data error: ")); 686 rc = EIO; 687 goto fatal; 688 } 689 drv->drv_flags &= ~DRV_TM; 690 drv->drv_flags |= (DRV_BOF | DRV_UDATA); 691 if (dm_get_bof_pos() != 0) { 692 DM_MSG_PREPEND(("cannot get bof position: ")); 693 rc = EIO; 694 goto fatal; 695 } 696 } 697 698 if ((drv->drv_flags & DRV_UDATA) == 0) { 699 /* 700 * Must be in user data now 701 */ 702 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 703 "Unable to reach user data in file")); 704 rc = EACCES; 705 goto fatal; 706 } 707 708 if ((drv->drv_flags & DRV_VALID_BOF_POS) == 0) { 709 /* 710 * Must have BOF position 711 */ 712 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 713 "Unable to get BOF position")); 714 rc = EACCES; 715 goto fatal; 716 } 717 718 /* 719 * Get EOF position from MM 720 */ 721 if (newfile) { 722 drv->drv_flags &= ~DRV_VALID_EOF_POS; 723 drv->drv_flags |= DRV_UPDATE_EOF_POS; 724 /* ignore send error */ 725 (void) dm_send_eof_pos(); 726 } else if ((drv->drv_flags & DRV_VALID_EOF_POS) == 0) { 727 if (dm_show_eof_pos() != 0) { 728 drv->drv_flags &= ~DRV_VALID_EOF_POS; 729 } 730 } 731 732 /* 733 * Position in the file 734 */ 735 if (newfile == 0) { 736 if (dm_open_pos() != 0) { 737 /* Error */ 738 DM_MSG_PREPEND(("unable to reposition file: ")); 739 rc = EIO; 740 goto fatal; 741 } 742 } 743 744 /* 745 * Now that the file is positioned correctly, reset the disposition 746 * so that open flags will be used. 747 */ 748 mnt->mnt_flags &= ~(MNT_CREAT | MNT_OLD); 749 drv->drv_flags &= ~DRV_CREAT; /* and turn off create */ 750 751 /* 752 * Switch to user's file 753 */ 754 if (DRV_CALL(drv_bind_raw_dev, 755 (req->drm_open_req.drm_open_flags | FNDELAY) != 0)) { 756 rc = errno; 757 DM_MSG_PREPEND(("Raw device open error: %s: ", strerror(rc))); 758 wka->dm_app_pid = 0; 759 goto fatal; 760 } 761 TRACE((MMS_DEBUG, "Opened by pid %d", (int)wka->dm_app_pid)); 762 763 /* 764 * Set up file blksize, density and compression 765 */ 766 if (dm_set_file_blksize(-1) != 0) { 767 /* 768 * Rebind to target base 769 */ 770 DM_MSG_PREPEND(("set file blocksize error: ")); 771 if (DRV_CALL(drv_rebind_target, ()) != 0) { 772 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 773 "Rebind base device error: %s", 774 strerror(errno))); 775 } 776 rc = EIO; 777 goto fatal; 778 } 779 780 /* 781 * Set the bit format 782 */ 783 if (dm_update_bitformat() != 0) { 784 DM_MSG_PREPEND(("unable to update bit format: ")); 785 rc = EIO; 786 goto fatal; 787 } 788 rep->drm_rep_flags |= (DRM_REP_NOTIFY_WRITE | DRM_REP_NOTIFY_READ); 789 if (rc == 0) { 790 /* Successfully positioned, turn off append */ 791 drv->drv_flags &= ~DRV_APPEND; 792 drv->drv_flags |= DRV_OPENED; 793 } 794 free(user); 795 return (rc); 796 797 fatal: 798 free(user); 799 wka->dm_app_pid = 0; 800 DRV_CALL(drv_locate, (&pos)); 801 DM_MSG_SEND((DM_ADM_ERR, DM_6516_MSG, DM_MSG_REASON)); 802 (void) dm_set_label_blksize(); 803 return (rc); 804 805 } 806 807 int 808 dm_open_labeled(int *newfile) 809 { 810 /* 811 * Position to the file seq 812 */ 813 if (dm_pos_fseq() != 0) { 814 return (EIO); 815 } 816 817 if (drv->drv_fseq != mnt->mnt_fseq) { 818 /* 819 * We must be at the file requested by the user 820 */ 821 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 822 "Unable to reach requested file")); 823 return (EIO); 824 } 825 826 /* 827 * Determine if a new file will be created 828 */ 829 830 *newfile = 0; 831 if (drv->drv_flags & DRV_CREAT) { 832 /* 833 * Create a new file 834 */ 835 *newfile = 1; 836 if (drv->drv_flags & DRV_UDATA) { 837 if (drv->drv_fseq == 1) { 838 if (DRV_CALL(drv_rewind, ()) != 0 || 839 DRV_CALL(drv_fsb, (1, 840 DRV_LOGICAL_CROSS_TM)) != 0) { 841 DM_MSG_PREPEND(("unable to " 842 "position cartridge: ")); 843 return (EIO); 844 } 845 } else { 846 if (dm_rewind_file() != 0 || 847 DRV_CALL(drv_bsf, (2)) != 0 || 848 DRV_CALL(drv_fsf, (1)) != 0) { 849 DM_MSG_PREPEND(("unable to " 850 "position cartridge: ")); 851 return (EIO); 852 } 853 } 854 drv->drv_flags &= ~DRV_UDATA; 855 } 856 if ((drv->drv_flags & DRV_VALIDATED_FNAME) != 0) { 857 if (dm_validate_fname() != 0) { 858 return (ENOENT); 859 } 860 } 861 drv->drv_flags |= DRV_VALIDATED_FNAME; 862 } else { 863 /* 864 * Writing over an existing file 865 */ 866 if ((drv->drv_flags & DRV_UDATA) == 0) { 867 /* Not in user data and validate filename */ 868 if ((drv->drv_flags & DRV_VALIDATED_FNAME) == 0) { 869 if (dm_validate_fname() != 0) { 870 return (EACCES); 871 } 872 } 873 } 874 } 875 876 /* 877 * Set up blocksize 878 */ 879 if (drv->drv_flags & DRV_CREAT) { 880 drv->drv_file_blksize = mnt->mnt_blksize > 0 ? 881 mnt->mnt_blksize : drv->drv_dflt_blksize; 882 } else { 883 drv->drv_file_blksize = mnt->mnt_blksize > 0 ? 884 mnt->mnt_blksize : drv->drv_lbl_blksize; 885 } 886 return (0); 887 } 888 889 int 890 dm_open_nonlabeled(int *newfile) 891 { 892 /* 893 * Mounted cartridge is NL 894 * If mount option is AL, then create label if not done already 895 */ 896 if (mnt->mnt_lbl_type == DRV_AL && (drv->drv_flags & DRV_BOM)) { 897 /* Can only create fseq 1 */ 898 if (mnt->mnt_fseq > 1) { 899 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 900 "Do not support fseq = %d", mnt->mnt_fseq)); 901 return (ENOENT); 902 } 903 /* 904 * Must create a new file 905 */ 906 *newfile = 1; 907 908 /* 909 * Set up blocksize 910 */ 911 drv->drv_file_blksize = mnt->mnt_blksize > 0 ? 912 mnt->mnt_blksize : drv->drv_dflt_blksize; 913 } 914 915 return (0); 916 } 917 918 int 919 dm_validate_xdate(void) 920 { 921 time_t curtime; 922 int curdate; 923 int xdate; 924 int tmp; 925 int i; 926 char lxdate[7]; 927 struct tm tm; 928 929 if (mnt->mnt_lbl_type == DRV_NL) { 930 /* nonlabeled */ 931 return (0); 932 } 933 934 strncpy(lxdate, drv->drv_hdr1.hdr1_xdate, 6); 935 lxdate[6] = '\0'; 936 if (strncmp(lxdate + 1, "00000", 5) == 0) { 937 /* No expiration date used */ 938 return (0); 939 } 940 941 /* 942 * If date is invalid, then ignore 943 */ 944 if (lxdate[0] != ' ' && lxdate[0] != '0') { 945 goto invalid_xdate; 946 } 947 for (i = 0; i < 5; i++) { 948 if (!isdigit(lxdate[1 + i])) { 949 goto invalid_xdate; 950 } 951 } 952 sscanf(lxdate + 3, "%d", &tmp); 953 if (tmp < 1 || tmp > 366) { 954 goto invalid_xdate; 955 } 956 957 if ((drv->drv_flags & DRV_VALIDATE_XDATE) == 0) { 958 /* Don't validate expiration date */ 959 return (0); 960 } 961 962 /* 963 * Get expiration date since 1900 964 */ 965 sscanf(lxdate + 1, "%d", &xdate); 966 if (lxdate[0] == '0') { 967 /* years since 1900 */ 968 xdate += 100000; 969 } 970 971 /* 972 * Get current date since 1900 973 */ 974 curtime = time(NULL); 975 localtime_r(&curtime, &tm); 976 curdate = tm.tm_year * 1000 + tm.tm_yday + 1; 977 978 if (xdate > curdate) { 979 /* file not expired */ 980 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 981 "Existing file not expired: " 982 "expiration date = %s", lxdate)); 983 return (-1); 984 } else { 985 /* File expired */ 986 return (0); 987 } 988 989 invalid_xdate: 990 TRACE((MMS_DEBUG, "invalid expiration date: %s", lxdate)); 991 return (0); 992 } 993 994 /* 995 * Currently, only one file is supported on each volume, so fseq can only be 1. 996 */ 997 998 int 999 dm_pos_fseq(void) 1000 { 1001 if (drv->drv_fseq == 0) { 1002 /* Tape not positioned */ 1003 if (DRV_CALL(drv_rewind, ()) != 0) { 1004 return (EIO); 1005 } 1006 if (drv->drv_lbl_type != DRV_NL) { 1007 if (DRV_CALL(drv_fsb, (1, DRV_LOGICAL_CROSS_TM))) { 1008 return (EIO); 1009 } 1010 } 1011 drv->drv_flags &= ~(DRV_UDATA | DRV_BOF | 1012 DRV_EOF | DRV_TM | DRV_HDR1 | 1013 DRV_HDR2 | DRV_EOF1 | DRV_EOF2); 1014 drv->drv_fseq = 1; 1015 } 1016 1017 if (mnt->mnt_fseq == drv->drv_fseq) { 1018 /* Already positioned to file */ 1019 return (0); 1020 } 1021 1022 /* 1023 * We don't support fseq > 1 for the time being 1024 */ 1025 if (mnt->mnt_fseq > 1) { 1026 return (EINVAL); 1027 } 1028 1029 return (0); 1030 } 1031 1032 int 1033 dm_get_bof_pos(void) 1034 { 1035 if ((drv->drv_flags & DRV_BOF) == 0) { 1036 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1037 "Not at BOF. Can't get BOF position")); 1038 return (EACCES); 1039 } 1040 1041 if (DRV_CALL(drv_get_pos, (&drv->drv_bof_pos)) != 0) { 1042 return (EIO); 1043 } 1044 drv->drv_flags |= DRV_VALID_BOF_POS; 1045 return (0); 1046 } 1047 1048 int 1049 dm_get_eof_pos(void) 1050 { 1051 if ((drv->drv_flags & DRV_EOF) == 0) { 1052 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1053 "not at EOF. cannot get EOF position")); 1054 return (EACCES); 1055 } 1056 1057 if (DRV_CALL(drv_get_pos, (&drv->drv_eof_pos)) != 0) { 1058 return (EIO); 1059 } 1060 drv->drv_flags |= DRV_VALID_EOF_POS; 1061 drv->drv_cur_pos = drv->drv_eof_pos; 1062 return (0); 1063 } 1064 1065 int 1066 dm_open_pos(void) 1067 { 1068 if ((drv->drv_flags & DRV_UDATA) == 0) { 1069 /* 1070 * Must be in uset data to do positioning at open 1071 */ 1072 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1073 "Not in user data. Can't do open position")); 1074 return (EACCES); 1075 } 1076 1077 if ((drv->drv_flags & DRV_VALID_BOF_POS) == 0) { 1078 /* 1079 * Must have BOF position 1080 */ 1081 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1082 "Don't have BOF position. " "Can't do open position")); 1083 return (EACCES); 1084 } 1085 1086 if (drv->drv_flags & DRV_CREAT) { 1087 if (DRV_CALL(drv_locate, (&drv->drv_bof_pos)) != 0) { 1088 return (EIO); 1089 } 1090 drv->drv_cur_pos = drv->drv_bof_pos; 1091 } else if (drv->drv_flags & DRV_APPEND) { 1092 /* Go to eof */ 1093 return (dm_goto_eof()); 1094 } 1095 return (0); 1096 } 1097 1098 int 1099 dm_goto_eof(void) 1100 { 1101 char buf[80] = ""; 1102 int rc; 1103 tapepos_t cur_pos = drv->drv_cur_pos; 1104 1105 if (drv->drv_flags & DRV_FATAL) { 1106 return (EIO); 1107 } 1108 1109 if ((drv->drv_flags & DRV_UDATA) == 0) { 1110 /* 1111 * Must be in user data to go to EOF 1112 */ 1113 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1114 "Not in user data. Can't go to EOF")); 1115 return (EACCES); 1116 } 1117 1118 if (DRV_CALL(drv_get_pos, (&cur_pos)) != 0) { 1119 return (EIO); 1120 } 1121 drv->drv_flags &= ~(DRV_TM | DRV_EOF); 1122 1123 /* 1124 * If eof position is valid, then locate to it 1125 */ 1126 if (dm_set_label_blksize()) { 1127 return (EIO); 1128 } 1129 if (drv->drv_flags & DRV_VALID_EOF_POS) { 1130 if (DRV_CALL(drv_locate, (&drv->drv_eof_pos)) != 0) { 1131 goto repos; 1132 } 1133 drv->drv_cur_pos = drv->drv_eof_pos; 1134 /* 1135 * If this is really EOF, then the next block must be a 1136 * tapemark followed by the trailor label. 1137 */ 1138 if (DRV_CALL(drv_fsb, (1, DRV_LOGICAL_CROSS_TM)) != 0) { 1139 /* Could not space 1 block */ 1140 /* We're at EOF if we hit EOM or blank check */ 1141 drv->drv_flags &= ~DRV_VALID_STAT; 1142 if (serr->se_senkey == SUN_KEY_EOT || 1143 serr->se_senkey == KEY_BLANK_CHECK) { 1144 TRACE((MMS_DEBUG, "Hit EOT/BLANK CHECK")); 1145 goto done; 1146 } 1147 /* 1148 * Hit a tapemark, read the next block to see if it is a 1149 * trailor label. 1150 */ 1151 if ((drv->drv_flags & DRV_TM) != 0) { 1152 if (DRV_CALL(drv_read, (buf, 80)) != 80) { 1153 /* 1154 * We're at EOF if we hit EOM or 1155 * blank check 1156 */ 1157 if (serr->se_senkey == SUN_KEY_EOT || 1158 serr->se_senkey == 1159 KEY_BLANK_CHECK) { 1160 TRACE((MMS_DEBUG, 1161 "Hit EOT/BLANK CHECK")); 1162 drv->drv_flags &= 1163 ~DRV_VALID_EOF_POS; 1164 goto done; 1165 } else { 1166 /* other error */ 1167 goto repos; 1168 } 1169 } 1170 /* 1171 * Read an 80 byte record 1172 */ 1173 if (dm_verify_trailor_label(buf) == 0) { 1174 TRACE((MMS_DEBUG, "Found EOF")); 1175 if (DRV_CALL(drv_locate, 1176 (&drv->drv_eof_pos)) != 0) { 1177 /* 1178 * Can't reposition 1179 * to EOF 1180 */ 1181 goto repos; 1182 } 1183 drv->drv_cur_pos = drv->drv_eof_pos; 1184 goto done; 1185 } 1186 } else { 1187 /* All errors, do it the hard way */ 1188 goto repos; 1189 } 1190 } else { 1191 /* Skipped a block, this is not EOF for sure */ 1192 goto repos; 1193 } 1194 repos: 1195 /* 1196 * Don't find trailor label. 1197 * Return to where we started and try to locate EOF 1198 * the hard way. 1199 */ 1200 if (dm_set_file_blksize(drv->drv_cur_blksize)) { 1201 return (EIO); 1202 } 1203 drv->drv_flags &= ~DRV_VALID_EOF_POS; 1204 buf[0] = '\0'; 1205 if (DRV_CALL(drv_locate, (&cur_pos)) != 0) { 1206 return (EIO); 1207 } 1208 drv->drv_cur_pos = cur_pos; 1209 drv->drv_flags &= ~(DRV_TM | DRV_EOF); 1210 } 1211 1212 /* 1213 * Eof position is not valid, find eof the hard way 1214 */ 1215 1216 if (dm_set_label_blksize()) { 1217 return (EIO); 1218 } 1219 for (;;) { 1220 if (DRV_CALL(drv_fsf, (1)) != 0) { 1221 /* We're at EOF if we hit EOM or blank check */ 1222 if (serr->se_senkey == SUN_KEY_EOT || 1223 serr->se_senkey == KEY_BLANK_CHECK) { 1224 TRACE((MMS_DEBUG, "Hit EOT/BLANK CHECK")); 1225 goto done; 1226 } 1227 goto err; 1228 } 1229 /* 1230 * Try to read the next block to see if it is a trailor label. 1231 * Skip over any tapemark we encounter 1232 */ 1233 while ((rc = DRV_CALL(drv_read, (buf, 80))) != 80) { 1234 /* We're at EOF if we hit EOM or blank check */ 1235 if (serr->se_senkey == SUN_KEY_EOT || 1236 serr->se_senkey == KEY_BLANK_CHECK) { 1237 TRACE((MMS_DEBUG, "Hit EOT/BLANK CHECK")); 1238 drv->drv_flags |= DRV_EOF; 1239 DRV_CALL(drv_clrerr, ()); 1240 goto done; 1241 } else if (drv->drv_flags & DRV_TM) { 1242 /* Hit a tapemark */ 1243 continue; /* Check for eof label */ 1244 } else if (rc > 0) { 1245 /* Read a short block */ 1246 continue; 1247 } else { 1248 /* other error */ 1249 goto err; 1250 } 1251 } 1252 if (rc != 80) { 1253 /* Read a short block */ 1254 continue; 1255 } 1256 /* 1257 * Read an 80 byte record 1258 */ 1259 if (strncmp(buf, "EOF1", 4) == 0 || 1260 strncmp(buf, "EOV1", 4) == 0) { 1261 if (dm_verify_trailor_label(buf) != 0) { 1262 /* Invalid label structure */ 1263 TRACE((MMS_ERR, "Invalid trailor label")); 1264 errno = EINVAL; 1265 goto err; 1266 } 1267 /* Found the EOF/EOV label */ 1268 TRACE((MMS_DEBUG, "Found EOF")); 1269 break; 1270 } 1271 } 1272 /* 1273 * We've read a trailor label. Position to the end of user data. 1274 */ 1275 if (DRV_CALL(drv_bsf, (1)) != 0) { 1276 goto err; 1277 } 1278 1279 done: 1280 drv->drv_flags &= ~DRV_TM; 1281 drv->drv_flags |= DRV_EOF; 1282 if (dm_set_file_blksize(drv->drv_cur_blksize)) { 1283 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1284 "Set file blksize error")); 1285 goto err; 1286 } 1287 1288 if ((drv->drv_flags & DRV_VALID_EOF_POS) == 0) { 1289 if (dm_get_eof_pos()) { 1290 TRACE((MMS_DEBUG, "Can't get EOF pos")); 1291 goto err; 1292 } 1293 drv->drv_flags |= DRV_UPDATE_EOF_POS; 1294 } 1295 return (0); 1296 1297 err: 1298 /* 1299 * Error going to EOF, reposition to where we started and return error 1300 */ 1301 DRV_CALL(drv_clrerr, ()); 1302 DRV_CALL(drv_locate, (&cur_pos)); 1303 if (dm_set_file_blksize(drv->drv_cur_blksize)) { 1304 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1305 "Set file blksize error")); 1306 } 1307 return (EIO); 1308 } 1309 1310 int 1311 dm_verify_trailor_label(char *buf) 1312 { 1313 drv_eof1_t *eof1 = (drv_eof1_t *)buf; 1314 drv_eov1_t *eov1 = (drv_eov1_t *)buf; 1315 drv_hdr1_t *hdr1 = &drv->drv_hdr1; 1316 1317 if (strncmp(eof1->eof1_id, "EOF1", 4) == 0) { 1318 if (strncmp(eof1->eof1_fseq, hdr1->hdr1_fseq, 4)) { 1319 /* 1320 * EOF1 does not match HDR1 1321 */ 1322 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1323 "EOF1 label does not match HDR1 label")); 1324 return (-1); 1325 } 1326 } else if (strncmp(eov1->eov1_id, "EOV1", 4) == 0) { 1327 if (strncmp(eov1->eov1_fseq, hdr1->hdr1_fseq, 4)) { 1328 /* 1329 * EOV1 does not match HDR1 1330 */ 1331 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1332 "EOV1 label does not match HDR1 label")); 1333 return (-1); 1334 } 1335 } 1336 1337 return (0); 1338 } 1339 1340 int 1341 dm_chk_eof(void) 1342 { 1343 int rc; 1344 char buf[80] = ""; 1345 tapepos_t pos; 1346 1347 if (DRV_CALL(drv_get_pos, (&pos)) != 0) { 1348 return (EIO); 1349 } 1350 1351 if ((rc = DRV_CALL(drv_read, (buf, 80))) <= 0) { 1352 /* We're at EOF if we hit EOM or blank check */ 1353 if (serr->se_senkey == SUN_KEY_EOT || 1354 serr->se_senkey == KEY_BLANK_CHECK) { 1355 TRACE((MMS_DEBUG, "Hit EOT/BLANK CHECK")); 1356 drv->drv_flags |= DRV_EOF; 1357 if (dm_get_eof_pos()) { 1358 rc = EIO; 1359 } else { 1360 rc = 0; 1361 } 1362 } else { 1363 /* Other error */ 1364 DRV_CALL(drv_clrerr, ()); 1365 rc = EIO; 1366 } 1367 } else if (rc >= 80 && 1368 (strncmp(buf, "EOF1", 4) == 0 || strncmp(buf, "EOV1", 4) == 0)) { 1369 TRACE((MMS_DEBUG, "Found EOF1/EOV1")); 1370 rc = 0; 1371 } 1372 1373 DRV_CALL(drv_locate, (&pos)); 1374 return (rc); 1375 } 1376 1377 int 1378 dm_validate_fname(void) 1379 { 1380 int rc; 1381 drv_hdr1_t *hdr1 = &drv->drv_hdr1; 1382 drv_hdr2_t *hdr2 = &drv->drv_hdr2; 1383 char tmp[18]; 1384 1385 drv->drv_flags &= ~DRV_FIXED; /* assume variable */ 1386 drv->drv_flags |= DRV_VARIABLE; 1387 drv->drv_file_blksize = drv->drv_dflt_blksize; /* default blksize */ 1388 1389 if ((drv->drv_flags & DRV_HDR1) == 0) { 1390 rc = DRV_CALL(drv_read, ((char *)&drv->drv_hdr1, 80)); 1391 if (rc != 80 || 1392 strncmp(drv->drv_hdr1.hdr1_id, "HDR1", 4) != 0) { 1393 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1394 "invalid header label structure, no HDR1")); 1395 return (EINVAL); 1396 } 1397 drv->drv_flags |= DRV_HDR1; 1398 1399 strncpy(drv->drv_fid, drv->drv_hdr1.hdr1_fid, 17); 1400 drv->drv_fid[17] = '\0'; 1401 } 1402 1403 /* 1404 * Validate filename 1405 */ 1406 if (drv->drv_flags & DRV_VALIDATE_FNAME) { 1407 /* validate filename */ 1408 if (strncmp(drv->drv_hdr1.hdr1_fid, mnt->mnt_fname, 17) != 0) { 1409 /* Mismatch filename */ 1410 strncpy(tmp, drv->drv_hdr1.hdr1_fid, 17); 1411 tmp[17] = '\0'; 1412 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1413 "filename mismatch: " 1414 "label %s, specified %s", tmp, mnt->mnt_fname)); 1415 } else { 1416 /* File verified */ 1417 drv->drv_flags |= DRV_VALIDATED_FNAME; 1418 } 1419 } else { 1420 /* File verified */ 1421 drv->drv_flags |= DRV_VALIDATED_FNAME; 1422 } 1423 1424 /* 1425 * HDR2 is optional 1426 */ 1427 if ((drv->drv_flags & DRV_HDR2) == 0) { 1428 rc = DRV_CALL(drv_read, ((char *)&drv->drv_hdr2, 80)); 1429 1430 /* 1431 * HDR2 optional. If no HDR2, then there must be a tapemark. 1432 */ 1433 if ((drv->drv_flags & DRV_TM) != 0) { 1434 TRACE((MMS_DEBUG, "No HDR2")); 1435 return (0); 1436 } 1437 1438 if (rc != 80 || 1439 strncmp(drv->drv_hdr2.hdr2_id, "HDR2", 4) != 0) { 1440 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1441 "invalid header label structure, " 1442 "invalid HDR2")); 1443 return (EIO); 1444 } 1445 1446 drv->drv_flags |= DRV_HDR2; 1447 1448 if (hdr2->hdr2_rformat == 'F') { 1449 drv->drv_flags |= DRV_FIXED; 1450 drv->drv_flags &= ~DRV_VARIABLE; 1451 } else { 1452 drv->drv_flags &= ~DRV_FIXED; 1453 drv->drv_flags |= DRV_VARIABLE; 1454 } 1455 1456 if (strncmp(hdr1->hdr1_impid, DRV_IMPID, DRV_IMPID_LEN) == 0 || 1457 strncmp(hdr1->hdr1_impid, DRV_IMPID2, DRV_IMPID_LEN) == 0) { 1458 /* Label created by MMS */ 1459 strncpy(tmp, hdr2->hdr2_blksize, 1460 sizeof (hdr2->hdr2_blksize)); 1461 tmp[sizeof (hdr2->hdr2_blksize)] = '\0'; 1462 sscanf(tmp, "%d", &drv->drv_lbl_blksize); 1463 } else { 1464 /* Label not created by MMS */ 1465 strncpy(tmp, hdr2->hdr2_blklen, 5); 1466 tmp[5] = '\0'; 1467 sscanf(tmp, "%d", &drv->drv_lbl_blksize); 1468 if (drv->drv_lbl_blksize >= 99999) { 1469 drv->drv_lbl_blksize = drv->drv_dflt_blksize; 1470 } 1471 } 1472 } 1473 return (0); 1474 } 1475 1476 1477 int 1478 dm_close(void) 1479 { 1480 TRACE((MMS_DEBUG, "Closing file")); 1481 1482 /* 1483 * In MMS mode, terminate the tape if necessary 1484 */ 1485 if (mnt->mnt_flags & MNT_MMS) { 1486 if (drv->drv_flags & DRV_UDATA) { 1487 if (drv->drv_flags & DRV_TERM_FILE) { 1488 drv->drv_flags |= DRV_EOF; 1489 if (drv->drv_flags & DRV_UPDATE_EOF_POS) { 1490 (void) dm_get_eof_pos(); 1491 } 1492 /* 1493 * Ignore error since there isn't anything 1494 * we can do except get it recorded. 1495 */ 1496 (void) dm_terminate_file(); 1497 drv->drv_flags &= ~DRV_TERM_FILE; 1498 } 1499 if ((mnt->mnt_flags & MNT_NOREWIND) == 0) { 1500 /* Rewind at close */ 1501 TRACE((MMS_DEBUG, "Rewind on close")); 1502 DRV_CALL(drv_locate, (&drv->drv_bof_pos)); 1503 drv->drv_cur_pos = drv->drv_bof_pos; 1504 } 1505 } 1506 } 1507 1508 /* 1509 * Rebind to target base 1510 */ 1511 if (DRV_CALL(drv_rebind_target, ()) != 0) { 1512 TRACE((MMS_ERR, "Rebind base device error: %s", 1513 strerror(errno))); 1514 drv->drv_flags |= DRV_FATAL; 1515 TRACE((MMS_DEBUG, "FATAL error")); 1516 } 1517 dm_clear_dev(); 1518 1519 ioctl(wka->dm_drm_fd, DRM_MMS_MODE, 1); 1520 if (drv->drv_flags & DRV_UPDATE_EOF_POS) { 1521 wka->dm_flags |= DM_SEND_EOF_POS; 1522 drv->drv_flags &= ~DRV_UPDATE_EOF_POS; 1523 } 1524 if (drv->drv_flags & DRV_UPDATE_CAPACITY) { 1525 wka->dm_flags |= DM_SEND_CAPACITY; 1526 drv->drv_flags &= ~DRV_UPDATE_CAPACITY; 1527 } 1528 wka->dm_app_pid = 0; 1529 TRACE((MMS_DEBUG, "Closed by pid %d", (int)wka->dm_app_pid)); 1530 drv->drv_flags &= ~DRV_OPENED; 1531 pthread_mutex_lock(&wka->dm_worker_mutex); 1532 wka->dm_work_todo = 1; 1533 pthread_cond_broadcast(&wka->dm_work_cv); 1534 pthread_mutex_unlock(&wka->dm_worker_mutex); 1535 return (0); 1536 } 1537 1538 /* 1539 * Terminate a acrtridge by writing either two tapemarks or trailor labels 1540 */ 1541 int 1542 dm_terminate_file(void) 1543 { 1544 tapepos_t pos; 1545 int rc = 0; 1546 int i; 1547 1548 /* 1549 * At EOF now 1550 */ 1551 drv->drv_flags |= DRV_EOF; 1552 1553 if ((drv->drv_flags & DRV_UDATA) == 0) { 1554 /* 1555 * Must be in user data to terminate file 1556 */ 1557 TRACE((MMS_ERR, "Not in user data. Can't terminate file")); 1558 return (EACCES); 1559 } 1560 1561 if ((drv->drv_flags & DRV_TERM_FILE) == 0) { 1562 /* 1563 * Must have set DRV_TERM_FILE to terminate a file 1564 */ 1565 TRACE((MMS_ERR, 1566 "DRV_TERM_FILE not set. Can't terminate file")); 1567 } 1568 1569 /* 1570 * Save EOF pos 1571 */ 1572 (void) dm_get_eof_pos(); 1573 1574 /* 1575 * Save capacity of cartridge 1576 */ 1577 drv->drv_avail = DRV_CALL(drv_get_avail_capacity, ()); 1578 drv->drv_pc_avail = (drv->drv_avail * 100) / drv->drv_capacity; 1579 drv->drv_flags |= DRV_UPDATE_CAPACITY; 1580 1581 if (DRV_CALL(drv_get_pos, (&pos)) != 0) { 1582 TRACE((MMS_ERR, "Can't read position")); 1583 return (EIO); 1584 } 1585 1586 ioctl(drv->drv_fd, MTIOCLRERR, 0); /* clear outstanding error */ 1587 if (drv->drv_lbl_type == DRV_NL) { 1588 /* write 2 tapemarks to terminate a NL tape */ 1589 for (i = 0; i < 2; i++) { 1590 if (DRV_CALL(drv_wtm, (2)) != 0) { 1591 DRV_CALL(drv_clrerr, ()); 1592 continue; 1593 } 1594 break; 1595 } 1596 if (i == 2) { 1597 TRACE((MMS_ERR, "Can't terminate cartridge")); 1598 rc = EIO; 1599 } 1600 } else { 1601 /* 1602 * Write EOF/EOV labels 1603 */ 1604 rc = dm_create_trailor_lbls(); 1605 } 1606 1607 /* 1608 * Reposition to the end of user data 1609 */ 1610 if (rc != 0) { 1611 DRV_CALL(drv_clrerr, ()); 1612 } 1613 if (DRV_CALL(drv_locate, (&drv->drv_eof_pos)) != 0) { 1614 TRACE((MMS_ERR, "Can't reposition to EOF")); 1615 rc = EIO; 1616 } 1617 if (dm_set_file_blksize(drv->drv_cur_blksize)) { 1618 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1619 "Set file blksize error")); 1620 rc = EIO; 1621 } 1622 drv->drv_flags &= ~DRV_TM; 1623 drv->drv_cur_pos = drv->drv_eof_pos; 1624 if (rc == 0) { 1625 /* 1626 * Successfully wrote trailor labels and return to end of 1627 * user data. We'er at EOF. 1628 */ 1629 drv->drv_flags |= DRV_EOF; 1630 } 1631 1632 return (rc); 1633 } 1634 1635 int 1636 dm_create_trailor_lbls(void) 1637 { 1638 int i; 1639 1640 for (i = 0; i < 2; i++) { 1641 if (DRV_CALL(drv_wtm, (1)) != 0) { 1642 if (serr->se_status == SUN_KEY_EOT && 1643 serr->se_resid == 1) { 1644 DRV_CALL(drv_wtm, (1)); 1645 } 1646 continue; 1647 } 1648 break; 1649 } 1650 if (i == 2) { 1651 TRACE((MMS_ERR, "Can't write terminating FM")); 1652 return (EIO); 1653 } 1654 1655 if (dm_set_label_blksize() != 0) { 1656 return (EIO); 1657 } 1658 1659 for (i = 0; i < 2; i++) { 1660 if (dm_create_eof1() != 0) { 1661 continue; 1662 } 1663 break; 1664 } 1665 if (i == 2) { 1666 return (EIO); 1667 } 1668 1669 for (i = 0; i < 2; i++) { 1670 if (dm_create_eof2() != 0) { 1671 continue; 1672 } 1673 break; 1674 } 1675 if (i == 2) { 1676 return (EIO); 1677 } 1678 1679 for (i = 0; i < 2; i++) { 1680 if (DRV_CALL(drv_wtm, (2)) != 0) { 1681 continue; 1682 } 1683 break; 1684 } 1685 if (i == 2) { 1686 return (EIO); 1687 } 1688 1689 return (0); 1690 } 1691 1692 /* 1693 * dm_read and dm_write are entered because we asked for it 1694 */ 1695 int 1696 dm_read(drm_reply_t *rep) 1697 { 1698 TRACE((MMS_DEBUG, "Starting to Read")); 1699 if (drv->drv_flags & DRV_FATAL) { 1700 return (EIO); 1701 } 1702 memset(rep, 0, sizeof (rep)); 1703 1704 if (drv->drv_flags & DRV_TERM_FILE) { 1705 /* 1706 * The previous movement command was an output command. 1707 * Let the driver fail this read. 1708 */ 1709 TRACE((MMS_ERR, "attempted read after write")); 1710 return (0); 1711 } 1712 /* 1713 * Notify when switching to output 1714 */ 1715 rep->drm_rep_flags |= DRM_REP_NOTIFY_WRITE; 1716 return (0); 1717 } 1718 1719 int 1720 dm_read_tm(drm_request_t *req) 1721 { 1722 uint64_t flags; 1723 char buf[4096]; 1724 tapepos_t cur_pos = drv->drv_cur_pos; 1725 1726 /* 1727 * Hit a tapemark. 1728 * Check to see if we reached EOF 1729 */ 1730 if (mnt->mnt_flags & MNT_NOBSD) { 1731 /* 1732 * Alway cross TM to check trailor labels 1733 */ 1734 DRV_CALL(drv_fsf, (1)); 1735 } 1736 1737 if (dm_set_label_blksize()) { 1738 goto err; 1739 } 1740 if (drv->drv_flags & DRV_VALID_EOF_POS) { 1741 if (DRV_CALL(drv_get_pos, (&cur_pos)) != 0) { 1742 goto err; 1743 } 1744 if (cur_pos.lgclblkno > drv->drv_eof_pos.lgclblkno) { 1745 if (DRV_CALL(drv_locate, (&drv->drv_eof_pos)) != 0) { 1746 goto err; 1747 } 1748 drv->drv_cur_pos = drv->drv_eof_pos; 1749 drv->drv_flags &= ~DRV_TM; 1750 drv->drv_flags |= DRV_EOF; 1751 } 1752 } else if (dm_chk_eof() == 0) { 1753 if (DRV_CALL(drv_bsf, (1)) != 0) { 1754 goto err; 1755 } 1756 drv->drv_cur_pos = cur_pos; 1757 drv->drv_flags &= ~DRV_TM; 1758 drv->drv_flags |= DRV_EOF; 1759 (void) dm_get_eof_pos(); 1760 } 1761 1762 if ((drv->drv_flags & DRV_EOF) == 0) { 1763 /* Not at EOF */ 1764 if (mnt->mnt_flags & MNT_NOBSD) { 1765 DRV_CALL(drv_bsf, (1)); 1766 read(drv->drv_fd, buf, sizeof (buf)); 1767 } 1768 drv->drv_flags |= DRV_TM; 1769 drv->drv_flags &= ~DRV_EOF; 1770 } 1771 1772 flags = drv->drv_flags & (DRV_TM | DRV_EOF); 1773 dm_get_mtstat(DRV_SAVE_STAT); 1774 drv->drv_flags &= ~(DRV_TM | DRV_EOF); 1775 drv->drv_flags |= flags; 1776 1777 drv->drv_mtget.drm_resid = req->drm_err_req.drm_resid; 1778 if (dm_set_file_blksize(drv->drv_cur_blksize)) { 1779 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1780 "Set file blksize error")); 1781 goto err; 1782 } 1783 return ((int)req->drm_err_req.drm_errno); 1784 1785 err: 1786 if (dm_set_file_blksize(drv->drv_cur_blksize)) { 1787 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1788 "Set file blksize error")); 1789 } 1790 drv->drv_mtget.drm_resid = req->drm_err_req.drm_resid; 1791 drv->drv_flags |= DRV_FATAL; 1792 TRACE((MMS_DEBUG, "FATAL error")); 1793 return (EIO); 1794 } 1795 1796 int 1797 dm_read_err(drm_request_t *req, drm_reply_t *rep) 1798 { 1799 TRACE((MMS_ERR, "Read error: resid = %lld, errno = %lld, %s", 1800 req->drm_err_req.drm_resid, req->drm_err_req.drm_errno, 1801 strerror(req->drm_err_req.drm_errno))); 1802 drv->drv_flags &= ~DRV_VALID_STAT; 1803 dm_get_mtstat(DRV_SAVE_STAT); 1804 dm_get_mt_error(EIO); 1805 DRV_CALL(drv_proc_error, ()); 1806 if (serr->se_senkey == KEY_HARDWARE_ERROR) { 1807 /* set DriveBroken to "yes" */ 1808 (void) dm_send_drive_broken(); 1809 } else if (serr->se_senkey == KEY_MEDIUM_ERROR) { 1810 /* Set CartridgeMediaError to "yes" */ 1811 (void) dm_send_cartridge_media_error(); 1812 } 1813 rep->drm_rep_flags |= DRM_REP_NOTIFY_WRITE; 1814 drv->drv_mtget.drm_resid = req->drm_err_req.drm_resid; 1815 return ((int)req->drm_err_req.drm_errno); 1816 1817 } 1818 1819 int 1820 dm_write(drm_reply_t *rep) 1821 { 1822 1823 TRACE((MMS_DEBUG, "In dm_write")); 1824 1825 if (drv->drv_flags & DRV_FATAL) { 1826 return (EIO); 1827 } 1828 1829 /* 1830 * Readonly, can't write to it 1831 */ 1832 if (drv->drv_flags & DRV_READONLY) { 1833 return (EACCES); 1834 } 1835 1836 memset(rep, 0, sizeof (rep)); 1837 drv->drv_flags |= DRV_TERM_FILE; 1838 drv->drv_flags &= ~DRV_VALID_EOF_POS; 1839 /* 1840 * DRV_UPDATE_EOF_POS is only set when valid eof flag is updated 1841 */ 1842 if ((drv->drv_flags & DRV_UPDATE_EOF_POS) == 0) { 1843 drv->drv_flags |= DRV_UPDATE_EOF_POS; 1844 (void) dm_send_eof_pos(); 1845 } 1846 /* 1847 * Notify when switching to input 1848 */ 1849 if (mnt->mnt_flags & MNT_MMS) { 1850 rep->drm_rep_flags |= DRM_REP_NOTIFY_READ; 1851 } 1852 drv->drv_flags &= ~DRV_MOVE_FLAGS; 1853 return (0); 1854 } 1855 1856 int 1857 dm_write_0(drm_request_t *req, drm_reply_t *rep) 1858 { 1859 TRACE((MMS_DEBUG, "In dm_write_0")); 1860 1861 memset(rep, 0, sizeof (rep)); 1862 dm_get_mtstat(DRV_SAVE_STAT); 1863 /* 1864 * Notify when switching to input 1865 */ 1866 rep->drm_rep_flags |= DRM_REP_NOTIFY_READ; 1867 drv->drv_mtget.drm_resid = req->drm_err_req.drm_resid; 1868 return ((int)req->drm_err_req.drm_errno); 1869 } 1870 1871 int 1872 dm_write_err(drm_request_t *req, drm_reply_t *rep) 1873 { 1874 TRACE((MMS_ERR, "Write error: resid = %lld, errno = %lld, %s", 1875 req->drm_err_req.drm_resid, req->drm_err_req.drm_errno, 1876 strerror(req->drm_err_req.drm_errno))); 1877 drv->drv_flags &= ~DRV_VALID_STAT; 1878 dm_get_mtstat(DRV_SAVE_STAT); 1879 dm_get_mt_error(EIO); 1880 DRV_CALL(drv_proc_error, ()); 1881 if (serr->se_senkey == KEY_HARDWARE_ERROR) { 1882 /* set DriveBroken to "yes" */ 1883 (void) dm_send_drive_broken(); 1884 } else if (serr->se_senkey == KEY_MEDIUM_ERROR) { 1885 /* Set CartridgeMediaError to "yes" */ 1886 (void) dm_send_cartridge_media_error(); 1887 } 1888 rep->drm_rep_flags |= DRM_REP_NOTIFY_READ; 1889 drv->drv_mtget.drm_resid = req->drm_err_req.drm_resid; 1890 return ((int)req->drm_err_req.drm_errno); 1891 } 1892 1893 int 1894 dm_create_vol1(void) 1895 { 1896 drv_vol1_t *vol1 = &drv->drv_vol1; 1897 char dumpbuf[MMS_DUMPBUF_SIZE(80)]; 1898 char *vp; 1899 char *buf; 1900 1901 memset(vol1, ' ', sizeof (drv_vol1_t)); 1902 strncpy(vol1->vol1_id, "VOL1", 4); 1903 if (mnt->mnt_vid == NULL) { 1904 vp = mnt->mnt_pcl; 1905 } else { 1906 vp = mnt->mnt_vid; 1907 } 1908 1909 buf = mms_strapp(NULL, 1910 "%-6.6s", vp); 1911 strncpy(vol1->vol1_vid, buf, 6); 1912 free(buf); 1913 vol1->vol1_acc = ' '; 1914 strncpy(vol1->vol1_impid, DRV_IMPID, 13); 1915 strncpy(vol1->vol1_owner, VOL1_OWNER, 14); 1916 vol1->vol1_ver = '4'; 1917 (void) mms_trace_dump((char *)vol1, 80, dumpbuf, sizeof (dumpbuf)); 1918 TRACE((MMS_DEBUG, "VOL1 label:\n%s", 1919 mms_trace_dump((char *)vol1, 80, dumpbuf, sizeof (dumpbuf)))); 1920 1921 if (DRV_CALL(drv_write, ((char *)vol1, 80)) != 80) { 1922 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 1923 "Unable to write VOL1 label")); 1924 return (EIO); 1925 } 1926 drv->drv_lbl_type = DRV_AL; 1927 TRACE((MMS_DEBUG, "Wrote VOL1")); 1928 strncpy(drv->drv_vid, vol1->vol1_vid, 6); 1929 drv->drv_flags |= (DRV_VOL1 | DRV_IDENTIFIED); 1930 drv->drv_fseq = 1; 1931 return (0); 1932 } 1933 1934 int 1935 dm_create_hdr1(void) 1936 { 1937 drv_hdr1_t *hdr1 = &drv->drv_hdr1; 1938 char *buf; 1939 char dumpbuf[MMS_DUMPBUF_SIZE(80)]; 1940 time_t curtime; 1941 struct tm tm; 1942 char *tmp; 1943 1944 memset(hdr1, ' ', sizeof (drv_hdr1_t)); 1945 1946 /* 1947 * Get creation date 1948 */ 1949 curtime = time(NULL); 1950 localtime_r(&curtime, &tm); 1951 if (tm.tm_year > 100) { 1952 tm.tm_year -= 100; 1953 hdr1->hdr1_cdate[0] = '0'; 1954 } else { 1955 hdr1->hdr1_cdate[0] = ' '; 1956 } 1957 tmp = mms_strapp(NULL, 1958 "%2.2d", tm.tm_year); 1959 strncpy(hdr1->hdr1_cdate + 1, tmp, 2); 1960 free(tmp); 1961 tmp = mms_strapp(NULL, 1962 "%3.3d", tm.tm_yday + 1); 1963 free(tmp); 1964 strncpy(hdr1->hdr1_cdate + 3, tmp, 3); 1965 1966 /* 1967 * Get expiration date 1968 */ 1969 if (drv->drv_retention == 0) { 1970 /* Don't use expiration date */ 1971 strncpy(hdr1->hdr1_xdate, "000000", 6); 1972 } else if (drv->drv_retention == 99999) { 1973 /* Never expires */ 1974 strncpy(hdr1->hdr1_xdate, "099366", 6); 1975 } else { 1976 /* expire time */ 1977 curtime += ((drv->drv_retention + 1) * 24 * 60 * 60); 1978 localtime_r(&curtime, &tm); 1979 if (tm.tm_year > 100) { 1980 tm.tm_year -= 100; 1981 hdr1->hdr1_xdate[0] = '0'; 1982 } else { 1983 hdr1->hdr1_xdate[0] = ' '; 1984 } 1985 tmp = mms_strapp(NULL, 1986 "%2.2d", tm.tm_year); 1987 strncpy(hdr1->hdr1_xdate + 1, tmp, 2); 1988 free(tmp); 1989 tmp = mms_strapp(NULL, 1990 "%3.3d", tm.tm_yday + 1); 1991 strncpy(hdr1->hdr1_xdate + 3, tmp, 3); 1992 free(tmp); 1993 } 1994 1995 strncpy(hdr1->hdr1_id, "HDR1", 4); 1996 strncpy(hdr1->hdr1_fid, mnt->mnt_fname, 17); 1997 strncpy(hdr1->hdr1_fsnum, "0001", 4); 1998 buf = mms_strapp(NULL, 1999 "%4.4d", mnt->mnt_fseq); 2000 strncpy(hdr1->hdr1_fseq, buf, 4); 2001 free(buf); 2002 strncpy(hdr1->hdr1_gnum, "0001", 4); 2003 strncpy(hdr1->hdr1_gver, "00", 2); 2004 strncpy(hdr1->hdr1_bcount, "000000", 6); 2005 strncpy(hdr1->hdr1_impid, DRV_IMPID, 13); 2006 (void) mms_trace_dump((char *)hdr1, 80, dumpbuf, sizeof (dumpbuf)); 2007 TRACE((MMS_DEBUG, "HDR1 label:\n%s", dumpbuf)); 2008 2009 2010 if (DRV_CALL(drv_write, ((char *)hdr1, 80)) != 80) { 2011 TRACE((MMS_ERR, "Unable to write HDR1 label")); 2012 return (EIO); 2013 } 2014 TRACE((MMS_DEBUG, "Wrote HDR1")); 2015 strncpy(drv->drv_fid, mnt->mnt_fname, 17); 2016 drv->drv_fid[17] = '\0'; 2017 drv->drv_flags |= (DRV_HDR1 | DRV_VALIDATED_FNAME); 2018 return (0); 2019 } 2020 2021 int 2022 dm_create_hdr2(void) 2023 { 2024 drv_hdr2_t *hdr2 = &drv->drv_hdr2; 2025 char *buf; 2026 char dumpbuf[MMS_DUMPBUF_SIZE(80)]; 2027 2028 memset(hdr2, ' ', 80); 2029 strncpy(hdr2->hdr2_id, "HDR2", 4); 2030 if (drv->drv_flags & DRV_FIXED) { 2031 hdr2->hdr2_rformat = 'F'; 2032 } else { 2033 hdr2->hdr2_rformat = 'D'; 2034 } 2035 2036 /* 2037 * Put file blksize in label 2038 */ 2039 drv->drv_lbl_blksize = drv->drv_file_blksize; 2040 if (mnt->mnt_blksize < 99999) { 2041 buf = mms_strapp(NULL, 2042 "%5.5d", drv->drv_lbl_blksize); 2043 strncpy(hdr2->hdr2_blklen, buf, sizeof (hdr2->hdr2_blklen)); 2044 strncpy(hdr2->hdr2_rcdlen, buf, sizeof (hdr2->hdr2_rcdlen)); 2045 free(buf); 2046 } else { 2047 strncpy(hdr2->hdr2_blklen, "99999", sizeof (hdr2->hdr2_blklen)); 2048 strncpy(hdr2->hdr2_rcdlen, "99999", sizeof (hdr2->hdr2_rcdlen)); 2049 } 2050 buf = mms_strapp(NULL, 2051 "%10.10d", drv->drv_lbl_blksize); 2052 strncpy(hdr2->hdr2_blksize, buf, sizeof (hdr2->hdr2_blksize)); 2053 free(buf); 2054 strncpy(hdr2->hdr2_off, "00", sizeof (hdr2->hdr2_off)); 2055 (void) mms_trace_dump((char *)hdr2, 80, dumpbuf, sizeof (dumpbuf)); 2056 TRACE((MMS_DEBUG, "HDR2 label:\n%s", dumpbuf)); 2057 2058 if (DRV_CALL(drv_write, ((char *)hdr2, 80)) != 80) { 2059 TRACE((MMS_ERR, "Unable to write HDR2 label")); 2060 return (EIO); 2061 } 2062 TRACE((MMS_DEBUG, "Wrote HDR2")); 2063 drv->drv_flags |= DRV_HDR2; 2064 return (0); 2065 } 2066 2067 int 2068 dm_create_eof1(void) 2069 { 2070 drv_eof1_t *eof1 = &drv->drv_eof1; 2071 char *buf; 2072 char dumpbuf[MMS_DUMPBUF_SIZE(80)]; 2073 2074 memset(eof1, ' ', sizeof (drv_eof1_t)); 2075 strncpy(eof1->eof1_id, "EOF1", 4); 2076 strncpy(eof1->eof1_fid, mnt->mnt_fname, 17); 2077 strncpy(eof1->eof1_fsnum, "0001", 4); 2078 buf = mms_strapp(NULL, 2079 "%4.4d", mnt->mnt_fseq); 2080 strncpy(eof1->eof1_fseq, buf, sizeof (eof1->eof1_fseq)); 2081 strncpy(eof1->eof1_gnum, "0001", sizeof (eof1->eof1_gnum)); 2082 strncpy(eof1->eof1_gver, "00", sizeof (eof1->eof1_gver)); 2083 strncpy(eof1->eof1_cdate, drv->drv_hdr1.hdr1_cdate, 2084 sizeof (eof1->eof1_cdate)); 2085 strncpy(eof1->eof1_xdate, drv->drv_hdr1.hdr1_xdate, 2086 sizeof (eof1->eof1_xdate)); 2087 strncpy(eof1->eof1_bcount, "000000", sizeof (eof1->eof1_bcount)); 2088 strncpy(eof1->eof1_impid, DRV_IMPID, sizeof (eof1->eof1_impid)); 2089 free(buf); 2090 (void) mms_trace_dump((char *)eof1, 80, dumpbuf, sizeof (dumpbuf)); 2091 TRACE((MMS_DEBUG, "EOF1 label:\n%s", dumpbuf)); 2092 2093 if (DRV_CALL(drv_write, ((char *)eof1, 80)) != 80) { 2094 TRACE((MMS_ERR, "Unable to write EOF1 label")); 2095 return (EIO); 2096 } 2097 TRACE((MMS_DEBUG, "Wrote EOF1")); 2098 strncpy(drv->drv_fid, mnt->mnt_fname, sizeof (drv->drv_fid)); 2099 drv->drv_fid[17] = '\0'; 2100 drv->drv_flags |= DRV_EOF1; 2101 return (0); 2102 } 2103 2104 int 2105 dm_create_eof2(void) 2106 { 2107 drv_eof2_t *eof2 = &drv->drv_eof2; 2108 char *buf; 2109 char dumpbuf[MMS_DUMPBUF_SIZE(80)]; 2110 2111 memset(eof2, ' ', 80); 2112 strncpy(eof2->eof2_id, "EOF2", 4); 2113 if (drv->drv_flags & DRV_FIXED) { 2114 eof2->eof2_rformat = 'F'; 2115 } else { 2116 eof2->eof2_rformat = 'D'; 2117 } 2118 if (mnt->mnt_blksize < 99999) { 2119 buf = mms_strapp(NULL, 2120 "%5.5d", drv->drv_lbl_blksize); 2121 strncpy(eof2->eof2_blklen, buf, sizeof (eof2->eof2_blklen)); 2122 strncpy(eof2->eof2_rcdlen, buf, sizeof (eof2->eof2_blklen)); 2123 free(buf); 2124 } else { 2125 strncpy(eof2->eof2_blklen, "99999", sizeof (eof2->eof2_blklen)); 2126 strncpy(eof2->eof2_rcdlen, "99999", sizeof (eof2->eof2_blklen)); 2127 } 2128 buf = mms_strapp(NULL, 2129 "%10.10d", drv->drv_lbl_blksize); 2130 strncpy(eof2->eof2_blksize, buf, sizeof (eof2->eof2_blksize)); 2131 strncpy(eof2->eof2_off, "00", sizeof (eof2->eof2_off)); 2132 free(buf); 2133 (void) mms_trace_dump((char *)eof2, 80, dumpbuf, sizeof (dumpbuf)); 2134 TRACE((MMS_DEBUG, "EOF2 label:\n%s", dumpbuf)); 2135 2136 if (DRV_CALL(drv_write, ((char *)eof2, 80)) != 80) { 2137 TRACE((MMS_ERR, "Unable to write EOF2 label")); 2138 return (EIO); 2139 } 2140 TRACE((MMS_DEBUG, "Wrote EOF2")); 2141 drv->drv_flags |= DRV_EOF2; 2142 return (0); 2143 } 2144 2145 int 2146 dm_rewind_file(void) 2147 { 2148 if ((drv->drv_flags & DRV_UDATA) == 0) { 2149 /* 2150 * Must be in user data to rewind 2151 */ 2152 TRACE((MMS_ERR, "Not in user data. Can't rewind file")); 2153 return (EACCES); 2154 } 2155 2156 if ((drv->drv_flags & DRV_VALID_BOF_POS) == 0) { 2157 /* 2158 * Must have valid BOF position 2159 */ 2160 TRACE((MMS_ERR, 2161 "Don't have BOF position. Can't rewind file")); 2162 return (EACCES); 2163 } 2164 2165 if (drv->drv_flags & DRV_BOF) { 2166 /* Already at BOF */ 2167 return (0); 2168 } 2169 if (DRV_CALL(drv_locate, (&drv->drv_bof_pos))) { 2170 TRACE((MMS_ERR, "Rewind file error")); 2171 return (EIO); 2172 } 2173 if (DRV_CALL(drv_bsb, (1, DRV_LOGICAL_CROSS_TM)) != 0) { 2174 if ((drv->drv_flags & DRV_TM)) { 2175 /* Hit a TM */ 2176 DRV_CALL(drv_fsf, (1)); 2177 } else if ((drv->drv_flags & DRV_BOM) == 0) { 2178 /* Did not hit BOM. Must be an error */ 2179 return (EIO); 2180 } 2181 } else { 2182 /* Not at BOF */ 2183 return (EIO); 2184 } 2185 2186 drv->drv_mtget.drm_resid = 0; 2187 drv->drv_flags &= ~(DRV_BOM | DRV_TM); 2188 drv->drv_flags |= DRV_BOF; 2189 2190 drv->drv_cur_pos = drv->drv_bof_pos; 2191 2192 return (0); 2193 } 2194 2195 int 2196 dm_ioctl_clrerr(drm_reply_t *rep) 2197 { 2198 int rc = 0; 2199 2200 memset(rep, 0, sizeof (drm_reply_t)); 2201 rc = DRV_CALL(drv_clrerr, ()); 2202 return (rc); 2203 } 2204 2205 int 2206 dm_ioctl_mtget(drm_request_t *req, drm_reply_t *rep) 2207 { 2208 if ((req->drm_req_flags & DRM_REQ_MOVED) || 2209 (drv->drv_flags & DRV_VALID_STAT) == 0) { 2210 /* If tape moved since last signal, get new status */ 2211 drv->drv_flags &= ~DRV_VALID_STAT; 2212 dm_get_mtstat(DRV_SAVE_STAT); 2213 } 2214 2215 memcpy(&rep->drm_mtget_rep, &drv->drv_mtget, sizeof (drm_mtget_t)); 2216 2217 if (drv->drv_flags & DRV_BOF) { 2218 rep->drm_mtget_rep.drm_erreg = SUN_KEY_BOT; 2219 } else if (drv->drv_flags & DRV_EOF) { 2220 rep->drm_mtget_rep.drm_erreg = SUN_KEY_EOT; 2221 } else if (drv->drv_flags & DRV_TM) { 2222 rep->drm_mtget_rep.drm_erreg = SUN_KEY_EOF; 2223 } 2224 2225 return (0); 2226 } 2227 2228 int 2229 dm_ioctl_rewind(void) 2230 { 2231 int rc = 0; 2232 2233 if (drv->drv_flags & DRV_FATAL) { 2234 return (EIO); 2235 } 2236 2237 drv->drv_flags &= ~(DRV_VALID_STAT | DRV_MOVE_FLAGS); 2238 if (drv->drv_flags & DRV_TERM_FILE) { 2239 if (dm_terminate_file() != 0) { 2240 TRACE((MMS_ERR, "Unable to terminate file")); 2241 rc = EIO; 2242 } 2243 drv->drv_flags &= ~DRV_TERM_FILE; 2244 } 2245 2246 rc = dm_rewind_file(); 2247 2248 return (rc); 2249 } 2250 2251 int 2252 dm_ioctl_fsf(int count) 2253 { 2254 int rc = 0; 2255 char buf[80]; 2256 int bytes; 2257 int i; 2258 2259 drv->drv_mtget.drm_resid = count; 2260 if (drv->drv_flags & DRV_FATAL) { 2261 return (EIO); 2262 } 2263 2264 drv->drv_flags &= ~(DRV_VALID_STAT | DRV_MOVE_FLAGS); 2265 drv->drv_flags &= ~DRV_EOF; 2266 if (dm_set_label_blksize()) { 2267 return (EIO); 2268 } 2269 for (i = 0; i < count; i++) { 2270 if (DRV_CALL(drv_fsf, (1)) != 0) { 2271 rc = EIO; 2272 break; 2273 } 2274 /* 2275 * Try to read the next block to see if it is a trailor label. 2276 */ 2277 while ((drv->drv_flags & DRV_EOF) == 0) { 2278 if ((bytes = DRV_CALL(drv_read, (buf, 80))) == 80) { 2279 if (strncmp(buf, "EOF1", 4) == 0 || 2280 strncmp(buf, "EOV1", 4) == 0) { 2281 /* Read trailor label */ 2282 /* Reposition to EOF */ 2283 TRACE((MMS_DEBUG, "Found EOF1/EOV1")); 2284 DRV_CALL(drv_bsf, (1)); 2285 drv->drv_flags &= ~DRV_TM; 2286 drv->drv_flags |= DRV_EOF; 2287 (void) dm_get_eof_pos(); 2288 rc = EIO; 2289 break; 2290 } 2291 } 2292 2293 if (bytes > 0) { 2294 /* 2295 * Read something other than a label 2296 */ 2297 if (i == (count - 1)) { 2298 /* 2299 * Spaced requested TM 2300 */ 2301 DRV_CALL(drv_bsb, 2302 (1, DRV_LOGICAL_CROSS_TM)); 2303 } 2304 break; 2305 } else if (drv->drv_flags & DRV_TM) { 2306 /* Read another tapemark */ 2307 drv->drv_flags &= ~DRV_TM; 2308 if (i == (count - 1)) { 2309 /* 2310 * Spaced requested TM 2311 */ 2312 DRV_CALL(drv_bsf, (1)); 2313 drv->drv_flags |= DRV_TM; 2314 break; 2315 } else { 2316 i++; /* skipped another TM */ 2317 } 2318 continue; /* try to read label again */ 2319 } else if (rc < 0) { 2320 if (serr->se_senkey == SUN_KEY_EOT || 2321 serr->se_senkey == KEY_BLANK_CHECK) { 2322 /* Hit EOM or blank check */ 2323 TRACE((MMS_DEBUG, 2324 "Hit EOT/BLANK CHECK")); 2325 drv->drv_flags |= DRV_EOF; 2326 if (dm_get_eof_pos()) { 2327 rc = EIO; 2328 goto done; 2329 } 2330 break; 2331 } else { 2332 /* Other error */ 2333 rc = EIO; 2334 goto done; 2335 } 2336 } else { 2337 /* 2338 * Some unknown error 2339 */ 2340 rc = EIO; 2341 break; 2342 } 2343 } 2344 2345 /* 2346 * Done if we are at EOF 2347 */ 2348 if (drv->drv_flags & DRV_EOF) { 2349 break; 2350 } 2351 } 2352 2353 2354 done: 2355 dm_get_mtstat(DRV_SAVE_STAT); 2356 if (dm_set_file_blksize(drv->drv_cur_blksize)) { 2357 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 2358 "Set file blksize error")); 2359 rc = EIO; 2360 } 2361 drv->drv_mtget.drm_resid = count - i; 2362 2363 return (rc); 2364 } 2365 2366 int 2367 dm_ioctl_fsb(int count) 2368 { 2369 uint64_t flags; 2370 uint64_t resid = 0; 2371 int rc = 0; 2372 tapepos_t pos; 2373 2374 if (drv->drv_flags & DRV_FATAL) { 2375 return (EIO); 2376 } 2377 2378 drv->drv_flags &= ~DRV_VALID_STAT; 2379 drv->drv_flags &= ~DRV_MOVE_FLAGS; 2380 2381 if (dm_set_label_blksize()) { 2382 return (EIO); 2383 } 2384 if (DRV_CALL(drv_fsb, (count, DRV_LOGICAL_CROSS_TM)) != 0) { 2385 resid = serr->se_resid; 2386 if (drv->drv_flags & DRV_TM) { 2387 /* 2388 * Hit a tapemark. 2389 * Check to see if we reached EOF 2390 */ 2391 DRV_CALL(drv_get_pos, (&pos)); 2392 if (drv->drv_flags & DRV_VALID_EOF_POS) { 2393 if (pos.lgclblkno >= 2394 drv->drv_eof_pos.lgclblkno) { 2395 /* passed EOF position */ 2396 DRV_CALL(drv_bsf, (1)); 2397 drv->drv_flags &= ~DRV_TM; 2398 drv->drv_flags |= DRV_EOF; 2399 drv->drv_cur_pos = drv->drv_eof_pos; 2400 } 2401 } else if (dm_chk_eof() == 0) { 2402 /* Not at EOF, check if at EOF */ 2403 DRV_CALL(drv_bsf, (1)); 2404 drv->drv_flags &= ~DRV_TM; 2405 drv->drv_flags |= DRV_EOF; 2406 } 2407 /* 2408 * If at EOF, and don't have EOF position, get it 2409 */ 2410 if (drv->drv_flags & DRV_EOF) { 2411 if ((drv->drv_flags & DRV_VALID_EOF_POS) == 0) { 2412 (void) dm_get_eof_pos(); 2413 drv->drv_cur_pos = drv->drv_eof_pos; 2414 } 2415 } else { 2416 /* 2417 * If not at EOF, must have hit a TM 2418 */ 2419 drv->drv_flags |= DRV_TM; 2420 /* 2421 * Deal with Solaris BSB/NOBSD behavior 2422 */ 2423 if ((mnt->mnt_flags & MNT_MMS_TM) == 0) { 2424 /* Not MMS TM, then do not cross TM */ 2425 DRV_CALL(drv_bsf, (1)); 2426 DRV_CALL(drv_fsb, 2427 (1, ~DRV_LOGICAL_CROSS_TM)); 2428 } 2429 } 2430 } 2431 rc = EIO; 2432 } 2433 2434 if (dm_set_file_blksize(drv->drv_cur_blksize)) { 2435 DM_MSG_ADD((MMS_INTERNAL, MMS_DM_E_INTERNAL, 2436 "Set file blksize error")); 2437 rc = EIO; 2438 } 2439 flags = drv->drv_flags & (DRV_EOF | DRV_TM); 2440 dm_get_mtstat(DRV_SAVE_STAT); 2441 drv->drv_flags &= ~(DRV_EOF | DRV_TM); 2442 drv->drv_flags |= flags; 2443 drv->drv_mtget.drm_resid = resid; 2444 2445 return (rc); 2446 } 2447 2448 int 2449 dm_ioctl_bsf(int count) 2450 { 2451 int rc = 0; 2452 int i; 2453 tapepos_t pos; 2454 2455 if (drv->drv_flags & DRV_FATAL) { 2456 return (EIO); 2457 } 2458 if (drv->drv_flags & DRV_TERM_FILE) { 2459 if (dm_terminate_file() != 0) { 2460 TRACE((MMS_ERR, "Write trailor label error")); 2461 rc = EIO; 2462 } 2463 drv->drv_flags &= ~DRV_TERM_FILE; 2464 } 2465 2466 drv->drv_flags &= ~DRV_VALID_STAT; 2467 drv->drv_flags &= ~DRV_MOVE_FLAGS; 2468 for (i = 0; i < count; i++) { 2469 DRV_CALL(drv_bsf, (1)); 2470 DRV_CALL(drv_get_pos, (&pos)); 2471 if (pos.lgclblkno < drv->drv_bof_pos.lgclblkno) { 2472 DRV_CALL(drv_locate, (&drv->drv_bof_pos)); 2473 drv->drv_flags |= DRV_BOF; 2474 drv->drv_cur_pos = drv->drv_bof_pos; 2475 rc = EIO; 2476 break; 2477 } 2478 } 2479 2480 dm_get_mtstat(DRV_SAVE_STAT); 2481 drv->drv_mtget.drm_resid = count - i; 2482 if (serr->se_resid == 0) { 2483 drv->drv_flags |= DRV_TM; 2484 } 2485 2486 return (rc); 2487 } 2488 2489 int 2490 dm_ioctl_bsb(int count) 2491 { 2492 tapepos_t pos; 2493 int cross; 2494 int resid = 0; 2495 int flags; 2496 int rc = 0; 2497 int err = 0; 2498 2499 if (drv->drv_flags & DRV_FATAL) { 2500 return (EIO); 2501 } 2502 2503 if (drv->drv_flags & DRV_TERM_FILE) { 2504 if (dm_terminate_file() != 0) { 2505 TRACE((MMS_ERR, "Write trailor label error")); 2506 return (EIO); 2507 } 2508 drv->drv_flags &= ~DRV_TERM_FILE; 2509 } 2510 2511 drv->drv_flags &= ~DRV_VALID_STAT; 2512 drv->drv_flags &= ~DRV_MOVE_FLAGS; 2513 if (mnt->mnt_flags & MNT_MMS_TM) { 2514 cross = DRV_LOGICAL_CROSS_TM; 2515 } else { 2516 cross = ~DRV_LOGICAL_CROSS_TM; 2517 } 2518 if (DRV_CALL(drv_bsb, (count, cross)) != 0) { 2519 err = errno; 2520 resid = serr->se_resid; 2521 if (drv->drv_flags & DRV_TM) { 2522 /* Hit a tapemark */ 2523 DRV_CALL(drv_get_pos, (&pos)); 2524 if (pos.lgclblkno <= drv->drv_bof_pos.lgclblkno) { 2525 if (DRV_CALL(drv_locate, (&drv->drv_bof_pos))) { 2526 /* Failed to reposition */ 2527 rc = EIO; 2528 } else { 2529 drv->drv_flags &= ~DRV_TM; 2530 drv->drv_flags |= DRV_BOF; 2531 drv->drv_cur_pos = drv->drv_bof_pos; 2532 } 2533 } 2534 } 2535 rc = EIO; 2536 errno = err; 2537 } 2538 2539 flags = drv->drv_flags & (DRV_TM | DRV_BOF); 2540 dm_get_mtstat(DRV_SAVE_STAT); 2541 drv->drv_flags &= ~(DRV_TM | DRV_BOF); 2542 drv->drv_flags |= flags; 2543 drv->drv_mtget.drm_resid = resid; 2544 2545 return (rc); 2546 } 2547 2548 int 2549 dm_ioctl_seek(int count) 2550 { 2551 int rc = 0; 2552 uint64_t flags; 2553 2554 if (drv->drv_flags & DRV_FATAL) { 2555 return (EIO); 2556 } 2557 2558 if (drv->drv_flags & DRV_TERM_FILE) { 2559 if (dm_terminate_file() != 0) { 2560 TRACE((MMS_ERR, "Write trailor label error")); 2561 return (EIO); 2562 } 2563 drv->drv_flags &= ~DRV_TERM_FILE; 2564 } 2565 2566 drv->drv_flags &= ~DRV_VALID_STAT; 2567 drv->drv_flags &= ~DRV_MOVE_FLAGS; 2568 2569 rc = DRV_CALL(drv_seek, ((uint64_t)count)); 2570 if (rc) { 2571 DM_MSG_SEND((DM_ADM_ERR, DM_6522_MSG, DM_MSG_REASON)); 2572 rc = EIO; 2573 } 2574 2575 flags = drv->drv_flags & (DRV_TM | DRV_BOF); 2576 dm_get_mtstat(DRV_SAVE_STAT); 2577 drv->drv_flags &= ~(DRV_TM | DRV_BOF); 2578 drv->drv_flags |= flags; 2579 2580 return (rc); 2581 } 2582 2583 int 2584 dm_ioctl_wtm(int count) 2585 { 2586 int rc = 0; 2587 int resid = 0; 2588 2589 if (drv->drv_flags & DRV_FATAL) { 2590 return (EIO); 2591 } 2592 2593 /* 2594 * Readonly, can't write to it 2595 */ 2596 if (drv->drv_flags & DRV_READONLY) { 2597 if (count > 0) { 2598 return (EACCES); 2599 } 2600 } 2601 2602 drv->drv_flags &= ~DRV_MOVE_FLAGS; 2603 drv->drv_flags &= ~DRV_VALID_EOF_POS; 2604 drv->drv_flags &= ~DRV_VALID_STAT; 2605 if (count > 0) { 2606 /* Terminate file if writing TM to tape */ 2607 drv->drv_flags |= DRV_TERM_FILE; 2608 } 2609 2610 if (DRV_CALL(drv_wtm, (count)) != 0) { 2611 resid = serr->se_resid; 2612 rc = EIO; 2613 } 2614 dm_get_mtstat(DRV_SAVE_STAT); 2615 if (resid != count) { 2616 /* Wrote some TM */ 2617 drv->drv_flags |= DRV_TM; 2618 } 2619 drv->drv_mtget.drm_resid = resid; 2620 2621 return (rc); 2622 } 2623 2624 int 2625 dm_ioctl_set_blksize(uint64_t blksize) 2626 { 2627 int rc; 2628 2629 rc = DRV_CALL(drv_set_blksize, (blksize)); 2630 2631 if (rc) { 2632 DM_MSG_SEND((DM_ADM_ERR, DM_6513_MSG, DM_MSG_REASON)); 2633 return (rc); 2634 } 2635 if ((drv->drv_cur_blksize = blksize) == 0) { 2636 drv->drv_flags &= ~DRV_FIXED; 2637 } else { 2638 drv->drv_flags |= DRV_FIXED; 2639 } 2640 return (0); 2641 } 2642 2643 int 2644 dm_ioctl_getpos(drm_reply_t *rep) 2645 { 2646 tapepos_t pos; 2647 2648 if (drv->drv_flags & DRV_FATAL) { 2649 return (EIO); 2650 } 2651 2652 if (DRV_CALL(drv_get_pos, (&pos)) != 0) { 2653 return (EIO); 2654 } 2655 rep->drm_pos_rep.mms_pos = pos.lgclblkno; 2656 2657 return (0); 2658 } 2659 2660 int 2661 dm_ioctl_mtgetpos(drm_reply_t *rep) 2662 { 2663 if (drv->drv_flags & DRV_FATAL) { 2664 return (EIO); 2665 } 2666 2667 if (DRV_CALL(drv_get_pos, (&rep->drm_mtpos_rep)) != 0) { 2668 return (EIO); 2669 } 2670 2671 return (0); 2672 } 2673 2674 int 2675 dm_ioctl_mtrestpos(drm_request_t *req) 2676 { 2677 if (drv->drv_flags & DRV_FATAL) { 2678 return (EIO); 2679 } 2680 2681 if (DRV_CALL(drv_locate, (&req->drm_mtpos_req)) != 0) { 2682 return (EIO); 2683 } 2684 2685 return (0); 2686 } 2687 2688 int 2689 dm_ioctl_locate(drm_request_t *req) 2690 { 2691 int rc = 0; 2692 uint64_t blkno = req->drm_pos_req.mms_pos; 2693 tapepos_t pos; 2694 2695 if (drv->drv_flags & DRV_FATAL) { 2696 return (EIO); 2697 } 2698 2699 if ((drv->drv_flags & DRV_VALID_EOF_POS) && 2700 drv->drv_eof_pos.lgclblkno < blkno) { 2701 TRACE((MMS_ERR, "Invalid locate to position: %lld", 2702 blkno)); 2703 return (EINVAL); 2704 } 2705 if (drv->drv_flags & DRV_TERM_FILE) { 2706 if (dm_terminate_file() != 0) { 2707 TRACE((MMS_ERR, "Unable to terminate file")); 2708 rc = EIO; 2709 } 2710 drv->drv_flags &= ~DRV_TERM_FILE; 2711 } 2712 2713 memset(&pos, 0, sizeof (tapepos_t)); 2714 pos.lgclblkno = blkno; 2715 pos.eof = ST_NO_EOF; 2716 pos.pmode = logical; 2717 if (DRV_CALL(drv_locate, (&pos)) != 0) { 2718 rc = EIO; 2719 } 2720 return (rc); 2721 } 2722 2723 int 2724 dm_ioctl_get_capacity(drm_reply_t *rep) 2725 { 2726 int rc = 0; 2727 mms_capacity_t *cap = &rep->drm_cap_rep; 2728 2729 if (DRV_CALL(drv_get_capacity, (cap)) != 0) { 2730 rc = EIO; 2731 } 2732 return (rc); 2733 } 2734 2735 int 2736 dm_ioctl_upt_capacity(void) 2737 { 2738 int rc = 0; 2739 2740 if (dm_update_capacity() != 0) { 2741 rc = EIO; 2742 } 2743 return (rc); 2744 } 2745 2746 int 2747 dm_ioctl_set_density(void) 2748 { 2749 int rc = 0; 2750 2751 if (drv->drv_flags & DRV_FATAL) { 2752 return (EIO); 2753 } 2754 2755 if ((mnt->mnt_flags & MNT_AUTO_DEN) == 0) { 2756 if (DRV_CALL(drv_set_density, 2757 (mnt->mnt_density->sym_code)) != 0) { 2758 drv->drv_flags |= DRV_FATAL; 2759 TRACE((MMS_DEBUG, "FATAL error")); 2760 rc = EIO; 2761 } 2762 } 2763 return (rc); 2764 } 2765 2766 int 2767 dm_ioctl_get_density(drm_reply_t *rep) 2768 { 2769 int rc = 0; 2770 int den; 2771 2772 if (DRV_CALL(drv_get_density, (&den, NULL)) != 0) { 2773 rc = EIO; 2774 } else { 2775 rep->drm_den_rep = den; 2776 } 2777 return (rc); 2778 } 2779 2780 void 2781 dm_clear_dev(void) 2782 { 2783 int i; 2784 2785 /* 2786 * Get rid of all attentions 2787 */ 2788 for (i = 0; i < 10; i++) { 2789 DRV_CALL(drv_tur, ()); 2790 } 2791 } 2792 2793 int 2794 dm_set_label_blksize(void) 2795 { 2796 if (DRV_CALL(drv_set_blksize, (0)) != 0) { 2797 return (EIO); 2798 } 2799 if (DRV_CALL(drv_set_compression, (0)) != 0) { 2800 return (EIO); 2801 } 2802 return (0); 2803 } 2804 2805 int 2806 dm_set_file_blksize(int blksize) 2807 { 2808 int rc; 2809 int comp; 2810 int bz; 2811 drm_blksize_t blk; 2812 2813 if (drv->drv_flags & DRV_FATAL) { 2814 return (EIO); 2815 } 2816 2817 /* 2818 * If blksize == -1, determine the blocksize. 2819 * If blksize >= 0, use blksize 2820 */ 2821 if (blksize == -1) { 2822 if (drv->drv_file_blksize <= 0) { 2823 drv->drv_file_blksize = drv->drv_dflt_blksize; 2824 } 2825 2826 if (drv->drv_flags & DRV_FIXED) { 2827 bz = drv->drv_file_blksize; 2828 } else { 2829 bz = 0; 2830 } 2831 } else { 2832 bz = blksize; 2833 } 2834 2835 /* 2836 * Set tape compression 2837 */ 2838 comp = (mnt->mnt_flags & MNT_COMPRESSION) ? 1 : 0; 2839 2840 if (DRV_CALL(drv_set_blksize, (bz)) != 0) { 2841 TRACE((MMS_ERR, "Unable to set tape blksize")); 2842 return (EIO); 2843 } else if (DRV_CALL(drv_set_compression, (comp)) != 0) { 2844 TRACE((MMS_ERR, "Unable to set tape compression: %d", 2845 comp)); 2846 return (EIO); 2847 } else { 2848 drv->drv_cur_blksize = bz; 2849 blk.drm_fixed = (drv->drv_flags & DRV_FIXED) ? 1 : 0; 2850 blk.drm_blksize = drv->drv_file_blksize; 2851 rc = ioctl(drv->drv_fd, DRM_BLKSIZE, &blk); 2852 TRACE((MMS_DEBUG, "Max blksize %lld", blk.drm_blksize)); 2853 } 2854 2855 return (rc == 0 ? 0 : EIO); 2856 } 2857