From d24dc8af74ac524f4a4807674f4863630d8f829f Mon Sep 17 00:00:00 2001 From: Stelian Pop Date: Mon, 15 Apr 2002 11:57:27 +0000 Subject: [PATCH] Fix rmt ioctl command with UNIX clients (mtio opcodes Linux incompatibilities) --- CHANGES | 13 +++- rmt/rmt.8.in | 201 ++++++++++++++++++++++++++++++++++++++++++--------- rmt/rmt.c | 127 ++++++++++++++++++++++++-------- 3 files changed, 275 insertions(+), 66 deletions(-) diff --git a/CHANGES b/CHANGES index 82097e9..e055370 100644 --- 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 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) ==================================================================== diff --git a/rmt/rmt.8.in b/rmt/rmt.8.in index be86334..6e93213 100644 --- a/rmt/rmt.8.in +++ b/rmt/rmt.8.in @@ -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 @@ -40,11 +40,15 @@ .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 diff --git a/rmt/rmt.c b/rmt/rmt.c index 2af48e3..acacb2d 100644 --- 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 #include -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 * 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; -- 2.39.5