"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. For more information about "mt.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes reports: 2021-08-14_vs_2021-09-18 or 2021-07-29_vs_2021-09-18.

    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 }