Split miscutils/Config.src items into miscutils/*.c files
[oweals/busybox.git] / miscutils / mt.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
4  */
5 //config:config MT
6 //config:       bool "mt"
7 //config:       default y
8 //config:       help
9 //config:         mt is used to control tape devices. You can use the mt utility
10 //config:         to advance or rewind a tape past a specified number of archive
11 //config:         files on the tape.
12
13 //usage:#define mt_trivial_usage
14 //usage:       "[-f device] opcode value"
15 //usage:#define mt_full_usage "\n\n"
16 //usage:       "Control magnetic tape drive operation\n"
17 //usage:       "\n"
18 //usage:       "Available Opcodes:\n"
19 //usage:       "\n"
20 //usage:       "bsf bsfm bsr bss datacompression drvbuffer eof eom erase\n"
21 //usage:       "fsf fsfm fsr fss load lock mkpart nop offline ras1 ras2\n"
22 //usage:       "ras3 reset retension rewind rewoffline seek setblk setdensity\n"
23 //usage:       "setpart tell unload unlock weof wset"
24
25 #include "libbb.h"
26 #include <sys/mtio.h>
27
28 /* missing: eod/seod, stoptions, stwrthreshold, densities */
29 static const short opcode_value[] = {
30         MTBSF,
31         MTBSFM,
32         MTBSR,
33         MTBSS,
34         MTCOMPRESSION,
35         MTEOM,
36         MTERASE,
37         MTFSF,
38         MTFSFM,
39         MTFSR,
40         MTFSS,
41         MTLOAD,
42         MTLOCK,
43         MTMKPART,
44         MTNOP,
45         MTOFFL,
46         MTOFFL,
47         MTRAS1,
48         MTRAS2,
49         MTRAS3,
50         MTRESET,
51         MTRETEN,
52         MTREW,
53         MTSEEK,
54         MTSETBLK,
55         MTSETDENSITY,
56         MTSETDRVBUFFER,
57         MTSETPART,
58         MTTELL,
59         MTWSM,
60         MTUNLOAD,
61         MTUNLOCK,
62         MTWEOF,
63         MTWEOF
64 };
65
66 static const char opcode_name[] ALIGN1 =
67         "bsf"             "\0"
68         "bsfm"            "\0"
69         "bsr"             "\0"
70         "bss"             "\0"
71         "datacompression" "\0"
72         "eom"             "\0"
73         "erase"           "\0"
74         "fsf"             "\0"
75         "fsfm"            "\0"
76         "fsr"             "\0"
77         "fss"             "\0"
78         "load"            "\0"
79         "lock"            "\0"
80         "mkpart"          "\0"
81         "nop"             "\0"
82         "offline"         "\0"
83         "rewoffline"      "\0"
84         "ras1"            "\0"
85         "ras2"            "\0"
86         "ras3"            "\0"
87         "reset"           "\0"
88         "retension"       "\0"
89         "rewind"          "\0"
90         "seek"            "\0"
91         "setblk"          "\0"
92         "setdensity"      "\0"
93         "drvbuffer"       "\0"
94         "setpart"         "\0"
95         "tell"            "\0"
96         "wset"            "\0"
97         "unload"          "\0"
98         "unlock"          "\0"
99         "eof"             "\0"
100         "weof"            "\0";
101
102 int mt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
103 int mt_main(int argc UNUSED_PARAM, char **argv)
104 {
105         const char *file = "/dev/tape";
106         struct mtop op;
107         struct mtpos position;
108         int fd, mode, idx;
109
110         if (!argv[1]) {
111                 bb_show_usage();
112         }
113
114         if (strcmp(argv[1], "-f") == 0) {
115                 if (!argv[2] || !argv[3])
116                         bb_show_usage();
117                 file = argv[2];
118                 argv += 2;
119         }
120
121         idx = index_in_strings(opcode_name, argv[1]);
122
123         if (idx < 0)
124                 bb_error_msg_and_die("unrecognized opcode %s", argv[1]);
125
126         op.mt_op = opcode_value[idx];
127         if (argv[2])
128                 op.mt_count = xatoi_positive(argv[2]);
129         else
130                 op.mt_count = 1;  /* One, not zero, right? */
131
132         switch (opcode_value[idx]) {
133                 case MTWEOF:
134                 case MTERASE:
135                 case MTWSM:
136                 case MTSETDRVBUFFER:
137                         mode = O_WRONLY;
138                         break;
139
140                 default:
141                         mode = O_RDONLY;
142                         break;
143         }
144
145         fd = xopen(file, mode);
146
147         switch (opcode_value[idx]) {
148                 case MTTELL:
149                         ioctl_or_perror_and_die(fd, MTIOCPOS, &position, "%s", file);
150                         printf("At block %d\n", (int) position.mt_blkno);
151                         break;
152
153                 default:
154                         ioctl_or_perror_and_die(fd, MTIOCTOP, &op, "%s", file);
155                         break;
156         }
157
158         return EXIT_SUCCESS;
159 }