Fix rmt ioctl command with UNIX clients (mtio opcodes Linux incompatibilities)
authorStelian Pop <stelian@popies.net>
Mon, 15 Apr 2002 11:57:27 +0000 (11:57 +0000)
committerStelian Pop <stelian@popies.net>
Mon, 15 Apr 2002 11:57:27 +0000 (11:57 +0000)
CHANGES
rmt/rmt.8.in
rmt/rmt.c

diff --git a/CHANGES b/CHANGES
index 82097e91c703ad7632637169a9b129c805aba9cc..e055370d6215a46659d5efab62badbe485342304 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,16 @@
-$Id: CHANGES,v 1.172 2002/04/12 12:45:50 stelian Exp $
+$Id: CHANGES,v 1.173 2002/04/15 11:57:27 stelian Exp $
 
+Changes between versions 0.4b28 and 0.4b29 (released ??????????????)
+====================================================================
+
+1.     Fixed a problem in the rmt ioctl command, where ioctl's issued from
+       non Linux clients were misinterpreted. The description of the problem
+       (incompatible numbering in Linux mtio opcodes) is documented at
+       ftp://ftp.fokus.gmd.de/pub/unix/star/README.mtio . Thanks to
+       Jörg Schilling <schilling@fokus.gmd.de> for reporting this bug and
+       providing an excellent, cross-platform replacement for rmt in his
+       star package.
+       
 Changes between versions 0.4b27 and 0.4b28 (released April 12, 2002)
 ====================================================================
 
index be863343c2a21fa835dc79b0843acdaeee7b3845..6e93213178e2fcbce436b84b5d24eba618757e4b 100644 (file)
@@ -29,7 +29,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"     $Id: rmt.8.in,v 1.7 2002/01/16 09:32:14 stelian Exp $
+.\"     $Id: rmt.8.in,v 1.8 2002/04/15 11:57:29 stelian Exp $
 .\"
 .Dd __DATE__
 .Dt RMT 8
 .Sh SYNOPSIS
 .Nm rmt
 .Sh DESCRIPTION
-.Nm Rmt
-is a program used by the remote dump and restore programs
-in manipulating a magnetic tape drive through an interprocess
+.Nm rmt
+is a program used by the remote 
+.Nm dump,
+.Nm restore 
+or
+.Nm tar
+programs in manipulating a magnetic tape drive through an interprocess
 communication connection.
-.Nm Rmt
+.Nm rmt
 is normally started up with an
 .Xr rexec 3
 or
@@ -53,12 +57,12 @@ call.
 .Pp
 The 
 .Nm
-program accepts requests specific to the manipulation of
-magnetic tapes, performs the commands, then responds with
-a status indication.  All responses are in
+program accepts requests specific to the manipulation of magnetic tapes, 
+performs the commands, then responds with a status indication.  
+All responses are in
 .Tn ASCII
-and in
-one of two forms. 
+and in one of the following two forms.
+.Pp
 Successful commands have responses of:
 .Bd -filled -offset indent
 .Sm off
@@ -66,10 +70,12 @@ Successful commands have responses of:
 .Sm on
 .Ed
 .Pp
-.Ar Number
+where
+.Ar number
 is an
 .Tn ASCII
 representation of a decimal number.
+.Pp
 Unsuccessful commands are responded to with:
 .Bd -filled -offset indent
 .Sm off
@@ -80,15 +86,15 @@ Unsuccessful commands are responded to with:
 .Sm on
 .Ed
 .Pp
-.Ar Error-number
-is one of the possible error
-numbers described in
+where
+.Ar error-number
+is one of the possible error numbers described in
 .Xr intro 2
 and
 .Ar error-message
-is the corresponding error string as printed
-from a call to
+is the corresponding error string as printed from a call to
 .Xr perror 3 .
+.Pp
 The protocol is comprised of the
 following commands, which are sent as indicated - no spaces are supplied
 between the command and its arguments, or between its arguments, and
@@ -99,6 +105,7 @@ indicates that a newline should be supplied:
 .It Xo Sy \&O Ar device
 .No \en Ar mode No \en
 .Xc
+.Sm on
 Open the specified 
 .Ar device
 using the indicated
@@ -108,16 +115,18 @@ is a full pathname and
 .Ar mode
 is an
 .Tn ASCII
-representation of a decimal
-number suitable for passing to
+representation of a decimal number suitable for passing to
 .Xr open 2 .
-If a device had already been opened, it is
-closed before a new open is performed.
+If a device had already been opened, it is closed before a 
+new open is performed.
+.Sm off
 .It Xo Sy C Ar device No \en
 .Xc
+.Sm on
 Close the currently open device.  The
 .Ar device
 specified is ignored.
+.Sm off
 .It Xo Sy L
 .Ar whence No \en
 .Ar offset No \en
@@ -133,13 +142,11 @@ call.
 .It Sy W Ar count No \en
 .Sm on
 Write data onto the open device.
-.Nm Rmt
+.Nm rmt
 reads
 .Ar count
-bytes from the connection, aborting if
-a premature end-of-file is encountered.
-The response value is that returned from
-the
+bytes from the connection, aborting if a premature end-of-file is encountered.
+The response value is that returned from the
 .Xr write 2
 call.
 .Sm off
@@ -152,17 +159,15 @@ If
 .Ar count
 exceeds the size of the data buffer (10 kilobytes), it is
 truncated to the data buffer size.
-.Nm Rmt
+.Nm rmt
 then performs the requested 
 .Xr read 2
 and responds with 
 .Sm off
 .Sy A Ar count-read No \en
 .Sm on
-if the read was
-successful; otherwise an error in the
-standard format is returned.  If the read
-was successful, the data read is then sent.
+if the read was successful; otherwise an error in the standard format 
+is returned.  If the read was successful, the data read is then sent.
 .Sm off
 .It Xo Sy I Ar operation
 .No \en Ar count No \en
@@ -171,11 +176,72 @@ was successful, the data read is then sent.
 Perform a
 .Dv MTIOCOP
 .Xr ioctl 2
+command using the specified parameters.  The parameters are interpreted as the
+.Tn ASCII
+representations of the decimal values to place in the 
+.Ar mt_op
+and
+.Ar mt_count
+fields of the structure used in the
+.Xr ioctl
+call.  The return value is the
+.Ar count
+parameter when the operation is successful.
+.Pp
+By issuing the
+.Ql I-1\en0\en
+command, a client will specify that he is using the VERSION 1 protocol.
+.Pp
+For a VERSION 0 client, the
+.Ar operation
+parameter is the platform 
+.Ar mt_op
+value (could be different if the client and the
+.Nm
+server are on two different platforms). For a VERSION 1 client,
+the 
+.Ar operation
+parameter is standardized as below:
+.Bl -tag -width Fl
+.It Ic 0
+Issue a MTWEOF command (write
+.Ar count
+end-of-file records).
+.It Ic 1
+Issue a MTFSF command (forward space over
+.Ar count
+file marks).
+.It Ic 2
+Issue a MTBSF command (backward space over
+.Ar count
+file marks).
+.It Ic 3
+Issue a MTFSR command (forward space
+.Ar count
+inter-record gaps).
+.It Ic 4
+Issue a MTBSR command (backward space
+.Ar count
+inter-record gaps).
+.It Ic 5
+Issue a MTREW command (rewind).
+.It Ic 6
+Issue a MTOFFL command (rewind and put the drive offline).
+.It Ic 7
+Issue a MTNOP command (no operation, set status only).
+.El
+.Sm off
+.It Xo Sy i Ar operation
+.No \en Ar count No \en
+.Xc
+.Sm on
+Perform an extended
+.Dv MTIOCOP
+.Xr ioctl 2
 command using the specified parameters.
 The parameters are interpreted as the
 .Tn ASCII
-representations of the decimal values
-to place in the 
+representations of the decimal values to place in the 
 .Ar mt_op
 and
 .Ar mt_count
@@ -184,8 +250,25 @@ fields of the structure used in the
 call.  The return value is the
 .Ar count
 parameter when the operation is successful.
+The possible operations are:
+.Bl -tag -width Fl
+.It Ic 0
+Issue a MTCACHE command (switch cache on).
+.It Ic 1
+Issue a MTNOCACHE command (switch cache off).
+.It Ic 2
+Issue a MTRETEN command (retension the tape).
+.It Ic 3
+Issue a MTERASE command (erase the entire tape).
+.It Ic 4
+Issue a MTEOM command (position to end of media).
+.It Ic 5
+Issue a MTNBSF command (backward space count files to BOF).
+.El
 .ne 1i
+.Sm off
 .It Sy S
+.Sm on
 Return the status of the open device, as
 obtained with a
 .Dv MTIOCGET
@@ -193,7 +276,57 @@ obtained with a
 call.  If the operation was successful,
 an ``ack'' is sent with the size of the
 status buffer, then the status buffer is
-sent (in binary).
+sent (in binary, which is non-portable between different platforms).
+.Sm off
+.It Xo Sy s Ar sub-command
+.Xc
+.Sm on
+This is a replacement for the previous S command, portable across different
+platforms. If the open device is a magnetic tape, return members of the 
+magnetic tape status structure, as obtained with a
+.Dv MTIOCGET 
+ioctl call. If the open device is not a magnetic tape, an error is returned.
+If the 
+.Dv MTIOCGET
+operation was successful, the numerical value of the structure member is 
+returned in decimal. The following sub commands are supported:
+.Bl -tag -width Fl
+.It Ic T
+return the content of the structure member
+.Ar mt_type
+which contains the type of the magnetic tape device.
+.It Ic D
+return the content of the structure member
+.Ar mt_dsreg
+which contains the "drive status register".
+.It Ic E
+return the content of the structure member
+.Ar mt_erreg
+which contains the "error register". This structure member must be retrieved
+first because it is cleared after each
+.Dv MTIOCGET
+ioctl call.
+.It Ic R
+return the content of the structure member
+.Ar mt_resid
+which contains the residual count of the last I/O.
+.It Ic F
+return the content of the structure member
+.Ar mt_fileno
+which contains the file number of the current tape position.
+.It Ic B
+return the content of the structure member
+.Ar mt_blkno
+which contains the block number of the current tape position.
+.It Ic f
+return the content of the structure member
+.Ar mt_flags
+which contains MTF_ flags from the driver.
+.It Ic b
+return the content of the structure member
+.Ar mt_bf
+which contains the optimum blocking factor.
+.El
 .El
 .Sm on
 .Pp
@@ -205,7 +338,7 @@ All responses are of the form described above.
 .Sh SEE ALSO
 .Xr rcmd 3 ,
 .Xr rexec 3 ,
-.Xr mtio 4 ,
+.Xr /usr/include/sys/mtio.h ,
 .Xr rdump 8 ,
 .Xr rrestore 8
 .Sh BUGS
index 2af48e3e0cd7f8560c2946a1faeb449c5da66169..acacb2d4f865d6a7d3d8f54fbfa887dbaccd5588 100644 (file)
--- a/rmt/rmt.c
+++ b/rmt/rmt.c
@@ -41,7 +41,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: rmt.c,v 1.17 2002/04/12 13:02:16 stelian Exp $";
+       "$Id: rmt.c,v 1.18 2002/04/15 11:57:29 stelian Exp $";
 #endif /* not linux */
 
 /*
@@ -62,18 +62,18 @@ static const char rcsid[] =
 #include <string.h>
 #include <unistd.h>
 
-int    tape = -1;
+static int     tape = -1;
 
-char   *record;
-int    maxrecsize = -1;
+static char    *record;
+static int     maxrecsize = -1;
 
 #define        SSIZE   64
-char   device[SSIZE];
-char   count[SSIZE], filemode[SSIZE], pos[SSIZE], op[SSIZE];
+static char    device[SSIZE];
+static char    count[SSIZE], filemode[SSIZE], pos[SSIZE], op[SSIZE];
 
-char   resp[BUFSIZ];
+static char    resp[BUFSIZ];
 
-FILE   *debug;
+static FILE    *debug;
 #define        DEBUG(f)        if (debug) fprintf(debug, f)
 #define        DEBUG1(f,a)     if (debug) fprintf(debug, f, a)
 #define        DEBUG2(f,a1,a2) if (debug) fprintf(debug, f, a1, a2)
@@ -82,27 +82,37 @@ FILE        *debug;
  * Support for Sun's extended RMT protocol
  *     code originally written by Jörg Schilling <schilling@fokus.gmd.de>
  *     and relicensed by his permission from GPL to BSD for use in dump.
+ *
+ *     rmt_version is 0 for regular clients (Linux included)
+ *     rmt_version is 1 for extended clients (Sun especially). In this cas
+ *             we support some extended commands (see below) and we remap
+ *             the ioctl commands to the UNIX "standard", as per:
+ *                     ftp://ftp.fokus.gmd.de/pub/unix/star/README.mtio
+ *
+ *     In order to use rmt version 1, a client must send "I-1\n0\n" 
+ *     before issuing the other I commands.
  */
-#define RMTI_VERSION    -1
-#define RMT_VERSION 1
+static int     rmt_version = 0;
+#define RMTI_VERSION   -1
+#define RMT_VERSION    1
  
 /* Extended 'i' commands */
-#define RMTI_CACHE  0
-#define RMTI_NOCACHE    1
-#define RMTI_RETEN  2
-#define RMTI_ERASE  3
-#define RMTI_EOM    4
-#define RMTI_NBSF   5
+#define RMTI_CACHE     0
+#define RMTI_NOCACHE   1
+#define RMTI_RETEN     2
+#define RMTI_ERASE     3
+#define RMTI_EOM       4
+#define RMTI_NBSF      5
  
 /* Extended 's' comands */
-#define MTS_TYPE    'T'
-#define MTS_DSREG   'D'
-#define MTS_ERREG   'E'
-#define MTS_RESID   'R'
-#define MTS_FILENO  'F'
-#define MTS_BLKNO   'B'
-#define MTS_FLAGS   'f'
-#define MTS_BF      'b'
+#define MTS_TYPE       'T'
+#define MTS_DSREG      'D'
+#define MTS_ERREG      'E'
+#define MTS_RESID      'R'
+#define MTS_FILENO     'F'
+#define MTS_BLKNO      'B'
+#define MTS_FLAGS      'f'
+#define MTS_BF         'b'
 
 char   *checkbuf __P((char *, int));
 void    error __P((int));
@@ -203,13 +213,68 @@ top:
                DEBUG2("rmtd: I %s %s\n", op, count);
                if (atoi(op) == RMTI_VERSION) {
                        rval = RMT_VERSION;
-               } else { 
-                 struct mtop mtop;
-                 mtop.mt_op = atoi(op);
-                 mtop.mt_count = atoi(count);
-                 if (ioctl(tape, MTIOCTOP, (char *)&mtop) < 0)
-                       goto ioerror;
-                 rval = mtop.mt_count;
+                       rmt_version = 1;
+               } 
+               else { 
+                       struct mtop mtop;
+                       mtop.mt_op = -1;
+                       if (rmt_version) {
+                               /* rmt version 1, assume UNIX client */
+                               switch (atoi(op)) {
+#ifdef  MTWEOF
+                                       case 0:
+                                               mtop.mt_op = MTWEOF;
+                                               break;
+#endif
+#ifdef  MTFSF
+                                       case 1:
+                                               mtop.mt_op = MTFSF;
+                                               break;
+#endif
+#ifdef  MTBSF
+                                       case 2:
+                                               mtop.mt_op = MTBSF;
+                                               break;
+#endif
+#ifdef  MTFSR
+                                       case 3:
+                                               mtop.mt_op = MTFSR;
+                                               break;
+#endif
+#ifdef  MTBSR
+                                       case 4:
+                                               mtop.mt_op = MTBSR;
+                                               break;
+#endif
+#ifdef  MTREW
+                                       case 5:
+                                               mtop.mt_op = MTREW;
+                                               break;
+#endif
+#ifdef  MTOFFL
+                                       case 6:
+                                               mtop.mt_op = MTOFFL;
+                                               break;
+#endif
+#ifdef  MTNOP
+                                       case 7:
+                                               mtop.mt_op = MTNOP;
+                                               break;
+#endif
+                               }
+                               if (mtop.mt_op == -1) {
+                                       errno = EINVAL;
+                                       goto ioerror;
+                               }
+                       }
+                       else {
+                               /* rmt version 0, assume linux client */
+                               mtop.mt_op = atoi(op);
+                       }
+                       mtop.mt_count = atoi(count);
+                       if (ioctl(tape, MTIOCTOP, (char *)&mtop) < 0)
+                               goto ioerror;
+                       rval = mtop.mt_count;
                }
                goto respond;