source: trunk/minix/commands/simple/mt.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 5.2 KB
Line 
1/* mt 1.3 - magnetic tape control Author: Kees J. Bot
2 * 4 Apr 1993
3 */
4#define nil NULL
5#ifndef _POSIX_SOURCE
6#define _POSIX_SOURCE 1
7#endif
8#include <sys/types.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <errno.h>
12#include <unistd.h>
13#include <fcntl.h>
14#include <string.h>
15#include <sys/ioctl.h>
16#include <sys/mtio.h>
17
18/* Device status. */
19#define DS_OK 0
20#define DS_ERR 1
21#define DS_EOF 2
22
23/* SCSI Sense key bits. */
24#define SENSE_KEY 0x0F /* The key part. */
25#define SENSE_ILI 0x20 /* Illegal block size. */
26#define SENSE_EOM 0x40 /* End-of-media. */
27#define SENSE_EOF 0x80 /* Filemark reached. */
28
29/* Supported operations: */
30
31typedef struct tape_operation {
32 int op; /* Opcode for MTIOCTOP ioctl (if any). */
33 char *cmd; /* Command name. */
34 int lim; /* Limits on count. */
35} tape_operation_t;
36
37#define SELF -1 /* Not a simple command, have to interpret. */
38#define IGN -1 /* Ignore count field (or accept anything.) */
39#define NNG 0 /* Nonnegative count field. */
40#define POS 1 /* Positive count field. */
41
42tape_operation_t tapeops[] = {
43 { MTWEOF, "eof", POS }, /* Write EOF mark */
44 { MTWEOF, "weof", POS }, /* Same */
45 { MTFSF, "fsf", POS }, /* Forward Space File */
46 { MTFSR, "fsr", POS }, /* Forward Space Record */
47 { MTBSF, "bsf", NNG }, /* Backward Space File */
48 { MTBSR, "bsr", POS }, /* Backward Space Record */
49 { MTEOM, "eom", IGN }, /* To End-Of-Media */
50 { MTREW, "rewind", IGN }, /* Rewind */
51 { MTOFFL, "offline", IGN }, /* Rewind and take offline */
52 { MTOFFL, "rewoffl", IGN }, /* Same */
53 { SELF, "status", IGN }, /* Tape Status */
54 { MTRETEN, "retension",IGN }, /* Retension the tape */
55 { MTERASE, "erase", IGN }, /* Erase the tape */
56 { MTMODE, "density", NNG }, /* Select density */
57 { MTBLKZ, "blksize", NNG }, /* Select block size */
58 { MTBLKZ, "blocksize",NNG }, /* Same */
59};
60
61#define arraysize(a) (sizeof(a)/sizeof((a)[0]))
62#define arraylimit(a) ((a) + arraysize(a))
63
64/* From aha_scsi.c: */
65char *dev_state[] = {
66 "OK", "ERR", "EOF"
67};
68
69char *scsi_sense[] = {
70 "NO SENSE INFO", "RECOVERED ERROR", "NOT READY", "MEDIUM ERROR",
71 "HARDWARE ERROR", "ILLEGAL REQUEST", "UNIT ATTENTION", "DATA PROTECT",
72 "BLANK CHECK", "VENDOR UNIQUE ERROR", "COPY ABORTED", "ABORTED COMMAND",
73 "EQUAL", "VOLUME OVERFLOW", "MISCOMPARE", "SENSE RESERVED"
74};
75
76void usage(void)
77{
78 fprintf(stderr, "Usage: mt [-f device] command [count]\n");
79 exit(1);
80}
81
82int main(int argc, char **argv)
83{
84 char *tape;
85 char *cmd;
86 int count= 1;
87 int fd, r;
88 tape_operation_t *op, *found;
89 struct mtop mtop;
90 struct mtget mtget;
91
92 tape= getenv("TAPE");
93
94 /* -f tape? */
95 if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'f') {
96 tape= argv[1] + 2;
97
98 if (*tape == 0) {
99 if (--argc < 2) usage();
100 argv++;
101 tape= argv[1];
102 }
103 argc--;
104 argv++;
105 }
106
107 if (argc != 2 && argc != 3) usage();
108
109 if (argc == 3) {
110 /* Check and convert the 'count' argument. */
111 char *end;
112
113 errno= 0;
114 count= strtol(argv[2], &end, 0);
115 if (*end != 0) usage();
116 if (errno == ERANGE || (mtop.mt_count= count) != count) {
117 fprintf(stderr, "mt: %s: count too large, overflow\n",
118 argv[2]);
119 exit(1);
120 }
121 }
122
123 if (tape == nil) {
124 fprintf(stderr,
125 "mt: tape device not specified by -f or $TAPE\n");
126 exit(1);
127 }
128
129 cmd= argv[1];
130 if (strcmp(cmd, "rew") == 0) cmd= "rewind"; /* aha! */
131 found= nil;
132
133 /* Search for an operation that is unambiguously named. */
134 for (op= tapeops; op < arraylimit(tapeops); op++) {
135 if (strncmp(op->cmd, cmd, strlen(cmd)) == 0) {
136 if (found != nil) {
137 fprintf(stderr, "mt: %s: ambiguous\n", cmd);
138 exit(1);
139 }
140 found= op;
141 }
142 }
143
144 if ((op= found) == nil) {
145 fprintf(stderr, "mt: unknown command '%s'\n", cmd);
146 exit(1);
147 }
148
149 /* Check count. */
150 switch (op->lim) {
151 case NNG:
152 if (count < 0) {
153 fprintf(stderr, "mt %s: count may not be negative\n",
154 op->cmd);
155 exit(1);
156 }
157 break;
158 case POS:
159 if (count <= 0) {
160 fprintf(stderr,
161 "mt %s: count must be greater than zero\n",
162 op->cmd);
163 exit(1);
164 }
165 break;
166 }
167
168 if (strcmp(tape, "-") == 0) {
169 fd= 0;
170 } else
171 if ((fd= open(tape, O_RDONLY)) < 0) {
172 fprintf(stderr, "mt: %s: %s\n", tape, strerror(errno));
173 exit(1);
174 }
175
176 if (op->op != SELF) {
177 /* A simple tape operation. */
178
179 mtop.mt_op= op->op;
180 mtop.mt_count= count;
181 r= ioctl(fd, MTIOCTOP, &mtop);
182 } else
183 if (strcmp(op->cmd, "status") == 0) {
184 /* Get status information. */
185
186 if ((r= ioctl(fd, MTIOCGET, &mtget)) == 0) {
187 printf("\
188SCSI tape drive %s:\n\
189 drive status = 0x%02x (%s), sense key = 0x%02x (%s%s%s%s)\n\
190 file no = %ld, block no = %ld, residual = %ld, block size = ",
191 tape, mtget.mt_dsreg,
192 mtget.mt_dsreg > 2 ? "?" :
193 dev_state[mtget.mt_dsreg],
194 mtget.mt_erreg,
195 mtget.mt_erreg & SENSE_EOF ? "EOF + " : "",
196 mtget.mt_erreg & SENSE_EOM ? "EOM + " : "",
197 mtget.mt_erreg & SENSE_ILI ? "ILI + " : "",
198 scsi_sense[mtget.mt_erreg & SENSE_KEY],
199 (long) mtget.mt_fileno,
200 (long) mtget.mt_blkno,
201 (long) mtget.mt_resid);
202 printf(mtget.mt_blksize == 0 ? "variable\n" : "%ld\n",
203 mtget.mt_blksize);
204 }
205 }
206 if (r < 0) {
207 if (errno == ENOTTY) {
208 fprintf(stderr, "mt: %s: command '%s' not supported\n",
209 tape, op->cmd);
210 exit(2);
211 }
212 fprintf(stderr, "mt: %s: %s\n", tape, strerror(errno));
213 exit(1);
214 }
215 exit(0);
216}
Note: See TracBrowser for help on using the repository browser.