chiark / gitweb /
[PATCH] update udev extras/scsi_id to version 0.2
authorpatmans@us.ibm.com <patmans@us.ibm.com>
Sun, 7 Dec 2003 16:55:40 +0000 (08:55 -0800)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 04:13:06 +0000 (21:13 -0700)
This patch updates scsi_id under udev from version 0.1 to version 0.2.

extras/scsi_id/ChangeLog [new file with mode: 0644]
extras/scsi_id/Makefile
extras/scsi_id/README
extras/scsi_id/TODO
extras/scsi_id/VERSION [deleted file]
extras/scsi_id/scsi_id.8 [new file with mode: 0644]
extras/scsi_id/scsi_id.c
extras/scsi_id/scsi_id.h
extras/scsi_id/scsi_serial.c

diff --git a/extras/scsi_id/ChangeLog b/extras/scsi_id/ChangeLog
new file mode 100644 (file)
index 0000000..7f23177
--- /dev/null
@@ -0,0 +1,64 @@
+2003-dec-05:
+       * Makefile, scsi_id.8: Add a man page.
+
+2003-dec-04:
+       * Makefile: Set and use variables that might be passed down when
+         built under udev (with or without klibc), don't set LDFLAGS or
+         STRIP.
+
+2003-dec-04:
+       * scsi_id.c, scsi_id.h: Fix a bad bug - when parsing file options,
+         no space was allocated for the creation of the new argv[]
+         strings.
+
+2003-dec-04:
+       * scsi_id.c: Catch too long a line in the config file.
+
+2003-dec-02:
+       * scsi_id.h: Add u8 typedef to avoid ummm scsi.h kernel header
+         problem when built with klibc.
+
+2003-dec-02:
+       * scsi_id.h: Add define of makedev() if built with klibc.
+
+2003-dec-02:
+       * scsi_id.c: reset optind to 1 since klibc does not work if it is
+         reset to zero.
+
+2003-dec-02:
+       * scsi_id.c: remove fflush() as it is not needed, and is not
+         supported by klibc.
+
+2003-dec-02:
+       * scsi_serial.c: Make the functions do_scsi_page0_inquiry and
+         do_scsi_page80_inquiry static.
+
+2003-dec-01:
+       * scsi_id.c: Don't use syslog LOG_PID, as it is not supported by
+         klibc.
+
+2003-dec-01:
+       * scsi_id.c, scsi_serial.c: Hack - change include path to libsysfs
+         if built under klibc.
+
+2003-dec-01:
+       * Makefile: Use "override" for CFLAGS so we can pass CFLAGS values
+         down when built with udev
+
+2003-dec-01:
+       * scsi_id.c, Makefile: Use SCSI_ID_VERSION instead of VERSION.
+
+2003-nov-25:
+       * scsi_id.c: Remove getopt_long (long option names), as there
+         is no support for that in klibc.
+
+2003-nov-17:
+       * scsi_id.c: Patch from Brian King: check result of setting model,
+         not vendor in per_dev_options.
+
+2003-nov-03:
+       * scsi_id.c, scsi_serial.c: Use new and correct path to libsysfs.h.
+
+2003-nov-03:
+       * scsi_id.h: Fix scsi_id.h so var args in marcros works ok with
+         older gcc.
index 5ad2bcf..ead2056 100644 (file)
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
-VERSION=0.1
+SCSI_ID_VERSION=0.2
 
 prefix =
 sbindir =      ${prefix}/sbin
+mandir =       ${prefix}/usr/share/man
 
 INSTALL  = /usr/bin/install -c
 INSTALL_PROGRAM = ${INSTALL}
 INSTALL_DATA  = ${INSTALL} -m 644
 
-CFLAGS=-DVERSION=\"$(VERSION)\" $(DEBUG) -Wall
+# Note some of the variables used here are set when built under udev, and
+# otherwise might not be set.
+
+override CFLAGS+=-DSCSI_ID_VERSION=\"$(SCSI_ID_VERSION)\" $(DEBUG) -Wall
 
 PROG=scsi_id
+SYSFS=-lsysfs
 
-LIBSYSFS=-lsysfs
-STRIP=-s
-LDFLAGS=$(STRIP) --static
+#
+# Built static and stripped when built with udev.
+#
+# STRIP=-s
+# LDFLAGS=$(STRIP)
+LD=$(CC)
 
 OBJS= scsi_id.o \
        scsi_serial.o \
 
 all:   $(PROG)
 
+# XXX use a compressed man page?
+
 install: all
        $(INSTALL_PROGRAM) -D $(PROG) $(sbindir)/$(PROG)
+       $(INSTALL_DATA) -D scsi_id.8 $(DESTDIR)$(mandir)/man8/scsi_id.8
        
 uninstall:
        -rm $(sbindir)/$(PROG)
+       -rm $(mandir)/man8/scsi_id.8
 
 $(OBJS): scsi_id.h scsi.h
 
@@ -48,4 +60,4 @@ clean:
        rm -f $(PROG) $(OBJS)
 
 $(PROG):       $(OBJS)
-       $(CC) $(OBJS) $(LDFLAGS) $(LIBSYSFS) -o $(PROG)
+       $(LD) $(LDFLAGS) -o $(PROG) $(CRT0) $(OBJS) $(SYSFS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
index b13cf1e..4281c31 100644 (file)
@@ -5,9 +5,9 @@ used by a multi-path configuration tool that requires SCSI id's.
 
 Requires:
 
-- Linux kernel 2.6
+       - Linux kernel 2.6
 
-- libsysfs 
+       - libsysfs
 
 No man page yet.
 
index ba52101..5d020c2 100644 (file)
@@ -1,16 +1,11 @@
-- Investigate shrinking build size: use klibc or uClibc, or copy whatever
-  udev does
+- add information abou the config file to the man page
 
-- write a man page
+- change so non-KLIBC builds under udev don't use /usr/include/sysfs,
+  but instead use the sysfs included with udev (needs udev change and/or
+  sysfsutils changes).
 
-- send in kernel patch for REQ_BLOCK_PC, to always set sd and sr set
-  retries (scmd->allowed) to <= 1
+- do something with callout code - remove or change to a tag?
 
-- Pull SG_IO code into one .c file.
-- implement callout to device specific serial id code.  The "-c prog" is
-  not implemented.
-
-  This needs an implementation of a device specific callout before it can
-  be completed. Someone with hardware requiring this needs to send in a
-  patch.
+  This needs an implementation of a device specific callout or device
+  specific code (called via some special  "tag" or such) before it can be
+  completed. Someone with such hardware to send in a patch.
diff --git a/extras/scsi_id/VERSION b/extras/scsi_id/VERSION
deleted file mode 100644 (file)
index 49d5957..0000000
+++ /dev/null
@@ -1 +0,0 @@
-0.1
diff --git a/extras/scsi_id/scsi_id.8 b/extras/scsi_id/scsi_id.8
new file mode 100644 (file)
index 0000000..a4fb881
--- /dev/null
@@ -0,0 +1,118 @@
+.TH SCSI_ID 8 "December 2003" "" "Linux Administrator's Manual"
+.SH NAME
+scsi_id \- retrieve and generate a unique SCSI identifier
+.SH SYNOPSIS
+.BI scsi_id 
+[\fIoptions\fP]
+.SH "DESCRIPTION"
+.B scsi_id
+queries a SCSI device via the SCSI INQUIRY vital product data (VPD) page 0x80 or
+0x83 and uses the resulting data to generate a value that is unique across
+all SCSI devices that properly support page 0x80 or page 0x83. 
+
+If a result is generated it is sent to standard output, and the program
+exits with a zero value. If no identifier is output, the program exits
+with a non-zero value.
+
+\fBscsi_id\fP is primarily for use by other utilities such as \fBudev\fP
+that require a unique SCSI identifier.
+
+By default all devices are assume black listed, the \fB-g\fP option must
+be specified on the command line or in the config file for any useful
+behaviour.
+
+SCSI commands are sent directly to the device via the SG_IO ioctl
+interface.
+
+In order to generate unique values for either page 0x80 or page 0x83, the
+serial numbers or world wide names are prefixed as follows.
+
+Identifiers based on page 0x80 are prefixed by the character 'S', the SCSI
+vendor, the SCSI product (model) and then the the serial number returned
+by page 0x80. For example:
+
+.sp
+.nf
+# scsi_id -p 0x80 -s /block/sdg
+SIBM     3542           1T05078453
+.fi
+.P
+
+Identifiers based on page 0x83 are prefixed by the identifier type
+followed by the page 0x83 identifier. For example, a device with a NAA
+(Name Address Authority) type of 3 (also in this case the page 0x83
+identifier starts with the NAA value of 6):
+
+.sp
+.nf
+# /sbin/scsi_id -p 0x83 -s /block/sdg
+3600a0b80000b174b000000d63efc5c8c
+.fi
+.P
+
+
+.SH OPTIONS
+.TP
+.BI \-b
+The default behaviour - treat the device as black listed, and do nothing
+unless a white listed device is found in the scsi_id config-file.
+.TP
+.BI \-d "\| device\^"
+Instead
+of determining and creating a device node based on a sysfs dev
+entry as done for the \fB-s\fP, send SG_IO commands to 
+\fBdevice\fP, such as \fB/dev/sdc\fP.
+.TP
+.BI \-e
+Send all output to standard error even if
+.B scsi_id 
+is running in hotplug mode.
+.TP
+.BI \-f "\| config-file"
+Read configuration and black/white list entries from
+.B config-file 
+rather than the default
+.B /etc/scsi_id.config
+file.
+.TP
+.BI \-g
+Treat the device as white listed. The \fB\-g\fP option must be specified
+on the command line or in the scsi_id configuration file for 
+.B scsi_id
+to generate any output.
+.TP
+.BI \-i
+Prefix the identification string with the  driver model (sysfs) bus id of
+the SCSI device.
+.TP
+.BI \-p "\| 0x80 | 0x83"
+Use SCSI INQUIRY VPD page code 0x80 or 0x83. The default behaviour is to
+query the available VPD pages, and use page 0x83 if found, else page 0x80
+if found, else nothing.
+.TP
+.BI \-s "\|sysfs-device"
+Generate an id for the
+.B sysfs-device.
+The sysfs mount point must not be included. For example, use /block/sd,
+not /sys/block/sd.
+.TP
+.BI \-v
+Generate verbose debugging output.
+.TP
+.BI \-V
+Display version number and exit.
+.RE
+.SH "FILES"
+.nf
+.ft B
+.ft
+/etc/scsi_id.config                  configuration and black/white list entries
+.fi
+.LP
+.SH "SEE ALSO"
+.BR udev (8)
+, especially the CALLOUT method.
+.SH AUTHORS
+Developed by Patrick Mansfield <patmans@us.ibm.com> based on SCSI ID
+source included in earlier linux 2.5 kernels, sg_utils source, and SCSI
+specifications.
index d34d928..df18271 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <getopt.h>
 #include <unistd.h>
 #include <signal.h>
 #include <fcntl.h>
 #include <stdarg.h>
 #include <ctype.h>
 #include <sys/stat.h>
-#include <sys/libsysfs.h>
+#ifdef __KLIBC__
+/*
+ * Assume built under udev with KLIBC
+ */
+#include <libsysfs.h>
+#else
+#include <sysfs/libsysfs.h>
+#endif
 #include "scsi_id.h"
 
-#ifndef VERSION
+#ifndef SCSI_ID_VERSION
 #warning No version
-#define VERSION        "unknown"
+#define SCSI_ID_VERSION        "unknown"
 #endif
 
 /*
 
 #define CONFIG_FILE "/etc/scsi_id.config"
 
-#define        MAX_NAME_LEN    72
-
-#define        MAX_SERIAL_LEN  128
-
 static const char short_options[] = "bc:d:ef:gip:s:vV";
-static const struct option long_options[] = {
-       {"broken",      no_argument,            NULL,   'b'}, /* also per dev */
-       {"callout",     required_argument,      NULL,   'c'}, /* also per dev */
-       {"device",      required_argument,      NULL,   'd'},
-       {"stderr",      no_argument,            NULL,   'e'},
-       {"file",        required_argument,      NULL,   'f'},
-       {"good",        no_argument,            NULL,   'g'}, /* also per dev */
-       {"busid",       no_argument,            NULL,   'i'}, /* also per dev */
-       {"page",        required_argument,      NULL,   'p'}, /* also per dev */
-       {"devpath",     required_argument,      NULL,   's'},
-       {"verbose",     no_argument,            NULL,   'v'},
-       {"version",     no_argument,            NULL,   'V'},
-       {0, 0, 0, 0}
-};
 /*
  * Just duplicate per dev options.
  */
 static const char dev_short_options[] = "bc:gp:";
-static const struct option dev_long_options[] = {
-       {"broken",      no_argument,            NULL,   'b'}, /* also per dev */
-       {"callout",     required_argument,      NULL,   'c'}, /* also per dev */
-       {"good",        no_argument,            NULL,   'g'}, /* also per dev */
-       {"page",        required_argument,      NULL,   'p'}, /* also per dev */
-       {0, 0, 0, 0}
-};
 
 char sysfs_mnt_path[SYSFS_PATH_MAX];
 
@@ -105,8 +86,13 @@ void log_message (int level, const char *format, ...)
                vfprintf(stderr, format, args);
        } else {
                static int logging_init = 0;
+               static unsigned char logname[32];
                if (!logging_init) {
-                       openlog ("scsi_id", LOG_PID, LOG_DAEMON);
+                       /*
+                        * klibc does not have LOG_PID.
+                        */
+                       snprintf(logname, 32, "scsi_id[%d]", getpid());
+                       openlog (logname, 0, LOG_DAEMON);
                        logging_init = 1;
                }
 
@@ -295,7 +281,7 @@ static int argc_count(char *opts)
 static int get_file_options(char *vendor, char *model, int *argc,
                            char ***newargv)
 {
-       char buffer[256];
+       char *buffer;
        FILE *fd;
        char *buf;
        char *str1;
@@ -303,7 +289,6 @@ static int get_file_options(char *vendor, char *model, int *argc,
        int lineno;
        int c;
        int retval = 0;
-       static char *prog_string = "arg0";
 
        dprintf("vendor='%s'; model='%s'\n", vendor, model);
        fd = fopen(config_file, "r");
@@ -318,16 +303,31 @@ static int get_file_options(char *vendor, char *model, int *argc,
                }
        }
 
+       /*
+        * Allocate a buffer rather than put it on the stack so we can
+        * keep it around to parse any options (any allocated newargv
+        * points into this buffer for its strings).
+        */
+       buffer = malloc(MAX_BUFFER_LEN);
+       if (!buffer) {
+               log_message(LOG_WARNING, "Can't allocate memory.\n");
+               return -1;
+       }
+
        *newargv = NULL;
        lineno = 0;
-
        while (1) {
                vendor_in = model_in = options_in = NULL;
 
-               buf = fgets(buffer, sizeof(buffer), fd);
+               buf = fgets(buffer, MAX_BUFFER_LEN, fd);
                if (buf == NULL)
                        break;
                lineno++;
+               if (buf[strlen(buffer) - 1] != '\n') {
+                       log_message(LOG_WARNING,
+                                   "Config file line %d too long.\n", lineno);
+                       break;
+               }
 
                while (isspace(*buf))
                        buf++;
@@ -419,18 +419,24 @@ static int get_file_options(char *vendor, char *model, int *argc,
                         * Something matched. Allocate newargv, and store
                         * values found in options_in.
                         */
-                       c = argc_count(options_in) + 2;
+                       strcpy(buffer, options_in);
+                       c = argc_count(buffer) + 2;
                        *newargv = calloc(c, sizeof(**newargv));
                        if (!*newargv) {
                                log_message(LOG_WARNING,
-                                           "Can't allocate memory\n");
+                                           "Can't allocate memory.\n");
                                retval = -1;
                        } else {
                                *argc = c;
                                c = 0;
-                               (*newargv)[c] = prog_string; /* nothing */
+                               /*
+                                * argv[0] at 0 is skipped by getopt, but
+                                * store the buffer address there for
+                                * alter freeing.
+                                */
+                               (*newargv)[c] = buffer;
                                for (c = 1; c < *argc; c++)
-                                       (*newargv)[c] = strsep(&options_in, " ");
+                                       (*newargv)[c] = strsep(&buffer, " ");
                        }
                } else {
                        /*
@@ -439,26 +445,26 @@ static int get_file_options(char *vendor, char *model, int *argc,
                        retval = 1;
                }
        }
+       if (retval != 0)
+               free(buffer);
        fclose(fd);
        return retval;
 }
 
 static int set_options(int argc, char **argv, const char *short_opts,
-                      const struct option *long_opts, char *target,
-                      char *maj_min_dev)
+                      char *target, char *maj_min_dev)
 {
        int option;
-       int option_ind;
 
        /*
-        * optind is a global extern used by getopt_long. Since we can
-        * call set_options twice (once for command line, and once for
-        * config file) we have to reset this back to 0.
+        * optind is a global extern used by getopt. Since we can call
+        * set_options twice (once for command line, and once for config
+        * file) we have to reset this back to 1. [Note glibc handles
+        * setting this to 0, but klibc does not.]
         */
-       optind = 0;
+       optind = 1;
        while (1) {
-               option = getopt_long(argc, argv, short_options, long_options,
-                                    &option_ind);
+               option = getopt(argc, argv, short_options);
                if (option == -1)
                        break;
 
@@ -521,7 +527,7 @@ static int set_options(int argc, char **argv, const char *short_opts,
 
                case 'V':
                        log_message(LOG_WARNING, "scsi_id version: %s\n",
-                                   VERSION);
+                                   SCSI_ID_VERSION);
                        exit(0);
                        break;
 
@@ -544,8 +550,6 @@ static int per_dev_options(struct sysfs_class_device *scsi_dev, int *good_bad,
        char *vendor;
        char *model;
        int option;
-       int option_ind;
-
 
        *good_bad = all_good;
        *page_code = default_page_code;
@@ -562,7 +566,7 @@ static int per_dev_options(struct sysfs_class_device *scsi_dev, int *good_bad,
        }
 
        model = sysfs_get_attr(scsi_dev, "model");
-       if (!vendor) {
+       if (!model) {
                log_message(LOG_WARNING, "%s: no model attribute\n",
                            scsi_dev->name);
                return -1;
@@ -570,10 +574,9 @@ static int per_dev_options(struct sysfs_class_device *scsi_dev, int *good_bad,
 
        retval = get_file_options(vendor, model, &newargc, &newargv);
 
-       optind = 0; /* global extern, reset to 0 */
+       optind = 1; /* reset this global extern */
        while (retval == 0) {
-               option = getopt_long(newargc, newargv, dev_short_options,
-                                    dev_long_options, &option_ind);
+               option = getopt(newargc, newargv, dev_short_options);
                if (option == -1)
                        break;
 
@@ -616,8 +619,10 @@ static int per_dev_options(struct sysfs_class_device *scsi_dev, int *good_bad,
                }
        }
 
-       if (newargv)
+       if (newargv) {
+               free(newargv[0]);
                free(newargv);
+       }
        return retval;
 }
 
@@ -747,7 +752,6 @@ static int scsi_id(const char *target_path, char *maj_min_dev)
                dprintf("%s\n", serial);
                retval = 0;
        }
-       fflush(stdout);
        sysfs_close_class_device(scsi_dev);
 
        if (!dev_specified)
@@ -797,8 +801,8 @@ int main(int argc, char **argv)
                strncpy(target_path, sysfs_mnt_path, MAX_NAME_LEN);
                strncat(target_path, devpath, MAX_NAME_LEN);
        } else {
-               if (set_options(argc, argv, short_options, long_options,
-                               target_path, maj_min_dev) < 0)
+               if (set_options(argc, argv, short_options, target_path,
+                               maj_min_dev) < 0)
                        exit(1);
        }
 
@@ -811,8 +815,8 @@ int main(int argc, char **argv)
        if (retval < 0) {
                exit(1);
        } else if (newargv && (retval == 0)) {
-               if (set_options(newargc, newargv, short_options, long_options,
-                               target_path, maj_min_dev) < 0)
+               if (set_options(newargc, newargv, short_options, target_path,
+                               maj_min_dev) < 0)
                        exit(1);
                free(newargv);
        }
index 8be492b..eb9498a 100644 (file)
  */
 
 #define dprintf(format, arg...) \
-       log_message(LOG_DEBUG, "%s: " format, __FUNCTION__, ## arg)
+       log_message(LOG_DEBUG, "%s: " format, __FUNCTION__ , ## arg)
 
 #define        MAX_NAME_LEN    72
 #define OFFSET (2 * sizeof(unsigned int))
 
+/*
+ * MAX_SERIAL_LEN: the maximum length of the serial number, including
+ * added prefixes such as vendor and product (model) strings.
+ */
+#define        MAX_SERIAL_LEN  128
+
+/*
+ * MAX_BUFFER_LEN: maximum buffer size and line length used while reading
+ * the config file.
+ */
+#define MAX_BUFFER_LEN 256
+
 static inline char *sysfs_get_attr(struct sysfs_class_device *dev,
                                    const char *attr)
 {
@@ -40,3 +52,10 @@ extern int scsi_get_serial (struct sysfs_class_device *scsi_dev,
 extern void log_message (int level, const char *format, ...)
        __attribute__ ((format (printf, 2, 3)));
 
+#ifdef __KLIBC__
+#define makedev(major, minor)  ((major) << 8) | (minor)
+#endif
+
+#ifndef u8
+typedef unsigned char u8;
+#endif
index 302429c..18cd290 100644 (file)
 #include <unistd.h>
 #include <syslog.h>
 #include <scsi/sg.h>
-#include <sys/libsysfs.h>
+#ifdef __KLIBC__
+/*
+ * Assume built under udev with KLIBC
+ */
+#include <libsysfs.h>
+#else
+#include <sysfs/libsysfs.h>
+#endif
 #include "scsi_id.h"
 #include "scsi.h"
 
@@ -348,6 +355,11 @@ resend:
                        retval = scsi_dump(scsi_dev, &io_hdr);
        }
 
+       /*
+        * XXX where is the length checked? That is, was our request
+        * buffer long enough?
+        */
+
        if (!retval) {
                retval = buflen;
                memcpy(buf, buffer, retval);
@@ -369,8 +381,8 @@ resend:
  * Ending here.
  */
 
-int do_scsi_page0_inquiry(struct sysfs_class_device *scsi_dev, int fd,
-                         char *buffer, int len)
+static int do_scsi_page0_inquiry(struct sysfs_class_device *scsi_dev, int fd,
+                                char *buffer, int len)
 {
        int retval;
        char *vendor;
@@ -527,8 +539,10 @@ static int check_fill_0x83_id(struct sysfs_class_device *scsi_dev,
        serial[0] = hex_str[id_search->id_type];
 
        /*
-        * Prepend the vendor and model before the id since if it is not
-        * unique across all vendors and models.
+        * For SCSI_ID_VENDOR_SPECIFIC prepend the vendor and model before
+        * the id since it is not unique across all vendors and models,
+        * this differs from SCSI_ID_T10_VENDOR, where the vendor is
+        * included in the identifier.
         */
        if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC)
                if (prepend_vendor_model(scsi_dev, &serial[1]) < 0) {
@@ -575,6 +589,12 @@ static int do_scsi_page83_inquiry(struct sysfs_class_device *scsi_dev, int fd,
                            scsi_dev->name);
                return 1;
        }
+       
+       /*
+        * XXX Some devices (IBM 3542) return all spaces for an identifier if
+        * the LUN is not actually configured. This leads to identifers of
+        * the form: "1            ".
+        */
 
        /*
         * Search for a match in the prioritized id_search_list.
@@ -609,8 +629,8 @@ static int do_scsi_page83_inquiry(struct sysfs_class_device *scsi_dev, int fd,
        return 1;
 }
 
-int do_scsi_page80_inquiry(struct sysfs_class_device *scsi_dev, int fd,
-                          char *serial, int max_len)
+static int do_scsi_page80_inquiry(struct sysfs_class_device *scsi_dev, int fd,
+                                 char *serial, int max_len)
 {
        int retval;
        int ser_ind;