1 /* $NetBSD: mt.c,v 1.45 2008/06/27 08:17:43 dogcow Exp $ */
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "@(#)mt.c 8.2 (Berkeley) 6/6/93";
42 __RCSID("$NetBSD: mt.c,v 1.45 2008/06/27 08:17:43 dogcow Exp $");
48 * magnetic tape manipulation program
50 #include <sys/types.h>
51 #include <sys/param.h>
52 #include <sys/ioctl.h>
66 /* pseudo ioctl constants */
70 const char *c_name
; /* command */
71 size_t c_namelen
; /* command len */
72 u_long c_spcl
; /* ioctl request */
73 int c_code
; /* ioctl code for MTIOCTOP command */
74 int c_ronly
; /* open tape read-only */
75 int c_mincount
; /* min allowed count value */
78 #define CMD(a) a, sizeof(a) - 1
79 const struct commands com
[] = {
80 { CMD("asf"), MTIOCTOP
, MTASF
, 1, 0 },
81 { CMD("blocksize"), MTIOCTOP
, MTSETBSIZ
, 1, 0 },
82 { CMD("bsf"), MTIOCTOP
, MTBSF
, 1, 1 },
83 { CMD("bsr"), MTIOCTOP
, MTBSR
, 1, 1 },
84 { CMD("compress"), MTIOCTOP
, MTCMPRESS
, 1, 0 },
85 { CMD("density"), MTIOCTOP
, MTSETDNSTY
, 1, 0 },
86 { CMD("eof"), MTIOCTOP
, MTWEOF
, 0, 1 },
87 { CMD("eom"), MTIOCTOP
, MTEOM
, 1, 0 },
88 { CMD("erase"), MTIOCTOP
, MTERASE
, 0, 0 },
89 { CMD("fsf"), MTIOCTOP
, MTFSF
, 1, 1 },
90 { CMD("fsr"), MTIOCTOP
, MTFSR
, 1, 1 },
91 { CMD("offline"), MTIOCTOP
, MTOFFL
, 1, 0 },
92 { CMD("rdhpos"), MTIOCRDHPOS
, 0, 1, 0 },
93 { CMD("rdspos"), MTIOCRDSPOS
, 0, 1, 0 },
94 { CMD("retension"), MTIOCTOP
, MTRETEN
, 1, 0 },
95 { CMD("rewind"), MTIOCTOP
, MTREW
, 1, 0 },
96 { CMD("rewoffl"), MTIOCTOP
, MTOFFL
, 1, 0 },
97 { CMD("setblk"), MTIOCTOP
, MTSETBSIZ
, 1, 0 },
98 { CMD("setdensity"), MTIOCTOP
, MTSETDNSTY
, 1, 0 },
99 { CMD("sethpos"), MTIOCHLOCATE
, 0, 1, 0 },
100 { CMD("setspos"), MTIOCSLOCATE
, 0, 1, 0 },
101 { CMD("status"), MTIOCGET
, MTNOP
, 1, 0 },
102 { CMD("weof"), MTIOCTOP
, MTWEOF
, 0, 1 },
103 { CMD("eew"), MTIOCTOP
, MTEWARN
, 1, 0 },
107 void printreg(const char *, u_int
, const char *);
108 void status(struct mtget
*);
110 int main(int, char *[]);
113 main(int argc
, char *argv
[])
115 const struct commands
*cp
, *comp
;
116 struct mtget mt_status
;
124 setprogname(argv
[0]);
125 if ((tape
= getenv("TAPE")) == NULL
)
126 tape
= _PATH_DEFTAPE
;
128 while ((ch
= getopt(argc
, argv
, "f:t:")) != -1)
141 if (argc
< 1 || argc
> 2)
144 len
= strlen(p
= *argv
++);
145 for (comp
= NULL
, cp
= com
; cp
->c_name
!= NULL
; cp
++) {
146 size_t clen
= MIN(len
, cp
->c_namelen
);
147 if (strncmp(p
, cp
->c_name
, clen
) == 0) {
149 errx(1, "%s: Ambiguous command `%s' or `%s'?",
150 p
, cp
->c_name
, comp
->c_name
);
156 errx(1, "%s: unknown command", p
);
159 count
= strtol(*argv
, &p
, 10);
160 if (count
< comp
->c_mincount
|| *p
)
161 errx(2, "%s: illegal count", *argv
);
165 flags
= comp
->c_ronly
? O_RDONLY
: O_WRONLY
;
167 if ((mtfd
= open(tape
, flags
)) < 0)
170 switch (comp
->c_spcl
) {
172 if (comp
->c_code
== MTASF
) {
174 /* If mtget.mt_fileno was implemented, We could
175 compute the minimal seek needed to position
176 the tape. Until then, rewind and seek from
179 mt_com
.mt_op
= MTREW
;
181 if (ioctl(mtfd
, MTIOCTOP
, &mt_com
) < 0)
185 mt_com
.mt_op
= MTFSF
;
186 mt_com
.mt_count
= count
;
187 if (ioctl(mtfd
, MTIOCTOP
, &mt_com
) < 0)
192 mt_com
.mt_op
= comp
->c_code
;
193 mt_com
.mt_count
= count
;
195 if (ioctl(mtfd
, MTIOCTOP
, &mt_com
) < 0)
196 err(2, "%s: %s", tape
, comp
->c_name
);
202 if (ioctl(mtfd
, MTIOCGET
, &mt_status
) < 0)
203 err(2, "%s: %s", tape
, comp
->c_name
);
209 if (ioctl(mtfd
, comp
->c_spcl
, (caddr_t
) &count
) < 0)
211 printf("%s: block location %u\n", tape
, (unsigned int) count
);
216 if (ioctl(mtfd
, comp
->c_spcl
, (caddr_t
) &count
) < 0)
221 errx(1, "internal error: unknown request %ld", comp
->c_spcl
);
228 #if defined(sun) && !defined(__SVR4)
229 #include <sundev/tmreg.h>
230 #include <sundev/arreg.h>
234 #include <tahoe/vba/cyreg.h>
237 const struct tape_desc
{
238 short t_type
; /* type of magtape device */
239 const char *t_name
; /* printing name */
240 const char *t_dsbits
; /* "drive status" register */
241 const char *t_erbits
; /* "error" register */
243 #if defined(sun) && !defined(__SVR4)
244 { MT_ISCPC
, "TapeMaster", TMS_BITS
, 0 },
245 { MT_ISAR
, "Archive", ARCH_CTRL_BITS
, ARCH_BITS
},
248 { MT_ISCY
, "cipher", CYS_BITS
, CYCW_BITS
},
250 #define SCSI_DS_BITS "\20\5WriteProtect\2Mounted"
251 { 0x7, "SCSI", SCSI_DS_BITS
, "76543210" },
257 * Interpret the status buffer returned
260 status(struct mtget
*bp
)
262 const struct tape_desc
*mt
;
264 for (mt
= tapes
;; mt
++) {
265 if (mt
->t_type
== 0) {
266 (void)printf("%d: unknown tape drive type\n",
270 if (mt
->t_type
== bp
->mt_type
)
273 (void)printf("%s tape drive, residual=%d\n", mt
->t_name
, bp
->mt_resid
);
274 printreg("ds", bp
->mt_dsreg
, mt
->t_dsbits
);
275 printreg("\ner", bp
->mt_erreg
, mt
->t_erbits
);
277 (void)printf("blocksize: %d (%d, %d, %d, %d)\n",
278 bp
->mt_blksiz
, bp
->mt_mblksiz
[0], bp
->mt_mblksiz
[1],
279 bp
->mt_mblksiz
[2], bp
->mt_mblksiz
[3]);
280 (void)printf("density: %d (%d, %d, %d, %d)\n",
281 bp
->mt_density
, bp
->mt_mdensity
[0], bp
->mt_mdensity
[1],
282 bp
->mt_mdensity
[2], bp
->mt_mdensity
[3]);
283 (void)printf("current file number: %d\n", bp
->mt_fileno
);
284 (void)printf("current block number: %d\n", bp
->mt_blkno
);
288 * Print a register a la the %b format of the kernel's printf.
291 printreg(const char *s
, u_int v
, const char *bits
)
297 if (bits
&& *bits
== 8)
298 printf("%s=%o", s
, v
);
300 printf("%s=%x", s
, v
);
301 if (v
&& bits
&& *++bits
) {
303 while ((i
= *bits
++)) {
304 if (v
& (1 << (i
-1))) {
308 for (; (c
= *bits
) > 32; bits
++)
311 for (; *bits
> 32; bits
++)
321 (void)fprintf(stderr
, "usage: %s [-f device] command [count]\n",