hush: trivial buglet found by randomconfig testing
[oweals/busybox.git] / miscutils / mt.c
index a61ad5a40cbe7c6c0ffc55000c8f2e39e07c9d5a..2971421eff2b23889b9f04a5bb7d2f8c9d204034 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 tarball for details.
+ */
 
-const char     mt_usage[] = "mt [-f device] opcode value\n";
+#include "libbb.h"
+#include <sys/mtio.h>
 
 struct mt_opcodes {
-       char *  name;
-       short   value;
+       const char *name;
+       short value;
 };
 
 /* 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 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},
+       {"rewind", 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}
 };
 
-extern int
-mt_main(int argc, char** argv)
+int mt_main(int argc, char **argv);
+int mt_main(int argc, 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";
+       const struct mt_opcodes *code = opcodes;
+       struct mtop op;
+       struct mtpos position;
+       int fd, mode;
+
+       if (argc < 2) {
+               bb_show_usage();
+       }
+
+       if (strcmp(argv[1], "-f") == 0) {
+               if (argc < 4) {
+                       bb_show_usage();
                }
                file = argv[2];
                argv += 2;
                argc -= 2;
        }
 
-       while ( code->name != 0 ) {
-               if ( strcmp(code->name, argv[1]) == 0 )
+       while (code->name != 0) {
+               if (strcmp(code->name, argv[1]) == 0)
                        break;
                code++;
        }
 
-       if ( code->name == 0 ) {
-               fprintf(stderr, "mt: unrecognized opcode %s.\n", argv[1]);
-               return( FALSE);
+       if (code->name == 0) {
+               bb_error_msg("unrecognized opcode %s", argv[1]);
+               return EXIT_FAILURE;
        }
 
        op.mt_op = code->value;
-       if ( argc >= 3 )
-               op.mt_count = atoi(argv[2]); 
+       if (argc >= 3)
+               op.mt_count = xatoi_u(argv[2]);
        else
-               op.mt_count = 1; /* One, not zero, right? */
+               op.mt_count = 1;                /* One, not zero, right? */
+
+       switch (code->value) {
+               case MTWEOF:
+               case MTERASE:
+               case MTWSM:
+               case MTSETDRVBUFFER:
+                       mode = O_WRONLY;
+                       break;
 
-       if ( (fd = open(file, O_RDONLY, 0)) < 0 ) {
-               perror(file);
-               return( FALSE);
+               default:
+                       mode = O_RDONLY;
+                       break;
        }
 
-       if ( ioctl(fd, MTIOCTOP, &op) != 0 ) {
-               perror(file);
-               return( FALSE);
+       fd = xopen(file, mode);
+
+       switch (code->value) {
+               case MTTELL:
+                       if (ioctl(fd, MTIOCPOS, &position) < 0)
+                               bb_perror_msg_and_die("%s", file);
+                       printf("At block %d.\n", (int) position.mt_blkno);
+                       break;
+
+               default:
+                       if (ioctl(fd, MTIOCTOP, &op) != 0)
+                               bb_perror_msg_and_die("%s", file);
+                       break;
        }
 
-       return( TRUE);
+       return EXIT_SUCCESS;
 }