📄 mt.c
字号:
/* This file contains the source of the 'mt' program intended for Linux systems. The program supports the basic mt commands found in most Unix-like systems. In addition to this the program supports several commands designed for use with the Linux SCSI tape drive. Maintained by Kai M鋕isara (email Kai.Makisara@kolumbus.fi) Copyright by Kai M鋕isara, 1998 - 2005. The program may be distributed according to the GNU Public License Last Modified: Sun Aug 21 21:48:06 2005 by kai.makisara*/#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <sys/types.h>#include <sys/ioctl.h>#include "mtio.h"#ifndef DEFTAPE#define DEFTAPE "/dev/tape" /* default tape device */#endif /* DEFTAPE */#define VERSION "0.9b"typedef int (* cmdfunc)(/* int, struct cmdef_tr *, int, char ** */);typedef struct cmdef_tr { char *cmd_name; int cmd_code; cmdfunc cmd_function; int cmd_count_bits; unsigned char cmd_fdtype; unsigned char arg_cnt; int error_tests;} cmdef_tr;#define NO_FD 0#define FD_RDONLY 1#define FD_RDWR 2#define NO_ARGS 0#define ONE_ARG 1#define TWO_ARGS 2#define MULTIPLE_ARGS 255#define DO_BOOLEANS 1002#define SET_BOOLEANS 1003#define CLEAR_BOOLEANS 1004#define ET_ONLINE 1#define ET_WPROT 2static void usage(int);static int do_standard(int, cmdef_tr *, int, char **);static int do_drvbuffer(int, cmdef_tr *, int, char **);static int do_options(int, cmdef_tr *, int, char **);static int do_tell(int, cmdef_tr *, int, char **);static int do_partseek(int, cmdef_tr *, int, char **);static int do_status(int, cmdef_tr *, int, char **);static int print_densities(int, cmdef_tr *, int, char **);static int do_asf(int, cmdef_tr *, int, char **);static void test_error(int, cmdef_tr *);static cmdef_tr cmds[] = { { "weof", MTWEOF, do_standard, 0, FD_RDWR, ONE_ARG, ET_ONLINE | ET_WPROT }, { "wset", MTWSM, do_standard, 0, FD_RDWR, ONE_ARG, ET_ONLINE | ET_WPROT }, { "eof", MTWEOF, do_standard, 0, FD_RDWR, ONE_ARG, ET_ONLINE }, { "fsf", MTFSF, do_standard, 0, FD_RDONLY, ONE_ARG, ET_ONLINE }, { "fsfm", MTFSFM, do_standard, 0, FD_RDONLY, ONE_ARG, ET_ONLINE }, { "bsf", MTBSF, do_standard, 0, FD_RDONLY, ONE_ARG, ET_ONLINE }, { "bsfm", MTBSFM, do_standard, 0, FD_RDONLY, ONE_ARG, ET_ONLINE }, { "fsr", MTFSR, do_standard, 0, FD_RDONLY, ONE_ARG, ET_ONLINE }, { "bsr", MTBSR, do_standard, 0, FD_RDONLY, ONE_ARG, ET_ONLINE }, { "fss", MTFSS, do_standard, 0, FD_RDONLY, ONE_ARG, ET_ONLINE }, { "bss", MTBSS, do_standard, 0, FD_RDONLY, ONE_ARG, ET_ONLINE }, { "rewind", MTREW, do_standard, 0, FD_RDONLY, NO_ARGS, ET_ONLINE }, { "offline", MTOFFL, do_standard, 0, FD_RDONLY, NO_ARGS, ET_ONLINE }, { "rewoffl", MTOFFL, do_standard, 0, FD_RDONLY, NO_ARGS, ET_ONLINE }, { "eject", MTOFFL, do_standard, 0, FD_RDONLY, NO_ARGS, ET_ONLINE }, { "retension", MTRETEN, do_standard, 0, FD_RDONLY, NO_ARGS, ET_ONLINE }, { "eod", MTEOM, do_standard, 0, FD_RDONLY, NO_ARGS, ET_ONLINE }, { "seod", MTEOM, do_standard, 0, FD_RDONLY, NO_ARGS, ET_ONLINE }, { "seek", MTSEEK, do_standard, 0, FD_RDONLY, ONE_ARG, ET_ONLINE }, { "tell", MTTELL, do_tell, 0, FD_RDONLY, NO_ARGS, ET_ONLINE }, { "status", MTNOP, do_status, 0, FD_RDONLY, NO_ARGS, 0 }, { "erase", MTERASE, do_standard, 0, FD_RDWR, ONE_ARG, ET_ONLINE }, { "setblk", MTSETBLK, do_standard, 0, FD_RDONLY, ONE_ARG, 0 }, { "lock", MTLOCK, do_standard, 0, FD_RDONLY, NO_ARGS, ET_ONLINE }, { "unlock", MTUNLOCK, do_standard, 0, FD_RDONLY, NO_ARGS, ET_ONLINE }, { "load", MTLOAD, do_standard, 0, FD_RDONLY, ONE_ARG, 0 }, { "compression", MTCOMPRESSION, do_standard, 0, FD_RDONLY, ONE_ARG, 0 }, { "setdensity", MTSETDENSITY, do_standard, 0, FD_RDONLY, ONE_ARG, 0 }, { "drvbuffer", MTSETDRVBUFFER, do_drvbuffer, 0, FD_RDONLY, ONE_ARG, 0 }, { "stwrthreshold", MTSETDRVBUFFER, do_drvbuffer, MT_ST_WRITE_THRESHOLD, FD_RDONLY, ONE_ARG, 0}, { "stoptions", DO_BOOLEANS, do_options, 0, FD_RDONLY, MULTIPLE_ARGS, 0}, { "stsetoptions", SET_BOOLEANS, do_options, 0, FD_RDONLY, MULTIPLE_ARGS, 0}, { "stclearoptions", CLEAR_BOOLEANS, do_options, 0, FD_RDONLY, MULTIPLE_ARGS, 0}, { "defblksize", MTSETDRVBUFFER, do_drvbuffer, MT_ST_DEF_BLKSIZE, FD_RDONLY, ONE_ARG, 0}, { "defdensity", MTSETDRVBUFFER, do_drvbuffer, MT_ST_DEF_DENSITY, FD_RDONLY, ONE_ARG, 0}, { "defdrvbuffer", MTSETDRVBUFFER, do_drvbuffer, MT_ST_DEF_DRVBUFFER, FD_RDONLY, ONE_ARG, 0}, { "defcompression", MTSETDRVBUFFER, do_drvbuffer, MT_ST_DEF_COMPRESSION, FD_RDONLY, ONE_ARG, 0}, { "stsetcln", MTSETDRVBUFFER, do_drvbuffer, MT_ST_SET_CLN, FD_RDONLY, ONE_ARG, 0}, { "sttimeout", MTSETDRVBUFFER, do_drvbuffer, MT_ST_SET_TIMEOUT, FD_RDONLY, ONE_ARG, 0}, { "stlongtimeout", MTSETDRVBUFFER, do_drvbuffer, MT_ST_SET_LONG_TIMEOUT, FD_RDONLY, ONE_ARG, 0}, { "densities", 0, print_densities, 0, NO_FD, NO_ARGS, 0 }, { "setpartition", MTSETPART, do_standard, 0, FD_RDONLY, ONE_ARG, ET_ONLINE }, { "mkpartition", MTMKPART, do_standard, 0, FD_RDWR, ONE_ARG, ET_ONLINE }, { "partseek", 0, do_partseek, 0, FD_RDONLY, TWO_ARGS, ET_ONLINE }, { "asf", 0, do_asf, MTREW, FD_RDONLY, ONE_ARG, ET_ONLINE }, { NULL, 0, 0, 0 }};static struct densities { int code; char *name;} density_tbl[] = { {0x00, "default"}, {0x01, "NRZI (800 bpi)"}, {0x02, "PE (1600 bpi)"}, {0x03, "GCR (6250 bpi)"}, {0x04, "QIC-11"}, {0x05, "QIC-45/60 (GCR, 8000 bpi)"}, {0x06, "PE (3200 bpi)"}, {0x07, "IMFM (6400 bpi)"}, {0x08, "GCR (8000 bpi)"}, {0x09, "GCR (37871 bpi)"}, {0x0a, "MFM (6667 bpi)"}, {0x0b, "PE (1600 bpi)"}, {0x0c, "GCR (12960 bpi)"}, {0x0d, "GCR (25380 bpi)"}, {0x0f, "QIC-120 (GCR 10000 bpi)"}, {0x10, "QIC-150/250 (GCR 10000 bpi)"}, {0x11, "QIC-320/525 (GCR 16000 bpi)"}, {0x12, "QIC-1350 (RLL 51667 bpi)"}, {0x13, "DDS (61000 bpi)"}, {0x14, "EXB-8200 (RLL 43245 bpi)"}, {0x15, "EXB-8500 or QIC-1000"}, {0x16, "MFM 10000 bpi"}, {0x17, "MFM 42500 bpi"}, {0x18, "TZ86"}, {0x19, "DLT 10GB"}, {0x1a, "DLT 20GB"}, {0x1b, "DLT 35GB"}, {0x1c, "QIC-385M"}, {0x1d, "QIC-410M"}, {0x1e, "QIC-1000C"}, {0x1f, "QIC-2100C"}, {0x20, "QIC-6GB"}, {0x21, "QIC-20GB"}, {0x22, "QIC-2GB"}, {0x23, "QIC-875"}, {0x24, "DDS-2"}, {0x25, "DDS-3"}, {0x26, "DDS-4 or QIC-4GB"}, {0x27, "Exabyte Mammoth"}, {0x28, "Exabyte Mammoth-2"}, {0x29, "QIC-3080MC"}, {0x30, "AIT-1 or MLR3"}, {0x31, "AIT-2"}, {0x32, "AIT-3"}, {0x33, "SLR6"}, {0x34, "SLR100"}, {0x40, "DLT1 40 GB, or Ultrium"}, {0x41, "DLT 40GB, or Ultrium2"}, {0x42, "LTO-2"}, {0x45, "QIC-3095-MC (TR-4)"}, {0x47, "TR-5"}, {0x80, "DLT 15GB uncomp. or Ecrix"}, {0x81, "DLT 15GB compressed"}, {0x82, "DLT 20GB uncompressed"}, {0x83, "DLT 20GB compressed"}, {0x84, "DLT 35GB uncompressed"}, {0x85, "DLT 35GB compressed"}, {0x86, "DLT1 40 GB uncompressed"}, {0x87, "DLT1 40 GB compressed"}, {0x88, "DLT 40GB uncompressed"}, {0x89, "DLT 40GB compressed"}, {0x8c, "EXB-8505 compressed"}, {0x90, "SDLT110 uncompr/EXB-8205 compr"}, {0x91, "SDLT110 compressed"}, {0x92, "SDLT160 uncompressed"}, {0x93, "SDLT160 comprssed"}};#define NBR_DENSITIES (sizeof(density_tbl) / sizeof(struct densities))static struct booleans { char *name; unsigned long bitmask; char *expl;} boolean_tbl[] = { {"buffer-writes", MT_ST_BUFFER_WRITES, "buffered writes"}, {"async-writes", MT_ST_ASYNC_WRITES, "asynchronous writes"}, {"read-ahead", MT_ST_READ_AHEAD, "read-ahead for fixed block size"}, {"debug", MT_ST_DEBUGGING, "debugging (if compiled into driver)"}, {"two-fms", MT_ST_TWO_FM, "write two filemarks when file closed"}, {"fast-eod", MT_ST_FAST_MTEOM, "space directly to eod (and lose file number)"}, {"auto-lock", MT_ST_AUTO_LOCK, "automatically lock/unlock drive door"}, {"def-writes", MT_ST_DEF_WRITES, "the block size and density are for writes"}, {"can-bsr", MT_ST_CAN_BSR, "drive can space backwards well"}, {"no-blklimits", MT_ST_NO_BLKLIMS, "drive doesn't support read block limits"}, {"can-partitions",MT_ST_CAN_PARTITIONS,"drive can handle partitioned tapes"}, {"scsi2logical", MT_ST_SCSI2LOGICAL, "logical block addresses used with SCSI-2"}, {"no-wait", MT_ST_NOWAIT, "immediate mode for rewind, etc."},#ifdef MT_ST_SYSV {"sysv", MT_ST_SYSV, "enable the SystemV semantics"},#endif {"cleaning", MT_ST_SET_CLN, "set the cleaning bit location and mask"}, {NULL, 0}};static char *tape_name; /* The tape name for messages */ intmain(int argc, char **argv){ int mtfd, cmd_code, i, argn, len, oflags; char *cmdstr; cmdef_tr *comp, *comp2; for (argn=1; argn < argc; argn++) if (*argv[argn] == '-') switch (*(argv[argn] + 1)) { case 'f': case 't': argn += 1; if (argn >= argc) { usage(0); exit(1); } tape_name = argv[argn]; break; case 'h': usage(1); exit(0); break; case 'v': printf("mt-st v. %s\n", VERSION); exit(0); break; case '-': if (*(argv[argn] + 1) == '-' && *(argv[argn] + 2) == 'v') { printf("mt-st v. %s\n", VERSION); exit(0); } /* Fall through */ default: usage(0); exit(1); } else break; if (tape_name == NULL && (tape_name = getenv("TAPE")) == NULL) tape_name = DEFTAPE; if (argn >= argc ) { usage(0); exit(1); } cmdstr = argv[argn++]; len = strlen(cmdstr); for (comp = cmds; comp->cmd_name != NULL; comp++) if (strncmp(cmdstr, comp->cmd_name, len) == 0) break; if (comp->cmd_name == NULL) { fprintf(stderr, "mt: unknown command \"%s\"\n", cmdstr); usage(1); exit(1); } if (len != strlen(comp->cmd_name)) { for (comp2 = comp + 1; comp2->cmd_name != NULL; comp2++) if (strncmp(cmdstr, comp2->cmd_name, len) == 0) break; if (comp2->cmd_name != NULL) { fprintf(stderr, "mt: ambiguous command \"%s\"\n", cmdstr); usage(1); exit(1); } } if (comp->arg_cnt != MULTIPLE_ARGS && comp->arg_cnt < argc - argn) { fprintf(stderr, "mt: too many arguments for the command '%s'.\n", comp->cmd_name); exit(1); } cmd_code = comp->cmd_code; if (comp->cmd_fdtype != NO_FD) { oflags = comp->cmd_fdtype == FD_RDONLY ? O_RDONLY : O_RDWR; if ((comp->error_tests & ET_ONLINE) == 0) oflags |= O_NONBLOCK; if ((mtfd = open(tape_name, oflags)) < 0) { perror(tape_name); exit(1); } } else mtfd = (-1); if (comp->cmd_function != NULL) { i = comp->cmd_function(mtfd, comp, argc - argn, (argc - argn > 0 ? argv + argn : NULL));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -