libcdio-devel
[Top][All Lists]
Advanced

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

[Libcdio-devel] [Patch] More bullet-proof drive detection for GNU/Linux


From: R. Bernstein
Subject: [Libcdio-devel] [Patch] More bullet-proof drive detection for GNU/Linux
Date: Mon, 20 Nov 2006 16:38:03 -0500

For the record, SCSI-1 had up to 8 devices off of a chain and SCSI-2
has up to 16 devices. It might have been that 0 was the address of the
controller -  I don't know.

Personally, I'm saddened by all of the nonesense that has to go on to
do something simple like get a list of CD-ROM drives. There's gotta be
a simpler way. HAL (Hardware Abstraction Layer)? Reading
/proc/scsi/sg/devices and /proc/ide?  Again, I don't know. Parsing
dmesg?

address@hidden writes:
 > Hi,
 > 
 > the drive detection for GNU/Linux had several flaws, e.g. if /dev/hda is
 > a harddisk and /dev/hdb is a CDRom which is *not* in fstab or mtab, it
 > wasn't found.
 > 
 > So I made a patch, does the following:
 > 
 > - The drive detection tries hd[a-z], sr[0-27], scd[0-27] and no longer
 >   stops if a non-cd drive was found (or if the device doesn't exist).
 >   I'm not a SCSI expert but I heard something about a maximum of
 >   4 SCSI controllers with 7 drives each.
 > 
 > - The function cdio_add_device_list() now adds drives, which come
 >   under different names (i.e. as symlinks) only once.
 > 
 > - A new function libcdio_follow_symlink() in util.c (moved from
 >   gnu_linux.c, where I wrote it earlier).
 > 
 > - Unrelated but trivial: The trailing "cvs" is removed from the
 >   LIBCDIO_VERSION_NUM in the configure script to allow arithmetic
 >   comparisons.
 > 
 > It works pretty well here, but since it changes some major behaviour,
 > I to post it here before I apply it.
 > 
 > Cheers
 > 
 > BurkhardIndex: configure.ac
 > ===================================================================
 > RCS file: /sources/libcdio/libcdio/configure.ac,v
 > retrieving revision 1.203
 > diff -u -r1.203 configure.ac
 > --- configure.ac     16 Nov 2006 00:47:28 -0000      1.203
 > +++ configure.ac     20 Nov 2006 19:05:36 -0000
 > @@ -32,7 +32,7 @@
 >  AC_CANONICAL_HOST
 >  AM_CONFIG_HEADER(config.h)
 >  
 > -LIBCDIO_VERSION_NUM=`echo RELEASE_NUM | cut -d . -f 1`
 > +LIBCDIO_VERSION_NUM=`echo RELEASE_NUM | cut -d . -f 1 | tr -d a-z`
 >  AC_SUBST(LIBCDIO_VERSION_NUM)
 >  
 >  AM_MISSING_PROG(HELP2MAN, help2man, $missing_dir)
 > @@ -480,7 +480,7 @@
 >  
 >  AC_CHECK_FUNCS( [bzero drand48 ftruncate geteuid getgid \
 >               getuid getpwuid gettimeofday lstat memcpy memset \
 > -             rand seteuid setegid snprintf  tzset vsnprintf] )
 > +             rand seteuid setegid snprintf  tzset vsnprintf readlink] )
 >  
 >  AC_CHECK_MEMBER([struct tm.tm_gmtoff],
 >                  [AC_DEFINE(HAVE_TM_GMTOFF, 1,
 > Index: include/cdio/util.h
 > ===================================================================
 > RCS file: /sources/libcdio/libcdio/include/cdio/util.h,v
 > retrieving revision 1.10
 > diff -u -r1.10 util.h
 > --- include/cdio/util.h      18 Mar 2006 00:53:20 -0000      1.10
 > +++ include/cdio/util.h      20 Nov 2006 19:05:36 -0000
 > @@ -100,6 +100,8 @@
 >  uint8_t cdio_to_bcd8(uint8_t n);
 >  uint8_t cdio_from_bcd8(uint8_t p);
 >  
 > +void cdio_follow_symlink (const char * src, char * dst);
 > +  
 >  #ifdef __cplusplus
 >  }
 >  #endif
 > Index: lib/driver/_cdio_generic.c
 > ===================================================================
 > RCS file: /sources/libcdio/libcdio/lib/driver/_cdio_generic.c,v
 > retrieving revision 1.22
 > diff -u -r1.22 _cdio_generic.c
 > --- lib/driver/_cdio_generic.c       26 Mar 2006 02:35:26 -0000      1.22
 > +++ lib/driver/_cdio_generic.c       20 Nov 2006 19:05:37 -0000
 > @@ -38,6 +38,7 @@
 >  #endif /*HAVE_UNISTD_H*/
 >  
 >  #include <fcntl.h>
 > +#include <limits.h>
 >  
 >  #include <sys/stat.h>
 >  #include <sys/types.h>
 > @@ -221,24 +222,22 @@
 >  {
 >    if (NULL != drive) {
 >      unsigned int j;
 > -
 > +    char real_device_1[PATH_MAX];
 > +    char real_device_2[PATH_MAX];
 > +    cdio_follow_symlink(drive, real_device_1);
 >      /* Check if drive is already in list. */
 >      for (j=0; j<*num_drives; j++) {
 > -      if (strcmp((*device_list)[j], drive) == 0) break;
 > +      cdio_follow_symlink((*device_list)[j], real_device_2);
 > +      if (strcmp(real_device_1, real_device_2) == 0) break;
 >      }
 >  
 >      if (j==*num_drives) {
 >        /* Drive not in list. Add it. */
 >        (*num_drives)++;
 > -      if (*device_list) {
 > -        *device_list = realloc(*device_list, (*num_drives) * sizeof(char 
 > *));
 > -      } else {
 > -        /* num_drives should be 0. Add assert? */
 > -        *device_list = malloc((*num_drives) * sizeof(char *));
 > +      *device_list = realloc(*device_list, (*num_drives) * sizeof(char *));
 > +      (*device_list)[*num_drives-1] = strdup(drive);
 >        }
 >        
 > -      (*device_list)[*num_drives-1] = strdup(drive);
 > -    }
 >    } else {
 >      (*num_drives)++;
 >      if (*device_list) {
 > Index: lib/driver/gnu_linux.c
 > ===================================================================
 > RCS file: /sources/libcdio/libcdio/lib/driver/gnu_linux.c,v
 > retrieving revision 1.26
 > diff -u -r1.26 gnu_linux.c
 > --- lib/driver/gnu_linux.c   21 Oct 2006 11:38:16 -0000      1.26
 > +++ lib/driver/gnu_linux.c   20 Nov 2006 19:05:40 -0000
 > @@ -595,30 +595,6 @@
 >    }
 >  }
 >  
 > -/*!
 > -  Follow symlinks until we have the real device file
 > -  (idea taken from libunieject). 
 > -*/
 > -
 > -static void follow_symlink (const char * src, char * dst) {
 > -  char tmp_src[PATH_MAX];
 > -  char tmp_dst[PATH_MAX];
 > -  
 > -  int len;
 > -
 > -  strcpy(tmp_src, src);
 > -  while(1) {
 > -    len = readlink(tmp_src, tmp_dst, PATH_MAX);
 > -    if(len < 0) {
 > -      strcpy(dst, tmp_src);
 > -      return;
 > -    }
 > -    else {
 > -      tmp_dst[len] = '\0';
 > -      strcpy(tmp_src, tmp_dst);
 > -    }
 > -  }
 > -}
 >  
 >  /*!
 >    Check, if a device is mounted and return the target (=mountpoint)
 > @@ -642,12 +618,12 @@
 >    if(!fp) return 0;
 >  
 >    /* Get real device */
 > -  follow_symlink(device, real_device_1);
 > +  cdio_follow_symlink(device, real_device_1);
 >      
 >    /* Read entries */
 >  
 >    while ( fscanf(fp, "%s %s %*s %*s %*d %*d\n", file_device, file_target) 
 > != EOF ) {
 > -    follow_symlink(file_device, real_device_2);
 > +    cdio_follow_symlink(file_device, real_device_2);
 >      if(!strcmp(real_device_1, real_device_2)) {
 >        strcpy(target, file_target);
 >        fclose(fp);
 > @@ -1351,9 +1327,20 @@
 >  static char checklist1[][40] = {
 >    {"cdrom"}, {"dvd"}, {""}
 >  };
 > -static char checklist2[][40] = {
 > -  {"?a hd?"}, {"?0 scd?"}, {"?0 sr?"}, {""}
 > -};
 > +
 > +static struct
 > +  {
 > +    const char * format;
 > +    int num_min;
 > +    int num_max;
 > +  }
 > +checklist2[] =
 > +  {
 > +    { "/dev/hd%c",  'a', 'z' },
 > +    { "/dev/scd%d", 0,   27 },
 > +    { "/dev/sr%d",  0,   27 },
 > +    { /* End of array */ }
 > +  };
 >  
 >  /* Set CD-ROM drive speed */
 >  static driver_return_code_t
 > @@ -1379,15 +1366,14 @@
 >    unsigned int i;
 >    char drive[40];
 >    char *ret_drive;
 > -  bool exists;
 >    char **drives = NULL;
 >    unsigned int num_drives=0;
 > -  
 > +
 >    /* Scan the system for CD-ROM drives.
 >    */
 >    for ( i=0; strlen(checklist1[i]) > 0; ++i ) {
 >      sprintf(drive, "/dev/%s", checklist1[i]);
 > -    if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) {
 > +    if ( is_cdrom_linux(drive, NULL) > 0 ) {
 >        cdio_add_device_list(&drives, drive, &num_drives);
 >      }
 >    }
 > @@ -1407,17 +1393,11 @@
 >    /* Scan the system for CD-ROM drives.
 >       Not always 100% reliable, so use the USE_MNTENT code above first.
 >    */
 > -  for ( i=0; strlen(checklist2[i]) > 0; ++i ) {
 > +  for ( i=0; checklist2[i].format; ++i ) {
 >      unsigned int j;
 > -    char *insert;
 > -    exists = true;
 > -    for ( j=checklist2[i][1]; exists; ++j ) {
 > -      sprintf(drive, "/dev/%s", &checklist2[i][3]);
 > -      insert = strchr(drive, '?');
 > -      if ( insert != NULL ) {
 > -    *insert = j;
 > -      }
 > -      if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) {
 > +    for ( j=checklist2[i].num_min; j<=checklist2[i].num_max; ++j ) {
 > +      sprintf(drive, checklist2[i].format, j);
 > +      if ( (is_cdrom_linux(drive, NULL)) > 0 ) {
 >      cdio_add_device_list(&drives, drive, &num_drives);
 >        }
 >      }
 > @@ -1439,14 +1419,13 @@
 >  #else
 >    unsigned int i;
 >    char drive[40];
 > -  bool exists;
 >    char *ret_drive;
 >  
 >    /* Scan the system for CD-ROM drives.
 >    */
 >    for ( i=0; strlen(checklist1[i]) > 0; ++i ) {
 >      sprintf(drive, "/dev/%s", checklist1[i]);
 > -    if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) {
 > +    if ( is_cdrom_linux(drive, NULL) > 0 ) {
 >        return strdup(drive);
 >      }
 >    }
 > @@ -1462,17 +1441,11 @@
 >    /* Scan the system for CD-ROM drives.
 >       Not always 100% reliable, so use the USE_MNTENT code above first.
 >    */
 > -  for ( i=0; strlen(checklist2[i]) > 0; ++i ) {
 > +  for ( i=0; checklist2[i].format; ++i ) {
 >      unsigned int j;
 > -    char *insert;
 > -    exists = true;
 > -    for ( j=checklist2[i][1]; exists; ++j ) {
 > -      sprintf(drive, "/dev/%s", &checklist2[i][3]);
 > -      insert = strchr(drive, '?');
 > -      if ( insert != NULL ) {
 > -    *insert = j;
 > -      }
 > -      if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) {
 > +    for ( j=checklist2[i].num_min; j<=checklist2[i].num_max; ++j ) {
 > +      sprintf(drive, checklist2[i].format, j);
 > +      if ( is_cdrom_linux(drive, NULL) > 0 ) {
 >      return(strdup(drive));
 >        }
 >      }
 > Index: lib/driver/util.c
 > ===================================================================
 > RCS file: /sources/libcdio/libcdio/lib/driver/util.c,v
 > retrieving revision 1.3
 > diff -u -r1.3 util.c
 > --- lib/driver/util.c        18 Mar 2006 00:53:20 -0000      1.3
 > +++ lib/driver/util.c        20 Nov 2006 19:05:40 -0000
 > @@ -27,6 +27,11 @@
 >  #include <stdlib.h>
 >  #include <stdio.h>
 >  #include <string.h>
 > +#include <limits.h>
 > +
 > +#ifdef HAVE_UNISTD_H // readlink
 > +#include <unistd.h>
 > +#endif
 >  
 >  #ifdef HAVE_INTTYPES_H
 >  #include "inttypes.h"
 > @@ -145,6 +150,36 @@
 >    return (0xf & p)+(10*(p >> 4));
 >  }
 >  
 > +/*!
 > +  Follow symlinks until we have the real device file
 > +  (idea taken from libunieject). 
 > +*/
 > +
 > +void cdio_follow_symlink (const char * src, char * dst) {
 > +#ifdef HAVE_READLINK
 > +  char tmp_src[PATH_MAX];
 > +  char tmp_dst[PATH_MAX];
 > +  
 > +  int len;
 > +
 > +  strcpy(tmp_src, src);
 > +  while(1) {
 > +    len = readlink(tmp_src, tmp_dst, PATH_MAX);
 > +    if(len < 0) {
 > +      strcpy(dst, tmp_src);
 > +      return;
 > +    }
 > +    else {
 > +      tmp_dst[len] = '\0';
 > +      strcpy(tmp_src, tmp_dst);
 > +    }
 > +  }
 > +#else
 > +  strcpy(dst, src);
 > +#endif
 > +  
 > +}
 > +
 >  
 >  /* 
 >   * Local variables:_______________________________________________
 > Libcdio-devel mailing list
 > address@hidden
 > http://lists.gnu.org/mailman/listinfo/libcdio-devel




reply via email to

[Prev in Thread] Current Thread [Next in Thread]