hexedit: fixes for redraw and down movement causing SEGV on attempt to access
[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 (2.6 kb)"
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 //applet:IF_MT(APPLET(mt, BB_DIR_BIN, BB_SUID_DROP))
14
15 //kbuild:lib-$(CONFIG_MT) += mt.o
16
17 //usage:#define mt_trivial_usage
18 //usage:       "[-f device] opcode value"
19 //usage:#define mt_full_usage "\n\n"
20 //usage:       "Control magnetic tape drive operation\n"
21 //usage:       "\n"
22 //usage:       "Available Opcodes:\n"
23 //usage:       "\n"
24 //usage:       "bsf bsfm bsr bss datacompression drvbuffer eof eom erase\n"
25 //usage:       "fsf fsfm fsr fss load lock mkpart nop offline ras1 ras2\n"
26 //usage:       "ras3 reset retension rewind rewoffline seek setblk setdensity\n"
27 //usage:       "setpart tell unload unlock weof wset"
28
29 #include "libbb.h"
30 #include <sys/mtio.h>
31
32 /* missing: eod/seod, stoptions, stwrthreshold, densities */
33 static const short opcode_value[] = {
34         MTBSF,
35         MTBSFM,
36         MTBSR,
37         MTBSS,
38         MTCOMPRESSION,
39         MTEOM,
40         MTERASE,
41         MTFSF,
42         MTFSFM,
43         MTFSR,
44         MTFSS,
45         MTLOAD,
46         MTLOCK,
47         MTMKPART,
48         MTNOP,
49         MTOFFL,
50         MTOFFL,
51         MTRAS1,
52         MTRAS2,
53         MTRAS3,
54         MTRESET,
55         MTRETEN,
56         MTREW,
57         MTSEEK,
58         MTSETBLK,
59         MTSETDENSITY,
60         MTSETDRVBUFFER,
61         MTSETPART,
62         MTTELL,
63         MTWSM,
64         MTUNLOAD,
65         MTUNLOCK,
66         MTWEOF,
67         MTWEOF
68 };
69
70 static const char opcode_name[] ALIGN1 =
71         "bsf"             "\0"
72         "bsfm"            "\0"
73         "bsr"             "\0"
74         "bss"             "\0"
75         "datacompression" "\0"
76         "eom"             "\0"
77         "erase"           "\0"
78         "fsf"             "\0"
79         "fsfm"            "\0"
80         "fsr"             "\0"
81         "fss"             "\0"
82         "load"            "\0"
83         "lock"            "\0"
84         "mkpart"          "\0"
85         "nop"             "\0"
86         "offline"         "\0"
87         "rewoffline"      "\0"
88         "ras1"            "\0"
89         "ras2"            "\0"
90         "ras3"            "\0"
91         "reset"           "\0"
92         "retension"       "\0"
93         "rewind"          "\0"
94         "seek"            "\0"
95         "setblk"          "\0"
96         "setdensity"      "\0"
97         "drvbuffer"       "\0"
98         "setpart"         "\0"
99         "tell"            "\0"
100         "wset"            "\0"
101         "unload"          "\0"
102         "unlock"          "\0"
103         "eof"             "\0"
104         "weof"            "\0";
105
106 int mt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
107 int mt_main(int argc UNUSED_PARAM, char **argv)
108 {
109         const char *file = "/dev/tape";
110         struct mtop op;
111         struct mtpos position;
112         int fd, mode, idx;
113
114         if (!argv[1]) {
115                 bb_show_usage();
116         }
117
118         if (strcmp(argv[1], "-f") == 0) {
119                 if (!argv[2] || !argv[3])
120                         bb_show_usage();
121                 file = argv[2];
122                 argv += 2;
123         }
124
125         idx = index_in_strings(opcode_name, argv[1]);
126
127         if (idx < 0)
128                 bb_error_msg_and_die("unrecognized opcode %s", argv[1]);
129
130         op.mt_op = opcode_value[idx];
131         if (argv[2])
132                 op.mt_count = xatoi_positive(argv[2]);
133         else
134                 op.mt_count = 1;  /* One, not zero, right? */
135
136         switch (opcode_value[idx]) {
137                 case MTWEOF:
138                 case MTERASE:
139                 case MTWSM:
140                 case MTSETDRVBUFFER:
141                         mode = O_WRONLY;
142                         break;
143
144                 default:
145                         mode = O_RDONLY;
146                         break;
147         }
148
149         fd = xopen(file, mode);
150
151         switch (opcode_value[idx]) {
152                 case MTTELL:
153                         ioctl_or_perror_and_die(fd, MTIOCPOS, &position, "%s", file);
154                         printf("At block %d\n", (int) position.mt_blkno);
155                         break;
156
157                 default:
158                         ioctl_or_perror_and_die(fd, MTIOCTOP, &op, "%s", file);
159                         break;
160         }
161
162         return EXIT_SUCCESS;
163 }