source: trunk/essentials/app-arch/cpio/src/mt.c

Last change on this file was 3332, checked in by bird, 18 years ago

cpio 2.7

File size: 7.8 KB
Line 
1/* mt -- control magnetic tape drive operation
2 Copyright (C) 1991, 1992, 1995, 2001 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301 USA
18*/
19
20
21/* If -f is not given, the environment variable TAPE is used;
22 if that is not set, a default device defined in sys/mtio.h is used.
23 The device must be either a character special file or a remote
24 tape drive with the form "[user@]system:path".
25 The default count is 1. Some operations ignore it.
26
27 Exit status:
28 0 success
29 1 invalid operation or device name
30 2 operation failed
31
32 Operations (unique abbreviations are accepted):
33 eof, weof Write COUNT EOF marks at current position on tape.
34 fsf Forward space COUNT files.
35 Tape is positioned on the first block of the file.
36 bsf Backward space COUNT files.
37 Tape is positioned on the first block of the file.
38 fsr Forward space COUNT records.
39 bsr Backward space COUNT records.
40 bsfm Backward space COUNT file marks.
41 Tape is positioned on the beginning-of-the-tape side of
42 the file mark.
43 asf Absolute space to file number COUNT.
44 Equivalent to rewind followed by fsf COUNT.
45 eom Space to the end of the recorded media on the tape
46 (for appending files onto tapes).
47 rewind Rewind the tape.
48 offline, rewoffl
49 Rewind the tape and, if applicable, unload the tape.
50 status Print status information about the tape unit.
51 retension Rewind the tape, then wind it to the end of the reel,
52 then rewind it again.
53 erase Erase the tape.
54
55 David MacKenzie <djm@gnu.ai.mit.edu> */
56
57#include <system.h>
58
59#include <stdio.h>
60#include <sys/types.h>
61#include <sys/stat.h>
62#include <sys/ioctl.h>
63#ifdef HAVE_SYS_MTIO_H
64# ifdef HAVE_SYS_IO_TRIOCTL_H
65# include <sys/io/trioctl.h>
66# endif
67# include <sys/mtio.h>
68#endif
69#include <sys/file.h>
70#include <fcntl.h>
71#include <errno.h>
72#include <getopt.h>
73#include <stdbool.h>
74
75#ifdef HAVE_LOCALE_H
76# include <locale.h>
77#endif
78#include <localedir.h>
79
80#if defined(HAVE_UNISTD_H)
81#include <unistd.h>
82#endif
83#include <rmt.h>
84
85#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
86#include <string.h>
87#else
88#include <strings.h>
89#endif
90
91#if defined(HAVE_STDLIB_H)
92# include <stdlib.h>
93#endif
94
95#if !HAVE_DECL_ERRNO
96extern int errno;
97#endif
98#if !HAVE_DECL_GETENV
99char *getenv ();
100#endif
101#if !HAVE_DECL_ATOI
102int atoi ();
103#endif
104#if !HAVE_DECL_EXIT
105void exit ();
106#endif
107
108char *opnames[] =
109{
110 "eof", "weof", "fsf", "bsf", "fsr", "bsr",
111 "rewind", "offline", "rewoffl", "eject", "status",
112#ifdef MTBSFM
113 "bsfm",
114#endif
115#ifdef MTEOM
116 "eom",
117#endif
118#ifdef MTRETEN
119 "retension",
120#endif
121#ifdef MTERASE
122 "erase",
123#endif
124 "asf",
125#ifdef MTFSFM
126 "fsfm",
127#endif
128#ifdef MTSEEK
129 "seek",
130#endif
131 NULL
132};
133
134#define MTASF 600 /* Random unused number. */
135short operations[] =
136{
137 MTWEOF, MTWEOF, MTFSF, MTBSF, MTFSR, MTBSR,
138 MTREW, MTOFFL, MTOFFL, MTOFFL, MTNOP,
139#ifdef MTBSFM
140 MTBSFM,
141#endif
142#ifdef MTEOM
143 MTEOM,
144#endif
145#ifdef MTRETEN
146 MTRETEN,
147#endif
148#ifdef MTERASE
149 MTERASE,
150#endif
151 MTASF,
152#ifdef MTFSFM
153 MTFSFM,
154#endif
155#ifdef MTSEEK
156 MTSEEK,
157#endif
158 0
159};
160
161struct option longopts[] =
162{
163 {"file", 1, NULL, 'f'},
164 {"rsh-command", 1, NULL, 1},
165 {"version", 0, NULL, 'V'},
166 {"help", 0, NULL, 'H'},
167 {NULL, 0, NULL, 0}
168};
169
170/* The name this program was run with. */
171char *program_name;
172
173void
174check_type (char *dev, int desc)
175{
176 struct stat stats;
177
178 if (_isrmt (desc))
179 return;
180 if (fstat (desc, &stats) == -1)
181 stat_error (dev);
182 if ((stats.st_mode & S_IFMT) != S_IFCHR)
183 error (1, 0, _("%s is not a character special file"), dev);
184}
185void
186perform_operation (char *dev, int desc, short op, int count)
187{
188 struct mtop control;
189
190 control.mt_op = op;
191 control.mt_count = count;
192 /* Debian hack: The rmtioctl function returns -1 in case of an
193 error, not 0. This bug has been reported to
194 "bug-gnu-utils@prep.ai.mit.edu". (96/7/10) -BEM */
195 if (rmtioctl (desc, MTIOCTOP, (char*)&control) == -1)
196 error (2, errno, _("%s: rmtioctl failed"), dev);
197}
198
199void
200print_status (char *dev, int desc)
201{
202 struct mtget status;
203
204 if (rmtioctl (desc, MTIOCGET, (char*)&status) == -1)
205 error (2, errno, _("%s: rmtioctl failed"), dev);
206
207 printf ("drive type = %d\n", (int) status.mt_type);
208#if defined(hpux) || defined(__hpux)
209 printf ("drive status (high) = %d\n", (int) status.mt_dsreg1);
210 printf ("drive status (low) = %d\n", (int) status.mt_dsreg2);
211#else
212 printf ("drive status = %d\n", (int) status.mt_dsreg);
213#endif
214 printf ("sense key error = %d\n", (int) status.mt_erreg);
215 printf ("residue count = %d\n", (int) status.mt_resid);
216#if !defined(ultrix) && !defined(__ultrix__) && !defined(hpux) && !defined(__hpux) && !defined(__osf__)
217 printf ("file number = %d\n", (int) status.mt_fileno);
218 printf ("block number = %d\n", (int) status.mt_blkno);
219#endif
220}
221
222void
223usage (FILE *fp,int status)
224{
225 fprintf (fp, _("\
226Usage: %s [-V] [-f device] [--file=device] [--rsh-command=command]\n\
227\t[--help] [--version] operation [count]\n"),
228 program_name);
229 exit (status);
230}
231
232int
233main (int argc, char **argv)
234{
235 short operation;
236 int count;
237 char *tapedev;
238 int tapedesc;
239 int i;
240 char *rsh_command_option = NULL;
241
242 setlocale (LC_ALL, "");
243 bindtextdomain (PACKAGE, LOCALEDIR);
244 textdomain (PACKAGE);
245
246 program_name = argv[0];
247 tapedev = NULL;
248 count = 1;
249
250 /* Debian hack: Fixed a bug in the -V flag. This bug has been
251 reported to "bug-gnu-utils@prep.ai.mit.edu". -BEM */
252 while ((i = getopt_long (argc, argv, "f:t:VH", longopts, (int *) 0)) != -1)
253 {
254 switch (i)
255 {
256 case 'f':
257 case 't':
258 tapedev = optarg;
259 break;
260
261 case 1:
262 rsh_command_option = optarg;
263 break;
264
265 case 'V':
266 printf ("mt (%s)\n", PACKAGE_STRING);
267 exit (0);
268 break;
269
270 case 'H':
271 default:
272 usage (stdout, 0);
273 }
274 }
275
276 if (optind == argc)
277 usage (stderr, 1);
278
279 i = argmatch (argv[optind], opnames);
280 if (i < 0)
281 {
282 argmatch_invalid ("tape operation", argv[optind], i);
283 exit (1);
284 }
285 operation = operations[i];
286
287 if (++optind < argc)
288 /* Debian hack: Replaced the atoi function call with strtol so
289 that hexidecimal values can be used for the count parameter.
290 This bug has been reported to "bug-gnu-utils@prep.ai.mit.edu".
291 (97/12/5) -BEM */
292#if defined(STDC_HEADERS)
293 count = (int) strtol (argv[optind], NULL, 0);
294#else
295 count = atoi (argv[optind]);
296#endif
297 if (++optind < argc)
298 usage (stderr, 1);
299
300 if (tapedev == NULL)
301 {
302 tapedev = getenv ("TAPE");
303 if (tapedev == NULL)
304#ifdef DEFTAPE /* From sys/mtio.h. */
305 tapedev = DEFTAPE;
306#else
307 error (1, 0, _("no tape device specified"));
308#endif
309 }
310
311 if ( (operation == MTWEOF)
312#ifdef MTERASE
313 || (operation == MTERASE)
314#endif
315 )
316 tapedesc = rmtopen (tapedev, O_WRONLY, 0, rsh_command_option);
317 else
318 tapedesc = rmtopen (tapedev, O_RDONLY, 0, rsh_command_option);
319 if (tapedesc == -1)
320 error (1, errno, _("%s: rmtopen failed"), tapedev);
321 check_type (tapedev, tapedesc);
322
323 if (operation == MTASF)
324 {
325 perform_operation (tapedev, tapedesc, MTREW, 1);
326 operation = MTFSF;
327 }
328 perform_operation (tapedev, tapedesc, operation, count);
329 if (operation == MTNOP)
330 print_status (tapedev, tapedesc);
331
332 if (rmtclose (tapedesc) == -1)
333 error (2, errno, _("%s: rmtclose failed"), tapedev);
334
335 exit (0);
336}
337
Note: See TracBrowser for help on using the repository browser.