1 /* $NetBSD: mt.c,v 1.20 1997/07/01 20:15:51 hannken Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #ifndef lint 37 static char copyright[] = 38 "@(#) Copyright (c) 1980, 1993\n\ 39 The Regents of the University of California. All rights reserved.\n"; 40 #endif /* not lint */ 41 42 #ifndef lint 43 #if 0 44 static char sccsid[] = "@(#)mt.c 8.2 (Berkeley) 6/6/93"; 45 #else 46 static char rcsid[] = "$NetBSD: mt.c,v 1.20 1997/07/01 20:15:51 hannken Exp $"; 47 #endif 48 #endif /* not lint */ 49 50 /* 51 * mt -- 52 * magnetic tape manipulation program 53 */ 54 #include <rmt.h> 55 #include <sys/types.h> 56 #include <sys/ioctl.h> 57 #include <sys/mtio.h> 58 #include <sys/stat.h> 59 60 #include <ctype.h> 61 #include <err.h> 62 #include <fcntl.h> 63 #include <paths.h> 64 #include <stdio.h> 65 #include <stdlib.h> 66 #include <string.h> 67 #include <unistd.h> 68 69 /* pseudo ioctl constants */ 70 #define MTASF 100 71 72 struct commands { 73 const char *c_name; /* command */ 74 int c_code; /* ioctl code for this command */ 75 int c_ronly; /* open tape read-only */ 76 int c_mincount; /* min allowed count value */ 77 }; 78 79 const struct commands com[] = { 80 { "asf", MTASF, 1, 1 }, 81 { "blocksize", MTSETBSIZ, 1, 0 }, 82 { "bsf", MTBSF, 1, 1 }, 83 { "bsr", MTBSR, 1, 1 }, 84 { "density", MTSETDNSTY, 1, 0 }, 85 { "eof", MTWEOF, 0, 1 }, 86 { "eom", MTEOM, 1, 0 }, 87 { "erase", MTERASE, 0, 0 }, 88 { "fsf", MTFSF, 1, 1 }, 89 { "fsr", MTFSR, 1, 1 }, 90 { "offline", MTOFFL, 1, 0 }, 91 { "rewind", MTREW, 1, 0 }, 92 { "rewoffl", MTOFFL, 1, 0 }, 93 { "status", MTNOP, 1, 0 }, 94 { "retension", MTRETEN, 1, 0 }, 95 { "weof", MTWEOF, 0, 1 }, 96 { NULL } 97 }; 98 99 void printreg __P((char *, u_int, char *)); 100 void status __P((struct mtget *)); 101 void usage __P((void)); 102 103 int 104 main(argc, argv) 105 int argc; 106 char *argv[]; 107 { 108 const struct commands *comp; 109 struct mtget mt_status; 110 struct mtop mt_com; 111 int ch, len, mtfd, flags; 112 char *p, *tape; 113 int count; 114 115 if ((tape = getenv("TAPE")) == NULL) 116 tape = _PATH_DEFTAPE; 117 118 while ((ch = getopt(argc, argv, "f:t:")) != -1) 119 switch (ch) { 120 case 'f': 121 case 't': 122 tape = optarg; 123 break; 124 case '?': 125 default: 126 usage(); 127 } 128 argc -= optind; 129 argv += optind; 130 131 if (argc < 1 || argc > 2) 132 usage(); 133 134 len = strlen(p = *argv++); 135 for (comp = com;; comp++) { 136 if (comp->c_name == NULL) 137 errx(1, "%s: unknown command", p); 138 if (strncmp(p, comp->c_name, len) == 0) 139 break; 140 } 141 142 if (*argv) { 143 count = strtol(*argv, &p, 10); 144 if (count < comp->c_mincount || *p) 145 errx(2, "%s: illegal count", *argv); 146 } 147 else 148 count = 1; 149 150 flags = comp->c_ronly ? O_RDONLY : O_WRONLY; 151 if ((mtfd = open(tape, flags)) < 0) 152 err(2, "%s", tape); 153 154 if (comp->c_code == MTASF) { 155 /* If mtget.mt_fileno was implemented, We could 156 compute the minimal seek needed to position 157 the tape. Until then, rewind and seek from 158 begining-of-tape */ 159 160 mt_com.mt_op = MTREW; 161 mt_com.mt_count = 1; 162 if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) 163 err(2, "%s", tape); 164 165 mt_com.mt_op = MTFSF; 166 mt_com.mt_count = count; 167 if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) 168 err(2, "%s", tape); 169 170 } else if (comp->c_code != MTNOP) { 171 mt_com.mt_op = comp->c_code; 172 mt_com.mt_count = count; 173 174 if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) 175 err(2, "%s: %s", tape, comp->c_name); 176 177 } else { 178 if (ioctl(mtfd, MTIOCGET, &mt_status) < 0) 179 err(2, "%s: %s", tape, comp->c_name); 180 status(&mt_status); 181 } 182 183 exit(0); 184 /* NOTREACHED */ 185 } 186 187 #ifdef sun 188 #include <sundev/tmreg.h> 189 #include <sundev/arreg.h> 190 #endif 191 192 #ifdef tahoe 193 #include <tahoe/vba/cyreg.h> 194 #endif 195 196 struct tape_desc { 197 short t_type; /* type of magtape device */ 198 char *t_name; /* printing name */ 199 char *t_dsbits; /* "drive status" register */ 200 char *t_erbits; /* "error" register */ 201 } tapes[] = { 202 #ifdef sun 203 { MT_ISCPC, "TapeMaster", TMS_BITS, 0 }, 204 { MT_ISAR, "Archive", ARCH_CTRL_BITS, ARCH_BITS }, 205 #endif 206 #ifdef tahoe 207 { MT_ISCY, "cipher", CYS_BITS, CYCW_BITS }, 208 #endif 209 { 0x7, "SCSI", "76543210", "76543210" }, 210 { 0 } 211 }; 212 213 /* 214 * Interpret the status buffer returned 215 */ 216 void 217 status(bp) 218 struct mtget *bp; 219 { 220 struct tape_desc *mt; 221 222 for (mt = tapes;; mt++) { 223 if (mt->t_type == 0) { 224 (void)printf("%d: unknown tape drive type\n", 225 bp->mt_type); 226 return; 227 } 228 if (mt->t_type == bp->mt_type) 229 break; 230 } 231 (void)printf("%s tape drive, residual=%d\n", mt->t_name, bp->mt_resid); 232 printreg("ds", bp->mt_dsreg, mt->t_dsbits); 233 printreg("\ner", bp->mt_erreg, mt->t_erbits); 234 (void)putchar('\n'); 235 (void)printf("blocksize: %ld (%ld, %ld, %ld, %ld)\n", 236 bp->mt_blksiz, bp->mt_mblksiz[0], bp->mt_mblksiz[1], 237 bp->mt_mblksiz[2], bp->mt_mblksiz[3]); 238 (void)printf("density: %ld (%ld, %ld, %ld, %ld)\n", 239 bp->mt_density, bp->mt_mdensity[0], bp->mt_mdensity[1], 240 bp->mt_mdensity[2], bp->mt_mdensity[3]); 241 } 242 243 /* 244 * Print a register a la the %b format of the kernel's printf. 245 */ 246 void 247 printreg(s, v, bits) 248 char *s; 249 u_int v; 250 char *bits; 251 { 252 int i, any = 0; 253 char c; 254 255 if (bits && *bits == 8) 256 printf("%s=%o", s, v); 257 else 258 printf("%s=%x", s, v); 259 bits++; 260 if (v && bits) { 261 putchar('<'); 262 while ((i = *bits++)) { 263 if (v & (1 << (i-1))) { 264 if (any) 265 putchar(','); 266 any = 1; 267 for (; (c = *bits) > 32; bits++) 268 putchar(c); 269 } else 270 for (; *bits > 32; bits++) 271 ; 272 } 273 putchar('>'); 274 } 275 } 276 277 void 278 usage() 279 { 280 (void)fprintf(stderr, "usage: mt [-f device] command [ count ]\n"); 281 exit(1); 282 } 283