mt.c revision 92764
144290Swollman/* 244290Swollman * Copyright (c) 1980, 1993 344290Swollman * The Regents of the University of California. All rights reserved. 444290Swollman * 544290Swollman * Redistribution and use in source and binary forms, with or without 644290Swollman * modification, are permitted provided that the following conditions 744290Swollman * are met: 844290Swollman * 1. Redistributions of source code must retain the above copyright 944290Swollman * notice, this list of conditions and the following disclaimer. 1044290Swollman * 2. Redistributions in binary form must reproduce the above copyright 1144290Swollman * notice, this list of conditions and the following disclaimer in the 1244290Swollman * documentation and/or other materials provided with the distribution. 1344290Swollman * 3. All advertising materials mentioning features or use of this software 1444290Swollman * must display the following acknowledgement: 1544290Swollman * This product includes software developed by the University of 1644290Swollman * California, Berkeley and its contributors. 1744290Swollman * 4. Neither the name of the University nor the names of its contributors 1844290Swollman * may be used to endorse or promote products derived from this software 1944290Swollman * without specific prior written permission. 2044290Swollman * 2144290Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2244290Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2344290Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2444290Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2544290Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2644290Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2744290Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2844290Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2944290Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3044290Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3144290Swollman * SUCH DAMAGE. 3244290Swollman */ 3344290Swollman 3444290Swollman#ifndef lint 3544290Swollmanstatic const char copyright[] = 3644290Swollman"@(#) Copyright (c) 1980, 1993\n\ 3744290Swollman The Regents of the University of California. All rights reserved.\n"; 3844290Swollman#endif /* not lint */ 3944290Swollman 4044290Swollman#ifndef lint 4144290Swollman#if 0 4244290Swollmanstatic char sccsid[] = "@(#)mt.c 8.2 (Berkeley) 5/4/95"; 4344290Swollman#endif 4444290Swollmanstatic const char rcsid[] = 4544290Swollman "$FreeBSD: head/usr.bin/mt/mt.c 92764 2002-03-20 07:44:09Z phk $"; 4644290Swollman#endif /* not lint */ 4744290Swollman 4844290Swollman/* 4944290Swollman * mt -- 5044290Swollman * magnetic tape manipulation program 5144290Swollman */ 5244290Swollman#include <sys/types.h> 5344290Swollman#include <sys/ioctl.h> 5444290Swollman#include <sys/mtio.h> 5544290Swollman 5644290Swollman#include <ctype.h> 5744290Swollman#include <err.h> 5844290Swollman#include <fcntl.h> 5944290Swollman#include <stdio.h> 6044290Swollman#include <stdlib.h> 6144290Swollman#include <string.h> 62#include <unistd.h> 63 64/* the appropriate sections of <sys/mtio.h> are also #ifdef'd for FreeBSD */ 65/* c_flags */ 66#define NEED_2ARGS 0x01 67#define ZERO_ALLOWED 0x02 68#define IS_DENSITY 0x04 69#define DISABLE_THIS 0x08 70#define IS_COMP 0x10 71 72#ifndef TRUE 73#define TRUE 1 74#endif 75#ifndef FALSE 76#define FALSE 0 77#endif 78 79struct commands { 80 char *c_name; 81 int c_code; 82 int c_ronly; 83 int c_flags; 84} com[] = { 85 { "bsf", MTBSF, 1 }, 86 { "bsr", MTBSR, 1 }, 87 /* XXX FreeBSD considered "eof" dangerous, since it's being 88 confused with "eom" (and is an alias for "weof" anyway) */ 89 { "eof", MTWEOF, 0, DISABLE_THIS }, 90 { "fsf", MTFSF, 1 }, 91 { "fsr", MTFSR, 1 }, 92 { "offline", MTOFFL, 1 }, 93 { "rewind", MTREW, 1 }, 94 { "rewoffl", MTOFFL, 1 }, 95 { "status", MTNOP, 1 }, 96 { "weof", MTWEOF, 0, ZERO_ALLOWED }, 97 { "erase", MTERASE, 0, ZERO_ALLOWED}, 98 { "blocksize", MTSETBSIZ, 0, NEED_2ARGS|ZERO_ALLOWED }, 99 { "density", MTSETDNSTY, 0, NEED_2ARGS|ZERO_ALLOWED|IS_DENSITY }, 100 { "eom", MTEOD, 1 }, 101 { "eod", MTEOD, 1 }, 102 { "smk", MTWSS, 0 }, 103 { "wss", MTWSS, 0 }, 104 { "fss", MTFSS, 1 }, 105 { "bss", MTBSS, 1 }, 106 { "comp", MTCOMP, 0, NEED_2ARGS|ZERO_ALLOWED|IS_COMP }, 107 { "retension", MTRETENS, 1 }, 108 { "rdhpos", MTIOCRDHPOS, 0 }, 109 { "rdspos", MTIOCRDSPOS, 0 }, 110 { "sethpos", MTIOCHLOCATE, 0, NEED_2ARGS|ZERO_ALLOWED }, 111 { "setspos", MTIOCSLOCATE, 0, NEED_2ARGS|ZERO_ALLOWED }, 112 { "errstat", MTIOCERRSTAT, 0 }, 113 { "setmodel", MTIOCSETEOTMODEL, 0, NEED_2ARGS|ZERO_ALLOWED }, 114 { "seteotmodel", MTIOCSETEOTMODEL, 0, NEED_2ARGS|ZERO_ALLOWED }, 115 { "getmodel", MTIOCGETEOTMODEL }, 116 { "geteotmodel", MTIOCGETEOTMODEL }, 117 { NULL } 118}; 119 120void printreg __P((char *, u_int, char *)); 121void status __P((struct mtget *)); 122void usage __P((void)); 123void st_status (struct mtget *); 124int stringtodens (const char *s); 125const char *denstostring (int d); 126int denstobp(int d, int bpi); 127u_int32_t stringtocomp(const char *s); 128const char * comptostring(u_int32_t comp); 129void warn_eof __P((void)); 130 131int 132main(argc, argv) 133 int argc; 134 char *argv[]; 135{ 136 register struct commands *comp; 137 struct mtget mt_status; 138 struct mtop mt_com; 139 int ch, len, mtfd; 140 char *p, *tape; 141 142 if ((tape = getenv("TAPE")) == NULL) 143 tape = DEFTAPE; 144 145 while ((ch = getopt(argc, argv, "f:t:")) != -1) 146 switch(ch) { 147 case 'f': 148 case 't': 149 tape = optarg; 150 break; 151 case '?': 152 default: 153 usage(); 154 } 155 argc -= optind; 156 argv += optind; 157 158 if (argc < 1 || argc > 2) 159 usage(); 160 161 len = strlen(p = *argv++); 162 for (comp = com;; comp++) { 163 if (comp->c_name == NULL) 164 errx(1, "%s: unknown command", p); 165 if (strncmp(p, comp->c_name, len) == 0) 166 break; 167 } 168 if((comp->c_flags & NEED_2ARGS) && argc != 2) 169 usage(); 170 if(comp->c_flags & DISABLE_THIS) { 171 warn_eof(); 172 } 173 if ((mtfd = open(tape, comp->c_ronly ? O_RDONLY : O_RDWR)) < 0) 174 err(1, "%s", tape); 175 if (comp->c_code != MTNOP) { 176 mt_com.mt_op = comp->c_code; 177 if (*argv) { 178 if (!isdigit(**argv) && 179 (comp->c_flags & IS_DENSITY)) { 180 const char *dcanon; 181 mt_com.mt_count = stringtodens(*argv); 182 if (mt_com.mt_count == 0) 183 errx(1, "%s: unknown density", *argv); 184 dcanon = denstostring(mt_com.mt_count); 185 if (strcmp(dcanon, *argv) != 0) 186 printf( 187 "Using \"%s\" as an alias for %s\n", 188 *argv, dcanon); 189 p = ""; 190 } else if (!isdigit(**argv) && 191 (comp->c_flags & IS_COMP)) { 192 193 mt_com.mt_count = stringtocomp(*argv); 194 if ((u_int32_t)mt_com.mt_count == 0xf0f0f0f0) 195 errx(1, "%s: unknown compression", 196 *argv); 197 p = ""; 198 } else 199 /* allow for hex numbers; useful for density */ 200 mt_com.mt_count = strtol(*argv, &p, 0); 201 if ((mt_com.mt_count <= 202 ((comp->c_flags & ZERO_ALLOWED)? -1: 0) 203 && ((comp->c_flags & IS_COMP) == 0) 204 ) || *p) 205 errx(1, "%s: illegal count", *argv); 206 } 207 else 208 mt_com.mt_count = 1; 209 switch (comp->c_code) { 210 case MTIOCERRSTAT: 211 { 212 int i; 213 union mterrstat umn; 214 struct scsi_tape_errors *s = &umn.scsi_errstat; 215 216 if (ioctl(mtfd, comp->c_code, (caddr_t)&umn) < 0) 217 err(2, "%s", tape); 218 (void)printf("Last I/O Residual: %u\n", s->io_resid); 219 (void)printf(" Last I/O Command:"); 220 for (i = 0; i < sizeof (s->io_cdb); i++) 221 (void)printf(" %02X", s->io_cdb[i]); 222 (void)printf("\n"); 223 (void)printf(" Last I/O Sense:\n\n\t"); 224 for (i = 0; i < sizeof (s->io_sense); i++) { 225 (void)printf(" %02X", s->io_sense[i]); 226 if (((i + 1) & 0xf) == 0) { 227 (void)printf("\n\t"); 228 } 229 } 230 (void)printf("\n"); 231 (void)printf("Last Control Residual: %u\n", 232 s->ctl_resid); 233 (void)printf(" Last Control Command:"); 234 for (i = 0; i < sizeof (s->ctl_cdb); i++) 235 (void)printf(" %02X", s->ctl_cdb[i]); 236 (void)printf("\n"); 237 (void)printf(" Last Control Sense:\n\n\t"); 238 for (i = 0; i < sizeof (s->ctl_sense); i++) { 239 (void)printf(" %02X", s->ctl_sense[i]); 240 if (((i + 1) & 0xf) == 0) { 241 (void)printf("\n\t"); 242 } 243 } 244 (void)printf("\n\n"); 245 exit(0); 246 /* NOTREACHED */ 247 } 248 case MTIOCRDHPOS: 249 case MTIOCRDSPOS: 250 { 251 u_int32_t block; 252 if (ioctl(mtfd, comp->c_code, (caddr_t)&block) < 0) 253 err(2, "%s", tape); 254 (void)printf("%s: %s block location %u\n", tape, 255 (comp->c_code == MTIOCRDHPOS)? "hardware" : 256 "logical", block); 257 exit(0); 258 /* NOTREACHED */ 259 } 260 case MTIOCSLOCATE: 261 case MTIOCHLOCATE: 262 { 263 u_int32_t block = (u_int32_t)mt_com.mt_count; 264 if (ioctl(mtfd, comp->c_code, (caddr_t)&block) < 0) 265 err(2, "%s", tape); 266 exit(0); 267 /* NOTREACHED */ 268 } 269 case MTIOCGETEOTMODEL: 270 { 271 u_int32_t om; 272 if (ioctl(mtfd, MTIOCGETEOTMODEL, (caddr_t)&om) < 0) 273 err(2, "%s", tape); 274 (void)printf("%s: the model is %u filemar%s at EOT\n", 275 tape, om, (om > 1)? "ks" : "k"); 276 exit(0); 277 /* NOTREACHED */ 278 } 279 case MTIOCSETEOTMODEL: 280 { 281 u_int32_t om, nm = (u_int32_t)mt_com.mt_count; 282 if (ioctl(mtfd, MTIOCGETEOTMODEL, (caddr_t)&om) < 0) 283 err(2, "%s", tape); 284 if (ioctl(mtfd, comp->c_code, (caddr_t)&nm) < 0) 285 err(2, "%s", tape); 286 (void)printf("%s: old model was %u filemar%s at EOT\n", 287 tape, om, (om > 1)? "ks" : "k"); 288 (void)printf("%s: new model is %u filemar%s at EOT\n", 289 tape, nm, (nm > 1)? "ks" : "k"); 290 exit(0); 291 /* NOTREACHED */ 292 } 293 default: 294 break; 295 } 296 if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) 297 err(1, "%s: %s", tape, comp->c_name); 298 } else { 299 if (ioctl(mtfd, MTIOCGET, &mt_status) < 0) 300 err(1, NULL); 301 status(&mt_status); 302 } 303 exit(0); 304 /* NOTREACHED */ 305} 306 307#if defined(__i386__) 308#include <machine/wtio.h> 309#endif 310 311struct tape_desc { 312 short t_type; /* type of magtape device */ 313 char *t_name; /* printing name */ 314 char *t_dsbits; /* "drive status" register */ 315 char *t_erbits; /* "error" register */ 316} tapes[] = { 317 /* 318 * XXX This is weird. The st driver reports the tape drive 319 * as 0x7 (MT_ISAR - Sun/Archive compatible); the wt driver 320 * either reports MT_ISVIPER1 for an Archive tape, or 0x11 321 * (MT_ISMFOUR) for other tapes. 322 * XXX for the wt driver, rely on it behaving like a "standard" 323 * magtape driver. 324 */ 325 { MT_ISAR, "SCSI tape drive", 0, 0 }, 326#if defined (__i386__) 327 { MT_ISVIPER1, "Archive Viper", WTDS_BITS, WTER_BITS }, 328 { MT_ISMFOUR, "Wangtek", WTDS_BITS, WTER_BITS }, 329#endif 330 { 0 } 331}; 332 333/* 334 * Interpret the status buffer returned 335 */ 336void 337status(bp) 338 register struct mtget *bp; 339{ 340 register struct tape_desc *mt; 341 342 for (mt = tapes;; mt++) { 343 if (mt->t_type == 0) { 344 (void)printf("%d: unknown tape drive type\n", 345 bp->mt_type); 346 return; 347 } 348 if (mt->t_type == bp->mt_type) 349 break; 350 } 351 if(mt->t_type == MT_ISAR) 352 st_status(bp); 353 else { 354 (void)printf("%s tape drive, residual=%d\n", 355 mt->t_name, bp->mt_resid); 356 printreg("ds", (unsigned short)bp->mt_dsreg, mt->t_dsbits); 357 printreg("\ner", (unsigned short)bp->mt_erreg, mt->t_erbits); 358 (void)putchar('\n'); 359 } 360} 361 362/* 363 * Print a register a la the %b format of the kernel's printf. 364 */ 365void 366printreg(s, v, bits) 367 char *s; 368 register u_int v; 369 register char *bits; 370{ 371 register int i, any = 0; 372 register char c; 373 374 if (bits && *bits == 8) 375 printf("%s=%o", s, v); 376 else 377 printf("%s=%x", s, v); 378 if (!bits) 379 return; 380 bits++; 381 if (v && bits) { 382 putchar('<'); 383 while ((i = *bits++)) { 384 if (v & (1 << (i-1))) { 385 if (any) 386 putchar(','); 387 any = 1; 388 for (; (c = *bits) > 32; bits++) 389 putchar(c); 390 } else 391 for (; *bits > 32; bits++) 392 ; 393 } 394 putchar('>'); 395 } 396} 397 398void 399usage() 400{ 401 (void)fprintf(stderr, "usage: mt [-f device] command [ count ]\n"); 402 exit(1); 403} 404 405struct densities { 406 int dens; 407 int bpmm; 408 int bpi; 409 const char *name; 410} dens[] = { 411 /* 412 * Taken from T10 Project 997D 413 * SCSI-3 Stream Device Commands (SSC) 414 * Revision 11, 4-Nov-97 415 */ 416 /*Num. bpmm bpi Reference */ 417 { 0x1, 32, 800, "X3.22-1983" }, 418 { 0x2, 63, 1600, "X3.39-1986" }, 419 { 0x3, 246, 6250, "X3.54-1986" }, 420 { 0x5, 315, 8000, "X3.136-1986" }, 421 { 0x6, 126, 3200, "X3.157-1987" }, 422 { 0x7, 252, 6400, "X3.116-1986" }, 423 { 0x8, 315, 8000, "X3.158-1987" }, 424 { 0x9, 491, 37871, "X3.180" }, 425 { 0xA, 262, 6667, "X3B5/86-199" }, 426 { 0xB, 63, 1600, "X3.56-1986" }, 427 { 0xC, 500, 12690, "HI-TC1" }, 428 { 0xD, 999, 25380, "HI-TC2" }, 429 { 0xF, 394, 10000, "QIC-120" }, 430 { 0x10, 394, 10000, "QIC-150" }, 431 { 0x11, 630, 16000, "QIC-320" }, 432 { 0x12, 2034, 51667, "QIC-1350" }, 433 { 0x13, 2400, 61000, "X3B5/88-185A" }, 434 { 0x14, 1703, 43245, "X3.202-1991" }, 435 { 0x15, 1789, 45434, "ECMA TC17" }, 436 { 0x16, 394, 10000, "X3.193-1990" }, 437 { 0x17, 1673, 42500, "X3B5/91-174" }, 438 { 0x18, 1673, 42500, "X3B5/92-50" }, 439 { 0x1C, 1654, 42000, "QIC-385M" }, 440 { 0x1D, 1512, 38400, "QIC-410M" }, 441 { 0x1E, 1385, 36000, "QIC-1000C" }, 442 { 0x1F, 2666, 67733, "QIC-2100C" }, 443 { 0x20, 2666, 67733, "QIC-6GB(M)" }, 444 { 0x21, 2666, 67733, "QIC-20GB(C)" }, 445 { 0x22, 1600, 40640, "QIC-2GB(C)" }, 446 { 0x23, 2666, 67733, "QIC-875M" }, 447 { 0x24, 2400, 61000, "DDS-2" }, 448 { 0x25, 3816, 97000, "DDS-3" }, 449 { 0x26, 3816, 97000, "DDS-4" }, 450 { 0x27, 3056, 77611, "Mammoth" }, 451 { 0x28, 1491, 37871, "X3.224" }, 452 { 0, 0, 0, NULL } 453}; 454 455struct compression_types { 456 u_int32_t comp_number; 457 const char *name; 458} comp_types[] = { 459 { 0x00, "none" }, 460 { 0x00, "off" }, 461 { 0x10, "IDRC" }, 462 { 0x20, "DCLZ" }, 463 { 0xffffffff, "enable" }, 464 { 0xffffffff, "on" }, 465 { 0xf0f0f0f0, NULL} 466}; 467 468const char * 469denstostring(int d) 470{ 471 static char buf[20]; 472 struct densities *sd; 473 474 /* densities 0 and 0x7f are handled as special cases */ 475 if (d == 0) 476 return "default"; 477 if (d == 0x7f) 478 return "same"; 479 for (sd = dens; sd->dens; sd++) 480 if (sd->dens == d) 481 break; 482 if (sd->dens == 0) 483 sprintf(buf, "0x%02x", d); 484 else 485 sprintf(buf, "0x%02x:%s", d, sd->name); 486 return buf; 487} 488 489/* 490 * Given a specific density number, return either the bits per inch or bits 491 * per millimeter for the given density. 492 */ 493int 494denstobp(int d, int bpi) 495{ 496 struct densities *sd; 497 498 for (sd = dens; sd->dens; sd++) 499 if (sd->dens == d) 500 break; 501 if (sd->dens == 0) 502 return(0); 503 else { 504 if (bpi) 505 return(sd->bpi); 506 else 507 return(sd->bpmm); 508 } 509} 510 511int 512stringtodens(const char *s) 513{ 514 struct densities *sd; 515 size_t l = strlen(s); 516 517 for (sd = dens; sd->dens; sd++) 518 if (strncasecmp(sd->name, s, l) == 0) 519 break; 520 return sd->dens; 521} 522 523 524const char * 525getblksiz(int bs) 526{ 527 static char buf[25]; 528 if (bs == 0) 529 return "variable"; 530 else { 531 sprintf(buf, "%d bytes", bs); 532 return buf; 533 } 534} 535 536const char * 537comptostring(u_int32_t comp) 538{ 539 static char buf[20]; 540 struct compression_types *ct; 541 542 if (comp == MT_COMP_DISABLED) 543 return "disabled"; 544 else if (comp == MT_COMP_UNSUPP) 545 return "unsupported"; 546 547 for (ct = comp_types; ct->name; ct++) 548 if (ct->comp_number == comp) 549 break; 550 551 if (ct->comp_number == 0xf0f0f0f0) { 552 sprintf(buf, "0x%x", comp); 553 return(buf); 554 } else 555 return(ct->name); 556} 557 558u_int32_t 559stringtocomp(const char *s) 560{ 561 struct compression_types *ct; 562 size_t l = strlen(s); 563 564 for (ct = comp_types; ct->name; ct++) 565 if (strncasecmp(ct->name, s, l) == 0) 566 break; 567 568 return(ct->comp_number); 569} 570 571void 572st_status(struct mtget *bp) 573{ 574 printf("Mode Density Blocksize bpi " 575 "Compression\n" 576 "Current: %-17s %-12s %-7d %s\n" 577 "---------available modes---------\n" 578 "0: %-17s %-12s %-7d %s\n" 579 "1: %-17s %-12s %-7d %s\n" 580 "2: %-17s %-12s %-7d %s\n" 581 "3: %-17s %-12s %-7d %s\n", 582 denstostring(bp->mt_density), getblksiz(bp->mt_blksiz), 583 denstobp(bp->mt_density, TRUE), comptostring(bp->mt_comp), 584 denstostring(bp->mt_density0), getblksiz(bp->mt_blksiz0), 585 denstobp(bp->mt_density0, TRUE), comptostring(bp->mt_comp0), 586 denstostring(bp->mt_density1), getblksiz(bp->mt_blksiz1), 587 denstobp(bp->mt_density1, TRUE), comptostring(bp->mt_comp1), 588 denstostring(bp->mt_density2), getblksiz(bp->mt_blksiz2), 589 denstobp(bp->mt_density2, TRUE), comptostring(bp->mt_comp2), 590 denstostring(bp->mt_density3), getblksiz(bp->mt_blksiz3), 591 denstobp(bp->mt_density3, TRUE), comptostring(bp->mt_comp3)); 592 593 if (bp->mt_dsreg != MTIO_DSREG_NIL) { 594 auto char foo[32]; 595 const char sfmt[] = "Current Driver State: %s.\n"; 596 printf("---------------------------------\n"); 597 switch (bp->mt_dsreg) { 598 case MTIO_DSREG_REST: 599 printf(sfmt, "at rest"); 600 break; 601 case MTIO_DSREG_RBSY: 602 printf(sfmt, "Communicating with drive"); 603 break; 604 case MTIO_DSREG_WR: 605 printf(sfmt, "Writing"); 606 break; 607 case MTIO_DSREG_FMK: 608 printf(sfmt, "Writing Filemarks"); 609 break; 610 case MTIO_DSREG_ZER: 611 printf(sfmt, "Erasing"); 612 break; 613 case MTIO_DSREG_RD: 614 printf(sfmt, "Reading"); 615 break; 616 case MTIO_DSREG_FWD: 617 printf(sfmt, "Spacing Forward"); 618 break; 619 case MTIO_DSREG_REV: 620 printf(sfmt, "Spacing Reverse"); 621 break; 622 case MTIO_DSREG_POS: 623 printf(sfmt, 624 "Hardware Positioning (direction unknown)"); 625 break; 626 case MTIO_DSREG_REW: 627 printf(sfmt, "Rewinding"); 628 break; 629 case MTIO_DSREG_TEN: 630 printf(sfmt, "Retensioning"); 631 break; 632 case MTIO_DSREG_UNL: 633 printf(sfmt, "Unloading"); 634 break; 635 case MTIO_DSREG_LD: 636 printf(sfmt, "Loading"); 637 break; 638 default: 639 (void) sprintf(foo, "Unknown state 0x%x", bp->mt_dsreg); 640 printf(sfmt, foo); 641 break; 642 } 643 } 644 if (bp->mt_resid == 0 && bp->mt_fileno == (daddr_t) -1 && 645 bp->mt_blkno == (daddr_t) -1) 646 return; 647 printf("---------------------------------\n"); 648 printf("File Number: %ld\tRecord Number: %ld\tResidual Count %d\n", 649 bp->mt_fileno, bp->mt_blkno, bp->mt_resid); 650} 651 652void 653warn_eof(void) 654{ 655 fprintf(stderr, 656 "The \"eof\" command has been disabled.\n" 657 "Use \"weof\" if you really want to write end-of-file marks,\n" 658 "or \"eom\" if you rather want to skip to the end of " 659 "recorded medium.\n"); 660 exit(1); 661} 662