hexedit: optimize output buffering
[oweals/busybox.git] / miscutils / mt.c
index 7168ef7ac79a07c160518c0848751fb225734ca3..fad656e956b448e89c1ed04950ae050dedca0699 100644 (file)
-#include "internal.h"
-#include <stdio.h>
-#include <sys/mtio.h>
-#include <sys/fcntl.h>
+/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+//config:config MT
+//config:      bool "mt (2.6 kb)"
+//config:      default y
+//config:      help
+//config:      mt is used to control tape devices. You can use the mt utility
+//config:      to advance or rewind a tape past a specified number of archive
+//config:      files on the tape.
 
-static const char      mt_usage[] = "mt [-f device] opcode value\n";
+//applet:IF_MT(APPLET(mt, BB_DIR_BIN, BB_SUID_DROP))
 
-struct mt_opcodes {
-       char *  name;
-       short   value;
-};
+//kbuild:lib-$(CONFIG_MT) += mt.o
+
+//usage:#define mt_trivial_usage
+//usage:       "[-f device] opcode value"
+//usage:#define mt_full_usage "\n\n"
+//usage:       "Control magnetic tape drive operation\n"
+//usage:       "\n"
+//usage:       "Available Opcodes:\n"
+//usage:       "\n"
+//usage:       "bsf bsfm bsr bss datacompression drvbuffer eof eom erase\n"
+//usage:       "fsf fsfm fsr fss load lock mkpart nop offline ras1 ras2\n"
+//usage:       "ras3 reset retension rewind rewoffline seek setblk setdensity\n"
+//usage:       "setpart tell unload unlock weof wset"
+
+#include "libbb.h"
+#include <sys/mtio.h>
 
 /* missing: eod/seod, stoptions, stwrthreshold, densities */
-static const struct mt_opcodes opcodes[] = {
-       { "bsf",        MTBSF },
-       { "bsfm",       MTBSFM },
-       { "bsr",        MTBSR },
-       { "bss",        MTBSS },
-       { "datacompression",    MTCOMPRESSION },
-       { "eom",        MTEOM },
-       { "erase",      MTERASE },
-       { "fsf",        MTFSF },
-       { "fsfm",       MTFSFM },
-       { "fsr",        MTFSR },
-       { "fss",        MTFSS },
-       { "load",       MTLOAD },
-       { "lock",       MTLOCK },
-       { "mkpart",     MTMKPART },
-       { "nop",        MTNOP },
-       { "offline",MTOFFL },
-       { "rewoffline",MTOFFL },
-       { "ras1",       MTRAS1 },
-       { "ras2",       MTRAS2 },
-       { "ras3",       MTRAS3 },
-       { "reset",      MTRESET },
-       { "retension",  MTRETEN },
-       { "rew",        MTREW },
-       { "seek",       MTSEEK },
-       { "setblk",     MTSETBLK },
-       { "setdensity", MTSETDENSITY },
-       { "drvbuffer",  MTSETDRVBUFFER },
-       { "setpart",    MTSETPART },
-       { "tell",       MTTELL },
-       { "wset",       MTWSM },
-       { "unload",     MTUNLOAD },
-       { "unlock",     MTUNLOCK },
-       { "eof",        MTWEOF },
-       { "weof",       MTWEOF },
-       { 0,                    0 }
+static const short opcode_value[] = {
+       MTBSF,
+       MTBSFM,
+       MTBSR,
+       MTBSS,
+       MTCOMPRESSION,
+       MTEOM,
+       MTERASE,
+       MTFSF,
+       MTFSFM,
+       MTFSR,
+       MTFSS,
+       MTLOAD,
+       MTLOCK,
+       MTMKPART,
+       MTNOP,
+       MTOFFL,
+       MTOFFL,
+       MTRAS1,
+       MTRAS2,
+       MTRAS3,
+       MTRESET,
+       MTRETEN,
+       MTREW,
+       MTSEEK,
+       MTSETBLK,
+       MTSETDENSITY,
+       MTSETDRVBUFFER,
+       MTSETPART,
+       MTTELL,
+       MTWSM,
+       MTUNLOAD,
+       MTUNLOCK,
+       MTWEOF,
+       MTWEOF
 };
 
-extern int
-mt_main(int argc, char** argv)
+static const char opcode_name[] ALIGN1 =
+       "bsf"             "\0"
+       "bsfm"            "\0"
+       "bsr"             "\0"
+       "bss"             "\0"
+       "datacompression" "\0"
+       "eom"             "\0"
+       "erase"           "\0"
+       "fsf"             "\0"
+       "fsfm"            "\0"
+       "fsr"             "\0"
+       "fss"             "\0"
+       "load"            "\0"
+       "lock"            "\0"
+       "mkpart"          "\0"
+       "nop"             "\0"
+       "offline"         "\0"
+       "rewoffline"      "\0"
+       "ras1"            "\0"
+       "ras2"            "\0"
+       "ras3"            "\0"
+       "reset"           "\0"
+       "retension"       "\0"
+       "rewind"          "\0"
+       "seek"            "\0"
+       "setblk"          "\0"
+       "setdensity"      "\0"
+       "drvbuffer"       "\0"
+       "setpart"         "\0"
+       "tell"            "\0"
+       "wset"            "\0"
+       "unload"          "\0"
+       "unlock"          "\0"
+       "eof"             "\0"
+       "weof"            "\0";
+
+int mt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int mt_main(int argc UNUSED_PARAM, char **argv)
 {
-       const char *                            file = "/dev/tape";
-       const struct mt_opcodes *       code = opcodes;
-       struct mtop                                     op;
-       int                                                     fd;
-       
-       if ( strcmp(argv[1], "-f") == 0 ) {
-               if ( argc < 4 ) {
-                   usage (mt_usage);
-               }
+       const char *file = "/dev/tape";
+       struct mtop op;
+       struct mtpos position;
+       int fd, mode, idx;
+
+       if (!argv[1]) {
+               bb_show_usage();
+       }
+
+       if (strcmp(argv[1], "-f") == 0) {
+               if (!argv[2] || !argv[3])
+                       bb_show_usage();
                file = argv[2];
                argv += 2;
-               argc -= 2;
        }
 
-       while ( code->name != 0 ) {
-               if ( strcmp(code->name, argv[1]) == 0 )
-                       break;
-               code++;
-       }
+       idx = index_in_strings(opcode_name, argv[1]);
 
-       if ( code->name == 0 ) {
-               fprintf(stderr, "mt: unrecognized opcode %s.\n", argv[1]);
-               return( FALSE);
-       }
+       if (idx < 0)
+               bb_error_msg_and_die("unrecognized opcode %s", argv[1]);
 
-       op.mt_op = code->value;
-       if ( argc >= 3 )
-               op.mt_count = atoi(argv[2]); 
+       op.mt_op = opcode_value[idx];
+       if (argv[2])
+               op.mt_count = xatoi_positive(argv[2]);
        else
-               op.mt_count = 1; /* One, not zero, right? */
+               op.mt_count = 1;  /* One, not zero, right? */
 
-       if ( (fd = open(file, O_RDONLY, 0)) < 0 ) {
-               perror(file);
-               return( FALSE);
+       switch (opcode_value[idx]) {
+               case MTWEOF:
+               case MTERASE:
+               case MTWSM:
+               case MTSETDRVBUFFER:
+                       mode = O_WRONLY;
+                       break;
+
+               default:
+                       mode = O_RDONLY;
+                       break;
        }
 
-       if ( ioctl(fd, MTIOCTOP, &op) != 0 ) {
-               perror(file);
-               return( FALSE);
+       fd = xopen(file, mode);
+
+       switch (opcode_value[idx]) {
+               case MTTELL:
+                       ioctl_or_perror_and_die(fd, MTIOCPOS, &position, "%s", file);
+                       printf("At block %d\n", (int) position.mt_blkno);
+                       break;
+
+               default:
+                       ioctl_or_perror_and_die(fd, MTIOCTOP, &op, "%s", file);
+                       break;
        }
 
-       return( TRUE);
+       return EXIT_SUCCESS;
 }