mt.c revision 23693
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 351590Srgrimesstatic char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1980, 1993\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 381590Srgrimes#endif /* not lint */ 391590Srgrimes 401590Srgrimes#ifndef lint 4123693Speterstatic char sccsid[] = "@(#)mt.c 8.2 (Berkeley) 5/4/95"; 421590Srgrimes#endif /* not lint */ 431590Srgrimes 441590Srgrimes/* 451590Srgrimes * mt -- 461590Srgrimes * magnetic tape manipulation program 471590Srgrimes */ 481590Srgrimes#include <sys/types.h> 491590Srgrimes#include <sys/ioctl.h> 501590Srgrimes#include <sys/mtio.h> 5123693Speter 5223693Speter#include <ctype.h> 5323693Speter#include <errno.h> 541590Srgrimes#include <fcntl.h> 5523693Speter#include <stdio.h> 561590Srgrimes#include <stdlib.h> 571590Srgrimes#include <string.h> 5823693Speter#include <unistd.h> 591590Srgrimes 607913Sjoerg/* the appropriate sections of <sys/mtio.h> are also #ifdef'd for FreeBSD */ 617913Sjoerg#if defined(__FreeBSD__) 627913Sjoerg/* c_flags */ 637913Sjoerg#define NEED_2ARGS 0x01 647929Sjoerg#define ZERO_ALLOWED 0x02 657929Sjoerg#define IS_DENSITY 0x04 669541Sjoerg#define DISABLE_THIS 0x08 677913Sjoerg#endif /* defined(__FreeBSD__) */ 687913Sjoerg 691590Srgrimesstruct commands { 701590Srgrimes char *c_name; 711590Srgrimes int c_code; 721590Srgrimes int c_ronly; 737913Sjoerg#if defined(__FreeBSD__) 747913Sjoerg int c_flags; 757913Sjoerg#endif /* defined(__FreeBSD__) */ 761590Srgrimes} com[] = { 771590Srgrimes { "bsf", MTBSF, 1 }, 781590Srgrimes { "bsr", MTBSR, 1 }, 799541Sjoerg#if defined(__FreeBSD__) 809541Sjoerg /* XXX FreeBSD considered "eof" dangerous, since it's being 819541Sjoerg confused with "eom" (and is an alias for "weof" anyway) */ 829541Sjoerg { "eof", MTWEOF, 0, DISABLE_THIS }, 839541Sjoerg#else 849541Sjoerg { "eof", MTWEOF, 0 }, 859541Sjoerg#endif 861590Srgrimes { "fsf", MTFSF, 1 }, 871590Srgrimes { "fsr", MTFSR, 1 }, 881590Srgrimes { "offline", MTOFFL, 1 }, 891590Srgrimes { "rewind", MTREW, 1 }, 901590Srgrimes { "rewoffl", MTOFFL, 1 }, 911590Srgrimes { "status", MTNOP, 1 }, 921590Srgrimes { "weof", MTWEOF, 0 }, 937913Sjoerg#if defined(__FreeBSD__) 947913Sjoerg { "erase", MTERASE, 0 }, 957913Sjoerg { "blocksize", MTSETBSIZ, 0, NEED_2ARGS|ZERO_ALLOWED }, 967929Sjoerg { "density", MTSETDNSTY, 0, NEED_2ARGS|ZERO_ALLOWED|IS_DENSITY }, 977913Sjoerg { "eom", MTEOD, 1 }, 987913Sjoerg { "comp", MTCOMP, 0, NEED_2ARGS|ZERO_ALLOWED }, 9913401Sjoerg { "retension", MTRETENS, 1 }, 1007913Sjoerg#endif /* defined(__FreeBSD__) */ 1011590Srgrimes { NULL } 1021590Srgrimes}; 1031590Srgrimes 1041590Srgrimesvoid err __P((const char *, ...)); 1051590Srgrimesvoid printreg __P((char *, u_int, char *)); 1061590Srgrimesvoid status __P((struct mtget *)); 1071590Srgrimesvoid usage __P((void)); 1087913Sjoerg#if defined (__FreeBSD__) 1097913Sjoergvoid st_status (struct mtget *); 1107929Sjoergint stringtodens (const char *s); 1117929Sjoergconst char *denstostring (int d); 1129541Sjoergvoid warn_eof __P((void)); 1137913Sjoerg#endif /* defined (__FreeBSD__) */ 1141590Srgrimes 1151590Srgrimesint 1161590Srgrimesmain(argc, argv) 1171590Srgrimes int argc; 1181590Srgrimes char *argv[]; 1191590Srgrimes{ 1201590Srgrimes register struct commands *comp; 1211590Srgrimes struct mtget mt_status; 1221590Srgrimes struct mtop mt_com; 1231590Srgrimes int ch, len, mtfd; 1241590Srgrimes char *p, *tape; 1251590Srgrimes 1261590Srgrimes if ((tape = getenv("TAPE")) == NULL) 1271590Srgrimes tape = DEFTAPE; 1281590Srgrimes 1291590Srgrimes while ((ch = getopt(argc, argv, "f:t:")) != EOF) 1301590Srgrimes switch(ch) { 1311590Srgrimes case 'f': 1321590Srgrimes case 't': 1331590Srgrimes tape = optarg; 1341590Srgrimes break; 1351590Srgrimes case '?': 1361590Srgrimes default: 1371590Srgrimes usage(); 1381590Srgrimes } 1391590Srgrimes argc -= optind; 1401590Srgrimes argv += optind; 1411590Srgrimes 1421590Srgrimes if (argc < 1 || argc > 2) 1431590Srgrimes usage(); 1441590Srgrimes 1451590Srgrimes len = strlen(p = *argv++); 1461590Srgrimes for (comp = com;; comp++) { 1471590Srgrimes if (comp->c_name == NULL) 1481590Srgrimes err("%s: unknown command", p); 1491590Srgrimes if (strncmp(p, comp->c_name, len) == 0) 1501590Srgrimes break; 1511590Srgrimes } 1527913Sjoerg#if defined(__FreeBSD__) 1537913Sjoerg if((comp->c_flags & NEED_2ARGS) && argc != 2) 1547913Sjoerg usage(); 1559541Sjoerg if(comp->c_flags & DISABLE_THIS) { 1569541Sjoerg warn_eof(); 1579541Sjoerg } 1587913Sjoerg#endif /* defined(__FreeBSD__) */ 1591590Srgrimes if ((mtfd = open(tape, comp->c_ronly ? O_RDONLY : O_RDWR)) < 0) 1601590Srgrimes err("%s: %s", tape, strerror(errno)); 1611590Srgrimes if (comp->c_code != MTNOP) { 1621590Srgrimes mt_com.mt_op = comp->c_code; 1631590Srgrimes if (*argv) { 1647913Sjoerg#if defined (__FreeBSD__) 1657929Sjoerg if (!isdigit(**argv) && 1667929Sjoerg comp->c_flags & IS_DENSITY) { 1677929Sjoerg const char *dcanon; 1687929Sjoerg mt_com.mt_count = stringtodens(*argv); 1697929Sjoerg if (mt_com.mt_count == 0) 1707929Sjoerg err("%s: unknown density", *argv); 1717929Sjoerg dcanon = denstostring(mt_com.mt_count); 1727929Sjoerg if (strcmp(dcanon, *argv) != 0) 1737929Sjoerg printf( 1747929Sjoerg "Using \"%s\" as an alias for %s\n", 1757929Sjoerg *argv, dcanon); 1767929Sjoerg p = ""; 1777929Sjoerg } else 1787929Sjoerg /* allow for hex numbers; useful for density */ 1797929Sjoerg mt_com.mt_count = strtol(*argv, &p, 0); 1807913Sjoerg#else 1811590Srgrimes mt_com.mt_count = strtol(*argv, &p, 10); 1827913Sjoerg#endif /* defined(__FreeBSD__) */ 1837913Sjoerg if (mt_com.mt_count <= 1847913Sjoerg#if defined (__FreeBSD__) 1857913Sjoerg ((comp->c_flags & ZERO_ALLOWED)? -1: 0) 1867913Sjoerg#else 1877913Sjoerg 0 1887913Sjoerg#endif /* defined (__FreeBSD__) */ 1897913Sjoerg || *p) 1901590Srgrimes err("%s: illegal count", *argv); 1911590Srgrimes } 1921590Srgrimes else 1931590Srgrimes mt_com.mt_count = 1; 1941590Srgrimes if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) 1951590Srgrimes err("%s: %s: %s", tape, comp->c_name, strerror(errno)); 1961590Srgrimes } else { 1971590Srgrimes if (ioctl(mtfd, MTIOCGET, &mt_status) < 0) 1981590Srgrimes err("%s", strerror(errno)); 1991590Srgrimes status(&mt_status); 2001590Srgrimes } 2011590Srgrimes exit (0); 2021590Srgrimes /* NOTREACHED */ 2031590Srgrimes} 2041590Srgrimes 2051590Srgrimes#ifdef vax 2061590Srgrimes#include <vax/mba/mtreg.h> 2071590Srgrimes#include <vax/mba/htreg.h> 2081590Srgrimes 2091590Srgrimes#include <vax/uba/utreg.h> 2101590Srgrimes#include <vax/uba/tmreg.h> 2111590Srgrimes#undef b_repcnt /* argh */ 2121590Srgrimes#include <vax/uba/tsreg.h> 2131590Srgrimes#endif 2141590Srgrimes 2151590Srgrimes#ifdef sun 2161590Srgrimes#include <sundev/tmreg.h> 2171590Srgrimes#include <sundev/arreg.h> 2181590Srgrimes#endif 2191590Srgrimes 2201590Srgrimes#ifdef tahoe 2211590Srgrimes#include <tahoe/vba/cyreg.h> 2221590Srgrimes#endif 2231590Srgrimes 22414176Sjoerg#ifdef __FreeBSD__ 22514176Sjoerg#include <machine/wtio.h> 22614176Sjoerg#endif 22714176Sjoerg 2281590Srgrimesstruct tape_desc { 2291590Srgrimes short t_type; /* type of magtape device */ 2301590Srgrimes char *t_name; /* printing name */ 2311590Srgrimes char *t_dsbits; /* "drive status" register */ 2321590Srgrimes char *t_erbits; /* "error" register */ 2331590Srgrimes} tapes[] = { 2341590Srgrimes#ifdef vax 2351590Srgrimes { MT_ISTS, "ts11", 0, TSXS0_BITS }, 2361590Srgrimes { MT_ISHT, "tm03", HTDS_BITS, HTER_BITS }, 2371590Srgrimes { MT_ISTM, "tm11", 0, TMER_BITS }, 2381590Srgrimes { MT_ISMT, "tu78", MTDS_BITS, 0 }, 2391590Srgrimes { MT_ISUT, "tu45", UTDS_BITS, UTER_BITS }, 2401590Srgrimes#endif 2411590Srgrimes#ifdef sun 2421590Srgrimes { MT_ISCPC, "TapeMaster", TMS_BITS, 0 }, 2431590Srgrimes { MT_ISAR, "Archive", ARCH_CTRL_BITS, ARCH_BITS }, 2441590Srgrimes#endif 2451590Srgrimes#ifdef tahoe 2461590Srgrimes { MT_ISCY, "cipher", CYS_BITS, CYCW_BITS }, 2471590Srgrimes#endif 2487913Sjoerg#if defined (__FreeBSD__) 2497913Sjoerg /* 25014176Sjoerg * XXX This is weird. The st driver reports the tape drive 2517913Sjoerg * as 0x7 (MT_ISAR - Sun/Archive compatible); the wt driver 2527913Sjoerg * either reports MT_ISVIPER1 for an Archive tape, or 0x11 2537913Sjoerg * (MT_ISMFOUR) for other tapes. 2547913Sjoerg * XXX for the wt driver, rely on it behaving like a "standard" 2557913Sjoerg * magtape driver. 2567913Sjoerg */ 2577913Sjoerg { MT_ISAR, "SCSI tape drive", 0, 0 }, 25814176Sjoerg { MT_ISVIPER1, "Archive Viper", WTDS_BITS, WTER_BITS }, 25914176Sjoerg { MT_ISMFOUR, "Wangtek", WTDS_BITS, WTER_BITS }, 2607913Sjoerg#endif /* defined (__FreeBSD__) */ 2611590Srgrimes { 0 } 2621590Srgrimes}; 2631590Srgrimes 2641590Srgrimes/* 2651590Srgrimes * Interpret the status buffer returned 2661590Srgrimes */ 2671590Srgrimesvoid 2681590Srgrimesstatus(bp) 2691590Srgrimes register struct mtget *bp; 2701590Srgrimes{ 2711590Srgrimes register struct tape_desc *mt; 2721590Srgrimes 2731590Srgrimes for (mt = tapes;; mt++) { 2741590Srgrimes if (mt->t_type == 0) { 2751590Srgrimes (void)printf("%d: unknown tape drive type\n", 2761590Srgrimes bp->mt_type); 2771590Srgrimes return; 2781590Srgrimes } 2791590Srgrimes if (mt->t_type == bp->mt_type) 2801590Srgrimes break; 2811590Srgrimes } 2827913Sjoerg#if defined (__FreeBSD__) 2837913Sjoerg if(mt->t_type == MT_ISAR) 2847913Sjoerg st_status(bp); 2857913Sjoerg else { 2867913Sjoerg#endif /* defined (__FreeBSD__) */ 2871590Srgrimes (void)printf("%s tape drive, residual=%d\n", mt->t_name, bp->mt_resid); 28814176Sjoerg printreg("ds", (unsigned short)bp->mt_dsreg, mt->t_dsbits); 28914176Sjoerg printreg("\ner", (unsigned short)bp->mt_erreg, mt->t_erbits); 2901590Srgrimes (void)putchar('\n'); 2917913Sjoerg#if defined (__FreeBSD__) 2927913Sjoerg } 2937913Sjoerg#endif /* defined (__FreeBSD__) */ 2941590Srgrimes} 2951590Srgrimes 2961590Srgrimes/* 2971590Srgrimes * Print a register a la the %b format of the kernel's printf. 2981590Srgrimes */ 2991590Srgrimesvoid 3001590Srgrimesprintreg(s, v, bits) 3011590Srgrimes char *s; 3021590Srgrimes register u_int v; 3031590Srgrimes register char *bits; 3041590Srgrimes{ 3051590Srgrimes register int i, any = 0; 3061590Srgrimes register char c; 3071590Srgrimes 3081590Srgrimes if (bits && *bits == 8) 3091590Srgrimes printf("%s=%o", s, v); 3101590Srgrimes else 3111590Srgrimes printf("%s=%x", s, v); 31211608Sbde if (!bits) 31311608Sbde return; 3141590Srgrimes bits++; 3151590Srgrimes if (v && bits) { 3161590Srgrimes putchar('<'); 3171590Srgrimes while (i = *bits++) { 3181590Srgrimes if (v & (1 << (i-1))) { 3191590Srgrimes if (any) 3201590Srgrimes putchar(','); 3211590Srgrimes any = 1; 3221590Srgrimes for (; (c = *bits) > 32; bits++) 3231590Srgrimes putchar(c); 3241590Srgrimes } else 3251590Srgrimes for (; *bits > 32; bits++) 3261590Srgrimes ; 3271590Srgrimes } 3281590Srgrimes putchar('>'); 3291590Srgrimes } 3301590Srgrimes} 3311590Srgrimes 3321590Srgrimesvoid 3331590Srgrimesusage() 3341590Srgrimes{ 3351590Srgrimes (void)fprintf(stderr, "usage: mt [-f device] command [ count ]\n"); 3361590Srgrimes exit(1); 3371590Srgrimes} 3381590Srgrimes 3391590Srgrimes#if __STDC__ 3401590Srgrimes#include <stdarg.h> 3411590Srgrimes#else 3421590Srgrimes#include <varargs.h> 3431590Srgrimes#endif 3441590Srgrimes 3451590Srgrimesvoid 3461590Srgrimes#if __STDC__ 3471590Srgrimeserr(const char *fmt, ...) 3481590Srgrimes#else 3491590Srgrimeserr(fmt, va_alist) 3501590Srgrimes char *fmt; 3511590Srgrimes va_dcl 3521590Srgrimes#endif 3531590Srgrimes{ 3541590Srgrimes va_list ap; 3551590Srgrimes#if __STDC__ 3561590Srgrimes va_start(ap, fmt); 3571590Srgrimes#else 3581590Srgrimes va_start(ap); 3591590Srgrimes#endif 3601590Srgrimes (void)fprintf(stderr, "mt: "); 3611590Srgrimes (void)vfprintf(stderr, fmt, ap); 3621590Srgrimes va_end(ap); 3631590Srgrimes (void)fprintf(stderr, "\n"); 3641590Srgrimes exit(1); 3651590Srgrimes /* NOTREACHED */ 3661590Srgrimes} 3677913Sjoerg 3687913Sjoerg#if defined (__FreeBSD__) 3697913Sjoerg 3707913Sjoergstruct densities { 3717913Sjoerg int dens; 3727913Sjoerg const char *name; 3737913Sjoerg} dens [] = { 3747929Sjoerg { 0x1, "X3.22-1983" }, 3757929Sjoerg { 0x2, "X3.39-1986" }, 3767929Sjoerg { 0x3, "X3.54-1986" }, 3777929Sjoerg { 0x5, "X3.136-1986" }, 3787929Sjoerg { 0x6, "X3.157-1987" }, 3797929Sjoerg { 0x7, "X3.116-1986" }, 3807929Sjoerg { 0x8, "X3.158-1986" }, 3817929Sjoerg { 0x9, "X3B5/87-099" }, 3827929Sjoerg { 0xA, "X3B5/86-199" }, 3837929Sjoerg { 0xB, "X3.56-1986" }, 3847929Sjoerg { 0xC, "HI-TC1" }, 3857929Sjoerg { 0xD, "HI-TC2" }, 3867929Sjoerg { 0xF, "QIC-120" }, 3877929Sjoerg { 0x10, "QIC-150" }, 3887929Sjoerg { 0x11, "QIC-320" }, 3897929Sjoerg { 0x12, "QIC-1350" }, 3907913Sjoerg { 0x13, "X3B5/88-185A" }, 3917929Sjoerg { 0x14, "X3.202-1991" }, 3927929Sjoerg { 0x15, "ECMA TC17" }, 3937929Sjoerg { 0x16, "X3.193-1990" }, 3947929Sjoerg { 0x17, "X3B5/91-174" }, 3957913Sjoerg { 0, 0 } 3967913Sjoerg}; 3977913Sjoerg 3987913Sjoergconst char * 3997929Sjoergdenstostring(int d) 4007913Sjoerg{ 4017913Sjoerg static char buf[20]; 4027913Sjoerg struct densities *sd; 4037913Sjoerg 4047913Sjoerg for (sd = dens; sd->dens; sd++) 4057913Sjoerg if (sd->dens == d) 4067913Sjoerg break; 4077913Sjoerg if (sd->dens == 0) { 4087929Sjoerg sprintf(buf, "0x%02x", d); 4097913Sjoerg return buf; 4107929Sjoerg } else 4117913Sjoerg return sd->name; 4127913Sjoerg} 4137913Sjoerg 4147929Sjoergint 4157929Sjoergstringtodens(const char *s) 4167929Sjoerg{ 4177929Sjoerg struct densities *sd; 4187929Sjoerg size_t l = strlen(s); 4197929Sjoerg 4207929Sjoerg for (sd = dens; sd->dens; sd++) 4217929Sjoerg if (strncasecmp(sd->name, s, l) == 0) 4227929Sjoerg break; 4237929Sjoerg return sd->dens; 4247929Sjoerg} 4257929Sjoerg 4267929Sjoerg 4277913Sjoergconst char * 4287913Sjoerggetblksiz(int bs) 4297913Sjoerg{ 4307913Sjoerg static char buf[25]; 4317913Sjoerg if (bs == 0) 4327913Sjoerg return "variable"; 4337913Sjoerg else { 4347913Sjoerg sprintf(buf, "= %d bytes", bs); 4357913Sjoerg return buf; 4367913Sjoerg } 4377913Sjoerg} 4387913Sjoerg 4397913Sjoerg 4407913Sjoergvoid 4417913Sjoergst_status(struct mtget *bp) 4427913Sjoerg{ 4437929Sjoerg printf("Present Mode: Density = %-12s Blocksize %s\n", 4447929Sjoerg denstostring(bp->mt_density), getblksiz(bp->mt_blksiz)); 4457913Sjoerg printf("---------available modes---------\n"); 4467929Sjoerg printf("Mode 0: Density = %-12s Blocksize %s\n", 4477929Sjoerg denstostring(bp->mt_density0), getblksiz(bp->mt_blksiz0)); 4487929Sjoerg printf("Mode 1: Density = %-12s Blocksize %s\n", 4497929Sjoerg denstostring(bp->mt_density1), getblksiz(bp->mt_blksiz1)); 4507929Sjoerg printf("Mode 2: Density = %-12s Blocksize %s\n", 4517929Sjoerg denstostring(bp->mt_density2), getblksiz(bp->mt_blksiz2)); 4527929Sjoerg printf("Mode 3: Density = %-12s Blocksize %s\n", 4537929Sjoerg denstostring(bp->mt_density3), getblksiz(bp->mt_blksiz3)); 4547913Sjoerg} 4557913Sjoerg 4569541Sjoergvoid 4579541Sjoergwarn_eof(void) 4589541Sjoerg{ 4599541Sjoerg fprintf(stderr, 4609541Sjoerg "The \"eof\" command has been disabled.\n" 4619541Sjoerg "Use \"weof\" if you really want to write end-of-file marks,\n" 4629541Sjoerg "or \"eom\" if you rather want to skip to the end of " 4639541Sjoerg "recorded medium.\n"); 4649541Sjoerg exit(1); 4659541Sjoerg} 4669541Sjoerg 4677913Sjoerg#endif /* defined (__FreeBSD__) */ 468