Index: VERSION
===================================================================
RCS file: /home/cvsroot/scsidev/VERSION,v
retrieving revision 1.8.2.1
retrieving revision 1.8.2.2
diff -u -r1.8.2.1 -r1.8.2.2
--- VERSION	2002/06/18 13:02:56	1.8.2.1
+++ VERSION	2002/07/29 01:12:16	1.8.2.2
@@ -1 +1 @@
-2.23
+2.24
Index: scsidev.c
===================================================================
RCS file: /home/cvsroot/scsidev/scsidev.c,v
retrieving revision 1.28.2.7
retrieving revision 1.28.2.9
diff -u -r1.28.2.7 -r1.28.2.9
--- scsidev.c	2002/07/27 00:16:10	1.28.2.7
+++ scsidev.c	2002/07/29 08:28:36	1.28.2.9
@@ -70,9 +70,16 @@
  *    - Fix hex number parser
  *  -> 2.23
  * 
- *  * 2002/07/30: Kurt Garloff <garloff@suse.de>
- *    - Support for /proc/scsi/scsi extensions
+ *  * 2002/07/28: Kurt Garloff <garloff@suse.de>
  *    - More sane way of storing permissions
+ *    - Agnostic of major numbers
+ *    - Support many SDs (only up to 255 that is)
+ *    - Support for SCSI changers
+ *  -> 2.24
+ *
+ *  * 2002/07/29: Kurt Garloff <garloff@suse.de>
+ *    - Support for /proc/scsi/scsi extensions
+ *    - Support for really large no of disks
  *  -> 2.25
  * 
  */
@@ -93,7 +100,7 @@
 #include <scsi/scsi_ioctl.h>
 
 
-static char rcsid[] ="$Id: scsidev.c,v 1.28.2.7 2002/07/27 00:16:10 garloff Exp $";
+static char rcsid[] ="$Id: scsidev.c,v 1.28.2.9 2002/07/29 08:28:36 garloff Exp $";
 static char *versid = "scsidev " VERSION " 2000/01/17";
 static char *copyright = "Copyright: GNU GPL  (see file COPYING)\n" \
 " (w)  1994--1997 Eric Youngdale <eric@andante.org>\n"\
@@ -135,7 +142,10 @@
 #define DEVSCSI "/dev/scsi"
 #define TESTDEV DEVSCSI "/testdev"
 #define PROCSCSI "/proc/scsi/scsi"
+#define SHADOW ".shadow"
 
+enum devtype_t { NONE=0, SG, SD, SR, ST, OSST, SCH, };
+
 /*
  * This program builds entries in /dev/scsi that have names that are tied
  * to the actual device number and lun.   This is pretty solid as long as
@@ -160,6 +170,7 @@
     char * rev;
     char * serial;
     unsigned long long wwid;
+    enum devtype_t devtp;
     char inq_devtp;
     char rmvbl;
     char unsafe;
@@ -197,6 +208,43 @@
 				 memcmp (spnt->model, "USB", 3) ) ) )
 
 
+enum devtype_t inq_devtp_to_devtp (const char inq_devtp, const sname *spnt)
+{
+	switch (inq_devtp) {
+	    case TYPE_DISK:
+	    case TYPE_MOD:
+		return SD;
+		
+	    case TYPE_TAPE:
+		if (spnt && OSST_SUPPORTS(spnt)) 
+			return OSST;
+		else
+			return ST;
+		
+	    case TYPE_ROM:
+	    case TYPE_WORM:
+		return SR;
+		
+	    case TYPE_MEDIUM_CHANGER:
+		return SCH;
+		
+	    default:
+		return SG;
+	}
+}
+
+inline char isblk (enum devtype_t devtp)
+{
+	switch (devtp) {
+	    case SD:
+	    case SR:
+		return 1;
+	    default:
+		return 0;
+	}
+}
+
+
 /*
  * Used to maintain a list of the nodes that we have seen
  * which we know to be OK and active.
@@ -205,15 +253,15 @@
 void dumplist ()
 {
     sname * pnt;
-    for (pnt = reglist; pnt; pnt = pnt->next) 
-    {
+    for (pnt = reglist; pnt; pnt = pnt->next) {
 	printf ("%s: %s %s %s (%s) %Lx\n", pnt->name,
 		pnt->manufacturer, pnt->model, pnt->rev, pnt->serial,
 		pnt->wwid);
 	printf ("  on %s (%d-%x): c%di%dl%d", pnt->hostname,
 		pnt->hostnum, pnt->hostid, pnt->chan, pnt->id, pnt->lun);
-	if (pnt->partition != -1) printf ("p%d", pnt->partition);
-	printf (" %c %x-%x\n", (SCSI_BLK_MAJOR(pnt->major)? 'b': 'c'),
+	if (pnt->partition != -1) 
+	    printf ("p%d", pnt->partition);
+	printf (" %c %x-%x\n", (isblk(pnt->devtp)? 'b': 'c'),
 		pnt->major, pnt->minor);
     }
 }
@@ -242,6 +290,7 @@
     // Compare INQUIRY DATA
     if (sp1->inq_devtp != sp2->inq_devtp ||
 	sp1->rmvbl != sp2->rmvbl) return 5;
+    // FIXME: Don't compare devtp??
     if (strcmp (sp1->manufacturer, sp2->manufacturer)) return 6;
     if (strcmp (sp1->model, sp2->model)) return 7;
     if (strcmp (sp1->rev, sp2->rev)) return 8;
@@ -286,18 +335,19 @@
 /*
  * We need to "fix" any device nodes that are currently not used because
  * it is a sercurity risk to leave these lying about.  These are fixed
- * by setting the minor number to 255.  If these become active again,
+ * by storing a shadow file.  If these become active again,
  * we will be able to use them again because the minor number will be
  * set back again, and we are preserving the ownership and permissions.
  */
 void sanitize_sdev ()
 {
     struct dirent * de;
-    char filename[60];
+    char filename[64];
     DIR * sdir;
     sname * spnt;
     struct stat statbuf;
     int status;
+    int i;
 
     /*
      * Next, delete all of the existing entries in the /dev/scsi directory.
@@ -305,30 +355,29 @@
      * changed.
      */
     sdir = opendir (DEVSCSI);
-    while (1)
-    {
+    while (1) {
 	de = readdir (sdir);
-	if (de == NULL) break;
+	if (de == NULL) 
+	    break;
+	/* If it's a .shadow name, leave it alone */
+	i = strlen (de->d_name) - strlen (SHADOW);
+	if (i > 0 && !strcmp (de->d_name+i, SHADOW))
+	    break;
 	/*
 	 * OK, we have the name.  See whether this is something
 	 * we know about already.
 	 */
-	for( spnt = reglist; spnt; spnt = spnt->next )
-	{
+	for( spnt = reglist; spnt; spnt = spnt->next ) {
 	    if( strcmp(de->d_name, strrchr (spnt->name, '/') + 1) == 0 )
-	    {
 		break;
-	    }
 	}
 	/* Didn't we find it? */
-	if (spnt == NULL)
-	{
+	if (spnt == NULL) {
 	    strcpy (filename, DEVSCSI); strcat (filename, "/");
 	    strcat (filename, de->d_name);
 	    status = stat (filename, &statbuf);
 	    if ( status == 0
-		 && (S_ISCHR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode)) )
-	    {
+		 && (S_ISCHR (statbuf.st_mode) || S_ISBLK (statbuf.st_mode)) ) {
 		/*
 		 * OK, this one is something new that we have to do something
 		 * with.  No big deal, stat it so we get the particulars, then
@@ -336,8 +385,8 @@
 		 */
 		unlink (filename);
 		if (!san_del) {
-		    status = mknod ( filename, statbuf.st_mode ,
-				     makedev (major (statbuf.st_rdev), 255) );
+		    strcat (filename, SHADOW);
+		    status = open (filename, O_RDWR | O_CREAT | O_EXCL);
 		    status = chmod (filename, statbuf.st_mode);
 		    chown (filename, statbuf.st_uid, statbuf.st_gid);
 		}
@@ -360,8 +409,7 @@
     char filename[60];
     DIR * sdir;
     sdir = opendir (DEVSCSI);
-    while (1)
-    {
+    while (1) {
 	de = readdir (sdir);
 	if (de == NULL) break;
 	//if (de->d_name[0] != 's' && de->d_name[0] != 'n') continue;
@@ -370,7 +418,8 @@
 	unlink (filename);
     }
     closedir (sdir);
-    if (!quiet) printf ("Flushed old " DEVSCSI " entries...\n");
+    if (!quiet) 
+	printf ("Flushed old " DEVSCSI " entries...\n");
 
 }
 
@@ -379,94 +428,158 @@
 {
     char nm[64]; char *genpart;
     char app[8];
-    char devchar;
+    char *dnm = 0;
+    enum devtype_t tp = spnt->devtp;
 
     *app = 0;
     strcpy (nm, DEVSCSI); strcat (nm, "/");
-    switch (spnt->major) {
-      case SCSI_GENERIC_MAJOR:
-	devchar = 'g'; break;
-      case SCSI_CDROM_MAJOR:
-	devchar = 'r'; break;
-      case SCSI_TAPE_MAJOR:
-	if (spnt->minor & 0x80) strcat (nm, "n");
-	devchar = 't'; break;
-      case OSST_MAJOR:
-	if (spnt->minor & 0x80) strcat (nm, "nos");
-	else strcat (nm, "os");
-	devchar = 't'; break;
-      default:
-	if (!(SCSI_DISK_MAJOR (spnt->major)))
-	{
+    /* FIXME */
+    switch (tp) {
+	case SG:
+	    dnm = "sg"; break;
+	case SR:
+	    dnm = "sr"; break;
+	case ST:
+	    if (spnt->minor & 0x80) 
+		dnm = "nst";
+	    else
+		dnm = "st";
+	    break;
+	case OSST:
+	    if (spnt->minor & 0x80) 
+		dnm = "nosst";
+	    else 
+		dnm = "osst";
+	    break;
+	case SD:
+	    dnm = "sd";
+	    if (spnt->minor & 0x0f) 
+		sprintf (app, "p%d", spnt->minor % 0x10);
+	    break;
+	case SCH:
+	    dnm = "sch";
+	    break;
+	default:
 	    fprintf (stderr, "scsidev: PANIC: Illegal major 0x%02x!\n",
 		     spnt->major);
 	    abort ();
-	}
-	devchar = 'd';
-	if (spnt->minor & 0x0f) 
-	    sprintf (app, "p%d", spnt->minor % 0x10);
     }
+    strcat (nm, dnm);
     genpart = nm + strlen (nm);
     if (nm_cbtu) 
-	sprintf (genpart, "s%cc%db%dt%du%d", devchar,
+	sprintf (genpart, "c%db%dt%du%d",
 		 spnt->hostnum, 
 		 spnt->chan, spnt->id, spnt->lun);
     else
-	sprintf (genpart, "s%ch%d-%xc%di%dl%d", devchar,
+	sprintf (genpart, "h%d-%xc%di%dl%d",
 		 spnt->hostnum, spnt->hostid,
 		 spnt->chan, spnt->id, spnt->lun);
-    if (*app) strcat (genpart, app);
+    if (*app) 
+	strcat (genpart, app);
     spnt->name = strdup (nm);
     return spnt->name;
 }
 
+/* Fortunately those are only needed for symlink mode
+ * and if there's no exteneded /proc/scsi/scsi  KG. 
+ */
+int sd_major_to_disknum (const int major, const int minor)
+{
+	if (major == SCSI_DISK0_MAJOR)
+		return minor >> 4;
+	else if (major >= SCSI_DISK1_MAJOR && major <= SCSI_DISK7_MAJOR)
+		return (minor >> 4) + ((major -  64) << 4);
+	else if (major >= 128 && major <= 135) /* SCSI_DISK10_MAJOR -- SCSI_DISK17_MAJOR */
+		return (minor >> 4) + ((major - 120) << 4);
+	else if (major >= 144) /* This is only a guess :-( */
+		return (minor >> 4) + ((major - 128) << 4);
+	else if (major >= 72 && major < 128) /* This is only a guess :-( */
+		return (minor >> 4) + ((major +  55) << 4);
+	else if (major >= 136 && major < 144) /* This is only a guess :-( */
+		return (minor >> 4) + ((major +  47) << 4);
+	else if (major >= 12 && major <= 64) /* This is only a guess :-( */
+		return (minor >> 4) + ((major + 179) << 4);
+	else return -1;
+}
+
+int disknum_to_sd_major (const int diskno)
+{
+	int mj = diskno >> 4;
+	if (mj == 0)
+		return 8; /* SCSI_DISK0_MAJOR */
+	else if (mj >= 1 && mj < 8)
+		return 64 + mj;
+	else if (mj >= 8 && mj < 16)
+		return 120 + mj;
+	else if (mj >= 16 && mj < 127)
+		return 128 + mj;
+	else if (mj >= 127 && mj < 183)
+		return mj - 55;
+	else if (mj >= 183 && mj < 191)
+		return mj - 47;
+	else if (mj >= 191 && mj < 244)
+		return mj - 179;
+	else return -1;
+}
+
+
+static void sd_devname(const unsigned int disknum, char *buffer)
+{
+	if (disknum < 26)
+		sprintf(buffer, "sd%c", 'a' + disknum);
+	else if (disknum < (26*27)) {
+		unsigned int min1 = disknum / 26 - 1;
+		unsigned int min2 = disknum % 26;
+		sprintf(buffer, "sd%c%c", 'a' + min1, 'a' + min2);
+	} else {
+		unsigned int min1 = (disknum / 26 - 1) / 26 - 1;
+		unsigned int min2 = (disknum / 26 - 1) % 26;
+		unsigned int min3 = disknum % 26;
+		sprintf(buffer, "sd%c%c%c", 'a' + min1, 'a' + min2, 'a' + min3);
+	}
+}
+
+
 // Creates an old /dev/s? name from the info in sname
 char * oldscsiname (sname *spnt)
 {
     char nm[64]; char *genpart;
     int diskno;
+    enum devtype_t tp = spnt->devtp;
 
     strcpy (nm, "/dev/"); genpart = nm + strlen (nm);
-    switch (spnt->major) {
-      case SCSI_GENERIC_MAJOR:
-	sprintf (genpart, "sg%d", spnt->minor); break;
-      case SCSI_CDROM_MAJOR:
-	sprintf (genpart, "sr%d", spnt->minor); break;
-      case SCSI_TAPE_MAJOR:
-	if (spnt->minor & 0x80) 
-	    sprintf (genpart, "nst%d", spnt->minor & 0x7f);
-	else
-	    sprintf (genpart, "st%d", spnt->minor & 0x7f);
-	break;
-      case OSST_MAJOR:
-	if (spnt->minor & 0x80) 
-	    sprintf (genpart, "nosst%d", spnt->minor & 0x7f);
-	else
-	    sprintf (genpart, "osst%d", spnt->minor & 0x7f);
-	break;
-      default:
-	if (!(SCSI_DISK_MAJOR (spnt->major)))
-	{
-	    fprintf (stderr, "scsidev: PANIC: Illegal major 0x%02x!\n",
+    /* FIXME */
+    switch (tp) {
+	case SG:
+	    sprintf (genpart, "sg%d", spnt->minor); break;
+	case SR:
+	    sprintf (genpart, "sr%d", spnt->minor); break;
+	case ST:
+	    if (spnt->minor & 0x80) 
+		sprintf (genpart, "nst%d", spnt->minor & 0x7f);
+	    else
+		sprintf (genpart, "st%d", spnt->minor & 0x7f);
+	    break;
+	case OSST:
+	    if (spnt->minor & 0x80) 
+		sprintf (genpart, "nosst%d", spnt->minor & 0x7f);
+	    else
+		sprintf (genpart, "osst%d", spnt->minor & 0x7f);
+	    break;
+	case SCH:
+	    sprintf (genpart, "sch%d", spnt->minor);
+	    break;
+	case SD:
+	    diskno = sd_major_to_disknum (spnt->major, spnt->minor);
+	    sd_devname (diskno, genpart);
+	    genpart += strlen (genpart);
+	    if (spnt->minor & 0xf) 
+		sprintf (genpart, "%d", (spnt->minor & 0xf));
+	    break;
+	default:
+	    fprintf (stderr, "scsidev: PANIC: Illegal device type major 0x%02x!\n",
 		     spnt->major);
 	    abort ();
-	}
-		
-	/* SCSI_DISK1 -- SCSI_DISK7 are contiguous in Linux-2.2+ */
-	if (spnt->major == SCSI_DISK0_MAJOR)
-	    diskno = spnt->minor >> 4;
-	else
-	    diskno = (spnt->minor >> 4) + 16 + spnt->major - SCSI_DISK1_MAJOR;
-	if (diskno + 'a' > 'z')
-	    sprintf (genpart, "sd%c%c",
-		     'a' + diskno / ('z'-'a') - 1,
-		     'a' + diskno % ('z'-'a'));
-	else
-	    sprintf (genpart, "sd%c", 'a' + diskno);
-	genpart += strlen (genpart);
-	if (spnt->minor & 0xf) 
-	    sprintf (genpart, "%d", (spnt->minor & 0xf));
-	break;
     }
     //spnt->name = strdup (nm);
     return strdup (nm);
@@ -478,43 +591,70 @@
  * if it does make sure the major and minor numbers are correct
  * and save permissions and ownerships if this is the case.
  */
-void update_device (char * path, int devtype, int major, int minor)
+void update_device (char * path, int fmode, int major, int minor)
 {
     struct stat statbuf;
     int recreate;
     int newmode;
     int uid, gid;
     int status;
+    char shadow[64];
+    strcpy (shadow, path);
 
-    newmode = devtype | 
+    /* FIXME */
+    newmode = fmode | 
 	(major != SCSI_CDROM_MAJOR ? filemode : (filemode & ~0222));
 
     recreate = 1;
     uid = gid = -1;
-    status = stat (path, &statbuf);
+    status = lstat (path, &statbuf);
+    /* If dev node does not exist, try to look up .shadow file */
+    if (status) {
+	strcat (shadow, SHADOW);
+	status = stat (shadow, &statbuf);
+    }
     if (status == 0) {
 	recreate = 0;
 	uid = statbuf.st_uid;
 	gid = statbuf.st_gid;
 	/*
-	 * Make sure we have the correct device type too.
+	 * We are NOT in symlink mode, when getting here.
 	 */
-	if ( (statbuf.st_mode & S_IFMT) != devtype )
+	if ( S_ISLNK (statbuf.st_mode) ) {
 	    recreate = 1;
+	    if (verbose >= 2) 
+		printf("is symbolic link ...\n");
+	    /* Try to get permissions from somewhere */
+	    strcat (shadow, SHADOW);
+	    status = stat (shadow, &statbuf);
+	    if (status) 
+		status = stat (path, &statbuf);
+	    uid = statbuf.st_uid;
+	    gid = statbuf.st_gid;
+	    newmode = fmode | (statbuf.st_mode & ~S_IFLNK);
+	    unlink (path);
+	}
 	/*
-	 * We are NOT in symlink mode, when getting here.
+	 * Make sure we have the correct device type too.
 	 */
-	if ( S_ISLNK (statbuf.st_mode) )
+	if ( (statbuf.st_mode & S_IFMT) != fmode ) {
 	    recreate = 1;
+	    newmode = fmode | (statbuf.st_mode & ~S_IFLNK);
+	    if (verbose >= 2) 
+		printf ("mode: %08x vs. %08x\n", 
+			statbuf.st_mode & S_IFMT, fmode);
+	}
 	/*
 	 * Compare the device number.  If something changed, then 
 	 * unlink it so that we can recreate it.  Save the mode of
 	 * the thing so that we can keep the same permissions.
 	 */
-	if ( statbuf.st_rdev != makedev (major, minor) )
-	{
+	if ( statbuf.st_rdev != makedev (major, minor) ) {
 	    recreate = 1;
-	    newmode = devtype | (statbuf.st_mode & ~S_IFLNK);
+	    newmode = fmode | (statbuf.st_mode & ~S_IFLNK);
+	    if (verbose >= 2) 
+		printf ("r_dev: %08x vs. %08x\n", 
+			(unsigned int)statbuf.st_rdev, makedev (major, minor));
 	}
 
 	if (verbose == 2 && recreate) 
@@ -524,17 +664,18 @@
     /*
      * If we need to recreate the device, then do it.
      */
-    if( recreate )
-    {
-	if (status == 0) unlink (path);
-	status = mknod (path, newmode,
-			makedev (major, minor));
+    if( recreate ) {
+	if (status == 0) 
+	    unlink (shadow);
+	status = mknod (path, newmode, makedev (major, minor));
 	//printf("Recreate maj %i min %i\n", major, minor);
 	if( status == -1 ) {
 	    fprintf (stderr, "mknod (%s) failed\n", path);
 	    exit (1);
 	}
       
+	if( uid != -1 )
+	    status = chown (path, uid, gid);
 	/*
 	 * The mknod system call will not always use
 	 * the right permissions because of umask.
@@ -546,8 +687,6 @@
 	    exit (1);
 	}
       
-	if( uid != -1 )
-	    chown (path, uid, gid);
     }  
 }
 
@@ -557,10 +696,13 @@
     int status;
     int newmode;
     struct stat statbuf;
-    int devtype = (SCSI_BLK_MAJOR (spnt->major)? S_IFBLK: S_IFCHR);
+    int devtype = isblk (spnt->devtp)? S_IFBLK: S_IFCHR;;
 	
-    if (use_symlink)
-    {
+    if (use_symlink) {
+	char shadow[64];
+	strcpy (shadow, spnt->name);
+	strcat (shadow, SHADOW);
+
 	linkto = oldscsiname (spnt);
 	unlink (spnt->name);
 	symlink (linkto, spnt->name);
@@ -570,76 +712,95 @@
 	 * actually exists.  If not, then create that device.
 	 */
 	status = stat (spnt->name, &statbuf);
-	if (status == 0)
-	{
+	if (status == 0) {
 	    if (statbuf.st_rdev != makedev(spnt->major, spnt->minor))
-	    {
 		fprintf (stderr,
 			 "Warning - device %s does not point to expected device\n", linkto);
-	    }
-	}
-	else
-	{
+	} else {
+	    newmode = devtype | filemode;
 	    /*
 	     * Unable to stat the file.  Assume this is 
 	     * because it did not exist, so we create it.
 	     */
-	    newmode = devtype | filemode;
 	    status = mknod (linkto, newmode,
 			    makedev (spnt->major, spnt->minor));
 	    fprintf (stderr, "Creating %s\n", linkto);
 	}
+	/* If a shadow file exists, get perms from there */
+	if (!stat (shadow, &statbuf)) {
+	    chown (linkto, statbuf.st_uid, statbuf.st_gid);
+	    chmod (linkto, devtype | statbuf.st_mode);
+	}
 	free (linkto);
     }
-    else
+    else /* ! use_symlink */
 	update_device (spnt->name, devtype, spnt->major, spnt->minor);
 }
 
-int getscsiinfo (int fd, sname *spnt)
+int getidlun (int fd, sname *spnt, int setidlun)
 {
-    int id[2];
-    int status;
-    char hostname[64];
-	
-    status = ioctl (fd, SCSI_IOCTL_GET_IDLUN, &id);
+	int status;
+	int id[2];
+
+	status = ioctl (fd, SCSI_IOCTL_GET_IDLUN, &id);
 	
-    if (status == -1)	{
-	if (verbose == 2)
-	{
-	    fprintf (stderr, "idlun(%x/%x) returned %d (%d)\n",
-		     spnt->major, spnt->minor, status, errno);
+	if (status == -1)	{
+		if (verbose == 2)
+			fprintf (stderr, "idlun(%x/%x) returned %d (%d)\n",
+				 spnt->major, spnt->minor, status, errno);
+		close (fd);
+		return -2;
 	}
-	close (fd);
-	return -2;
-    }
 	
-    *(int*)hostname = 63;
-    status = ioctl (fd, SCSI_IOCTL_PROBE_HOST, hostname);
-    hostname[63] = '\0';
-    //close (fd);
-    spnt->hostname = strdup (hostname);
+	if (setidlun) {
+		/* This unfortunately limits all the numbers to be <= 255 */
+		spnt->hostnum = id[0] >> 24 & 0xff;
+		spnt->chan    = id[0] >> 16 & 0xff;
+		spnt->lun     = id[0] >>  8 & 0xff;
+		spnt->id      = id[0]       & 0xff;
+	}
+	spnt->hostid  = id[1];
 	
-    if (status == -1)	{
 	if (verbose == 2)
-	{
-	    fprintf (stderr, "probe (%x/%x) returned %d (%d)\n",
-		     spnt->major, spnt->minor, status, errno);
-	}
-	return -1;
-    };
+		fprintf (stderr, "Found %x:%x with idlun %08x\n", 
+			 spnt->major, spnt->minor, id[0]);
+
+	return status;
+}
+
+
+int getscsihostname (int fd, sname *spnt)
+{
+	int status;
+	char hostname[64];
+	*(int*)hostname = 63;
+	status = ioctl (fd, SCSI_IOCTL_PROBE_HOST, hostname);
+	hostname[63] = '\0';
 	
-    if (verbose == 2)
-	fprintf (stderr, "Found %x with idlun %x\n", 
-		 makedev (spnt->major, spnt->minor), id[0]);
-    spnt->hostnum = id[0] >> 24 & 0xff;
-    spnt->chan    = id[0] >> 16 & 0xff;
-    spnt->lun     = id[0] >>  8 & 0xff;
-    spnt->id      = id[0]       & 0xff;
-    spnt->hostid  = id[1];
+	if (status == -1)	{
+		if (verbose == 2)
+			fprintf (stderr, "probe host (%x/%x) returned %d (%d)\n",
+				 spnt->major, spnt->minor, status, errno);
+		spnt->hostname = 0;
+		return -1;
+	};
+	spnt->hostname = strdup (hostname);
+	return status;
+}
 
+int getscsiinfo (int fd, sname *spnt, int setidlun)
+{
+    int status;
+
+    if ((status = getidlun (fd, spnt, setidlun)))
+	return status;
+    if ((status = getscsihostname (fd, spnt)) < 0)
+	return status;	
+
     status = inquiry (fd, spnt);
     scsiname (spnt);
     return status;
+
 #if 0
     spnt = register_dev (scsidev, major, minor, 
 			 h_id, id[1], chan, scsi_id, lun, -1, hostname, NULL);
@@ -654,8 +815,9 @@
 {
     int minor; int fd; int status;
     sname * spnt1 = sname_dup (spnt);
-    spnt1->major = (no < 16? SCSI_DISK0_MAJOR: SCSI_DISK1_MAJOR + no/16 - 1);
-    spnt1->minor = (no << 4) % 256; spnt->partition = -1;
+    spnt1->major = disknum_to_sd_major (no);
+    spnt1->minor = (no << 4) & 0xf0; spnt->partition = -1;
+    spnt1->devtp = SD;
     scsiname (spnt1);
     spnt1->next = reglist; reglist = spnt1;
     create_dev (spnt1);
@@ -667,7 +829,8 @@
 	spnt1->unsafe = 1;
 	/* If it is a removable device, we can't do much more than 
 	 * trusting it or not support it at all */
-	if (spnt1->rmvbl && supp_rmvbl) return 0;
+	if (spnt1->rmvbl && supp_rmvbl) 
+	    return 0;
 	fprintf (stderr, "Can't access %sremovable %s, which should "
 		 "be equal to %s!\n", (spnt1->rmvbl? "": "NON-"), 
 		 strrchr (spnt1->name, '/') + 1,
@@ -679,12 +842,12 @@
     }
 	
     /* Sanity checks */
-    status = getscsiinfo (fd, spnt1);
+    status = getscsiinfo (fd, spnt1, 1);
     close (fd);
-    if (status) fprintf (stderr, "scsidev: Strange: Could not get info from %s\n",
-			 strrchr (spnt1->name, '/') + 1);
-    if (sname_cmp (spnt, spnt1))
-    {
+    if (status) 
+	fprintf (stderr, "scsidev: Strange: Could not get info from %s\n",
+		 strrchr (spnt1->name, '/') + 1);
+    if (sname_cmp (spnt, spnt1)) {
 	fprintf (stderr, "scsidev: What's going on? Dev %s is different from %s\n", 
 		 strrchr (spnt1->name, '/') + 1, strrchr (spnt->name, '/') + 1);
 	spnt -> related = 0; spnt1 -> related = 0;
@@ -695,8 +858,7 @@
     }
     /* Now do a partition scan ... */
     spnt = spnt1;
-    for (minor = spnt1->minor+1; minor % 16; minor++)
-    {
+    for (minor = spnt1->minor+1; minor % 16; minor++) {
 	struct stat statbuf; int status;
 	status = stat (TESTDEV, &statbuf);
 	if (status == 0)
@@ -706,7 +868,8 @@
 			 makedev (spnt1->major, minor) );
 	fd = open (TESTDEV, O_RDONLY | O_NONBLOCK);
 	unlink (TESTDEV);
-	if (fd < 0) continue;
+	if (fd < 0) 
+	    continue;
 	// TO DO: Add sanity checks here ??
 	close (fd);
 	spnt1 = sname_dup (spnt);
@@ -725,6 +888,7 @@
     sname * spnt1 = sname_dup (spnt);
     spnt1->major = SCSI_TAPE_MAJOR;
     spnt1->minor = no;
+    spnt1->devtp = ST;
     scsiname (spnt1);
     spnt1->next = reglist; reglist = spnt1;
     create_dev (spnt1);
@@ -741,12 +905,12 @@
 	return 1;
     }
     /* Do a sanity check here */
-    status = getscsiinfo (fd, spnt1);
+    status = getscsiinfo (fd, spnt1, 1);
     close (fd);
-    if (status) fprintf (stderr, "scsidev: Strange: Could not get info from %s\n",
-			 strrchr (spnt1->name, '/') + 1);
-    if (sname_cmp (spnt, spnt1))
-    {
+    if (status) 
+	fprintf (stderr, "scsidev: Strange: Could not get info from %s\n",
+		 strrchr (spnt1->name, '/') + 1);
+    if (sname_cmp (spnt, spnt1)) {
 	fprintf (stderr, "scsidev: What's going on? Dev %s is different from %s\n", 
 		 strrchr (spnt1->name, '/') + 1, strrchr (spnt->name, '/') + 1);
 	spnt -> related = 0; spnt1 -> related = 0;
@@ -771,6 +935,7 @@
     sname * spnt1 = sname_dup (spnt);
     spnt1->major = OSST_MAJOR;
     spnt1->minor = no;
+    spnt1->devtp = OSST;
     scsiname (spnt1);
     spnt1->next = reglist; reglist = spnt1;
     create_dev (spnt1);
@@ -780,22 +945,23 @@
 	/* OnStream tapes are NOT always accessible, as they have a heavy open() function */
 	spnt1->unsafe = 1;
 	if (!quiet || !supp_rmvbl) 
-		    fprintf (stderr, "Can't access tape %s, which should "
-			     "be equal to %s!\n", strrchr (spnt1->name, '/') + 1,
-			     strrchr (spnt->name, '/') + 1);
-	if (supp_rmvbl) goto osst_force_success;
+	    fprintf (stderr, "Can't access tape %s, which should "
+		     "be equal to %s!\n", strrchr (spnt1->name, '/') + 1,
+		     strrchr (spnt->name, '/') + 1);
+	if (supp_rmvbl) 
+	    goto osst_force_success;
 	/* We don't unlink spnt1->name! Let sanitize take care of it ... */
 	reglist = spnt1->next; free (spnt1->name); 
 	spnt->related = 0; free (spnt1);
 	return 1;
     }
     /* Do a sanity check here */
-    status = getscsiinfo (fd, spnt1);
+    status = getscsiinfo (fd, spnt1, 1);
     close (fd);
-    if (status) fprintf (stderr, "scsidev: Strange: Could not get info from %s\n",
-			 strrchr (spnt1->name, '/') + 1);
-    if (sname_cmp (spnt, spnt1))
-    {
+    if (status) 
+	fprintf (stderr, "scsidev: Strange: Could not get info from %s\n",
+		 strrchr (spnt1->name, '/') + 1);
+    if (sname_cmp (spnt, spnt1)) {
 	fprintf (stderr, "scsidev: What's going on? Dev %s is different from %s\n", 
 		 strrchr (spnt1->name, '/') + 1, strrchr (spnt->name, '/') + 1);
 	spnt -> related = 0; spnt1 -> related = 0;
@@ -804,7 +970,7 @@
 	spnt->related = 0; free (spnt1);
 	return 1;
     }
-osst_force_success:
+ osst_force_success:
     /* And create the no-rewind alias */
     spnt1 = sname_dup (spnt1);
     spnt1->minor |= 0x80;
@@ -821,6 +987,7 @@
     sname * spnt1 = sname_dup (spnt);
     spnt1->major = SCSI_CDROM_MAJOR;
     spnt1->minor = no;
+    spnt1->devtp = SR;	
     scsiname (spnt1);
     spnt1->next = reglist; reglist = spnt1;
     create_dev (spnt1);
@@ -829,7 +996,8 @@
     if (fd < 0) {
 	spnt1->unsafe = 1;
 	/* Removable block devs are hairy! */
-	if (spnt1->rmvbl && supp_rmvbl) return 0;
+	if (spnt1->rmvbl && supp_rmvbl) 
+	    return 0;
 	fprintf (stderr, "Can't access %sremovable %s, which should "
 		 "be equal to %s!\n", (spnt1->rmvbl? "": "NON-"), 
 		 strrchr (spnt1->name, '/') + 1,
@@ -841,12 +1009,12 @@
     }
 	
     /* Do a sanity check */
-    status = getscsiinfo (fd, spnt1);
+    status = getscsiinfo (fd, spnt1, 1);
     close (fd);
-    if (status) fprintf (stderr, "scsidev: Strange: Could not get info from %s\n",
-			 strrchr (spnt1->name, '/') + 1);
-    if (sname_cmp (spnt, spnt1))
-    {
+    if (status) 
+	fprintf (stderr, "scsidev: Strange: Could not get info from %s\n",
+		 strrchr (spnt1->name, '/') + 1);
+    if (sname_cmp (spnt, spnt1)) {
 	fprintf (stderr, "scsidev: What's going on? Dev %s is different from %s\n", 
 		 strrchr (spnt1->name, '/') + 1, strrchr (spnt->name, '/') + 1);
 	/* And now ? */
@@ -857,20 +1025,66 @@
     return 0;
 }
 
+int build_changer (sname * spnt, int no)
+{
+    int fd; int status;
+    sname * spnt1 = sname_dup (spnt);
+    spnt1->major = 86;	/* SCSI_CHANGER_MAJOR; */
+    spnt1->minor = no;
+    spnt1->devtp = SCH;
+    scsiname (spnt1);
+    spnt1->next = reglist; reglist = spnt1;
+    create_dev (spnt1);
+    fd =  open (spnt1->name, O_RDONLY | O_NONBLOCK);
+    /* No access to medium / part. table */
+    if (fd < 0) {
+	spnt1->unsafe = 1;
+	/* Removable block devs are hairy! */
+	if (spnt1->rmvbl && supp_rmvbl) 
+	    return 0;
+	fprintf (stderr, "Can't access %sremovable %s, which should "
+		 "be equal to %s!\n", (spnt1->rmvbl? "": "NON-"), 
+		 strrchr (spnt1->name, '/') + 1,
+		 strrchr (spnt->name, '/') + 1);
+	/* We don't unlink spnt1->name! Let sanitize take care of it ... */
+	reglist = spnt1->next; free (spnt1->name); 
+	spnt->related = 0; free (spnt1);
+	return 1;
+    }
+
+    /* Do a sanity check */
+    status = getscsiinfo (fd, spnt1, 1);
+    close (fd);
+    if (status) 
+	fprintf (stderr, "scsidev: Strange: Could not get info from %s\n",
+		 strrchr (spnt1->name, '/') + 1);
+    if (sname_cmp (spnt, spnt1)) {
+	fprintf (stderr, "scsidev: What's going on? Dev %s is different from %s\n",
+		 strrchr (spnt1->name, '/') + 1, strrchr (spnt->name, '/') + 1);
+	/* And now ? */
+	reglist = spnt1->next; free (spnt1->name); 
+	spnt->related = 0; free (spnt1);
+	return 1;
+    }
+    return 0;
+}
+
 
+
 void build_sgdevlist ()
 {
     int fd; 
     struct stat statbuf;
     int status;
     sname * spnt;
-    int disks = 0, tapes = 0, cdroms = 0;
+    int disks = 0, tapes = 0, cdroms = 0, changers = 0;
     int miss = 0;	
     int minor = 0;
     int major = SCSI_GENERIC_MAJOR; 
-    char devchar = 'g'; int mode = O_RDWR;
-    int devtype = (SCSI_BLK_MAJOR(major)? S_IFBLK: S_IFCHR);
-
+    int mode = O_RDWR;
+    //    int devtype = (SCSI_BLK_MAJOR(major)? S_IFBLK: S_IFCHR);
+    enum devtype_t devtp;
+    
     status = stat (DEVSCSI, &statbuf);
     if (status == -1)
 	return;
@@ -880,72 +1094,92 @@
 	unlink (TESTDEV);
 
     if (verbose >= 1)
-	fprintf (stderr, "Building list for s%c (%s dev major %i)\n",
-		 devchar, (SCSI_BLK_MAJOR(major)? "block": "char"), major);
-    while (minor <= 255)
-    {
+	fprintf (stderr, "Building list for sg (%s dev major %i)\n",
+		 "char", major);
+
+    while (minor <= 255) {
 	errno = 0;
-	status = mknod ( TESTDEV, 0600 | devtype ,
+	status = mknod ( TESTDEV, 0600 | S_IFCHR, 
 			 makedev (major, minor) );
-	if (status) { perror ("scsidev: mknod"); exit (3); }
+	if (status) { 
+	    perror ("scsidev: mknod"); 
+	    exit (3); 
+	}
 	fd = open (TESTDEV, mode);
 	unlink (TESTDEV);
 	if (fd == -1) {
 	    if (verbose == 2)
-	    {
 		fprintf (stderr, "open(%x/%x) returned %d (%d)\n",
 			 major, minor, fd, errno);
-	    }
 	    miss++;
-	    if (miss > maxmiss) break;
-	    else { minor++; continue; }
+	    if (miss > maxmiss) 
+		break;
+	    else { 
+		minor++; continue; 
+	    }
 	}
 	spnt = (sname*) malloc (sizeof (sname));
 	spnt->major = major;   spnt->minor = minor;
+	spnt->devtp = SG;
 	spnt->name  = TESTDEV; spnt->partition = -1;
-	status = getscsiinfo (fd, spnt);
+	status = getscsiinfo (fd, spnt, 1);
 	close (fd);
 
 	if (status) { 
 		free (spnt); miss++;
-		if (miss > maxmiss) break;
-		else { minor++; continue; }
+		if (miss > maxmiss) 
+		    break;
+		else { 
+		    minor++; continue; 
+		}
 	}
-	scsiname (spnt);
+	//scsiname (spnt);
 
 	spnt->next = reglist; reglist = spnt;
 	create_dev (spnt);
 
-	if (!quiet) printf ("Found %s (Type %02x) %c on %s \n", spnt->name,
-			    spnt->inq_devtp, (spnt->rmvbl? 'R' : ' '),
-			    spnt->hostname);
+	devtp = inq_devtp_to_devtp (spnt->inq_devtp, spnt);
+
+	if (!quiet) 
+	    printf ("Found %s (Type %02x) %c on %s \n", spnt->name,
+		    spnt->inq_devtp, (spnt->rmvbl? 'R' : ' '),
+		    spnt->hostname);
 
 	/* Now register cdroms, tapes, and disks as well */
-	switch (spnt->inq_devtp) {
-	  case TYPE_DISK:
-	  case TYPE_MOD:
-	    if (!build_disk (spnt, disks)) disks++;
-	    else if (!build_disk (spnt, disks+1)) disks += 2;
-	    break;
-	  case TYPE_TAPE:
-	    if (OSST_SUPPORTS(spnt)) 
-	    {
-		if (!build_os_tape (spnt, tapes)) tapes++;
-		else if (!build_os_tape (spnt, tapes+1)) tapes += 2;
-	    }		    
-	    else
-	    {
-		if (!build_tape (spnt, tapes)) tapes++;
-		else if (!build_tape (spnt, tapes+1)) tapes += 2;
-	    }
-	    break;
-	  case TYPE_ROM:
-	  case TYPE_WORM:
-	    if (!build_cdrom (spnt, cdroms)) cdroms++;
-	    else if (!build_cdrom (spnt, cdroms+1)) cdroms += 2;
-	    break;
-	  default:
-	    ;/* nothing to be done */
+	switch (devtp) {
+	    case SD:
+		if (!build_disk (spnt, disks)) 
+			disks++;
+		else if (!build_disk (spnt, disks+1)) 
+			disks += 2;
+		break;
+	    case ST:
+		if (!build_tape (spnt, tapes)) 
+			tapes++;
+		else if (!build_tape (spnt, tapes+1)) 
+			tapes += 2;
+		break;
+	    case OSST:
+		if (!build_os_tape (spnt, tapes)) 
+			tapes++;
+		else if (!build_os_tape (spnt, tapes+1)) 
+			tapes += 2;
+		break;
+	    case SR:
+		if (!build_cdrom (spnt, cdroms)) 
+			cdroms++;
+		else if (!build_cdrom (spnt, cdroms+1)) 
+			cdroms += 2;
+		break;
+	    case SCH:
+		if (!build_changer (spnt, changers)) 
+			changers++;
+		else if (!build_cdrom (spnt, changers+1)) 
+			changers += 2;
+		break;
+		
+	    default:
+		;/* nothing to be done */
 	}
 	minor += 1;
     }
@@ -1004,7 +1238,6 @@
     buf = malloc(128); buflen = 128;
 
 	
-	
     while (getline (&buf, &buflen, mapfile) != -1)
     {
 	int h,c,i,l;
@@ -1123,16 +1356,12 @@
     if ( status == -1 )
 	mkdir (DEVSCSI, 0755);
     status = stat(DEVSCSI, &statbuf);
-    if ( status == -1
-	 || !S_ISDIR(statbuf.st_mode))
-    {
+    if ( status == -1 || !S_ISDIR(statbuf.st_mode)) {
 	fprintf(stderr, DEVSCSI " either does not exist, or is not a directory\n");
 	exit(0);
     }
-    while ((c = getopt(argc, argv, "flLvqshnderm:c:")) != EOF)
-    {
-	switch (c)
-	{
+    while ((c = getopt(argc, argv, "flLvqshnderm:c:")) != EOF) {
+	switch (c) {
 	  case 'f':
 	    force = 1; break;
 	  case 'm':
@@ -1165,8 +1394,10 @@
 	}
     }
 
-    if( verbose >= 1 ) fprintf( stderr, "%s\n", versid );
-    if( force ) flush_sdev ();
+    if( verbose >= 1 ) 
+	fprintf( stderr, "%s\n", versid );
+    if( force ) 
+	flush_sdev ();
 
 #ifdef DEBUG
     register_dev("/dev/scsi/sdh4-334c0i0l0",  8,  0, 6, 0x334, 0, 0, 0, -1, "debug", NULL);
@@ -1183,15 +1414,15 @@
     build_sgdevlist ();
 #endif
 
-    if( show_serial )
-    {
+    if( show_serial ) {
 	if (verbose)
 	    dumplist();
-	for (spnt = reglist; spnt; spnt = spnt->next)
-	{
-	    if( spnt->partition != -1 ) continue;
-	    if( spnt->major == SCSI_TAPE_MAJOR
-		&& (spnt->minor & 0x80) != 0 ) continue;
+	for (spnt = reglist; spnt; spnt = spnt->next) {
+	    if( spnt->partition != -1 ) 
+		continue;
+	    if( (spnt->devtp == ST || spnt->devtp == OSST)
+		&& (spnt->minor & 0x80) != 0 )
+		continue;
 
 	    //if( spnt->serial == NULL ) inquiry (spnt);
 	    if( spnt->serial == no_serial )
@@ -1228,20 +1459,21 @@
 
     *result = pnt;
 
-    if( quote != 0 )
-    {
+    if( quote != 0 ) {
 	while ( *pnt != quote ) pnt++;
 	*pnt++ = 0;
-    }
-    else
-    {
-	while ( *pnt != ',' && *pnt != ' ' && *pnt != '\t' && *pnt != '\0' ) pnt++;
+    } else {
+	while ( *pnt != ',' && *pnt != ' ' && *pnt != '\t' && *pnt != '\0' ) 
+	    pnt++;
 	*pnt++ = 0;
     }
 
-    while (*pnt == ' ' || *pnt == '\t') pnt++;
-    if (*pnt == ',') pnt++;
-    while (*pnt == ' ' || *pnt == '\t') pnt++;
+    while (*pnt == ' ' || *pnt == '\t') 
+	pnt++;
+    if (*pnt == ',') 
+	pnt++;
+    while (*pnt == ' ' || *pnt == '\t') 
+	pnt++;
     return pnt;
 }
 
@@ -1250,34 +1482,31 @@
     int base = 10;
     unsigned long long num;
 
-    while (*pnt == ' ' || *pnt == '\t') pnt++;
-    if (pnt[0] == '0' && pnt[1] == 'x') { base = 16; pnt += 2; }
+    while (*pnt == ' ' || *pnt == '\t') 
+	pnt++;
+    if (pnt[0] == '0' && pnt[1] == 'x') { 
+	base = 16; pnt += 2;
+    }
 
     num = 0;
-    while (1)
-    {
-	if (base == 10 && *pnt >= '0' && *pnt <= '9' )
-	{
+    while (1) {
+	if (base == 10 && *pnt >= '0' && *pnt <= '9' ) {
 	    num = num * 10ULL + *pnt - '0';
 	    pnt++;
 	    continue;
 	}
-	if ( base == 16 )
-	{
-	    if (*pnt >= '0' && *pnt <= '9')
-	    {
+	else if ( base == 16 ) {
+	    if (*pnt >= '0' && *pnt <= '9') {
 		num = (num << 4) + *pnt - '0';
 		pnt++;
 		continue;
 	    }
-	    if (*pnt >= 'a' && *pnt <= 'f')
-	    {
+	    if (*pnt >= 'a' && *pnt <= 'f') {
 		num = (num << 4) + *pnt - 'a' + 10;
 		pnt++;
 		continue;
 	    }
-	    if (*pnt >= 'A' && *pnt <= 'F')
-	    {
+	    if (*pnt >= 'A' && *pnt <= 'F') {
 		num = (num << 4) + *pnt - 'A' + 10;
 		pnt++;
 		continue;
@@ -1289,9 +1518,12 @@
 	 */
 	break;
     }
-    while (*pnt == ' ' || *pnt == '\t') pnt++;
-    if (*pnt == ',') pnt++;
-    while (*pnt == ' ' || *pnt == '\t') pnt++;
+    while (*pnt == ' ' || *pnt == '\t') 
+	pnt++;
+    if (*pnt == ',') 
+	pnt++;
+    while (*pnt == ' ' || *pnt == '\t') 
+	pnt++;
     *result = num;
     return pnt;
 
@@ -1302,34 +1534,31 @@
     int base = 10;
     int num;
 
-    while (*pnt == ' ' || *pnt == '\t') pnt++;
-    if (pnt[0] == '0' && pnt[1] == 'x') { base = 16; pnt += 2; }
+    while (*pnt == ' ' || *pnt == '\t') 
+	pnt++;
+    if (pnt[0] == '0' && pnt[1] == 'x') { 
+	base = 16; pnt += 2; 
+    }
 
     num = 0;
-    while (1)
-    {
-	if (base == 10 && *pnt >= '0' && *pnt <= '9' )
-	{
+    while (1) {
+	if (base == 10 && *pnt >= '0' && *pnt <= '9' ) {
 	    num = num * 10 + *pnt - '0';
 	    pnt++;
 	    continue;
 	}
-	if ( base == 16 )
-	{
-	    if (*pnt >= '0' && *pnt <= '9')
-	    {
+	else if ( base == 16 ) {
+	    if (*pnt >= '0' && *pnt <= '9') {
 		num = (num << 4) + *pnt - '0';
 		pnt++;
 		continue;
 	    }
-	    if (*pnt >= 'a' && *pnt <= 'f')
-	    {
+	    if (*pnt >= 'a' && *pnt <= 'f') {
 		num = (num << 4) + *pnt - 'a' + 10;
 		pnt++;
 		continue;
 	    }
-	    if (*pnt >= 'A' && *pnt <= 'F')
-	    {
+	    if (*pnt >= 'A' && *pnt <= 'F') {
 		num = (num << 4) + *pnt - 'A' + 10;
 		pnt++;
 		continue;
@@ -1341,9 +1570,12 @@
 	 */
 	break;
     }
-    while (*pnt == ' ' || *pnt == '\t') pnt++;
-    if (*pnt == ',') pnt++;
-    while (*pnt == ' ' || *pnt == '\t') pnt++;
+    while (*pnt == ' ' || *pnt == '\t') 
+	pnt++;
+    if (*pnt == ',') 
+	pnt++;
+    while (*pnt == ' ' || *pnt == '\t') 
+	pnt++;
     *result = num;
     return pnt;
 
@@ -1384,7 +1616,7 @@
     int lun, chan, id, part, hostid, hostnum;
     int line;
     unsigned long long wwid;	/* host byte order ... */
-    int devtype_i;
+    enum devtype_t devtype_i;
     char *manufacturer, *model, *serial_number, *name, *devtype, *rev, *host;
     char *scsialias;
 
@@ -1401,18 +1633,19 @@
     }
 
     line = 0;
-    while (1)
-    {
+    while (1) {
 	*buffer = 0;
 	fgets (buffer, sizeof(buffer), configfile);
 	line++;
-	if (feof (configfile) && !*buffer) break;
+	if (feof (configfile) && !*buffer) 
+	    break;
 	
 	/*
 	 * Remove trailing \n, if present.
 	 */
 	pnt = buffer + strlen(buffer) - 1;
-	if( *pnt == '\n' ) *pnt = '\0';
+	if( *pnt == '\n' ) 
+	    *pnt = '\0';
 
 	/*
 	 * First, tokenize the input line, and pick out the parameters.
@@ -1424,80 +1657,54 @@
 	host = NULL;
 	manufacturer = NULL; model = NULL;
 	serial_number = NULL; rev = NULL;
-	name = NULL; 
+	name = NULL; devtype_i = NONE;
 	devtype = NULL;
 	pnt = buffer;
 	while (*pnt == ' ' || *pnt == '\t') pnt++;
 
 	/* allow blank lines and comments... */
-	if( *pnt == '\0' ) continue;
-	if( *pnt == '#' ) continue;
+	if( *pnt == '\0' ) 
+	    continue;
+	if( *pnt == '#'  ) 
+	    continue;
 
-	while (1)
-	{
+	while (1) {
 	    pnt1 = pnt;
-	    while (*pnt1 != '=' && *pnt1 != '\0') pnt1++;
-	    if( *pnt1 == '\0' ) break;
+	    while (*pnt1 != '=' && *pnt1 != '\0') 
+		pnt1++;
+	    if( *pnt1 == '\0' ) 
+		break;
 
 	    *pnt1 = '\0';
 	    if( strncmp(pnt, "manu", 4) == 0 )
-	    {
 		pnt = get_string(pnt1 + 1, &manufacturer);
-	    }
 	    else if ( strncmp(pnt, "mode", 4) == 0 )
-	    {
 		pnt = get_string(pnt1 + 1, &model);
-	    }
 	    else if ( strncmp(pnt, "seri", 4) == 0 )
-	    {
 		pnt = get_string(pnt1 + 1, &serial_number);
-	    }
 	    else if ( strcmp(pnt, "wwid") == 0 )
-	    {
 		pnt = get_llnumber(pnt1 + 1, &wwid);
-	    }
 	    else if ( strncmp(pnt, "rev", 3) == 0 )
-	    {
 		pnt = get_string(pnt1 + 1, &rev);
-	    }
 	    else if ( strncmp(pnt, "hostname", 6) == 0 )
-	    {
 		pnt = get_string(pnt1 + 1, &host);
-	    }
 	    else if ( strcmp(pnt, "id") == 0 )
-	    {
 		pnt = get_number(pnt1 + 1, &id);
-	    }
 	    else if ( strcmp(pnt, "lun") == 0 )
-	    {
 		pnt = get_number(pnt1 + 1, &lun);
-	    }
 	    else if ( strncmp(pnt, "chan", 4) == 0 )
-	    {
 		pnt = get_number(pnt1 + 1, &chan);
-	    }
 	    else if ( strncmp(pnt, "part", 4) == 0 )
-	    {
 		pnt = get_number(pnt1 + 1, &part);
-	    }
 	    else if ( strcmp(pnt, "hostid") == 0 )
-	    {
 		pnt = get_number(pnt1 + 1, &hostid);
-	    }
 	    else if ( strcmp(pnt, "hostnum") == 0 )
-	    {
 		pnt = get_number(pnt1 + 1, &hostnum);
-	    }
 	    else if ( strncmp(pnt, "alia", 4) == 0 )
-	    {
 		pnt = get_string(pnt1 + 1, &name);
-	    }
 	    else if ( strncmp(pnt, "devt", 4) == 0 )
-	    {
 		pnt = get_string(pnt1 + 1, &devtype);
-	    }
-	    else
-	    {
+	    else {
 		fprintf(stderr,"Unrecognized specifier \"%s\" on line %i\n", pnt,
 			line);
 		break;
@@ -1508,28 +1715,27 @@
 	 * OK, got one complete entry.  Make sure it has the required
 	 * fields, and then attempt to match it to a real device.
 	 */
-	if( name == NULL )
-	{
+	if( name == NULL ) {
 	    fprintf(stderr,"Line %d is missing \"alias\" specifier\n", line);
 	    continue;
 	}
-	if( devtype == NULL )
-	{
+	if( devtype == NULL ) {
 	    fprintf(stderr,"Line %d is missing \"devtype\" specifier\n", line);
 	    continue;
 	}
 	if( strcmp(devtype, "disk") == 0 )
-	    devtype_i = SCSI_DISK0_MAJOR;
+	    devtype_i = SD;
 	else if( strcmp(devtype, "cdrom") == 0)
-	    devtype_i = SCSI_CDROM_MAJOR;
+	    devtype_i = SR;
 	else if( strcmp(devtype, "tape") == 0)
-	    devtype_i = SCSI_TAPE_MAJOR;
+	    devtype_i = ST;
 	else if( strcmp(devtype, "osst") == 0)
-	    devtype_i = OSST_MAJOR;
+	    devtype_i = OSST;
 	else if(strcmp(devtype, "generic") == 0 )
-	    devtype_i = SCSI_GENERIC_MAJOR;
-	else
-	{
+	    devtype_i = SG;
+	else if(strcmp(devtype, "changer") == 0 )
+	    devtype_i = SCH;
+	else {
 	    fprintf(stderr,"Line %d has invalid  \"devtype\" specifier(%s)\n", 
 		    line, devtype);
 	    continue;
@@ -1540,25 +1746,32 @@
 	 * we know about already.
 	 */
 	match = NULL;
-	for (spnt = reglist; spnt; spnt = spnt->next)
-	{
-	    if( spnt->alias != NULL ) continue;
+	for (spnt = reglist; spnt; spnt = spnt->next) {
+	    if( spnt->alias != NULL )
+		continue;
 	    /*
 	     * Check the integers first.  Some of the strings we have to
 	     * request, and we want to avoid this if possible.
 	     */
-	    if( id != -1 && id != spnt->id ) continue;
-	    if( chan != -1 && id != spnt->chan ) continue;
-	    if( lun != -1 && lun != spnt->lun ) continue;
-	    if( hostid != -1 && hostid != spnt->hostid ) continue;
-	    if( hostnum != -1 && hostnum != spnt->hostnum ) continue;
-	    if( devtype_i != spnt->major && 
-		(devtype_i != SCSI_DISK0_MAJOR || ! SCSI_DISK_MAJOR(spnt->major)) )
-		continue;
-	    if( part != spnt->partition ) continue;
-	    if( (spnt->major == SCSI_TAPE_MAJOR || spnt->major == OSST_MAJOR)
-		&& (spnt->minor & 0x80) != 0) continue;
-	    if( wwid != no_wwid && wwid != spnt->wwid ) continue;
+	    if( id != -1 && id != spnt->id ) 
+		continue;
+	    if( chan != -1 && id != spnt->chan ) 
+		continue;
+	    if( lun != -1 && lun != spnt->lun ) 
+		continue;
+	    if( hostid != -1 && hostid != spnt->hostid ) 
+		continue;
+	    if( hostnum != -1 && hostnum != spnt->hostnum ) 
+		continue;
+	    if( spnt->devtp != devtype_i )
+		continue;
+	    if( part != spnt->partition )
+		continue;
+	    if( (spnt->devtp == ST || spnt->devtp == OSST)
+		&& (spnt->minor & 0x80) != 0) 
+		continue;
+	    if( wwid != no_wwid && wwid != spnt->wwid ) 
+		continue;
 
 	    /*
 	     * OK, that matches, now obtain some of the strings
@@ -1588,8 +1801,7 @@
 	     * We have a match.  Record it and keep looking just in
 	     * case we find a duplicate.
 	     */
-	    if( match != NULL )
-	    {
+	    if( match != NULL ) {
 		fprintf (stderr, "Line %d not matched uniquely\n", line);
 		fprintf (stderr, " Prev. match: %s\n", match->name);
 		fprintf (stderr, " Curr. match: %s\n", spnt->name);
@@ -1608,8 +1820,7 @@
 	if( spnt != NULL )
 	    continue;
 
-	if( match != NULL )
-	{
+	if( match != NULL ) {
 	    /*
 	     * OK, we have a unique match.  Create the device entries,
 	     * as requested.
@@ -1622,14 +1833,11 @@
 		    fprintf (stderr, "(%s=%s)\n",
 			     strrchr (match->related->name, '/') + 1,
 			     strrchr (oldscsiname (match->related), '/') + 1);
-		else fprintf (stderr, "\n");
+		else 
+		    fprintf (stderr, "\n");
 	    }
 
-	    if( SCSI_DISK_MAJOR(devtype_i)
-		|| devtype_i == SCSI_CDROM_MAJOR )
-		type = S_IFBLK;
-	    else
-		type = S_IFCHR;
+	    type = isblk (match->devtp)? S_IFBLK: S_IFCHR;
 
 	    /*
 	     * If this is just an ordinary single device type,
@@ -1646,8 +1854,7 @@
 		update_device (scsidev, type, 
 			       match->major, match->minor);
 
-	    if( devtype_i == SCSI_TAPE_MAJOR || devtype_i == OSST_MAJOR )
-	    {
+	    if( devtype_i == ST || devtype_i == OSST ) {
 		sprintf (scsidev, DEVSCSI "/n%s", name);
 		register_dev (scsidev, match->major, match->minor | 0x80, 
 			      0, 0, 0, 0, 0, 0, 0, match);
@@ -1661,9 +1868,8 @@
 				   match->major, (match->minor | 0x80) );
 	    }
 
-	    if ( devtype_i == SCSI_DISK0_MAJOR
-		 && match->partition == -1 )
-	    {
+	    if ( devtype_i == SD 
+		 && match->partition == -1 ) {
 		/*
 		 * This is the master entry for a disk.
 		 * we need to go through and generate entries
@@ -1671,8 +1877,7 @@
 		 * all of the related entries so we know which
 		 * ones we actually need to create.
 		 */
-		for( spnt = reglist; spnt; spnt = spnt->next )
-		{
+		for( spnt = reglist; spnt; spnt = spnt->next ) {
 		    if( spnt->alias != NULL ) continue;
 		    if( spnt->partition == -1 ) continue;
 		    if( spnt->major != devtype_i ) continue;
@@ -1689,8 +1894,7 @@
 		    if (symlink_alias) {
 			unlink (scsidev);
 			symlink (match->name, scsidev);
-		    }
-		    else
+		    } else
 			update_device (scsidev, S_IFBLK, 
 				       match->major, spnt->minor);
 		}
@@ -1803,8 +2007,7 @@
     // Std. inquiry
     status = get_inq_page (infile, 0, buffer, 0, 0);
 
-    if (status) 
-    { 
+    if (status) { 
 	fprintf (stderr, "INQUIRY failed for %s (%i-%i/%02x:%02x)!\n",
 		 spnt->name, spnt->id, spnt->lun, spnt->major, spnt->minor);
 	return -1;
