Add ability to retrieve SCSI tuple for a name and/or fake one up. This
helps programs that want to be cd-record compatible. In particular to parameters were added to cdio_get_arg, "scsi-tuple", and "scsi-tuple-linux". Code from Thomas Schmitt.
This commit is contained in:
@@ -1,6 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
$Id: _cdio_generic.c,v 1.27 2008/04/22 15:29:11 karl Exp $
|
|
||||||
|
|
||||||
Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
|
Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
|
||||||
Rocky Bernstein <rocky@gnu.org>
|
Rocky Bernstein <rocky@gnu.org>
|
||||||
|
|
||||||
@@ -105,6 +103,9 @@ cdio_generic_free (void *p_user_data)
|
|||||||
if (p_env->fd >= 0)
|
if (p_env->fd >= 0)
|
||||||
close (p_env->fd);
|
close (p_env->fd);
|
||||||
|
|
||||||
|
if (p_env->scsi_tuple != NULL)
|
||||||
|
free (p_env->scsi_tuple);
|
||||||
|
|
||||||
free (p_env);
|
free (p_env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,16 @@ extern "C" {
|
|||||||
but 263 bytes possible */
|
but 263 bytes possible */
|
||||||
int scsi_mmc_sense_valid; /* Number of valid sense bytes */
|
int scsi_mmc_sense_valid; /* Number of valid sense bytes */
|
||||||
|
|
||||||
|
/* Memorized eventual system specific SCSI address tuple text.
|
||||||
|
Empty text means that there is no such text defined for the drive.
|
||||||
|
NULL means that the driver does not support "scsi-tuple".
|
||||||
|
To be read by cdio_get_arg("scsi-tuple").
|
||||||
|
System specific suffixes to the key may demand and eventually
|
||||||
|
guarantee a further specified format.
|
||||||
|
E.g. "scsi-tuple-linux" guarantees either "Bus,Host,Channel,Target,Lun",
|
||||||
|
or empty text, or NULL. No other forms.
|
||||||
|
*/
|
||||||
|
char *scsi_tuple;
|
||||||
} generic_img_private_t;
|
} generic_img_private_t;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
@@ -385,6 +385,10 @@ get_arg_linux (void *env, const char key[])
|
|||||||
case _AM_NONE:
|
case _AM_NONE:
|
||||||
return "no access method";
|
return "no access method";
|
||||||
}
|
}
|
||||||
|
} else if (!strcmp (key, "scsi-tuple")) {
|
||||||
|
return _obj->gen.scsi_tuple;
|
||||||
|
} else if (!strcmp (key, "scsi-tuple-linux")) {
|
||||||
|
return _obj->gen.scsi_tuple;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1548,6 +1552,77 @@ close_tray_linux (const char *psz_device)
|
|||||||
#endif /*HAVE_LINUX_CDROM*/
|
#endif /*HAVE_LINUX_CDROM*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Produce a text composed from the system SCSI address tuple according to
|
||||||
|
habits of Linux 2.4 and 2.6 : "Bus,Host,Channel,Target,Lun" and store
|
||||||
|
it in generic_img_private_t.scsi_tuple.
|
||||||
|
To be accessed via cdio_get_arg("scsi-tuple-linux") or ("scsi-tuple").
|
||||||
|
Drivers which implement this code have to return 5 valid decimal numbers
|
||||||
|
separated by comma, or empty text if no such numbers are available.
|
||||||
|
@return 1=success , 0=failure
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
set_scsi_tuple_linux(_img_private_t *env)
|
||||||
|
{
|
||||||
|
int bus_no = -1, host_no = -1, channel_no = -1, target_no = -1, lun_no = -1;
|
||||||
|
int ret, i;
|
||||||
|
char tuple[160], hdx[10];
|
||||||
|
#ifdef SCSI_IOCTL_GET_IDLUN
|
||||||
|
struct my_scsi_idlun {
|
||||||
|
int x;
|
||||||
|
int host_unique_id;
|
||||||
|
};
|
||||||
|
struct my_scsi_idlun idlun;
|
||||||
|
#endif
|
||||||
|
struct stat stbuf, env_stbuf;
|
||||||
|
|
||||||
|
/* Check whether this is a hdX and declare tuple unavailable.
|
||||||
|
/dev/hdX is traditionally for IDE drives and the ioctls here traditionally
|
||||||
|
return ok and all 0s for all IDE drives. So the tuples are no unique ids.
|
||||||
|
*/
|
||||||
|
if (fstat(env->gen.fd, &env_stbuf) == -1)
|
||||||
|
goto no_tuple;
|
||||||
|
strcpy(hdx, "/dev/hdX");
|
||||||
|
for (i = 'a'; i <= 'z'; i++) {
|
||||||
|
hdx[7] = i;
|
||||||
|
if (stat(hdx, &stbuf) == -1)
|
||||||
|
continue;
|
||||||
|
if (env_stbuf.st_dev == stbuf.st_dev && env_stbuf.st_ino == stbuf.st_ino)
|
||||||
|
goto no_tuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SCSI_IOCTL_GET_BUS_NUMBER
|
||||||
|
if (ioctl(env->gen.fd, SCSI_IOCTL_GET_BUS_NUMBER, &bus_no) == -1)
|
||||||
|
bus_no = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SCSI_IOCTL_GET_IDLUN
|
||||||
|
/* http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/scsi_g_idlun.html */
|
||||||
|
|
||||||
|
ret = ioctl(env->gen.fd, SCSI_IOCTL_GET_IDLUN, &idlun);
|
||||||
|
if (ret != -1) {
|
||||||
|
host_no= (idlun.x >> 24) & 255;
|
||||||
|
channel_no= (idlun.x >> 16) & 255;
|
||||||
|
target_no= (idlun.x) & 255;
|
||||||
|
lun_no= (idlun.x >> 8) & 255;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (env->gen.scsi_tuple != NULL)
|
||||||
|
free (env->gen.scsi_tuple);
|
||||||
|
env->gen.scsi_tuple = NULL;
|
||||||
|
if (bus_no < 0 || host_no < 0 || channel_no < 0 || target_no < 0 ||
|
||||||
|
lun_no < 0) {
|
||||||
|
no_tuple:;
|
||||||
|
env->gen.scsi_tuple = strdup("");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sprintf(tuple, "%d,%d,%d,%d,%d",
|
||||||
|
bus_no, host_no, channel_no, target_no, lun_no);
|
||||||
|
env->gen.scsi_tuple = strdup(tuple);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Initialization routine. This is the only thing that doesn't
|
Initialization routine. This is the only thing that doesn't
|
||||||
get called via a function pointer. In fact *we* are the
|
get called via a function pointer. In fact *we* are the
|
||||||
@@ -1685,6 +1760,7 @@ cdio_open_am_linux (const char *psz_orig_source, const char *access_mode)
|
|||||||
else
|
else
|
||||||
open_access_mode |= O_RDONLY;
|
open_access_mode |= O_RDONLY;
|
||||||
if (cdio_generic_init(_data, open_access_mode)) {
|
if (cdio_generic_init(_data, open_access_mode)) {
|
||||||
|
set_scsi_tuple_linux(_data);
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
cdio_generic_free (_data);
|
cdio_generic_free (_data);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ main(int argc, const char *argv[])
|
|||||||
|
|
||||||
cdio_loglevel_default = (argc > 1) ? CDIO_LOG_DEBUG : CDIO_LOG_INFO;
|
cdio_loglevel_default = (argc > 1) ? CDIO_LOG_DEBUG : CDIO_LOG_INFO;
|
||||||
/* snprintf(psz_nrgfile, sizeof(psz_nrgfile)-1,
|
/* snprintf(psz_nrgfile, sizeof(psz_nrgfile)-1,
|
||||||
"%s/%s", TEST_DIR, cue_file[i]);
|
"%s/%s", TEST_DIR, cue_file[i]);
|
||||||
*/
|
*/
|
||||||
if (!cdio_have_driver(DRIVER_LINUX)) return(77);
|
if (!cdio_have_driver(DRIVER_LINUX)) return(77);
|
||||||
ppsz_drives = cdio_get_devices(DRIVER_DEVICE);
|
ppsz_drives = cdio_get_devices(DRIVER_DEVICE);
|
||||||
@@ -56,14 +56,32 @@ main(int argc, const char *argv[])
|
|||||||
if (p_cdio) {
|
if (p_cdio) {
|
||||||
const char *psz_source = cdio_get_arg(p_cdio, "source");
|
const char *psz_source = cdio_get_arg(p_cdio, "source");
|
||||||
if (0 != strncmp(psz_source, ppsz_drives[0],
|
if (0 != strncmp(psz_source, ppsz_drives[0],
|
||||||
strlen(ppsz_drives[0]))) {
|
strlen(ppsz_drives[0]))) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Got %s; should get back %s, the name we opened.\n",
|
"Got %s; should get back %s, the name we opened.\n",
|
||||||
psz_source, ppsz_drives[0]);
|
psz_source, ppsz_drives[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const char *psz_source = NULL, *scsi_tuple, *scsi_tuple_linux;
|
||||||
|
|
||||||
|
scsi_tuple_linux = cdio_get_arg(p_cdio, "scsi-tuple-linux");
|
||||||
|
if (scsi_tuple_linux == NULL) {
|
||||||
|
fprintf(stderr, "cdio_get_arg(\"scsi-tuple-linux\") returns NULL.\n");
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
scsi_tuple = cdio_get_arg(p_cdio, "scsi-tuple");
|
||||||
|
if (scsi_tuple != scsi_tuple_linux) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"cdio_get_arg(\"scsi-tuple\") differs from cdio_get_arg(\"scsi-tuple-linux\").\n");
|
||||||
|
exit(4);
|
||||||
|
}
|
||||||
|
if (cdio_loglevel_default == CDIO_LOG_DEBUG)
|
||||||
|
printf("Drive '%s' has cdio_get_arg(\"scsi-tuple\") = '%s'\n",
|
||||||
|
psz_source, scsi_tuple);
|
||||||
|
}
|
||||||
|
|
||||||
cdio_destroy(p_cdio);
|
cdio_destroy(p_cdio);
|
||||||
p_cdio = cdio_open_am_linux(ppsz_drives[0], "MMC_RDWR");
|
p_cdio = cdio_open_am_linux(ppsz_drives[0], "MMC_RDWR");
|
||||||
@@ -71,10 +89,10 @@ main(int argc, const char *argv[])
|
|||||||
const char *psz_access_mode = cdio_get_arg(p_cdio, "access-mode");
|
const char *psz_access_mode = cdio_get_arg(p_cdio, "access-mode");
|
||||||
|
|
||||||
if (0 != strncmp(psz_access_mode, "MMC_RDWR", strlen("MMC_RDWR"))) {
|
if (0 != strncmp(psz_access_mode, "MMC_RDWR", strlen("MMC_RDWR"))) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Got %s; Should get back %s, the access mode requested.\n",
|
"Got %s; Should get back %s, the access mode requested.\n",
|
||||||
psz_access_mode, "MMC_RDWR");
|
psz_access_mode, "MMC_RDWR");
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user