busybox/miscutils/mt.c
<<
>>
Prefs
   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.5 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:       "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 */
  33static const short opcode_value[] ALIGN2 = {
  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
  70static 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
 106int mt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 107int 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}
 164