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
|
||||
Rocky Bernstein <rocky@gnu.org>
|
||||
|
||||
@@ -105,6 +103,9 @@ cdio_generic_free (void *p_user_data)
|
||||
if (p_env->fd >= 0)
|
||||
close (p_env->fd);
|
||||
|
||||
if (p_env->scsi_tuple != NULL)
|
||||
free (p_env->scsi_tuple);
|
||||
|
||||
free (p_env);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,16 @@ extern "C" {
|
||||
but 263 bytes possible */
|
||||
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;
|
||||
|
||||
/*!
|
||||
|
||||
@@ -385,6 +385,10 @@ get_arg_linux (void *env, const char key[])
|
||||
case _AM_NONE:
|
||||
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;
|
||||
}
|
||||
@@ -1548,6 +1552,77 @@ close_tray_linux (const char *psz_device)
|
||||
#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
|
||||
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
|
||||
open_access_mode |= O_RDONLY;
|
||||
if (cdio_generic_init(_data, open_access_mode)) {
|
||||
set_scsi_tuple_linux(_data);
|
||||
return ret;
|
||||
} else {
|
||||
cdio_generic_free (_data);
|
||||
|
||||
@@ -64,6 +64,24 @@ main(int argc, const char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
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);
|
||||
p_cdio = cdio_open_am_linux(ppsz_drives[0], "MMC_RDWR");
|
||||
|
||||
Reference in New Issue
Block a user