Make GNU/Linux smarter about finding a default device -- code sort of from SDL.

Better error checking all around.
This commit is contained in:
rocky
2003-06-12 04:46:27 +00:00
parent 55d3b3196d
commit 67051b0f71
4 changed files with 225 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
/*
$Id: _cdio_generic.c,v 1.9 2003/06/07 16:49:50 rocky Exp $
$Id: _cdio_generic.c,v 1.10 2003/06/12 04:46:27 rocky Exp $
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
@@ -27,7 +27,7 @@
# include "config.h"
#endif
static const char _rcsid[] = "$Id: _cdio_generic.c,v 1.9 2003/06/07 16:49:50 rocky Exp $";
static const char _rcsid[] = "$Id: _cdio_generic.c,v 1.10 2003/06/12 04:46:27 rocky Exp $";
#include <stdio.h>
#include <stdlib.h>
@@ -148,9 +148,22 @@ cdio_is_device_generic(const char *source_name)
{
struct stat buf;
if (0 != stat(source_name, &buf)) {
cdio_error ("Can't get file status for %s:\n%s", source_name,
cdio_warn ("Can't get file status for %s:\n%s", source_name,
strerror(errno));
return false;
}
return (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode));
}
/*!
Like above, but don't give a warning device doesn't exist.
*/
bool
cdio_is_device_quiet_generic(const char *source_name)
{
struct stat buf;
if (0 != stat(source_name, &buf)) {
return false;
}
return (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode));
}

View File

@@ -1,5 +1,5 @@
/*
$Id: _cdio_linux.c,v 1.12 2003/05/16 07:18:27 rocky Exp $
$Id: _cdio_linux.c,v 1.13 2003/06/12 04:46:27 rocky Exp $
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
@@ -27,7 +27,7 @@
# include "config.h"
#endif
static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.12 2003/05/16 07:18:27 rocky Exp $";
static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.13 2003/06/12 04:46:27 rocky Exp $";
#include <string.h>
@@ -36,8 +36,6 @@ static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.12 2003/05/16 07:18:27 rock
#include "cdio_assert.h"
#include "cdio_private.h"
#define DEFAULT_CDIO_DEVICE "/dev/cdrom"
#ifdef HAVE_LINUX_CDROM
#if defined(HAVE_LINUX_VERSION_H)
@@ -56,6 +54,7 @@ static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.12 2003/05/16 07:18:27 rock
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <mntent.h>
#include <linux/cdrom.h>
#include <scsi/scsi.h>
@@ -88,6 +87,109 @@ typedef struct {
} _img_private_t;
/* Some ioctl() errno values which occur when the tray is empty */
#define ERRNO_TRAYEMPTY(errno) \
((errno == EIO) || (errno == ENOENT) || (errno == EINVAL))
/* Check a drive to see if it is a CD-ROM
Return 1 if a CD-ROM. 0 if it exists but isn't a CD-ROM drive
and -1 if no device exists .
*/
static int
cdio_is_cdrom(char *drive, char *mnttype)
{
bool is_cd=false;
int cdfd;
struct cdrom_tochdr tochdr;
/* If it doesn't exist, return -1 */
if ( !cdio_is_device_quiet_generic(drive) ) {
return(false);
}
/* If it does exist, verify that it's an available CD-ROM */
cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0);
if ( cdfd >= 0 ) {
if ( ioctl(cdfd, CDROMREADTOCHDR, &tochdr) != -1 ) {
is_cd = true;
}
close(cdfd);
}
/* Even if we can't read it, it might be mounted */
else if ( mnttype && (strcmp(mnttype, "iso9660") == 0) ) {
is_cd = true;
}
return(is_cd);
}
static char *
cdio_check_mounts(const char *mtab)
{
FILE *mntfp;
struct mntent *mntent;
mntfp = setmntent(mtab, "r");
if ( mntfp != NULL ) {
char *tmp;
char *mnt_type;
char *mnt_dev;
while ( (mntent=getmntent(mntfp)) != NULL ) {
mnt_type = malloc(strlen(mntent->mnt_type) + 1);
if (mnt_type == NULL)
continue; /* maybe you'll get lucky next time. */
mnt_dev = malloc(strlen(mntent->mnt_fsname) + 1);
if (mnt_dev == NULL) {
free(mnt_type);
continue;
}
strcpy(mnt_type, mntent->mnt_type);
strcpy(mnt_dev, mntent->mnt_fsname);
/* Handle "supermount" filesystem mounts */
if ( strcmp(mnt_type, "supermount") == 0 ) {
tmp = strstr(mntent->mnt_opts, "fs=");
if ( tmp ) {
free(mnt_type);
mnt_type = strdup(tmp + strlen("fs="));
if ( mnt_type ) {
tmp = strchr(mnt_type, ',');
if ( tmp ) {
*tmp = '\0';
}
}
}
tmp = strstr(mntent->mnt_opts, "dev=");
if ( tmp ) {
free(mnt_dev);
mnt_dev = strdup(tmp + strlen("dev="));
if ( mnt_dev ) {
tmp = strchr(mnt_dev, ',');
if ( tmp ) {
*tmp = '\0';
}
}
}
}
if ( strcmp(mnt_type, "iso9660") == 0 ) {
if (cdio_is_cdrom(mnt_dev, mnt_type) > 0) {
free(mnt_dev);
free(mnt_type);
endmntent(mntfp);
return strdup(mnt_dev);
}
}
free(mnt_dev);
free(mnt_type);
}
endmntent(mntfp);
}
return NULL;
}
static int
_set_bsize (int fd, unsigned int bsize)
{
@@ -766,7 +868,59 @@ _cdio_get_track_msf(void *user_data, track_t track_num, msf_t *msf)
char *
cdio_get_default_device_linux(void)
{
return strdup(DEFAULT_CDIO_DEVICE);
#ifndef HAVE_LINUX_CDROM
return NULL;
#else
/* checklist: /dev/cdrom, /dev/dvd /dev/hd?, /dev/scd? /dev/sr? */
static char checklist1[][40] = {
{"cdrom"}, {"dvd"}, {""}
};
static char checklist2[][40] = {
{"?a hd?"}, {"?0 scd?"}, {"?0 sr?"}, {""}
};
unsigned int i;
char drive[40];
int 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=cdio_is_cdrom(drive, NULL)) > 0 ) {
return strdup(drive);
}
}
/* Now check the currently mounted CD drives */
if (NULL != (ret_drive = cdio_check_mounts("/etc/mtab")))
return ret_drive;
/* Finally check possible mountable drives in /etc/fstab */
if (NULL != (ret_drive = cdio_check_mounts("/etc/fstab")))
return ret_drive;
/* 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 ) {
unsigned int j;
char *insert;
exists = 1;
for ( j=checklist2[i][1]; exists; ++j ) {
sprintf(drive, "/dev/%s", &checklist2[i][3]);
insert = strchr(drive, '?');
if ( insert != NULL ) {
*insert = j;
}
if ( (exists=cdio_is_cdrom(drive, NULL)) > 0 ) {
return(strdup(drive));
}
}
}
return NULL;
#endif /*HAVE_LINUX_CDROM*/
}
/*!
Initialization routine. This is the only thing that doesn't
@@ -774,12 +928,13 @@ cdio_get_default_device_linux(void)
ones to set that up.
*/
CdIo *
cdio_open_linux (const char *source_name)
cdio_open_linux (const char *orig_source_name)
{
#ifdef HAVE_LINUX_CDROM
CdIo *ret;
_img_private_t *_data;
char *source_name;
cdio_funcs _funcs = {
.eject_media = _cdio_eject_media,
@@ -806,8 +961,13 @@ cdio_open_linux (const char *source_name)
_data->gen.init = false;
_data->gen.fd = -1;
_cdio_set_arg(_data, "source", (NULL == source_name)
? DEFAULT_CDIO_DEVICE: source_name);
if (NULL == orig_source_name) {
source_name=cdio_get_default_device_linux();
if (NULL == source_name) return NULL;
_cdio_set_arg(_data, "source", source_name);
free(source_name);
} else
_cdio_set_arg(_data, "source", orig_source_name);
ret = cdio_new (_data, &_funcs);
if (ret == NULL) return NULL;

View File

@@ -1,5 +1,5 @@
/*
$Id: cdio_private.h,v 1.9 2003/06/07 16:48:33 rocky Exp $
$Id: cdio_private.h,v 1.10 2003/06/12 04:46:27 rocky Exp $
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
@@ -272,6 +272,12 @@ extern "C" {
bool cdio_is_device_generic(const char *source_name);
/*!
Like above, but don't give a warning device doesn't exist.
*/
bool cdio_is_device_quiet_generic(const char *source_name);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -1,5 +1,5 @@
/*
$Id: cd-info.c,v 1.11 2003/06/07 22:16:10 rocky Exp $
$Id: cd-info.c,v 1.12 2003/06/12 04:46:27 rocky Exp $
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
Copyright (C) 1996,1997,1998 Gerd Knorr <kraxel@bytesex.org>
@@ -95,8 +95,9 @@
#endif
#define err_exit(fmt, args...) \
fprintf(stderr, "%s: "fmt, program_name, ##args); \
myexit(EXIT_FAILURE)
{ fprintf(stderr, "%s: "fmt, program_name, ##args); \
myexit(EXIT_FAILURE); \
}
/*
Subject: -65- How can I read an IRIX (EFS) CD-ROM on a machine which
@@ -469,12 +470,17 @@ PARTICULAR PURPOSE.\n\
"));
if (version_only) {
char *default_device;
for (driver_id=DRIVER_UNKNOWN+1; driver_id<=MAX_DRIVER; driver_id++) {
if (cdio_have_driver(driver_id)) {
printf("Have driver: %s\n", cdio_driver_describe(driver_id));
}
}
printf("Default CD-ROM device: %s\n", cdio_get_default_device(NULL));
default_device=cdio_get_default_device(NULL);
if (default_device)
printf("Default CD-ROM device: %s\n", default_device);
else
printf("No CD-ROM device found.\n");
exit(100);
}
@@ -1033,23 +1039,43 @@ main(int argc, const char *argv[])
case IMAGE_UNKNOWN:
case IMAGE_AUTO:
cdio = cdio_open (source_name, DRIVER_UNKNOWN);
if (cdio==NULL) {
err_exit("%s: Error in automatically selecting driver with input\n",
program_name);
}
break;
case IMAGE_DEVICE:
cdio = cdio_open (source_name, DRIVER_DEVICE);
if (cdio==NULL) {
err_exit("%s: Error in automatically selecting device with input\n",
program_name);
}
break;
case IMAGE_BIN:
cdio = cdio_open (source_name, DRIVER_BINCUE);
if (cdio==NULL) {
err_exit("%s: Error in opeing bin/cue\n",
program_name);
}
break;
case IMAGE_CUE:
cdio = cdio_open_cue(source_name);
if (cdio==NULL) {
err_exit("%s: Error in opening cue/bin with input\n",
program_name);
}
break;
case IMAGE_NRG:
cdio = cdio_open (source_name, DRIVER_NRG);
if (cdio==NULL) {
err_exit("%s: Error in opening NRG with input\n",
program_name);
}
break;
}
if (cdio==NULL) {
err_exit("%s: Error in finding a usable device driver\n", program_name);
err_exit("%s: Error in opening device driver\n", program_name);
}
if (opts.debug_level > 0) {
@@ -1058,6 +1084,9 @@ main(int argc, const char *argv[])
if (source_name==NULL) {
source_name=strdup(cdio_get_arg(cdio, "source"));
if (NULL == source_name) {
err_exit("%s: No input device given/found\n", program_name);
}
}
first_track_num = cdio_get_first_track_num(cdio);