1/* vi: set sw=4 ts=4: */
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <sys/mtio.h>
6#include <sys/fcntl.h>
7#include "busybox.h"
8
9struct mt_opcodes {
10	char *name;
11	short value;
12};
13
14/* missing: eod/seod, stoptions, stwrthreshold, densities */
15static const struct mt_opcodes opcodes[] = {
16	{"bsf", MTBSF},
17	{"bsfm", MTBSFM},
18	{"bsr", MTBSR},
19	{"bss", MTBSS},
20	{"datacompression", MTCOMPRESSION},
21	{"eom", MTEOM},
22	{"erase", MTERASE},
23	{"fsf", MTFSF},
24	{"fsfm", MTFSFM},
25	{"fsr", MTFSR},
26	{"fss", MTFSS},
27	{"load", MTLOAD},
28	{"lock", MTLOCK},
29	{"mkpart", MTMKPART},
30	{"nop", MTNOP},
31	{"offline", MTOFFL},
32	{"rewoffline", MTOFFL},
33	{"ras1", MTRAS1},
34	{"ras2", MTRAS2},
35	{"ras3", MTRAS3},
36	{"reset", MTRESET},
37	{"retension", MTRETEN},
38	{"rewind", MTREW},
39	{"seek", MTSEEK},
40	{"setblk", MTSETBLK},
41	{"setdensity", MTSETDENSITY},
42	{"drvbuffer", MTSETDRVBUFFER},
43	{"setpart", MTSETPART},
44	{"tell", MTTELL},
45	{"wset", MTWSM},
46	{"unload", MTUNLOAD},
47	{"unlock", MTUNLOCK},
48	{"eof", MTWEOF},
49	{"weof", MTWEOF},
50	{0, 0}
51};
52
53extern int mt_main(int argc, char **argv)
54{
55	const char *file = "/dev/tape";
56	const struct mt_opcodes *code = opcodes;
57	struct mtop op;
58	struct mtpos position;
59	int fd, mode;
60
61	if (argc < 2) {
62		show_usage();
63	}
64
65	if (strcmp(argv[1], "-f") == 0) {
66		if (argc < 4) {
67			show_usage();
68		}
69		file = argv[2];
70		argv += 2;
71		argc -= 2;
72	}
73
74	while (code->name != 0) {
75		if (strcmp(code->name, argv[1]) == 0)
76			break;
77		code++;
78	}
79
80	if (code->name == 0) {
81		error_msg("unrecognized opcode %s.", argv[1]);
82		return EXIT_FAILURE;
83	}
84
85	op.mt_op = code->value;
86	if (argc >= 3)
87		op.mt_count = atoi(argv[2]);
88	else
89		op.mt_count = 1;		/* One, not zero, right? */
90
91	switch (code->value) {
92		case MTWEOF:
93		case MTERASE:
94		case MTWSM:
95		case MTSETDRVBUFFER:
96			mode = O_WRONLY;
97			break;
98
99		default:
100			mode = O_RDONLY;
101			break;
102	}
103
104	if ((fd = open(file, mode, 0)) < 0)
105		perror_msg_and_die("%s", file);
106
107	switch (code->value) {
108		case MTTELL:
109			if (ioctl(fd, MTIOCPOS, &position) < 0)
110				perror_msg_and_die("%s", file);
111			printf ("At block %d.\n", (int) position.mt_blkno);
112			break;
113
114		default:
115			if (ioctl(fd, MTIOCTOP, &op) != 0)
116				perror_msg_and_die("%s", file);
117			break;
118	}
119
120	return EXIT_SUCCESS;
121}
122