"Fossies" - the Fresh Open Source Software Archive

Member "schily-2021-09-18/mt/mt.c" (20 Aug 2021, 15409 Bytes) of package /linux/privat/schily-2021-09-18.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* @(#)mt.c 1.32 21/08/20 Copyright 2000-2021 J. Schilling */
    2 #include <schily/mconfig.h>
    3 #ifndef lint
    4 static  UConst char sccsid[] =
    5     "@(#)mt.c   1.32 21/08/20 Copyright 2000-2021 J. Schilling";
    6 #endif
    7 /*
    8  *  Magnetic tape manipulation program
    9  *
   10  *  Copyright (c) 2000-2021 J. Schilling
   11  */
   12 /*
   13  * The contents of this file are subject to the terms of the
   14  * Common Development and Distribution License, Version 1.0 only
   15  * (the "License").  You may not use this file except in compliance
   16  * with the License.
   17  *
   18  * See the file CDDL.Schily.txt in this distribution for details.
   19  * A copy of the CDDL is also available via the Internet at
   20  * http://www.opensource.org/licenses/cddl1.txt
   21  *
   22  * When distributing Covered Code, include this CDDL HEADER in each
   23  * file and include the License file CDDL.Schily.txt from this distribution.
   24  */
   25 
   26 #include <schily/mconfig.h>
   27 
   28 /*
   29  * XXX Until we find a better way, the next definitions must be in sync
   30  * XXX with the definitions in librmt/remote.c
   31  */
   32 #if !defined(HAVE_FORK) || !defined(HAVE_SOCKETPAIR) || !defined(HAVE_DUP2)
   33 #undef  USE_RCMD_RSH
   34 #endif
   35 #if !defined(HAVE_GETSERVBYNAME)
   36 #undef  USE_REMOTE              /* Cannot get rcmd() port # */
   37 #endif
   38 #if (!defined(HAVE_NETDB_H) || !defined(HAVE_RCMD)) && !defined(USE_RCMD_RSH)
   39 #undef  USE_REMOTE              /* There is no rcmd() */
   40 #endif
   41 
   42 #include <schily/stdio.h>
   43 #include <schily/stdlib.h>
   44 #include <schily/unistd.h>
   45 #include <schily/string.h>
   46 #include <schily/utypes.h>
   47 #include <schily/fcntl.h>
   48 #include <schily/ioctl.h>
   49 #include <schily/errno.h>
   50 
   51 #define GT_COMERR       /* #define comerr gtcomerr */
   52 #define GT_ERROR        /* #define error gterror   */
   53 #include <schily/schily.h>
   54 #include <schily/standard.h>
   55 /*#undef    HAVE_SYS_MTIO_H*/
   56 #include <schily/mtio.h>
   57 #include <schily/librmt.h>
   58 #include <schily/nlsdefs.h>
   59 
   60 LOCAL BOOL  help;
   61 LOCAL BOOL  prvers;
   62 LOCAL BOOL  wready;
   63 LOCAL int   debug;
   64 
   65 LOCAL struct mtop   mt_op;
   66 LOCAL struct rmtget mt_status;
   67 
   68 #ifndef HAVE_MTGET_TYPE
   69 #ifdef  HAVE_MTGET_MODEL
   70 #define HAVE_MTGET_TYPE
   71 #define mt_type mt_model
   72 #endif
   73 #endif
   74 
   75 #define NO_ASF      1000
   76 #define NO_NBSF     1001
   77 #ifndef MTASF
   78 #   define  MTASF   NO_ASF
   79 #endif
   80 #ifndef MTNBSF
   81 #   define  MTNBSF  NO_NBSF
   82 #endif
   83 
   84 #define MTC_NONE    0   /* No flags defined         */
   85 #define MTC_RW      0   /* This command writes to the tape  */
   86 #define MTC_RDO     1   /* This command does not write      */
   87 #define MTC_CNT     2   /* This command uses the count arg  */
   88 #define MTC_NDEL    4   /* Open the tape drive with O_NDELAY    */
   89 
   90 
   91 LOCAL struct mt_cmds {
   92     char *mtc_name;     /* The name of the command      */
   93     char *mtc_text;     /* Description of the command       */
   94     int mtc_opcode;     /* The opcode for mtio          */
   95     int mtc_flags;      /* Flags for this command       */
   96 } cmds[] = {
   97 #ifdef  MTWEOF
   98     { "weof",   "write EOF mark",       MTWEOF,     MTC_RW|MTC_CNT },
   99     { "eof",    "write EOF mark",       MTWEOF,     MTC_RW|MTC_CNT },
  100 #endif
  101 #ifdef  MTFSF
  102     { "fsf",    "forward skip FILE mark",   MTFSF,      MTC_RDO|MTC_CNT },
  103 #endif
  104 #ifdef  MTBSF
  105     { "bsf",    "backward skip FILE mark",  MTBSF,      MTC_RDO|MTC_CNT },
  106 #endif
  107     { "asf",    "absolute FILE mark pos",   MTASF,      MTC_RDO|MTC_CNT },
  108 #ifdef  MTFSR
  109     { "fsr",    "forward skip record",      MTFSR,      MTC_RDO|MTC_CNT },
  110 #endif
  111 #ifdef  MTBSR
  112     { "bsr",    "backward skip record",     MTBSR,      MTC_RDO|MTC_CNT },
  113 #endif
  114 #ifdef  MTREW
  115     { "rewind", "rewind tape",          MTREW,      MTC_RDO },
  116 #endif
  117 #ifdef  MTOFFL
  118     { "offline",    "rewind and unload",        MTOFFL,     MTC_RDO },
  119     { "rewoffl",    "rewind and unload",        MTOFFL,     MTC_RDO },
  120 #endif
  121 #ifdef  MTNOP
  122     { "status", "get tape status",      MTNOP,      MTC_RDO },
  123 #endif
  124     { "nop",    "no operation",         MTNOP,      MTC_RDO },
  125 #ifdef  MTRETEN
  126     { "retension",  "retension tape cartridge", MTRETEN,    MTC_RDO },
  127 #endif
  128 #ifdef  MTERASE
  129     { "erase",  "erase tape",           MTERASE,    MTC_RW },
  130 #endif
  131 #ifdef  MTEOM
  132     { "eom",    "position to EOM",      MTEOM,      MTC_RDO },
  133 #endif
  134 
  135 #if MTNBSF != NO_NBSF
  136     { "nbsf",   "backward skip FILE mark",  MTNBSF,     MTC_RDO|MTC_CNT },
  137 #endif
  138 
  139 #ifdef  MTLOAD
  140     { "load",   "load tape",            MTLOAD,     MTC_RDO|MTC_NDEL },
  141 #endif
  142 
  143     { NULL,     NULL,               0,      MTC_NONE }
  144 };
  145 
  146 LOCAL   void    usage       __PR((int ex));
  147 EXPORT  int main        __PR((int ac, char *av[]));
  148 LOCAL   void    mtstatus    __PR((struct rmtget *sp));
  149 LOCAL   char    *print_key  __PR((Llong key));
  150 LOCAL   int openremote  __PR((char *tape));
  151 LOCAL   int opentape    __PR((char *tape, struct mt_cmds *cp));
  152 LOCAL   int mtioctl     __PR((int cmd, caddr_t arg));
  153 
  154 LOCAL void
  155 usage(ex)
  156     int ex;
  157 {
  158     struct mt_cmds  *cp;
  159     int     i;
  160 
  161     error("Usage: mt [ -f device ] [options] command [ count ]\n");
  162     error("Options:\n");
  163     error("\t-help\t\tprint this online help\n");
  164     error("\t-version\tprint version number\n");
  165     error("\t-wready\t\twait for the tape to become ready before doing command\n");
  166     error("\n");
  167     error("Commands are:\n");
  168     for (cp = cmds; cp->mtc_name != NULL; cp++) {
  169         error("%s%n", cp->mtc_name, &i);
  170         error("%*s%s\n", 14-i, "", cp->mtc_text);
  171     }
  172     exit(ex);
  173 }
  174 
  175 LOCAL char  opts[] = "f*,t*,version,help,h,debug,wready";
  176 
  177 int
  178 main(ac, av)
  179     int ac;
  180     char    *av[];
  181 {
  182     int cac;
  183     char    * const *cav;
  184     char    *tape = NULL;
  185     char    *cmd = "BADCMD";
  186     int count = 1;
  187     struct mt_cmds  *cp;
  188 
  189     save_args(ac, av);
  190 
  191     (void) setlocale(LC_ALL, "");
  192 
  193 #ifdef  USE_NLS
  194 #if !defined(TEXT_DOMAIN)   /* Should be defined by cc -D */
  195 #define TEXT_DOMAIN "mt"    /* Use this only if it weren't */
  196 #endif
  197     { char  *dir;
  198     dir = searchfileinpath("share/locale", F_OK,
  199                     SIP_ANY_FILE|SIP_NO_PATH, NULL);
  200     if (dir)
  201         (void) bindtextdomain(TEXT_DOMAIN, dir);
  202     else
  203 #if defined(PROTOTYPES) && defined(INS_BASE)
  204     (void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
  205 #else
  206     (void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
  207 #endif
  208     (void) textdomain(TEXT_DOMAIN);
  209     }
  210 #endif  /* USE_NLS */
  211 
  212     cac = --ac;
  213     cav = ++av;
  214     
  215     if (getallargs(&cac, &cav, opts,
  216             &tape, &tape,
  217             &prvers,
  218             &help, &help,
  219             &debug,
  220             &wready) < 0) {
  221         errmsgno(EX_BAD, "Bad Option: '%s'.\n", cav[0]);
  222         usage(EX_BAD);
  223     }
  224     if (help) usage(0);
  225     if (prvers) {
  226         gtprintf("mt %s %s (%s-%s-%s)\n\n", "1.32", "2021/08/20", HOST_CPU, HOST_VENDOR, HOST_OS);
  227         gtprintf("Copyright (C) 2000-2021 %s\n", _("Jörg Schilling"));
  228         gtprintf("This is free software; see the source for copying conditions.  There is NO\n");
  229         gtprintf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
  230         exit(0);
  231     }
  232 
  233     if (tape == NULL && (tape = getenv("TAPE")) == NULL) {
  234 #ifdef  DEFTAPE
  235         tape = DEFTAPE;
  236 #else
  237         errmsgno(EX_BAD, "No default tape defined.\n");
  238         usage(EX_BAD);
  239         /* NOTREACHED */
  240 #endif
  241     }
  242 
  243     cac = ac;
  244     cav = av;
  245     if (getfiles(&cac, &cav, opts) == 0) {
  246         errmsgno(EX_BAD, "Missing args.\n");
  247         usage(EX_BAD);
  248     } else {
  249         cmd = cav[0];
  250         cav++;
  251         cac--;  
  252     }
  253     if (getfiles(&cac, &cav, opts) > 0) {
  254         if (*astoi(cav[0], &count) != '\0') {
  255             errmsgno(EX_BAD, "Not a number: '%s'.\n", cav[0]);
  256             usage(EX_BAD);
  257         }
  258         if (count < 0) {
  259             comerrno(EX_BAD, "negative file number or repeat count\n");
  260             /* NOTREACHED */
  261         }
  262         cav++;
  263         cac--;  
  264     }
  265     if (getfiles(&cac, &cav, opts) > 0) {
  266         errmsgno(EX_BAD, "Too many args.\n");
  267         usage(EX_BAD);
  268     }
  269 
  270     for (cp = cmds; cp->mtc_name != NULL; cp++) {
  271         if (strncmp(cmd, cp->mtc_name, strlen(cmd)) == 0)
  272             break;
  273     }
  274     if (cp->mtc_name == NULL) {
  275         comerrno(EX_BAD, "Unknown command: %s\n", cmd);
  276         /* NOTREACHED */
  277     }
  278 #ifdef  DEBUG
  279     error("cmd: %s opcode: %d %s %s\n",
  280         cp->mtc_name, cp->mtc_opcode,
  281         (cp->mtc_flags & MTC_RDO) != 0 ? "RO":"RW",
  282         (cp->mtc_flags & MTC_CNT) != 0 ? "usecount":"");
  283 #endif
  284 
  285     if ((cp->mtc_flags & MTC_CNT) == 0)
  286         count = 1;
  287 
  288 #ifdef  USE_REMOTE
  289     rmtdebug(debug);
  290     (void)openremote(tape);     /* This needs super user privilleges */
  291 #endif
  292 #ifdef  HAVE_SETREUID
  293     if (setreuid(-1, getuid()) < 0)
  294 #else
  295 #ifdef  HAVE_SETEUID
  296     if (seteuid(getuid()) < 0)
  297 #else
  298     if (setuid(getuid()) < 0)
  299 #endif
  300 #endif
  301         comerr("Panic cannot set back effective uid.\n");
  302 
  303     if (opentape(tape, cp) < 0) {
  304         if (geterrno() == EIO) {
  305             comerrno(EX_BAD, "'%s': no tape loaded or drive offline.\n",
  306                 tape);
  307         } else if ((cp->mtc_flags & MTC_RDO) == 0 &&
  308                 geterrno() == EACCES) {
  309             comerr("Cannot open '%s': tape may be write protected.\n", tape);
  310         } else {
  311             comerr("Cannot open '%s'.\n", tape); 
  312         }
  313         /* NOTREACHED */
  314     }
  315 
  316 #ifdef  DEBUG
  317     error("Tape: %s cmd : %s (%s) count: %d\n", tape, cmd, cp->mtc_name, count);
  318 #endif
  319 
  320     if (cp->mtc_opcode == MTNOP) {
  321         if (strcmp(cp->mtc_name, "nop")) {
  322             /*
  323              * Status ioctl
  324              */
  325             if (mtioctl(MTIOCGET, (caddr_t)&mt_status) < 0) {
  326                 comerr("Cannot get mt status from '%s'.\n", tape);
  327                 /* NOTREACHED */
  328             }
  329             mtstatus(&mt_status);
  330         }
  331 #if MTASF == NO_ASF
  332     } else if (cp->mtc_opcode == MTASF) {
  333         (void)mtioctl(MTIOCGET, (caddr_t)&mt_status);
  334         if (mtioctl(MTIOCGET, (caddr_t)&mt_status) < 0) {
  335             comerr("Cannot get mt status from '%s'.\n", tape); 
  336             /* NOTREACHED */
  337         }
  338         /*
  339          * If the device does not support to report the current file
  340          * tape file position - rewind the tape, and space forward.
  341          */
  342 #ifndef MTF_ASF
  343         if (1) {
  344 #else
  345         if (!(mt_status.mt_flags & MTF_ASF) || MTNBSF == NO_NBSF) {
  346 #endif
  347             mt_status.mt_fileno = 0;
  348             mt_op.mt_count = 1;
  349             mt_op.mt_op = MTREW;
  350             if (mtioctl(MTIOCTOP, (caddr_t)&mt_op) < 0) {
  351                 comerr("%s %s %d failed\n", tape, cp->mtc_name,
  352                             count);
  353                 /* NOTREACHED */
  354             }
  355         }
  356         if (count < mt_status.mt_fileno) {
  357             mt_op.mt_op = MTNBSF;
  358             mt_op.mt_count =  mt_status.mt_fileno - count;
  359             /*printf("mt: bsf= %lld\n", (Llong)mt_op.mt_count);*/
  360         } else {
  361             mt_op.mt_op = MTFSF;
  362             mt_op.mt_count =  count - mt_status.mt_fileno;
  363             /*printf("mt: fsf= %lld\n", (Llong)mt_op.mt_count);*/
  364         }
  365         if (mtioctl(MTIOCTOP, (caddr_t)&mt_op) < 0) {
  366             if (mtioctl(MTIOCTOP, (caddr_t)&mt_op) < 0) {
  367                 comerr("%s %s %d failed\n", tape, cp->mtc_name,
  368                             count);
  369                 /* NOTREACHED */
  370             }
  371         }
  372 #endif
  373     } else {
  374         /*
  375          * Regular magnetic tape ioctl
  376          */
  377         mt_op.mt_op = cp->mtc_opcode;
  378         mt_op.mt_count = count;
  379         if (mtioctl(MTIOCTOP, (caddr_t)&mt_op) < 0) {
  380             comerr("%s %s %lld failed\n", tape, cp->mtc_name,
  381                         (Llong)mt_op.mt_count);
  382             /* NOTREACHED */
  383         }
  384     }
  385     return (0);
  386 }
  387 
  388 /*
  389  * If we try to make this portable, we need a way to initialize it
  390  * in an OS independant way.
  391  * Don't use it for now.
  392  */
  393 /*LOCAL */
  394 struct tape_info {
  395     short   t_type;     /* type of magnetic tape device */
  396     char    *t_name;    /* name for prining     */
  397     char    *t_dsbits;  /* "drive status" register  */
  398     char    *t_erbits;  /* "error" register     */
  399 };
  400 #ifdef  XXX
  401  tapes[] = {
  402     { MT_ISTS,  "ts11",     0,      TSXS0_BITS },
  403     { 0 }
  404 };
  405 #endif
  406 
  407 /*
  408  * Interpret the status buffer returned
  409  */
  410 LOCAL void
  411 mtstatus(sp)
  412     register struct rmtget *sp;
  413 {
  414     register struct tape_info *mt = NULL;
  415 
  416 #ifdef  XXX
  417 #ifdef  HAVE_MTGET_TYPE
  418     for (mt = tapes; mt->t_type; mt++)
  419         if (mt->t_type == sp->mt_type)
  420             break;
  421 #endif
  422 #endif
  423 
  424 #if defined(MTF_SCSI)
  425 
  426     if ((sp->mt_xflags & RMT_FLAGS) && (sp->mt_flags & MTF_SCSI)) {
  427         /*
  428          * Handle SCSI tape drives specially.
  429          */
  430         if (sp->mt_xflags & RMT_TYPE) {
  431             if (mt != NULL && mt->t_type == sp->mt_type)
  432                 gtprintf("%s tape drive:\n", mt->t_name);
  433             else
  434                 gtprintf("%s tape drive:\n", "SCSI");
  435         } else {
  436             gtprintf("Unknown SCSI tape drive:\n");
  437         }
  438         printf("   sense key(0x%llx)= %s   residual= %lld   ",
  439             sp->mt_erreg, print_key(sp->mt_erreg), sp->mt_resid);
  440         gtprintf("retries= %lld\n", sp->mt_dsreg);
  441     } else
  442 #endif  /* MTF_SCSI */
  443         {
  444         /*
  445          * Handle other drives below.
  446          */
  447         if (sp->mt_xflags & RMT_TYPE) {
  448             if (mt == NULL || mt->t_type == 0) {
  449                 gtprintf("Unknown tape drive type (0x%llX):\n", (Ullong)sp->mt_type);
  450             } else {
  451                 gtprintf("%s tape drive:\n", mt->t_name);
  452             }
  453         } else {
  454             gtprintf("Unknown tape drive:\n");
  455         }
  456         if (sp->mt_xflags & RMT_RESID)
  457             gtprintf("   residual= %lld", sp->mt_resid);
  458         /*
  459          * If we implement better support for specific OS,
  460          * then we may want to implement something like the
  461          * *BSD kernel %b printf format (e.g. printreg).
  462          */
  463         if (sp->mt_xflags & RMT_DSREG)
  464             printf  ("   ds = %llX", (Ullong)sp->mt_dsreg);
  465 
  466         if (sp->mt_xflags & RMT_ERREG)
  467             printf  ("   er = %llX", sp->mt_erreg);
  468         putchar('\n');
  469     }
  470     gtprintf("   file no= %lld   block no= %lld\n",
  471             (sp->mt_xflags & RMT_FILENO)?
  472                 sp->mt_fileno:
  473                 (Llong)-1,
  474             (sp->mt_xflags & RMT_BLKNO)?
  475                 sp->mt_blkno:
  476                 (Llong)-1);
  477 
  478     if (sp->mt_xflags & RMT_BF)
  479         gtprintf("   optimum blocking factor= %ld\n", sp->mt_bf);
  480 
  481     if (sp->mt_xflags & RMT_FLAGS)
  482         gtprintf("   flags= 0x%llX\n", sp->mt_flags);
  483 }
  484 
  485 static char *sense_keys[] = {
  486     "No Additional Sense",      /* 0x00 */
  487     "Recovered Error",      /* 0x01 */
  488     "Not Ready",            /* 0x02 */
  489     "Medium Error",         /* 0x03 */
  490     "Hardware Error",       /* 0x04 */
  491     "Illegal Request",      /* 0x05 */
  492     "Unit Attention",       /* 0x06 */
  493     "Data Protect",         /* 0x07 */
  494     "Blank Check",          /* 0x08 */
  495     "Vendor Unique",        /* 0x09 */
  496     "Copy Aborted",         /* 0x0a */
  497     "Aborted Command",      /* 0x0b */
  498     "Equal",            /* 0x0c */
  499     "Volume Overflow",      /* 0x0d */
  500     "Miscompare",           /* 0x0e */
  501     "Reserved"          /* 0x0f */
  502 };
  503 
  504 LOCAL char *
  505 print_key(key)
  506     Llong   key;
  507 {
  508     static  char keys[32];
  509 
  510     if (key >= 0 && key < (sizeof(sense_keys)/sizeof(sense_keys[0])))
  511         return (sense_keys[key]);
  512     js_snprintf(keys, sizeof(keys), "Unknown Key: %lld", key);
  513     return (keys);
  514 }
  515 
  516 /*--------------------------------------------------------------------------*/
  517 LOCAL int   isremote;
  518 LOCAL int   remfd   = -1;
  519 LOCAL int   mtfd;
  520 LOCAL char  *remfn;
  521 
  522 #ifdef  USE_REMOTE
  523 LOCAL int
  524 openremote(tape)
  525     char    *tape;
  526 {
  527     char    host[128];
  528 
  529     if ((remfn = rmtfilename(tape)) != NULL) {
  530         rmthostname(host, sizeof(host), tape);
  531         isremote++;
  532 
  533         if (debug)
  534             errmsgno(EX_BAD, "Remote: %s Host: %s file: %s\n",
  535                             tape, host, remfn);
  536 
  537         if ((remfd = rmtgetconn(host, 4096, 0)) < 0)
  538             comerrno(EX_BAD, "Cannot get connection to '%s'.\n",
  539                 /* errno not valid !! */        host);
  540     }
  541     return (isremote);
  542 }
  543 #endif
  544 
  545 LOCAL int
  546 opentape(tape, cp)
  547         char        *tape;
  548     register struct mt_cmds *cp;
  549 {
  550     int ret;
  551     int n = 0;
  552     int oflag;
  553 
  554     oflag = (cp->mtc_flags & MTC_RDO) ? O_RDONLY : O_RDWR;
  555 #ifdef  O_NDELAY
  556     if (cp->mtc_flags & MTC_NDEL)
  557         oflag |= O_NDELAY;
  558 #endif
  559 
  560 retry:
  561     ret = 0;
  562     if (isremote) {
  563 #ifdef  USE_REMOTE
  564         if (rmtopen(remfd, remfn, oflag) < 0)
  565             ret = -1;
  566 #else
  567         comerrno(EX_BAD, "Remote tape support not present.\n");
  568 #endif
  569     } else if ((mtfd = open(tape, oflag)) < 0) {
  570             ret = -1;
  571     }
  572     if (wready && n++ < 120 && ret < 0 &&
  573         (geterrno() == EIO || geterrno() == EBUSY)) {
  574         sleep(1);
  575         goto retry;
  576     }
  577     return (ret);
  578 }
  579 
  580 LOCAL int
  581 mtioctl(cmd, arg)
  582     int cmd;
  583     caddr_t arg;
  584 {
  585     int ret = -1;
  586     struct rmtget *mtp;
  587     struct mtop *mop;
  588 
  589     if (isremote) {
  590 #ifdef  USE_REMOTE
  591         switch (cmd) {
  592 
  593         case MTIOCGET:
  594             ret = rmtxstatus(remfd, (struct rmtget *)arg);
  595             if (ret < 0)
  596                 return (ret);
  597 
  598             mtp = (struct rmtget *)arg;
  599 /*#define   DEBUG*/
  600 #ifdef  DEBUG
  601 error("type: %llX ds: %llX er: %llX resid: %lld fileno: %lld blkno: %lld flags: %llX bf: %ld\n",
  602 mtp->mt_type, mtp->mt_dsreg, mtp->mt_erreg, mtp->mt_resid, mtp->mt_fileno,
  603 mtp->mt_blkno, mtp->mt_flags, mtp->mt_bf);
  604 #endif
  605             break;
  606         case MTIOCTOP:
  607             mop = (struct mtop *)arg;
  608             ret = rmtioctl(remfd, mop->mt_op, mop->mt_count);
  609             break;
  610         default:
  611             comerrno(ENOTTY, "Invalid mtioctl.\n");
  612             /* NOTREACHED */
  613         }
  614 #else
  615         comerrno(EX_BAD, "Remote tape support not present.\n");
  616 #endif
  617     } else {
  618 #ifdef  HAVE_IOCTL
  619         if (cmd == MTIOCGET) {
  620             struct mtget mtget;
  621 
  622             ret = ioctl(mtfd, cmd, &mtget);
  623             if (ret >= 0) {
  624                 if (_mtg2rmtg((struct rmtget *)arg, &mtget) < 0)
  625                     ret = -1;
  626             }
  627         } else
  628         ret = ioctl(mtfd, cmd, arg);
  629 #else
  630         ret = -1;
  631 #ifdef  ENOSYS
  632         seterrno(ENOSYS);
  633 #else
  634         seterrno(EINVAL);
  635 #endif
  636 #endif
  637     }
  638     return (ret);
  639 }