[Top][All Lists]
[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
- [Libcdio-devel] [Patch] More bullet-proof drive detection for GNU/Linux, plaum, 2006/11/20
- [Libcdio-devel] [Patch] More bullet-proof drive detection for GNU/Linux,
R. Bernstein <=
- [Libcdio-devel] [Patch] More bullet-proof drive detection for GNU/Linux, R. Bernstein, 2006/11/20
- Re: [Libcdio-devel] [Patch] More bullet-proof drive detection for GNU/Linux, plaum, 2006/11/21
- Message not available
- Re: [Libcdio-devel] [Patch] More bullet-proof drive detection for GNU/Linux, plaum, 2006/11/27
- Re: [Libcdio-devel] [Patch] More bullet-proof drive detection for GNU/Linux, R. Bernstein, 2006/11/28
- Re: [Libcdio-devel] [Patch] More bullet-proof drive detection for GNU/Linux, Burkhard Plaum, 2006/11/28
- Re: [Libcdio-devel] [Patch] More bullet-proof drive detection for GNU/Linux, R. Bernstein, 2006/11/28
- Re: [Libcdio-devel] [Patch] More bullet-proof drive detection for GNU/Linux, Burkhard Plaum, 2006/11/28
- Re: [Libcdio-devel] [Patch] More bullet-proof drive detection for GNU/Linux, R. Bernstein, 2006/11/28
- Re: [Libcdio-devel] [Patch] More bullet-proof drive detection for GNU/Linux, Burkhard Plaum, 2006/11/28