[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#20674: marked as done (hwtools: patch -- many scsidev buffer overrun fixes, etc.)



Your message dated Mon, 26 Apr 1999 00:49:56 +0200
with message-id <19990426004955.A5275@cibalia.gkvk.hr>
and subject line new hwtools 0.4
has caused the attached bug report to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what I'm
talking about this indicates a serious mail system misconfiguration
somewhere.  Please contact me immediately.)

Ian Jackson
(administrator, Debian bugs database)

Received: (at submit) by bugs.debian.org; 4 Apr 1998 21:48:18 +0000
Received: (qmail 7923 invoked from network); 4 Apr 1998 21:48:18 -0000
Received: from mail.cs.utexas.edu (root@128.83.139.10)
  by debian.novare.net with SMTP; 4 Apr 1998 21:48:18 -0000
Received: from nevermore.csres.utexas.edu (dial-73-9.ots.utexas.edu [128.83.254.73])
	by mail.cs.utexas.edu (8.8.5/8.8.5) with ESMTP id PAA16081
	for <submit@bugs.debian.org>; Sat, 4 Apr 1998 15:48:00 -0600 (CST)
Received: from rlb by nevermore.csres.utexas.edu with local (Exim 1.891 #1)
	id 0yLan8-0002sx-00 (Debian); Sat, 4 Apr 1998 15:47:58 -0600
To: submit@bugs.debian.org
Subject: hwtools: patch -- many scsidev buffer overrun fixes, etc.
From: Rob Browning <rlb@cs.utexas.edu>
Date: 04 Apr 1998 15:47:58 -0600
Message-ID: <87zpi1tg1d.fsf@nevermore.csres.utexas.edu>
Lines: 989
X-Mailer: Gnus v5.6.2/Emacs 20.2


Package: hwtools
Version: 0.3-4

I just sent these to Christoph, but I recall him saying something
about being in transition right now, so I wanted to make sure these
patches ended up somplace safe for now.

Christoph Lameter <christoph@lameter.com> writes:

> Definitely.
> 
> On 15 Feb 1998, Rob Browning wrote:
> 
> > 
> > I needed scsidev and friends here, and I found that the current
> > version segfaults on an unstable system.  So I cleaned up the source a
> > bit, fixed a few bugs, and got rid of a bunch of warnings that popped
> > up under -Wall.  It seems to work fine now.
> > 
> > Would you be interested in the patches?

Sorry this took so long, but I've been busy, and I had to migrate my
changes into your new upstream version.  The diffs follow.

I had to modify configure.in in the scsidev directory, but I included
the diffs to the generated configure file, so you don't need to re-run
autoconf unless you just want to.

There are also some stylistic changes here (in debian/rules, etc.)
that you can feel free to ignore if you don't like them.  I had to
change a few important things in debian/rules, though, so be careful
what you ignore.

The biggest change is to scsidev.c.  There were potential buffer
overruns everywhere.  I managed to eliminate many of them completely,
but for a couple I had to just make the buffer *really* large and hope
for the best because in those cases I couldn't find any documentation
for what the potential maximum size was.

Oh, and the patch looks bigger than it really is because I turned on
-Wall, and cleaned up all the resulting errors.  This meant
rearranging the order of the functions so that they'd be defined
before use.

Let me know if you have any questions, and thanks...


diff -ru hwtools-0.3/debian/rules hwtools-0.3.fixed/debian/rules
--- hwtools-0.3/debian/rules	Sat Apr  4 13:45:19 1998
+++ hwtools-0.3.fixed/debian/rules	Sat Apr  4 11:20:16 1998
@@ -15,25 +15,28 @@
 
 package=hwtools
 
+kernel_headers = /usr/src/linux/include
+
 build:
 	$(checkdir)
-	cd irqtune;make kvers sbin
-	cd memtest86;make
-	cd scanport/src;gcc -s -O2 -o scanport scanport.c;gcc -s -O2 -o inb inb.c
-	cd scsiinfo-1.7;make
-	cd scsidev-1.5;./configure prefix=/usr;make
-	cd qic02;make
+	cd irqtune && make kvers sbin
+	cd memtest86 && make
+	cd scanport/src && \
+          gcc -s -O2 -o scanport scanport.c;gcc -s -O2 -o inb inb.c
+	cd scsiinfo-1.7 && make KERNEL_INCLUDES=-I${kernel_headers}
+	cd scsidev-1.5 && ./configure --prefix=/usr && make
+	cd qic02 && make
 	touch build
 
 clean:
 	$(checkdir)
 	-rm -f build
-	-cd memtest86;make clean
-	-cd irqtune;make clean
-	-cd scanport/src;rm scanport inb
-	-cd scsiinfo-1.7;make clean
-	-cd scsidev-1.5;make clean
-	-cd qic02;make clean
+	-cd memtest86 && make clean
+	-cd irqtune && make clean
+	-cd scanport/src && rm scanport inb
+	-cd scsiinfo-1.7 && make clean
+	-cd scsidev-1.5 && make clean
+	-cd qic02 && make clean
 	-rm `find . -name "*~"`
 	-rm -rf debian/tmp debian/files* debian/substvars
 
@@ -56,7 +59,13 @@
 	cd qic*;make install DESTDIR=../debian/tmp
 	cp memtest86/image debian/tmp/usr/lib/hwtools/memtest86.bin
 	cd irqtune;make install DESTDIR=../../debian/tmp
-	cd scsidev-1.5;make install prefix=../debian/tmp/usr DESTDIR=../debian/tmp
+
+	cd scsidev-1.5 && \
+          make install prefix=../debian/tmp/usr DESTDIR=../debian/tmp
+#	scsidev has to be on the root filesystem to do any good at startup
+	install -d debian/tmp/bin
+	mv debian/tmp/usr/bin/scsidev debian/tmp/bin
+
 	install -d debian/tmp/usr/doc/$(package)/scsiinfo
 # Dos executables
 	cp scanport/dos/*.exe debian/tmp/usr/lib/hwtools
diff -ru hwtools-0.3/qic02/Makefile hwtools-0.3.fixed/qic02/Makefile
--- hwtools-0.3/qic02/Makefile	Sat Apr  4 13:45:19 1998
+++ hwtools-0.3.fixed/qic02/Makefile	Sat Apr  4 11:16:19 1998
@@ -29,4 +29,4 @@
 	-rm -f qic02conf
 
 qic02conf: qic02conf.c
-	gcc -O2 -Wall -s -N -o $@ $<
+	gcc -I/usr/src/linux/include -O2 -Wall -s -N -o $@ $<
diff -ru hwtools-0.3/scsidev-1.5/Makefile.in hwtools-0.3.fixed/scsidev-1.5/Makefile.in
--- hwtools-0.3/scsidev-1.5/Makefile.in	Sat Apr  4 13:45:19 1998
+++ hwtools-0.3.fixed/scsidev-1.5/Makefile.in	Sat Apr  4 11:25:02 1998
@@ -27,7 +27,7 @@
 manext = 8
 
 #### End of system configuration section. ####
-CFLAGS=@CFLAGS@ -g # -DDEBUG
+CFLAGS=@CFLAGS@ -Wall -g # -DDEBUG
 
 World: scsidev
 
diff -ru hwtools-0.3/scsidev-1.5/configure hwtools-0.3.fixed/scsidev-1.5/configure
--- hwtools-0.3/scsidev-1.5/configure	Sat Mar 29 09:55:44 1997
+++ hwtools-0.3.fixed/scsidev-1.5/configure	Sat Apr  4 11:14:21 1998
@@ -825,7 +825,7 @@
 fi
 echo "$ac_t""$CPP" 1>&6
 
-for ac_hdr in linux/scsi.h scsi/scsi.h /usr/src/linux/drivers/scsi/scsi.h
+for ac_hdr in linux/scsi.h scsi/scsi.h /usr/src/linux/drivers/scsi/scsi.h /usr/src/linux/include/scsi/scsi.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
diff -ru hwtools-0.3/scsidev-1.5/configure.in hwtools-0.3.fixed/scsidev-1.5/configure.in
--- hwtools-0.3/scsidev-1.5/configure.in	Sat Mar 29 09:47:03 1997
+++ hwtools-0.3.fixed/scsidev-1.5/configure.in	Sat Apr  4 11:14:12 1998
@@ -4,6 +4,6 @@
 AC_CONFIG_HEADER(config.h)
 AC_PROG_CC
 AC_CONST
-AC_CHECK_HEADERS(linux/scsi.h scsi/scsi.h /usr/src/linux/drivers/scsi/scsi.h)
+AC_CHECK_HEADERS(linux/scsi.h scsi/scsi.h /usr/src/linux/drivers/scsi/scsi.h /usr/src/linux/include/scsi/scsi.h)
 AC_PROG_INSTALL
 AC_OUTPUT(Makefile)
diff -ru hwtools-0.3/scsidev-1.5/scsidev.c hwtools-0.3.fixed/scsidev-1.5/scsidev.c
--- hwtools-0.3/scsidev-1.5/scsidev.c	Sat Apr  4 13:45:19 1998
+++ hwtools-0.3.fixed/scsidev-1.5/scsidev.c	Sat Apr  4 13:52:30 1998
@@ -1,5 +1,4 @@
 #include <stdio.h>
-#include <sys/vfs.h>
 #include <sys/sysmacros.h>
 #include <fcntl.h>
 #include <linux/major.h>
@@ -8,6 +7,13 @@
 #include <errno.h>
 #include <strings.h>
 
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+
 static char rcsid[] ="$Id: scsidev.c,v 1.2 1997/03/29 15:45:50 eric Exp $";
 
 #include "config.h"
@@ -69,6 +75,7 @@
  * Used to maintain a list of the nodes that we have seen
  * which we know to be OK and active.
  */
+void
 register_dev(char * name, int major, int minor, int hnum, 
 	     int hid, int chan, int id, 
 	     int lun, int part, struct regnames * alias)
@@ -77,6 +84,7 @@
   char * pnt;
 
   rpnt = (struct regnames *) malloc(sizeof(struct regnames));
+  assert(rpnt != 0);
   pnt = strrchr(name, '/');
   rpnt->name = strdup(pnt + 1);
   rpnt->major = major;
@@ -105,8 +113,6 @@
  */
 void sanitize_sdev()
 {
-  struct dirent * de;
-  char filename[60];
   DIR * sdir;
   struct regnames * rpnt;
   struct stat statbuf;
@@ -118,9 +124,9 @@
    * changed.
    */
   sdir = opendir("/dev/scsi");
-  while(1==1)
+  while(1)
     {
-      de = readdir(sdir);
+      struct dirent * de = readdir(sdir);
       if(de == NULL) break;
       /*
        * OK, we have the name.  See whether this is something
@@ -135,6 +141,9 @@
 	}
       if( rpnt == NULL )
 	{
+          char *filename = malloc((strlen("/dev/scsi/") +
+                                   strlen(de->d_name) + 1) * sizeof(char));
+          assert(filename != NULL);
 	  strcpy(filename, "/dev/scsi/");
 	  strcat(filename, de->d_name);
 	  status = stat(filename, &statbuf);
@@ -154,6 +163,7 @@
 	      chown(filename, statbuf.st_uid, statbuf.st_gid);
 
 	    }
+          free(filename);
 	}
     }
   closedir(sdir);
@@ -163,8 +173,6 @@
 
 void flush_sdev()
 {
-  struct dirent * de;
-  char filename[60];
   DIR * sdir;
   /*
    * Next, delete all of the existing entries in the /dev/scsi directory.
@@ -172,18 +180,23 @@
    * changed.
    */
   sdir = opendir("/dev/scsi");
-  while(1==1)
+  while(1)
     {
-      de = readdir(sdir);
+      char *filename = NULL;
+      struct dirent *de = readdir(sdir);
       if(de == NULL) break;
       if(de->d_name[0] != 's' && de->d_name[0] != 'r') continue;
+      filename = malloc((strlen("/dev/scsi/") + strlen(de->d_name) + 1) *
+                        sizeof(char));
+      assert(filename != NULL);
       strcpy(filename, "/dev/scsi/");
       strcat(filename, de->d_name);
       unlink(filename);
+      free(filename);
+      filename = NULL;
     }
   closedir(sdir);
-  printf("Flushed old /dev/scsi entries...\n", de->d_name);
-
+  printf("Flushed old /dev/scsi entries...\n");
 }
 
 /*
@@ -260,18 +273,19 @@
 {
   int chan;
   int fd;
-  char hostname[60];
+  char hostname[512]; /* Make it huge, it's just stack space...
+                         If anyone knows an upper limit on the return from
+                         SCSI_IOCTL_PROBE_HOST, then use that.  Until then
+                         this is still potentially dangerous. */
   int newmode;
-  int recreate;
   int h_id;
   int id[2];
   int lun;
   int minor = 0;
-  int uid, gid;
   struct stat statbuf;
   int scsi_id;
-  char scsidev[64];
-  char linkto[64];
+  char scsidev[MAXPATHLEN]; /* This isn't ideal, but it'll do for now. */
+  char linkto[MAXPATHLEN];  /* This isn't ideal, but it'll do for now. */
   int status;
 
   status = stat("/tmp/testdev", &statbuf);
@@ -284,7 +298,7 @@
   if(status == -1)
       return;
 
-  while(1==1)
+  while(1)
     {
       status = mknod("/tmp/testdev",0600 | devtype ,
 		     makedev(major,minor));
@@ -477,139 +491,34 @@
   unlink("/tmp/testdev");
 }
 
-
-/*
- * Build a /dev/scsi tree that contains the correct device entries.
- */
-
-usage()
-{
-  fprintf(stderr,"scsidev v1.3\n");
-  fprintf(stderr,"Usage: scsidev [-f] [-l] [-v] [-m mode]\n");
-}
-
-main(int argc, char * argv[])
-{
-  char c;
-  int force = 0;
-  int show_serial = 0;
-  struct stat statbuf;
-  struct regnames * rpnt;
-  int status;
-
-  status = stat("/dev/scsi", &statbuf);
-  if(    status == -1
-      || !S_ISDIR(statbuf.st_mode))
-    {
-      fprintf(stderr,"/dev/scsi either does not exist, or is not a directory\n");
-      exit(0);
-    }
-  while ((c = getopt(argc, argv, "flvsm:")) != EOF)
-    {
-      switch (c)
-	{
-	case 'f':
-	  force = 1;
-	  break;
-	case 'm':
-	  filemode = strtoul(optarg, 0, 0);
-	  break;
-	case 'l':
-	  use_symlink = 1;
-	  break;
-	case 's':
-	  show_serial = 1;
-	  break;
-	case 'v':
-	  verbose++;
-	  break;
-	default:
-	  usage();
-	  exit(1);
-	  break;
-	}
-    }
-
-  if( force ) flush_sdev();
-
-#ifdef DEBUG
-  register_dev("/dev/scsi/sdh4-334c0i0l0",   8,  0, 6, 0x334, 0, 0, 0, -1, NULL);
-  register_dev("/dev/scsi/sdh4-334c0i0l0p1", 8,  1, 6, 0x334, 0, 0, 0,  1, NULL);
-  register_dev("/dev/scsi/sdh4-334c0i0l0p2",8,  2,6, 0x334, 0, 0, 0,  2, NULL);
-  register_dev("/dev/scsi/sdh4-334c0i0l0p3",8,  3,6, 0x334, 0, 0, 0,  3, NULL);
-  register_dev("/dev/scsi/sgh4-334c0i0l0", 21,  0,6, 0x334, 0, 0, 0, -1, NULL);
-  register_dev("/dev/scsi/sgh4-334c0i2l0", 21,  1,6, 0x334, 0, 2, 0, -1, NULL);
-  register_dev("/dev/scsi/sgh4-334c0i5l0", 21,  2,6, 0x334, 0, 5, 0, -1, NULL);
-  register_dev("/dev/scsi/srh4-334c0i2l0", 11,  0,6, 0x334, 0, 2, 0, -1, NULL);
-  register_dev("/dev/scsi/sth4-334c0i5l0",  9,  0,6, 0x334, 0, 5, 0, -1, NULL);
-  register_dev("/dev/scsi/rsth4-334c0i5l0", 9,128,6, 0x334, 0, 5, 0, -1, NULL);
-#else
-  build_sdev(SCSI_DISK_MAJOR,    O_RDONLY, S_IFBLK, 'd');
-  build_sdev(SCSI_CDROM_MAJOR,   O_RDONLY, S_IFBLK, 'r');
-  build_sdev(SCSI_TAPE_MAJOR,    O_RDONLY, S_IFCHR, 't');
-  build_sdev(SCSI_GENERIC_MAJOR, O_RDWR,   S_IFCHR, 'g');
-#endif
-
-  if( show_serial )
-    {
-      for (rpnt = reglist; rpnt; rpnt = rpnt->next)
-	{
-	  if( rpnt->partition != -1 ) continue;
-	  if( rpnt->major == SCSI_TAPE_MAJOR
-	      && (rpnt->minor & 0x80) != 0 ) continue;
-
-	  if( rpnt->serial == NULL )  get_serial_number(rpnt);
-	  if( rpnt->serial == no_serial )
-	    printf("Device  %s has no serial number\n", rpnt->name);
-	  else
-	    printf("Serial number of %s: \"%s\"\n", rpnt->name, rpnt->serial);
-	}
-    }
-  /*
-   * Now, read the configuration file and see whether there
-   * are any special device names we want to try and match.
-   */
-  build_special();
-
-  if( !force )
-    {
-      sanitize_sdev();
-    }
-
-}
-
-char * get_string (char * pnt, char **result)
+char *
+get_string (char * pnt, char **result)
 {
   char quote = 0;
 
-  while (*pnt == ' ' || *pnt == '\t') pnt++;
-
-  if( *pnt == '"' ) 
-    {
-      quote = *pnt++;
-    }
+  while (*pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
 
-  if( *pnt == '\'' ) 
-    {
-      quote = *pnt++;
-    }
-
-  *result = pnt;
-
-  if( quote != 0 )
-    {
-      while( *pnt != quote ) pnt++;
-      *pnt++ = 0;
-    }
-  else
-    {
-      while( *pnt != ',' && *pnt != ' ' && *pnt != '\t' ) pnt++;
-      *pnt++ = 0;
-    }
-
-  while (*pnt == ' ' || *pnt == '\t') pnt++;
-  if(*pnt == ',') pnt++;
-  while (*pnt == ' ' || *pnt == '\t') pnt++;
+  if(*pnt) {
+    if( *pnt == '"' ) quote = *pnt++;
+    if( *pnt == '\'' ) quote = *pnt++;
+    
+    *result = pnt;
+    
+    if( quote != 0 )
+      {
+        while( *pnt && *pnt != quote ) pnt++;
+        *pnt++ = 0;
+      }
+    else
+      {
+        while( *pnt && *pnt != ',' && *pnt != ' ' && *pnt != '\t' ) pnt++;
+        *pnt++ = 0;
+      }
+    
+    while (*pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
+    if(*pnt == ',') pnt++;
+    while (*pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
+  }
   return pnt;
 }
 
@@ -666,6 +575,175 @@
 }
 
 /*
+ * Note that this does the same thing as an inquiry, but
+ * it also grabs the serial number too.  Some devices complain
+ * if you ask for the serial number, so we have a version with and
+ * without.
+ */
+void
+get_serial_number(struct regnames * rpnt)
+{
+#ifdef DEBUG
+  /*
+   * Fill in some entries, just so I can test this on a non-scsi system.
+   */
+  if(rpnt->id == 0 )  rpnt->serial = strdup("DX908FK");
+  else  rpnt->serial = no_serial;
+#else
+  int status, i;
+  unsigned char *cmd;
+  unsigned char * pagestart;
+  unsigned char buffer[2048]; /* Doubled from 1024.  Just trying to be sure. */
+  char path[MAXPATHLEN]; /* This isn't ideal, but it'll do for now. */
+  int infile;
+  struct regnames * rpnt1;
+
+  memset(buffer, 0, sizeof(buffer));
+  
+  *( (int *)  buffer )		= 0;	/* length of input data */
+
+  /* length of buffer = buffer size - 2 (for these length bytes)
+                                    - 6 (for the cmd length) */
+  *(((int *) buffer) + 1) = sizeof(buffer)/sizeof(*buffer) - (2 + 6);
+
+  cmd = (char *) ( ((int *) buffer) + 2 );
+  
+  cmd[0] = 0x12;			/* INQUIRY */
+  cmd[1] = 0x01;			/* lun=0, evpd=1 */
+  cmd[2] = 0x80;			/* page code = 0x80, serial number */
+  cmd[3] = 0x00;			/* (reserved) */
+  cmd[4] = 0xff;			/* allocation length */
+  cmd[5] = 0x00;			/* control */
+
+  strcpy(path, "/dev/scsi/");
+  strcat(path, rpnt->name);
+  infile = open(path, O_RDONLY);
+  if( infile == -1 ) return;
+  status = ioctl( infile, 1 /* SCSI_IOCTL_SEND_COMMAND */, buffer );
+  close(infile);
+
+  if(status) rpnt->serial = no_serial;
+
+  pagestart = buffer + 8;
+
+  rpnt->serial = (char *) malloc(pagestart[3] + 1);
+  memcpy(rpnt->serial, pagestart+4, pagestart[3]);
+
+  /*
+   * NULL terminate and trim trailing whitespace.
+   */
+  rpnt->serial[pagestart[3]] = '\0';
+  for(i = pagestart[3] - 1; i >= 0 && rpnt->serial[i] == ' '; i-- )
+      rpnt->serial[i] = '\0';
+
+  /*
+   * Copy information to identical nodes to avoid excessive probing.
+   */
+  for( rpnt1 = reglist; rpnt1; rpnt1 = rpnt1->next )
+    {
+      if( rpnt1 == rpnt ) continue;
+      if( rpnt1->alias != NULL ) continue;
+      if( rpnt1->id != rpnt->id ) continue;
+      if( rpnt1->chan != rpnt->chan ) continue;
+      if( rpnt1->hostnum != rpnt->hostnum ) continue;
+      if( rpnt1->hostid != rpnt->hostid ) continue;
+      if( rpnt1->serial == NULL ) rpnt1->serial = rpnt->serial;
+    }
+#endif
+}
+
+void
+inquire(struct regnames * rpnt)
+{
+#ifdef DEBUG
+  /*
+   * Fill in some entries just so that I can test this.
+   */
+  if(rpnt->id == 0 ) {
+    rpnt->manufacturer = strdup("CONNER");
+    rpnt->model=strdup("CFP4207S");
+  } else if(rpnt->id == 2 ) {
+    rpnt->manufacturer = strdup("HP");
+    rpnt->model=strdup("C4324/C4325");
+  } else if(rpnt->id == 5 ) {
+    rpnt->manufacturer = strdup("WANGTEK");
+    rpnt->model=strdup("5150ES");
+  }
+#else
+  int status, i;
+  char c;
+  unsigned char *cmd;
+  unsigned char * pagestart;
+  unsigned char buffer[2048]; /* Doubled from 1024.  Just trying to be sure. */
+  char path[MAXPATHLEN]; /* This isn't ideal, but it'll do for now. */
+  struct regnames * rpnt1;
+  int infile;
+
+  memset(buffer, 0, sizeof(buffer));
+  
+  *( (int *)  buffer )		= 0;	/* length of input data */
+
+  /* length of buffer = buffer size - 2 (for these length bytes)
+                                    - 6 (for the cmd length) */
+  *(((int *) buffer) + 1) = sizeof(buffer)/sizeof(*buffer) - (2 + 6);
+
+  cmd = (char *) ( ((int *) buffer) + 2 );
+  
+  cmd[0] = 0x12;			/* INQUIRY */
+  cmd[1] = 0x00;			/* lun=0, evpd=0 */
+  cmd[2] = 0x00;			/* page code = 0 */
+  cmd[3] = 0x00;			/* (reserved) */
+  cmd[4] = 0xff;			/* allocation length */
+  cmd[5] = 0x00;			/* control */
+
+  strcpy(path, "/dev/scsi/");
+  strcat(path, rpnt->name);
+  infile = open(path, O_RDONLY);
+  if( infile == -1 ) return;
+
+  status = ioctl( infile, 1 /* SCSI_IOCTL_SEND_COMMAND */, buffer );
+
+  close(infile);
+
+  if(status) return;
+  
+  pagestart = buffer + 8;
+  
+  for( i = 15; i >= 8 && pagestart[i] == ' '; i-- ) 
+    pagestart[i] = 0;
+  
+  c = pagestart[16];
+  pagestart[16] = 0;
+  rpnt->manufacturer = strdup(pagestart+8);
+  pagestart[16] = c;
+
+  for( i = 31; i >= 16 && pagestart[i] == ' '; i-- ) 
+    pagestart[i] = 0;
+  c = pagestart[32];
+  pagestart[32] = 0;
+  rpnt->model = strdup(pagestart+16);
+  pagestart[32] = c;
+
+  /*
+   * Copy information to identical nodes to avoid excessive probing.
+   */
+  for( rpnt1 = reglist; rpnt1; rpnt1 = rpnt1->next )
+    {
+      if( rpnt1 == rpnt ) continue;
+      if( rpnt1->alias != NULL ) continue;
+      if( rpnt1->id != rpnt->id ) continue;
+      if( rpnt1->chan != rpnt->chan ) continue;
+      if( rpnt1->hostnum != rpnt->hostnum ) continue;
+      if( rpnt1->hostid != rpnt->hostid ) continue;
+      if( rpnt1->manufacturer == NULL ) 
+	rpnt1->manufacturer = rpnt->manufacturer;
+      if( rpnt1->model == NULL ) rpnt1->model = rpnt->model;
+    }
+  return;
+#endif
+}
+
+/*
  * The configuration file is designed to be something that can match
  * any number of fields.  Thus we need to be able to specify a large
  * number of different things in the hope that we can uniquely match
@@ -683,14 +761,16 @@
  * NAME="string"
  * DEVTYPE="disk", "tape", "generic", or "cdrom".
  */
+void
 build_special()
 {
   FILE *	configfile;
-  char buffer[256];
+  char * buffer = NULL;
+  char * buffer_length = 0;
   char * pnt;
   char * pnt1;
   struct regnames * rpnt, *match;
-  char scsidev[64];
+  char scsidev[MAXPATHLEN]; /* This isn't ideal, but it'll do for now. */
   int type;
 
   int lun, chan, id, part, hostid, hostnum;
@@ -704,9 +784,9 @@
   configfile = fopen("/etc/scsi.alias", "r");
 #endif
   line = 0;
-  while(1==1)
+  while(1)
     {
-      fgets(buffer, sizeof(buffer), configfile);
+      if(getline(&buffer, &buffer_length, configfile) == -1) break;
       line++;
       if( feof(configfile)) break;
 
@@ -737,7 +817,7 @@
       if( *pnt == '\0' ) continue;
       if( *pnt == '#' ) continue;
 
-      while(1==1)
+      while(1)
 	{
 	  pnt1 = pnt;
 	  while (*pnt1 != '=' && *pnt1 != '\0') pnt1++;
@@ -790,7 +870,7 @@
 	    }
 	  else
 	    {
-	      fprintf(stderr,"Unrecognized specifier \"%s\" on line\n", pnt,
+	      fprintf(stderr,"Unrecognized specifier \"%s\" on line %d\n", pnt,
 		      line);
 	      break;
 	    }
@@ -832,6 +912,7 @@
       match = NULL;
       for (rpnt = reglist; rpnt; rpnt = rpnt->next)
 	{
+
 	  /*
 	   * Check the integers first.  Some of the strings we have to
 	   * request, and we want to avoid this if possible.
@@ -966,168 +1047,112 @@
 	  fprintf(stderr,"Unable to match device for line %d\n", line);
 	}
     }
-
   fclose(configfile);
+  if(buffer) free(buffer);
 }
 
-/*
- * Note that this does the same thing as an inquiry, but
- * it also grabs the serial number too.  Some devices complain
- * if you ask for the serial number, so we have a version with and
- * without.
- */
-int get_serial_number(struct regnames * rpnt)
-{
-#ifdef DEBUG
-  /*
-   * Fill in some entries, just so I can test this on a non-scsi system.
-   */
-  if(rpnt->id == 0 )  rpnt->serial = strdup("DX908FK");
-  else  rpnt->serial = no_serial;
-#else
-  int status, i;
-  unsigned char *cmd;
-  unsigned char * pagestart;
-  unsigned char buffer[1024];
-  char path[64];
-  int infile;
-  struct regnames * rpnt1;
-
-  memset(buffer, 0, sizeof(buffer));
-  
-  *( (int *)  buffer )		= 0;	/* length of input data */
-  *( ((int *) buffer) + 1 )	= 1024;	/* length of output buffer */
-
-  cmd = (char *) ( ((int *) buffer) + 2 );
-  
-  cmd[0] = 0x12;			/* INQUIRY */
-  cmd[1] = 0x01;			/* lun=0, evpd=1 */
-  cmd[2] = 0x80;			/* page code = 0x80, serial number */
-  cmd[3] = 0x00;			/* (reserved) */
-  cmd[4] = 0xff;			/* allocation length */
-  cmd[5] = 0x00;			/* control */
-
-  strcpy(path, "/dev/scsi/");
-  strcat(path, rpnt->name);
-  infile = open(path, O_RDONLY);
-  if( infile == -1 ) return;
-  status = ioctl( infile, 1 /* SCSI_IOCTL_SEND_COMMAND */, buffer );
-  close(infile);
-
-  if(status) rpnt->serial = no_serial;
-
-  pagestart = buffer + 8;
 
-  rpnt->serial = (char *) malloc(pagestart[3] + 1);
-  memcpy(rpnt->serial, pagestart+4, pagestart[3]);
 
-  /*
-   * NULL terminate and trim trailing whitespace.
-   */
-  rpnt->serial[pagestart[3]] = '\0';
-  for(i = pagestart[3] - 1; i >= 0 && rpnt->serial[i] == ' '; i-- )
-      rpnt->serial[i] = '\0';
+/*
+ * Build a /dev/scsi tree that contains the correct device entries.
+ */
 
-  /*
-   * Copy information to identical nodes to avoid excessive probing.
-   */
-  for( rpnt1 = reglist; rpnt1; rpnt1 = rpnt1->next )
-    {
-      if( rpnt1 == rpnt ) continue;
-      if( rpnt1->alias != NULL ) continue;
-      if( rpnt1->id != rpnt->id ) continue;
-      if( rpnt1->chan != rpnt->chan ) continue;
-      if( rpnt1->hostnum != rpnt->hostnum ) continue;
-      if( rpnt1->hostid != rpnt->hostid ) continue;
-      if( rpnt1->serial == NULL ) rpnt1->serial = rpnt->serial;
-    }
-#endif
+void
+usage()
+{
+  fprintf(stderr,"scsidev v1.5\n");
+  fprintf(stderr,"Usage: scsidev [-f] [-l] [-v] [-m mode]\n");
 }
 
-int inquire(struct regnames * rpnt)
+int
+main(int argc, char * argv[])
 {
-#ifdef DEBUG
-  /*
-   * Fill in some entries just so that I can test this.
-   */
-  if(rpnt->id == 0 ) {
-    rpnt->manufacturer = strdup("CONNER");
-    rpnt->model=strdup("CFP4207S");
-  } else if(rpnt->id == 2 ) {
-    rpnt->manufacturer = strdup("HP");
-    rpnt->model=strdup("C4324/C4325");
-  } else if(rpnt->id == 5 ) {
-    rpnt->manufacturer = strdup("WANGTEK");
-    rpnt->model=strdup("5150ES");
-  }
-#else
-  int status, i;
   char c;
-  unsigned char *cmd;
-  unsigned char * pagestart;
-  unsigned char tmp;
-  unsigned char buffer[1024];
-  char path[64];
-  struct regnames * rpnt1;
-  int infile;
-
-  memset(buffer, 0, sizeof(buffer));
-  
-  *( (int *)  buffer )		= 0;	/* length of input data */
-  *( ((int *) buffer) + 1 )	= 1024;	/* length of output buffer */
-
-  cmd = (char *) ( ((int *) buffer) + 2 );
-  
-  cmd[0] = 0x12;			/* INQUIRY */
-  cmd[1] = 0x00;			/* lun=0, evpd=0 */
-  cmd[2] = 0x00;			/* page code = 0 */
-  cmd[3] = 0x00;			/* (reserved) */
-  cmd[4] = 0xff;			/* allocation length */
-  cmd[5] = 0x00;			/* control */
-
-  strcpy(path, "/dev/scsi/");
-  strcat(path, rpnt->name);
-  infile = open(path, O_RDONLY);
-  if( infile == -1 ) return;
-
-  status = ioctl( infile, 1 /* SCSI_IOCTL_SEND_COMMAND */, buffer );
-
-  close(infile);
-
-  if(status) return;
+  int force = 0;
+  int show_serial = 0;
+  struct stat statbuf;
+  struct regnames * rpnt;
+  int status;
 
-  pagestart = buffer + 8;
+  status = stat("/dev/scsi", &statbuf);
+  if(    status == -1
+      || !S_ISDIR(statbuf.st_mode))
+    {
+      fprintf(stderr,"/dev/scsi either does not exist, or is not a directory\n");
+      exit(0);
+    }
+  while ((c = getopt(argc, argv, "flvsm:")) != EOF)
+    {
+      switch (c)
+	{
+	case 'f':
+	  force = 1;
+	  break;
+	case 'm':
+	  filemode = strtoul(optarg, 0, 0);
+	  break;
+	case 'l':
+	  use_symlink = 1;
+	  break;
+	case 's':
+	  show_serial = 1;
+	  break;
+	case 'v':
+	  verbose++;
+	  break;
+	default:
+	  usage();
+	  exit(1);
+	  break;
+	}
+    }
 
-  for( i = 15; i >= 8 && pagestart[i] == ' '; i-- ) 
-    pagestart[i] = 0;
+  if( force ) flush_sdev();
 
-  c = pagestart[16];
-  pagestart[16] = 0;
-  rpnt->manufacturer = strdup(pagestart+8);
-  pagestart[16] = c;
+#ifdef DEBUG
+  register_dev("/dev/scsi/sdh4-334c0i0l0",   8,  0, 6, 0x334, 0, 0, 0, -1, NULL);
+  register_dev("/dev/scsi/sdh4-334c0i0l0p1", 8,  1, 6, 0x334, 0, 0, 0,  1, NULL);
+  register_dev("/dev/scsi/sdh4-334c0i0l0p2",8,  2,6, 0x334, 0, 0, 0,  2, NULL);
+  register_dev("/dev/scsi/sdh4-334c0i0l0p3",8,  3,6, 0x334, 0, 0, 0,  3, NULL);
+  register_dev("/dev/scsi/sgh4-334c0i0l0", 21,  0,6, 0x334, 0, 0, 0, -1, NULL);
+  register_dev("/dev/scsi/sgh4-334c0i2l0", 21,  1,6, 0x334, 0, 2, 0, -1, NULL);
+  register_dev("/dev/scsi/sgh4-334c0i5l0", 21,  2,6, 0x334, 0, 5, 0, -1, NULL);
+  register_dev("/dev/scsi/srh4-334c0i2l0", 11,  0,6, 0x334, 0, 2, 0, -1, NULL);
+  register_dev("/dev/scsi/sth4-334c0i5l0",  9,  0,6, 0x334, 0, 5, 0, -1, NULL);
+  register_dev("/dev/scsi/rsth4-334c0i5l0", 9,128,6, 0x334, 0, 5, 0, -1, NULL);
+#else
+  build_sdev(SCSI_DISK_MAJOR,    O_RDONLY, S_IFBLK, 'd');
+  build_sdev(SCSI_CDROM_MAJOR,   O_RDONLY, S_IFBLK, 'r');
+  build_sdev(SCSI_TAPE_MAJOR,    O_RDONLY, S_IFCHR, 't');
+  build_sdev(SCSI_GENERIC_MAJOR, O_RDWR,   S_IFCHR, 'g');
+#endif
 
-  for( i = 31; i >= 16 && pagestart[i] == ' '; i-- ) 
-    pagestart[i] = 0;
-  c = pagestart[32];
-  pagestart[32] = 0;
-  rpnt->model = strdup(pagestart+16);
-  pagestart[32] = c;
+  if( show_serial )
+    {
+      for (rpnt = reglist; rpnt; rpnt = rpnt->next)
+	{
+	  if( rpnt->partition != -1 ) continue;
+	  if( rpnt->major == SCSI_TAPE_MAJOR
+	      && (rpnt->minor & 0x80) != 0 ) continue;
 
+	  if( rpnt->serial == NULL )  get_serial_number(rpnt);
+	  if( rpnt->serial == no_serial )
+	    printf("Device  %s has no serial number\n", rpnt->name);
+	  else
+	    printf("Serial number of %s: \"%s\"\n", rpnt->name, rpnt->serial);
+	}
+    }
   /*
-   * Copy information to identical nodes to avoid excessive probing.
+   * Now, read the configuration file and see whether there
+   * are any special device names we want to try and match.
    */
-  for( rpnt1 = reglist; rpnt1; rpnt1 = rpnt1->next )
+  build_special();
+
+  if( !force )
     {
-      if( rpnt1 == rpnt ) continue;
-      if( rpnt1->alias != NULL ) continue;
-      if( rpnt1->id != rpnt->id ) continue;
-      if( rpnt1->chan != rpnt->chan ) continue;
-      if( rpnt1->hostnum != rpnt->hostnum ) continue;
-      if( rpnt1->hostid != rpnt->hostid ) continue;
-      if( rpnt1->manufacturer == NULL ) 
-	rpnt1->manufacturer = rpnt->manufacturer;
-      if( rpnt1->model == NULL ) rpnt1->model = rpnt->model;
+      sanitize_sdev();
     }
-  return;
-#endif
+
+  return 0;
 }
+
diff -ru hwtools-0.3/scsiinfo-1.7/Makefile hwtools-0.3.fixed/scsiinfo-1.7/Makefile
--- hwtools-0.3/scsiinfo-1.7/Makefile	Sat Apr  4 13:45:19 1998
+++ hwtools-0.3.fixed/scsiinfo-1.7/Makefile	Sat Apr  4 11:09:13 1998
@@ -1,4 +1,4 @@
-CFLAGS=-O2 -fomit-frame-pointer -Wall -fno-strength-reduce -D_GNU_SOURCE
+CFLAGS=${KERNEL_INCLUDES} -O2 -fomit-frame-pointer -Wall -fno-strength-reduce -D_GNU_SOURCE
 #CFLAGS=-g -Wall -fno-strength-reduce
 LDFLAGS=-s
 
diff -ru hwtools-0.3/scsiinfo-1.7/scsiformat.c hwtools-0.3.fixed/scsiinfo-1.7/scsiformat.c
--- hwtools-0.3/scsiinfo-1.7/scsiformat.c	Sat Apr  4 13:45:19 1998
+++ hwtools-0.3.fixed/scsiinfo-1.7/scsiformat.c	Sat Apr  4 12:25:46 1998
@@ -736,7 +736,7 @@
 	if (!par_deflistform) {
 	    fprintf(fh, "\nUser supplied defect logical blocks:\n");
 	    for (i = off = 0; off < par_defectlen; i++, off += 4) {
-		fprintf(fh, " %9lu", ntohl(par_defects[i]));
+		fprintf(fh, " %9u", ntohl(par_defects[i]));
 		if ((i & 7) == 7) {
 		    fprintf(fh, "\n");
 		    flag = 1;
@@ -747,7 +747,7 @@
 	    fprintf(fh, "\nUser supplied defects in Cylinder:Head:%s format:\n",
 	     par_deflistform == 5 ? "PhysicalSector" : "BytesFromIndex");
 	    for (i = off = 0; off < par_defectlen; i += 2, off += 8) {
-		sprintf(buffer, " %lu:%lu:%ld", ntohl(par_defects[i]) >> 8,
+		sprintf(buffer, " %u:%u:%ld", ntohl(par_defects[i]) >> 8,
 			ntohl(par_defects[i]) & 255, (long) ntohl(par_defects[i + 1]));
 		fprintf(fh, "%20s", buffer);
 		if ((i & 3) == 3) {

-- 
Rob Browning <rlb@cs.utexas.edu>
PGP fingerprint = E8 0E 0D 04 F5 21 A0 94  53 2B 97 F5 D6 4E 39 30


Reply to: