diff --git a/src/lib/libutil/Makefile b/src/lib/libutil/Makefile index c64984c8..6bbb8167 100644 --- a/src/lib/libutil/Makefile +++ b/src/lib/libutil/Makefile @@ -1,17 +1,17 @@ -# $OpenBSD: Makefile,v 1.26 2003/05/15 01:26:26 ian Exp $ +# $OpenBSD: Makefile,v 1.27 2003/07/23 23:10:25 deraadt Exp $ # $NetBSD: Makefile,v 1.8 1996/05/16 07:03:28 thorpej Exp $ LIB= util CFLAGS+=-DLIBC_SCCS -HDRS= util.h scsi.h +HDRS= util.h SRCS= check_expire.c getmaxpartitions.c getrawpartition.c login.c \ login_tty.c logout.c logwtmp.c opendev.c passwd.c pty.c readlabel.c \ - scsi.c login_fbtab.c uucplock.c fparseln.c opendisk.c pidfile.c \ + login_fbtab.c uucplock.c fparseln.c opendisk.c pidfile.c \ fmt_scaled.c MAN= check_expire.3 getmaxpartitions.3 getrawpartition.3 login.3 opendev.3 \ - openpty.3 pw_init.3 pw_lock.3 readlabelfs.3 scsi.3 pw_getconf.3 \ + openpty.3 pw_init.3 pw_lock.3 readlabelfs.3 pw_getconf.3 \ uucplock.3 fparseln.3 opendisk.3 login_fbtab.3 pidfile.3 \ fmt_scaled.3 @@ -29,17 +29,6 @@ MLINKS+=pw_init.3 pw_scan.3 MLINKS+=pw_init.3 pw_error.3 MLINKS+=pw_lock.3 pw_mkdb.3 MLINKS+=pw_lock.3 pw_abort.3 -MLINKS+=scsi.3 scsireq_buff_decode.3 -MLINKS+=scsi.3 scsireq_build.3 -MLINKS+=scsi.3 scsireq_decode.3 -MLINKS+=scsi.3 scsireq_encode.3 -MLINKS+=scsi.3 scsireq_enter.3 -MLINKS+=scsi.3 scsireq_new.3 -MLINKS+=scsi.3 scsireq_reset.3 -MLINKS+=scsi.3 SCSIREQ_ERROR.3 -MLINKS+=scsi.3 scsi_open.3 -MLINKS+=scsi.3 scsi_debug.3 -MLINKS+=scsi.3 scsi_debug_output.3 MLINKS+=uucplock.3 uu_lock.3 MLINKS+=uucplock.3 uu_unlock.3 MLINKS+=uucplock.3 uu_lockerr.3 diff --git a/src/lib/libutil/scsi.3 b/src/lib/libutil/scsi.3 deleted file mode 100644 index 1624564f..00000000 --- a/src/lib/libutil/scsi.3 +++ /dev/null @@ -1,357 +0,0 @@ -.\" $OpenBSD: scsi.3,v 1.11 2003/07/15 10:20:51 jmc Exp $ -.\" Copyright (c) 1994 HD Associates (hd@world.std.com) -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by HD Associates -.\" 4. Neither the name of the HD Associates nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" -.Dd November 20, 1994 -.Dt SCSI 3 -.Os -.Sh NAME -.Nm scsireq_buff_decode , -.Nm scsireq_build , -.Nm scsireq_decode , -.Nm scsireq_encode , -.Nm scsireq_enter , -.Nm scsireq_new , -.Nm scsireq_reset , -.Nm SCSIREQ_ERROR , -.Nm scsi_open , -.Nm scsi_debug , -.Nm scsi_debug_output -.Nd SCSI User library -.Sh SYNOPSIS -.Fd #include -.Fd #include -.Fd #include -.Ft int -.Fn "scsireq_buff_decode" "u_char *ptr" "size_t len" "char *fmt" "..." -.Ft "struct scsireq *" -.Fn "scsireq_build" "struct scsireq *" "u_long len" "caddr_t buf" "u_long flags" "char *fmt" "..." -.Ft "int" -.Fn "scsireq_decode" "struct scsireq *" "char *fmt" "..." -.Ft int -.Fn "scsireq_encode" "struct scsireq *" "char *fmt" "..." -.Ft int -.Fn "scsireq_enter" "int fid" "struct scsireq *s" -.Ft "struct scsireq *" -.Fn "scsireq_new" "void" -.Ft struct scsireq * -.Fn "scsireq_reset" "struct scsireq *" -.Ft int -.Fn "SCSIREQ_ERROR" "struct scsireq *" -.Ft int -.Fn "scsi_open" "const char *path" "int flags" -.Ft void -.Fn "scsi_debug" "FILE *f" "int ret" "struct scsireq *s" -.Ft "FILE *" -.Fn "scsi_debug_output" "char *s" -.Sh DESCRIPTION -These functions -use the SCIOCCOMMAND -.Xr ioctl 2 -of the SCSI subsystem -to provide user level access to SCSI commands. -The programmer must know the SCSI CDB (Command Descriptor -Block) to perform the desired command. -These functions assist in -building up the CDB, submitting it to the SCSI subsystem, and decoding -the result. -.Pp -Look at the -.Xr scsi 8 -command before using the library directly - simple programs are -best implemented as scripts using that facility. -.Pp -To provide for security, -not all devices accept the SCIOCCOMAND ioctl. -It is accepted by the -control device for tape drives, partition D for disk drives, partition C -for CD ROM drives, and any "unknown" device. -.\" The "super scsi" -.\" .Xr ssc 4 -.\" device also accepts the ioctl. -.Pp -Most of the SCSI library functions build up and manipulate the -.Ar scsireq -structure found in the include file -.Aq Pa sys/scsiio.h : -.Bd -literal -offset indent -#define SENSEBUFLEN 48 -.Pp -typedef struct scsireq { - u_long flags; /* info about the request status and type */ - u_long timeout; - u_char cmd[16]; /* 12 is actually the max */ - u_char cmdlen; - caddr_t databuf; /* address in user space of buffer */ - u_long datalen; /* size of user buffer (request) */ - u_long datalen_used; /* size of user buffer (used)*/ - u_char sense[SENSEBUFLEN]; /* returned sense will be in here */ - u_char senselen; /* sensedata request size (MAX of SENSEBUFLEN)*/ - u_char senselen_used; /* return value only */ - u_char status; /* what the scsi status was from the adapter */ - u_char retsts; /* the return status for the command */ - int error; /* error bits */ -} scsireq_t; -.Ed -.Pp -.Fn scsireq_new -allocates a new -.Ar scsireq -structure and returns a pointer to it or NULL if it can't allocate -memory. -.Pp -.Fn scsireq_reset -resets the structure to reasonable values and returns the same pointer passed -in to it. -It gracefully handles the NULL pointer passed in to it so that you can -unconditionally use -.Ar scsireq_new . -.Pp -.Fn scsireq_build -builds up a scsireq structure based on the information provided in -the variable argument list. -It gracefully handles a NULL pointer passed to it. -.Pp -.Fa len -is the length of the data phase; the data transfer direction is -determined by the -.Ar flags -argument. -.Pp -.Fa buf -is the data buffer used during the SCSI data phase. -If it is NULL it is allocated via malloc and -.Ar scsireq->databuf -is set to point to the newly allocated memory. -.Pp -.Fa flags -are the flags defined in -.Aq Pa sys/scsiio.h : -.Bd -literal -offset indent -/* bit definitions for flags */ -#define SCCMD_READ 0x00000001 -#define SCCMD_WRITE 0x00000002 -#define SCCMD_IOV 0x00000004 -#define SCCMD_ESCAPE 0x00000010 -#define SCCMD_TARGET 0x00000020 -.Ed -.Pp -Only two of these flags are supported in this release of the software: -.Fa SCCMD_READ -indicates a data in phase (a transfer into the user buffer at -.Ar scsireg->databuf ) , -and -.Fa SCCMD_WRITE -indicates a data out phase (a transfer out of the user buffer). -.Pp -.Fa fmt -is a CDB format specifier used to build up the SCSI CDB. -This text string is made up of a list of field specifiers. -Field specifiers specify the value for each CDB field (including indicating -that the value be taken from the next argument in the -variable argument list), the width -of the field in bits or bytes, and an optional name. -Whitespace is ignored, and the pound sign ('#') introduces a comment that -ends at the end of the current line. -.Pp -The optional name is the first part of a field specifier and -is in curly braces. -The text in curly braces in this example are the names: -.Bd -literal -offset indent -.Em "{PS} v:b1 {Reserved} 0:b1 {Page Code} v:b6 # Mode select page" -.Ed -.Pp -This field specifier has two one bit fields and one six bit field. -The second one bit field is the constant value 0 and the first -one bit field and the six bit field are taken from the variable -argument list. -Multi byte fields are swapped into the SCSI byte order in the -CDB and whitespace is ignored. -.Pp -When the field is a hex value or the letter v, (e.g., -.Fa "1A" -or -.Fa "v" ) -then a single byte value -is copied to the next unused byte of the CDB. -When the letter -.Fa v -is used the next integer argument is taken from the variable argument list -and that value used. -.Pp -A constant hex value followed by a field width specifier or the letter -.Fa v -followed by a field width specifier (e.g., -.Fa 3:4 , -.Fa 3:b4 , -.Fa 3:i3 , -.Fa v:i3 ) -specifies a field of a given bit or byte width. -Either the constant value or (for the V specifier) the next integer value from -the variable argument list is copied to the next unused -bits or bytes of the CDB. -.Pp -A decimal number or the letter -.Fa b -followed by a decimal number field width indicates a bit field of that width. -The bit fields are packed as tightly as possible beginning with the -high bit (so that it reads the same as the SCSI spec), and a new byte of -the CDB is started whenever a byte fills completely or when an -.Fa i -field is encountered. -.Pp -A field width specifier consisting of the letter -.Fa i -followed by either -1, 2, 3 or 4 indicates a 1, 2, 3 or 4 byte integral value that must -be swapped into SCSI byte order (MSB first). -.Pp -For the -.Fa v -field specifier the next integer argument is taken from the variable argument -list and that value is used swapped into SCSI byte order. -.Pp -.Fn scsireq_decode -is used to decode information from the data in phase of the SCSI -transfer. -.Pp -The decoding is similar to -the command specifier processing of -.Fn scsireq_build -except that the data is extracted from the data pointed to by -.Fa scsireq->databuf . -The stdarg list should be pointers to integers instead of integer -values. -A seek field type and a suppression modifier are added. -The -.Fa * -suppression modifier (e.g., -.Fa *i3 -or -.Fa *b4 ) -suppresses assignment from the field and can be used to skip -over bytes or bits in the data, without having to copy -them to a dummy variable in the arg list. -.Pp -The seek field type -.Fa s -permits you to skip over data. -This seeks to an absolute position -.Pq Fa s3 -or a relative position -.Pq Fa s+3 -in the data, based on whether or not the '+' sign is present. -The seek value can be specified as -.Fa v -and the next integer value from the argument list will be -used as the seek value. -.Pp -.Fn scsireq_buff_decode -decodes an arbitrary data buffer using the method -described above in -.Fn scsireq_decode . -.Pp -.Fn scsireq_encode -encodes the data phase section of the structure. -The encoding is handled identically as the encoding of the CDB structure by -.Fn scsireq_build . -.Pp -.Fn scsireq_enter -submits the built up structure for processing using -the SCIOCCOMMAND ioctl. -.Pp -.Fn SCSIREQ_ERROR -is a macro that determines if the result of the SCIOCCOMMAND ioctl may -have been -in error by examining the host adapter return code, whether sense was sent -or not, and so on. -.Pp -.Fn scsi_open -checks environment variables and initializes the library for -consistent library use and then calls the regular open system call. -.Pp -.Fn scsi_debug -prints the results of a scsireq_enter function to the specified stdio -stream. -.Pp -.Fn scsi_debug_output -requests that the results of all transactions be debugged to the -supplied file using -.Fn scsi_debug . -.Sh RETURN VALUES -The function -.Fn scsireq_new -returns a pointer to storage allocated from malloc, and therefore -potentially a NULL. -.Pp -The functions -.Fn scsireq_build -and -.Fn scsireq_reset -return the same pointer as the one passed in. -.Pp -The functions -.Fn scsireq_buff_decode and -.Fn scsireq_decode -return the number of assignments performed. -.Pp -.Fn scsireq_encode -returns the number of fields processed. -.Pp -The function -.Fn scsireq_enter -returns the result of the ioctl call. -.Sh SEE ALSO -.Xr scsi 4 , -.Xr scsi 8 -.Sh HISTORY -Many systems have comparable interfaces to permit a user to construct a -SCSI command in user space. -.Pp -The data structure is almost identical to the SGI /dev/scsi data -structure. -If anyone knows the name of the authors it should -go here; Peter Dufault first read about it in a 1989 Sun Expert magazine. -.Pp -Peter Dufault implemented a clone of SGI's interface in 386bsd that -led to this library and the related kernel ioctl. -If anyone needs that for compatibility contact dufault@hda.com. -.Sh BUGS -This only works completely for the 1542C. -The host adapter code -that sets up the residual amount of data transfer has to be added -to each individual adapter. -This library is usable on the other -host adapters; however, the SCSI driver pretends that the proper -amount of data is always transferred. -If you have an Adaptec 174x -and can hack contact dufault@hda.com and you can have the code to -calculate residual data for the 174x series to integrate and test. diff --git a/src/lib/libutil/scsi.c b/src/lib/libutil/scsi.c deleted file mode 100644 index b759c006..00000000 --- a/src/lib/libutil/scsi.c +++ /dev/null @@ -1,1211 +0,0 @@ -/* $OpenBSD: scsi.c,v 1.5 2002/08/23 23:47:32 deraadt Exp $ */ - -/* Copyright (c) 1994 HD Associates - * (contact: dufault@hda.com) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by HD Associates - * 4. Neither the name of the HD Associaates nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: scsi.c,v 1.6 1995/05/30 05:47:26 rgrimes Exp $ - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "scsi.h" - -static struct -{ - FILE *db_f; - int db_level; - int db_trunc; -} behave; - -/* scsireq_reset: Reset a scsireq structure. - */ -scsireq_t *scsireq_reset(scsireq_t *scsireq) -{ - if (scsireq == 0) - return scsireq; - - scsireq->flags = 0; /* info about the request status and type */ - scsireq->timeout = 2000; /* 2 seconds */ - bzero(scsireq->cmd, sizeof(scsireq->cmd)); - scsireq->cmdlen = 0; - /* Leave scsireq->databuf alone */ - /* Leave scsireq->datalen alone */ - scsireq->datalen_used = 0; - bzero(scsireq->sense, sizeof(scsireq->sense)); - scsireq->senselen = sizeof(scsireq->sense); - scsireq->senselen_used = 0; - scsireq->status = 0; - scsireq->retsts = 0; - scsireq->error = 0; - - return scsireq; -} - -/* scsireq_new: Allocate and initialize a new scsireq. - */ -scsireq_t *scsireq_new(void) -{ - scsireq_t *p = (scsireq_t *)malloc(sizeof(scsireq_t)); - - if (p) - scsireq_reset(p); - - return p; -} - -/* - * Decode: Decode the data section of a scsireq. This decodes - * trivial grammar: - * - * fields : field fields - * ; - * - * field : field_specifier - * | control - * ; - * - * control : 's' seek_value - * | 's' '+' seek_value - * ; - * - * seek_value : DECIMAL_NUMBER - * | 'v' // For indirect seek, i.e., value from the arg list - * ; - * - * field_specifier : type_specifier field_width - * | '{' NAME '}' type_specifier field_width - * ; - * - * field_width : DECIMAL_NUMBER - * ; - * - * type_specifier : 'i' // Integral types (i1, i2, i3, i4) - * | 'b' // Bits - * | 't' // Bits - * | 'c' // Character arrays - * | 'z' // Character arrays with zeroed trailing spaces - * ; - * - * Notes: - * 1. Integral types are swapped into host order. - * 2. Bit fields are allocated MSB to LSB to match the SCSI spec documentation. - * 3. 's' permits "seeking" in the string. "s+DECIMAL" seeks relative to - * DECIMAL; "sDECIMAL" seeks absolute to decimal. - * 4. 's' permits an indirect reference. "sv" or "s+v" will get the - * next integer value from the arg array. - * 5. Field names can be anything between the braces - * - * BUGS: - * i and b types are promoted to ints. - * - */ - -static int do_buff_decode(u_char *databuf, size_t len, -void (*arg_put)(void *, int , void *, int, char *), void *puthook, -char *fmt, va_list ap) -{ - int assigned = 0; - int width; - int suppress; - int plus; - int done = 0; - static u_char mask[] = {0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; - int value; - u_char *base = databuf; - char letter; - char field_name[80]; - -# define ARG_PUT(ARG) \ - do \ - { \ - if (!suppress) \ - { \ - if (arg_put) \ - (*arg_put)(puthook, (letter == 't' ? 'b' : letter), \ - (void *)((long)(ARG)), 1, field_name); \ - else \ - *(va_arg(ap, int *)) = (ARG); \ - assigned++; \ - } \ - field_name[0] = 0; \ - suppress = 0; \ - } while (0) - - u_char bits = 0; /* For bit fields */ - int shift = 0; /* Bits already shifted out */ - suppress = 0; - field_name[0] = 0; - - while (!done) - { - switch(letter = *fmt) - { - case ' ': /* White space */ - case '\t': - case '\r': - case '\n': - case '\f': - fmt++; - break; - - case '#': /* Comment */ - while (*fmt && (*fmt != '\n')) - fmt++; - if (fmt) - fmt++; /* Skip '\n' */ - break; - - case '*': /* Suppress assignment */ - fmt++; - suppress = 1; - break; - - case '{': /* Field Name */ - { - int i = 0; - fmt++; /* Skip '{' */ - while (*fmt && (*fmt != '}')) - { - if (i < sizeof(field_name)) - field_name[i++] = *fmt; - - fmt++; - } - if (fmt) - fmt++; /* Skip '}' */ - field_name[i] = 0; - } - break; - - case 't': /* Bit (field) */ - case 'b': /* Bits */ - fmt++; - width = strtol(fmt, &fmt, 10); - if (width > 8) - done = 1; - else - { - if (shift <= 0) - { - bits = *databuf++; - shift = 8; - } - value = (bits >> (shift - width)) & mask[width]; - -#if 0 - printf("shift %2d bits %02x value %02x width %2d mask %02x\n", - shift, bits, value, width, mask[width]); -#endif - - ARG_PUT(value); - - shift -= width; - } - - break; - - case 'i': /* Integral values */ - shift = 0; - fmt++; - width = strtol(fmt, &fmt, 10); - switch(width) - { - case 1: - ARG_PUT(*databuf); - databuf++; - break; - - case 2: - ARG_PUT( - (*databuf) << 8 | - *(databuf + 1)); - databuf += 2; - break; - - case 3: - ARG_PUT( - (*databuf) << 16 | - (*(databuf + 1)) << 8 | - *(databuf + 2)); - databuf += 3; - break; - - case 4: - ARG_PUT( - (*databuf) << 24 | - (*(databuf + 1)) << 16 | - (*(databuf + 2)) << 8 | - *(databuf + 3)); - databuf += 4; - break; - - default: - done = 1; - } - - break; - - case 'c': /* Characters (i.e., not swapped) */ - case 'z': /* Characters with zeroed trailing spaces */ - shift = 0; - fmt++; - width = strtol(fmt, &fmt, 10); - if (!suppress) - { - if (arg_put) - (*arg_put)(puthook, (letter == 't' ? 'b' : letter), - databuf, width, field_name); - else - { - char *dest; - dest = va_arg(ap, char *); - bcopy(databuf, dest, width); - if (letter == 'z') - { - char *p; - for (p = dest + width - 1; - (p >= (char *)dest) && (*p == ' '); p--) - *p = 0; - } - } - assigned++; - } - databuf += width; - field_name[0] = 0; - suppress = 0; - break; - - case 's': /* Seek */ - shift = 0; - fmt++; - if (*fmt == '+') - { - plus = 1; - fmt++; - } - else - plus = 0; - - if (tolower(*fmt) == 'v') - { - /* You can't suppress a seek value. You also - * can't have a variable seek when you are using - * "arg_put". - */ - width = (arg_put) ? 0 : va_arg(ap, int); - fmt++; - } - else - width = strtol(fmt, &fmt, 10); - - if (plus) - databuf += width; /* Relative seek */ - else - databuf = base + width; /* Absolute seek */ - - break; - - case 0: - done = 1; - break; - - default: - fprintf(stderr, "Unknown letter in format: %c\n", letter); - fmt++; - } - } - - return assigned; -} - -int scsireq_decode(scsireq_t *scsireq, char *fmt, ...) -{ - va_list ap; - int ret; - - va_start (ap, fmt); - ret = do_buff_decode(scsireq->databuf, (size_t)scsireq->datalen, - 0, 0, fmt, ap); - va_end (ap); - return (ret); -} - -int scsireq_decode_visit(scsireq_t *scsireq, char *fmt, -void (*arg_put)(void *, int , void *, int, char *), void *puthook) -{ - va_list ap; - int ret; - - ret = do_buff_decode(scsireq->databuf, (size_t)scsireq->datalen, - arg_put, puthook, fmt, ap); - va_end (ap); - return (ret); -} - -int scsireq_buff_decode(u_char *buff, size_t len, char *fmt, ...) -{ - va_list ap; - int ret; - - va_start (ap, fmt); - ret = do_buff_decode(buff, len, 0, 0, fmt, ap); - va_end (ap); - return (ret); -} - -int scsireq_buff_decode_visit(u_char *buff, size_t len, char *fmt, -void (*arg_put)(void *, int, void *, int, char *), void *puthook) -{ - va_list ap; - - /* XXX */ - return do_buff_decode(buff, len, arg_put, puthook, fmt, ap); -} - -/* next_field: Return the next field in a command specifier. This - * builds up a SCSI command using this trivial grammar: - * - * fields : field fields - * ; - * - * field : value - * | value ':' field_width - * ; - * - * field_width : digit - * | 'i' digit // i2 = 2 byte integer, i3 = 3 byte integer etc. - * ; - * - * value : HEX_NUMBER - * | 'v' // For indirection. - * ; - * - * Notes: - * Bit fields are specified MSB first to match the SCSI spec. - * - * Examples: - * TUR: "0 0 0 0 0 0" - * WRITE BUFFER: "38 v:3 0:2 0:3 v v:i3 v:i3 0", mode, buffer_id, list_length - * - * The function returns the value: - * 0: For reached end, with error_p set if an error was found - * 1: For valid stuff setup - * 2: For "v" was entered as the value (implies use varargs) - * - */ - -static int next_field(char **pp, -char *fmt, int *width_p, int *value_p, char *name, int n_name, int *error_p, -int *suppress_p) -{ - char *p = *pp; - - int something = 0; - - enum - { - BETWEEN_FIELDS, - START_FIELD, - GET_FIELD, - DONE, - } state; - - int value = 0; - int field_size; /* Default to byte field type... */ - int field_width; /* 1 byte wide */ - int is_error = 0; - int suppress = 0; - - field_size = 8; /* Default to byte field type... */ - *fmt = 'i'; - field_width = 1; /* 1 byte wide */ - if (name) - *name = 0; - - state = BETWEEN_FIELDS; - - while (state != DONE) - { - switch(state) - { - case BETWEEN_FIELDS: - if (*p == 0) - state = DONE; - else if (isspace(*p)) - p++; - else if (*p == '#') - { - while (*p && *p != '\n') - p++; - if (p) - p++; - } - else if (*p == '{') - { - int i = 0; - - p++; - - while (*p && *p != '}') - { - if(name && i < n_name) - { - name[i] = *p; - i++; - } - p++; - } - - if(name && i < n_name) - name[i] = 0; - - if (*p == '}') - p++; - } - else if (*p == '*') - { - p++; - suppress = 1; - } - else if (isxdigit(*p)) - { - something = 1; - value = strtol(p, &p, 16); - state = START_FIELD; - } - else if (tolower(*p) == 'v') - { - p++; - something = 2; - value = *value_p; - state = START_FIELD; - } -/* Try to work without the "v". - */ - else if (tolower(*p) == 'i') - { - something = 2; - value = *value_p; - p++; - - *fmt = 'i'; - field_size = 8; - field_width = strtol(p, &p, 10); - state = DONE; - } - -/* XXX: B can't work: Sees the 'b' as a hex digit in "isxdigit". - * try "t" for bit field. - */ - else if (tolower(*p) == 't') - { - something = 2; - value = *value_p; - p++; - - *fmt = 'b'; - field_size = 1; - field_width = strtol(p, &p, 10); - state = DONE; - } - else if (tolower(*p) == 's') /* Seek */ - { - *fmt = 's'; - p++; - if (tolower(*p) == 'v') - { - p++; - something = 2; - value = *value_p; - } - else - { - something = 1; - value = strtol(p, &p, 0); - } - state = DONE; - } - else - { - fprintf(stderr, "Invalid starting character: %c\n", *p); - is_error = 1; - state = DONE; - } - break; - - case START_FIELD: - if (*p == ':') - { - p++; - field_size = 1; /* Default to bits when specified */ - state = GET_FIELD; - } - else - state = DONE; - break; - - case GET_FIELD: - if (isdigit(*p)) - { - *fmt = 'b'; - field_size = 1; - field_width = strtol(p, &p, 10); - state = DONE; - } - else if (*p == 'i') /* Integral (bytes) */ - { - p++; - - *fmt = 'i'; - field_size = 8; - field_width = strtol(p, &p, 10); - state = DONE; - } - else if (*p == 'b') /* Bits */ - { - p++; - - *fmt = 'b'; - field_size = 1; - field_width = strtol(p, &p, 10); - state = DONE; - } - else - { - fprintf(stderr, "Invalid startfield %c (%02x)\n", - *p, *p); - is_error = 1; - state = DONE; - } - break; - - case DONE: - break; - } - } - - if (is_error) - { - *error_p = 1; - return 0; - } - - *error_p = 0; - *pp = p; - *width_p = field_width * field_size; - *value_p = value; - *suppress_p = suppress; - - return something; -} - -static int do_encode(u_char *buff, size_t vec_max, size_t *used, -int (*arg_get)(void *, char *), void *gethook, -char *fmt, va_list ap) -{ - int ind; - int shift; - u_char val; - int ret; - int width, value, error, suppress; - char c; - int encoded = 0; - char field_name[80]; - - ind = 0; - shift = 0; - val = 0; - - while ((ret = next_field(&fmt, - &c, &width, &value, field_name, sizeof(field_name), &error, &suppress))) - { - encoded++; - - if (ret == 2) { - if (suppress) - value = 0; - else - value = arg_get ? (*arg_get)(gethook, field_name) : va_arg(ap, int); - } - -#if 0 - printf( -"do_encode: ret %d fmt %c width %d value %d name \"%s\" error %d suppress %d\n", - ret, c, width, value, field_name, error, suppress); -#endif - - if (c == 's') /* Absolute seek */ - { - ind = value; - continue; - } - - if (width < 8) /* A width of < 8 is a bit field. */ - { - - /* This is a bit field. We start with the high bits - * so it reads the same as the SCSI spec. - */ - - shift += width; - - val |= (value << (8 - shift)); - - if (shift == 8) - { - if (ind < vec_max) - { - buff[ind++] = val; - val = 0; - } - shift = 0; - } - } - else - { - if (shift) - { - if (ind < vec_max) - { - buff[ind++] = val; - val = 0; - } - shift = 0; - } - switch(width) - { - case 8: /* 1 byte integer */ - if (ind < vec_max) - buff[ind++] = value; - break; - - case 16: /* 2 byte integer */ - if (ind < vec_max - 2 + 1) - { - buff[ind++] = value >> 8; - buff[ind++] = value; - } - break; - - case 24: /* 3 byte integer */ - if (ind < vec_max - 3 + 1) - { - buff[ind++] = value >> 16; - buff[ind++] = value >> 8; - buff[ind++] = value; - } - break; - - case 32: /* 4 byte integer */ - if (ind < vec_max - 4 + 1) - { - buff[ind++] = value >> 24; - buff[ind++] = value >> 16; - buff[ind++] = value >> 8; - buff[ind++] = value; - } - break; - - default: - fprintf(stderr, "do_encode: Illegal width\n"); - break; - } - } - } - - /* Flush out any remaining bits - */ - if (shift && ind < vec_max) - { - buff[ind++] = val; - val = 0; - } - - - if (used) - *used = ind; - - if (error) - return -1; - - return encoded; -} - -/* XXX: Should be a constant in scsiio.h - */ -#define CMD_BUFLEN 16 - -scsireq_t *scsireq_build(scsireq_t *scsireq, - u_long datalen, caddr_t databuf, u_long flags, - char *cmd_spec, ...) -{ - size_t cmdlen; - va_list ap; - - if (scsireq == 0) - return 0; - - scsireq_reset(scsireq); - - if (databuf) - { - scsireq->databuf = databuf; - scsireq->datalen = datalen; - scsireq->flags = flags; - } - else if (datalen) - { - /* XXX: Good way to get a memory leak. Perhaps this should be - * removed. - */ - if ( (scsireq->databuf = malloc(datalen)) == 0) - return 0; - - scsireq->datalen = datalen; - scsireq->flags = flags; - } - - va_start(ap, cmd_spec); - - if (do_encode(scsireq->cmd, CMD_BUFLEN, &cmdlen, 0, 0, cmd_spec, ap) == -1) - return 0; - va_end (ap); - - scsireq->cmdlen = cmdlen; - return scsireq; -} - -scsireq_t -*scsireq_build_visit(scsireq_t *scsireq, - u_long datalen, caddr_t databuf, u_long flags, char *cmd_spec, - int (*arg_get)(void *hook, char *field_name), void *gethook) -{ - size_t cmdlen; - va_list ap; - - if (scsireq == 0) - return 0; - - scsireq_reset(scsireq); - - if (databuf) - { - scsireq->databuf = databuf; - scsireq->datalen = datalen; - scsireq->flags = flags; - } - else if (datalen) - { - /* XXX: Good way to get a memory leak. Perhaps this should be - * removed. - */ - if ( (scsireq->databuf = malloc(datalen)) == 0) - return 0; - - scsireq->datalen = datalen; - scsireq->flags = flags; - } - - if (do_encode(scsireq->cmd, CMD_BUFLEN, &cmdlen, arg_get, gethook, - cmd_spec, ap) == -1) - return 0; - - scsireq->cmdlen = cmdlen; - - return scsireq; -} - -int scsireq_encode(scsireq_t *scsireq, char *fmt, ...) -{ - va_list ap; - int ret; - - if (scsireq == 0) - return 0; - - va_start(ap, fmt); - - ret = do_encode(scsireq->databuf, - scsireq->datalen, 0, 0, 0, fmt, ap); - va_end (ap); - return (ret); -} - -int scsireq_buff_encode_visit(u_char *buff, size_t len, char *fmt, - int (*arg_get)(void *hook, char *field_name), void *gethook) -{ - va_list ap; - return do_encode(buff, len, 0, - arg_get, gethook, fmt, ap); -} - -int scsireq_encode_visit(scsireq_t *scsireq, char *fmt, - int (*arg_get)(void *hook, char *field_name), void *gethook) -{ - va_list ap; - return do_encode(scsireq->databuf, scsireq->datalen, 0, - arg_get, gethook, fmt, ap); -} - -FILE *scsi_debug_output(char *s) -{ - if (s == 0) - behave.db_f = 0; - else - { - behave.db_f = fopen(s, "w"); - - if (behave.db_f == 0) - behave.db_f = stderr; - } - - return behave.db_f; -} - -#define SCSI_TRUNCATE -1 - -typedef struct scsi_assoc -{ - int code; - char *text; -} scsi_assoc_t; - -static scsi_assoc_t retsts[] = -{ - { SCCMD_OK, "No error" }, - { SCCMD_TIMEOUT, "Command Timeout" }, - { SCCMD_BUSY, "Busy" }, - { SCCMD_SENSE, "Sense Returned" }, - { SCCMD_UNKNOWN, "Unknown return status" }, - - { 0, 0 } -}; - -static char *scsi_assoc_text(int code, scsi_assoc_t *tab) -{ - while (tab->text) - { - if (tab->code == code) - return tab->text; - - tab++; - } - - return "Unknown code"; -} - -void scsi_dump(FILE *f, char *text, u_char *p, int req, int got, int dump_print) -{ - int i; - int trunc = 0; - - if (f == 0 || req == 0) - return; - - fprintf(f, "%s (%d of %d):\n", text, got, req); - - if (behave.db_trunc != -1 && got > behave.db_trunc) - { - trunc = 1; - got = behave.db_trunc; - } - - for (i = 0; i < got; i++) - { - fprintf(f, "%02x", p[i]); - - putc(' ', f); - - if ((i % 16) == 15 || i == got - 1) - { - int j; - if (dump_print) - { - fprintf(f, " # "); - for (j = i - 15; j <= i; j++) - putc((isprint(p[j]) ? p[j] : '.'), f); - - putc('\n', f); - } - else - putc('\n', f); - } - } - - fprintf(f, "%s", (trunc) ? "(truncated)...\n" : "\n"); -} - -/* XXX: sense_7x_dump and scsi_sense dump was just sort of - * grabbed out of the old ds - * library and not really merged in carefully. It should use the - * new buffer decoding stuff. - */ - -/* Get unsigned long. - */ -static u_long g_u_long(u_char *s) -{ - return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; -} - -/* In the old software you could patch in a special error table: - */ -static scsi_assoc_t *error_table = 0; - -static void sense_7x_dump(FILE *f, scsireq_t *scsireq) -{ - int code; - u_char *s = (u_char *)scsireq->sense; - int valid = (*s) & 0x80; - u_long val; - - static scsi_assoc_t sense[] = { - { 0, "No sense" }, - { 1, "Recovered error" }, - { 2, "Not Ready" }, - { 3, "Medium error" }, - { 4, "Hardware error" }, - { 5, "Illegal request" }, - { 6, "Unit attention" }, - { 7, "Data protect" }, - { 8, "Blank check" }, - { 9, "Vendor specific" }, - { 0xa, "Copy aborted" }, - { 0xb, "Aborted Command" }, - { 0xc, "Equal" }, - { 0xd, "Volume overflow" }, - { 0xe, "Miscompare" }, - { 0, 0 }, - }; - - static scsi_assoc_t code_tab[] = { - {0x70, "current errors"}, - {0x71, "deferred errors"}, - }; - - fprintf(f, "Error code is \"%s\"\n", scsi_assoc_text(s[0]&0x7F, code_tab)); - fprintf(f, "Segment number is %02x\n", s[1]); - - if (s[2] & 0x20) - fprintf(f, "Incorrect Length Indicator is set.\n"); - - fprintf(f, "Sense key is \"%s\"\n", scsi_assoc_text(s[2] & 0x7, sense)); - - val = g_u_long(s + 3); - fprintf(f, "The Information field is%s %08lx (%ld).\n", - valid ? "" : " not valid but contains", (long)val, (long)val); - - val = g_u_long(s + 8); - fprintf(f, "The Command Specific Information field is %08lx (%ld).\n", - (long)val, (long)val); - - fprintf(f, "Additional sense code: %02x\n", s[12]); - fprintf(f, "Additional sense code qualifier: %02x\n", s[13]); - - code = (s[12] << 8) | s[13]; - - if (error_table) - fprintf(f, "%s\n", scsi_assoc_text(code, error_table)); - - if (s[15] & 0x80) - { - if ((s[2] & 0x7) == 0x05) /* Illegal request */ - { - int byte; - u_char value, bit; - int bad_par = ((s[15] & 0x40) == 0); - fprintf(f, "Illegal value in the %s.\n", - (bad_par ? "parameter list" : "command descriptor block")); - byte = ((s[16] << 8) | s[17]); - value = bad_par ? (u_char)scsireq->databuf[byte] : (u_char)scsireq->cmd[byte]; - bit = s[15] & 0x7; - if (s[15] & 0x08) - fprintf(f, "Bit %d of byte %d (value %02x) is illegal.\n", - bit, byte, value); - else - fprintf(f, "Byte %d (value %02x) is illegal.\n", byte, value); - } - else - { - fprintf(f, "Sense Key Specific (valid but not illegal request):\n"); - fprintf(f, - "%02x %02x %02x\n", s[15] & 0x7f, s[16], s[17]); - } - } -} - -/* scsi_sense_dump: Dump the sense portion of the scsireq structure. - */ -void scsi_sense_dump(FILE *f, scsireq_t *scsireq) -{ - u_char *s = (u_char *)scsireq->sense; - int code = (*s) & 0x7f; - - if (scsireq->senselen_used == 0) - { - fprintf(f, "No sense sent.\n"); - return; - } - -#if 0 - if (!valid) - fprintf(f, "The sense data is not valid.\n"); -#endif - - switch(code) - { - case 0x70: - case 0x71: - sense_7x_dump(f, scsireq); - break; - - default: - fprintf(f, "No sense dump for error code %02x.\n", code); - } - scsi_dump(f, "sense", s, scsireq->senselen, scsireq->senselen_used, 0); -} - -void scsi_retsts_dump(FILE *f, scsireq_t *scsireq) -{ - if (scsireq->retsts == 0) - return; - - fprintf(f, "return status %d (%s)", - scsireq->retsts, scsi_assoc_text(scsireq->retsts, retsts)); - - switch(scsireq->retsts) - { - case SCCMD_TIMEOUT: - fprintf(f, " after %ld ms", scsireq->timeout); - break; - - default: - break; - } -} - -int scsi_debug(FILE *f, int ret, scsireq_t *scsireq) -{ - char *d; - if (f == 0) - return 0; - - fprintf(f, "SCIOCCOMMAND ioctl"); - - if (ret == 0) - fprintf(f, ": Command accepted."); - else - { - if (ret != -1) - fprintf(f, ", return value %d?", ret); - - if (errno) - { - fprintf(f, ": %s", strerror(errno)); - errno = 0; - } - } - - fputc('\n', f); - - if (ret == 0 && (scsireq->status || scsireq->retsts || behave.db_level)) - { - scsi_retsts_dump(f, scsireq); - - if (scsireq->status) - fprintf(f, " host adapter status %d\n", scsireq->status); - - if (scsireq->flags & SCCMD_READ) - d = "Data in"; - else if (scsireq->flags & SCCMD_WRITE) - d = "Data out"; - else - d = "No data transfer?"; - - if (scsireq->cmdlen == 0) - fprintf(f, "Zero length command????\n"); - - scsi_dump(f, "Command out", - (u_char *)scsireq->cmd, scsireq->cmdlen, scsireq->cmdlen, 0); - scsi_dump(f, d, - (u_char *)scsireq->databuf, scsireq->datalen, - scsireq->datalen_used, 1); - scsi_sense_dump(f, scsireq); - } - - fflush(f); - - return ret; -} - -static char *debug_output; - -int scsi_open(const char *path, int flags) -{ - int fd = open(path, flags); - - if (fd != -1) - { - char *p; - debug_output = getenv("SU_DEBUG_OUTPUT"); - (void)scsi_debug_output(debug_output); - - if ((p = getenv("SU_DEBUG_LEVEL"))) - sscanf(p, "%d", &behave.db_level); - - if ((p = getenv("SU_DEBUG_TRUNCATE"))) - sscanf(p, "%d", &behave.db_trunc); - else - behave.db_trunc = SCSI_TRUNCATE; - } - - return fd; -} - -int scsireq_enter(int fid, scsireq_t *scsireq) -{ - int ret; - - if (scsireq == 0) - return EFAULT; - - ret = ioctl(fid, SCIOCCOMMAND, (void *)scsireq); - - if (behave.db_f) scsi_debug(behave.db_f, ret, scsireq); - - return ret; -} diff --git a/src/lib/libutil/scsi.h b/src/lib/libutil/scsi.h deleted file mode 100644 index 3551ce54..00000000 --- a/src/lib/libutil/scsi.h +++ /dev/null @@ -1,83 +0,0 @@ -/* $OpenBSD: scsi.h,v 1.3 2002/02/17 19:42:26 millert Exp $ */ - -/* Copyright (c) 1994 HD Associates (hd@world.std.com) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by HD Associates - * 4. Neither the name of the HD Associaates nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _SCSI_H_ -#define _SCSI_H_ - -#include - -/* libscsi: Library header file for the SCSI user library. - */ - -#include -#include - -#define SCSIREQ_ERROR(SR) (\ -0 \ -|| SR->senselen_used /* Sent sense */ \ -|| SR->status /* Host adapter status */ \ -|| SR->retsts /* SCSI transfer status */ \ -|| SR->error /* copy of errno */ \ -) - -scsireq_t *scsireq_reset(scsireq_t *); -scsireq_t *scsireq_new(void); - -int scsireq_buff_decode(u_char *, size_t, char *, ...); -int scsireq_buff_decode_visit(u_char *, size_t, char *, - void (*a)(void *, int, void *, int, char *), void *); - -int scsireq_decode(scsireq_t *, char *, ...); -int scsireq_decode_visit(scsireq_t *, char *, - void (*)(void *, int, void *, int, char *), void *); - -int scsireq_encode(scsireq_t *, char *, ...); -int scsireq_encode_visit(scsireq_t *, char *, - int (*)(void *, char *), void *); -int scsireq_buff_encode_visit(u_char *, size_t, char *, - int (*)(void *, char *), void *); - -scsireq_t *scsireq_build(scsireq_t *, u_long, caddr_t, u_long, char *, ...); - -scsireq_t *scsireq_build_visit(scsireq_t *, u_long, caddr_t, u_long, char *, - int (*)(void *, char *), void *); - -int scsireq_enter(int, scsireq_t *); - -void scsi_dump(FILE *, char *, u_char *, int, int, int ); - -int scsi_debug(FILE *, int, scsireq_t *); -FILE *scsi_debug_output(char *); -int scsi_open(const char *, int ); - -#endif /* _SCSI_H_ */ diff --git a/src/lib/libutil/shlib_version b/src/lib/libutil/shlib_version index 00604e64..1c5d96eb 100644 --- a/src/lib/libutil/shlib_version +++ b/src/lib/libutil/shlib_version @@ -1,2 +1,2 @@ -major=8 -minor=1 +major=9 +minor=0