Taking into respect drive list from /proc/sys/dev/cdrom/info

This commit is contained in:
Thomas Schmitt 2008-08-05 18:00:37 +00:00
parent 98d742a4ef
commit ea17318e18
7 changed files with 270 additions and 38 deletions

View File

@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps .\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1) .\" other parameters are allowed: see man(7), man(1)
.TH CDRSKIN 1 "May 17, 2008" .TH CDRSKIN 1 "Aug 05, 2008"
.\" Please adjust this date whenever revising the manpage. .\" Please adjust this date whenever revising the manpage.
.\" .\"
.\" Some roff macros, for reference: .\" Some roff macros, for reference:
@ -1080,8 +1080,9 @@ Linux specific: Do not ask the operating system to prevent opening busy drives.
Wether this leads to senseful behavior depends on operating system and kernel. Wether this leads to senseful behavior depends on operating system and kernel.
.TP .TP
.BI drive_scsi_dev_family= sr | scd | sg .BI drive_scsi_dev_family= sr | scd | sg
Linux specific: Select a SCSI device file family to be used for drive command Linux specific: Select a SCSI device file family to be scanned for by
transactions. Normally this is /dev/sgN on kernel versions < 2.6 and /dev/srN options --devices and -scanbus.
Normally this is /dev/sgN on kernel versions < 2.6 and /dev/srN
on kernels >= 2.6 . This option allows to explicitely override that default on kernels >= 2.6 . This option allows to explicitely override that default
in order to meet other programs at a common device file for each drive. in order to meet other programs at a common device file for each drive.
On kernel 2.4 families sr and scd will find no drives. On kernel 2.4 families sr and scd will find no drives.

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2008.08.01.101053" #define Cdrskin_timestamP "2008.08.05.175930"

View File

@ -196,6 +196,31 @@ unsigned int burn_drive_count(void)
} }
/* ts A80801 */
int burn_drive_is_listed(char *path, struct burn_drive **found, int flag)
{
int i, ret;
char drive_adr[BURN_DRIVE_ADR_LEN], off_adr[BURN_DRIVE_ADR_LEN];
ret = burn_drive_convert_fs_adr(path, off_adr);
if (ret <= 0)
strcpy(off_adr, path);
for (i = 0; i <= drivetop; i++) {
if (drive_array[i].global_index < 0)
continue;
ret = burn_drive_d_get_adr(&(drive_array[i]), drive_adr);
if (ret <= 0)
continue;
if(strcmp(off_adr, drive_adr) == 0) {
if (found != NULL)
*found= &(drive_array[i]);
return 1;
}
}
return 0;
}
/* ts A61125 : media status aspects of burn_drive_grab() */ /* ts A61125 : media status aspects of burn_drive_grab() */
int burn_drive_inquire_media(struct burn_drive *d) int burn_drive_inquire_media(struct burn_drive *d)
{ {

View File

@ -131,4 +131,8 @@ int burn_drive_whitelist_count(void);
char *burn_drive_whitelist_item(int idx, int flag); char *burn_drive_whitelist_item(int idx, int flag);
/* ts A80801 */
int burn_drive_is_listed(char *path, struct burn_drive **found, int flag);
#endif /* __DRIVE */ #endif /* __DRIVE */

View File

@ -432,6 +432,8 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020007 (NOTE,HIGH) = Closed O_EXCL scsi siblings 0x00020007 (NOTE,HIGH) = Closed O_EXCL scsi siblings
0x00020008 (SORRY,HIGH) = Device busy. Failed to fcntl-lock 0x00020008 (SORRY,HIGH) = Device busy. Failed to fcntl-lock
0x00020009 (SORRY,HIGH) = Neither stdio-path nor its directory exist 0x00020009 (SORRY,HIGH) = Neither stdio-path nor its directory exist
0x0002000a (FAILURE,HIGH) = Cannot accept '...' as SG_IO CDROM drive
0x0002000b (FAILURE,HIGH) = File object '...' not found
General library operations: General library operations:

View File

@ -51,11 +51,17 @@ SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536 #define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
/* To hold the index number of the most recently delivered address from /* To hold the position of the most recently delivered address from
device enumeration. device enumeration.
*/ */
struct burn_drive_enumerator_struct {
int pos;
int info_count;
char **info_list;
};
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \ #define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
typedef int burn_drive_enumerator_t; typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
/* Parameters for sibling list. See sibling_fds, sibling_fnames */ /* Parameters for sibling list. See sibling_fds, sibling_fnames */

View File

@ -1093,19 +1093,62 @@ static void sg_enumerate(void)
#ifdef Libburn_drive_new_deaL #ifdef Libburn_drive_new_deaL
/* ts A80731 : Directly open the given address from a single-item whitlist */
int single_enumerate(int flag)
{
int wl_count, is_ata= 0, is_scsi= 0;
int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1;
char *fname;
wl_count= burn_drive_whitelist_count(); /* ts A80805 : eventually produce the other official name of a device file */
if (wl_count != 1) static int fname_other_name(char *fname, char other_name[80], int flag)
{
if(strncmp(fname, "/dev/sr", 7) == 0 &&
(fname[7] >= '0' && fname[7] <= '9') &&
(fname[8] == 0 ||
(fname[8] >= '0' && fname[8] <= '9' && fname[9] == 0))) {
sprintf(other_name, "/dev/scd%s", fname + 7);
return 1;
}
if(strncmp(fname, "/dev/scd", 8) == 0 &&
(fname[8] >= '0' && fname[8] <= '9') &&
(fname[9] == 0 ||
(fname[9] >= '0' && fname[9] <= '9' && fname[10] == 0))) {
sprintf(other_name, "/dev/sr%s", fname + 8);
return 1;
}
return 0; return 0;
fname= burn_drive_whitelist_item(0, 0); }
if (fname == NULL)
/* ts A80805 */
static int fname_drive_is_listed(char *fname, int flag)
{
char other_fname[80];
if (burn_drive_is_listed(fname, NULL, 0))
return 1;
if (fname_other_name(fname, other_fname, 0) > 0)
if (burn_drive_is_listed(other_fname, NULL, 0))
return 2;
return 0; return 0;
}
/* ts A80731 : Directly open the given address.
@param flag bit0= do not compain about missing file
*/
static int fname_enumerate(char *fname, int flag)
{
int is_ata= 0, is_scsi= 0;
int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1;
char msg[BURN_DRIVE_ADR_LEN + 80];
struct stat stbuf;
if (fname_drive_is_listed(fname, 0))
return 2;
if (stat(fname, &stbuf) == -1) {
sprintf(msg, "File object '%s' not found", fname);
if (!(flag & 1))
libdax_msgs_submit(libdax_messenger, -1, 0x0002000b,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return -1;
}
is_ata = is_ata_drive(fname); is_ata = is_ata_drive(fname);
if (is_ata < 0) if (is_ata < 0)
@ -1126,6 +1169,124 @@ int single_enumerate(int flag)
target_no, lun_no); target_no, lun_no);
return 1; return 1;
} }
/* ts A80731 : Directly open the given address from a single-item whitlist */
static int single_enumerate(int flag)
{
int ret, wl_count;
char *fname, msg[BURN_DRIVE_ADR_LEN + 80];
wl_count= burn_drive_whitelist_count();
if (wl_count != 1)
return 0;
fname= burn_drive_whitelist_item(0, 0);
if (fname == NULL)
return 0;
ret = fname_enumerate(fname, 0);
if (ret <= 0) {
sprintf(msg, "Cannot access '%s' as SG_IO CDROM drive", fname);
libdax_msgs_submit(libdax_messenger, -1, 0x0002000a,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
ret = -1;
}
return ret;
}
/* ts A80801 : looking up drives listed in /proc/sys/dev/cdrom/info line like:
drive name: sr1 hdc hda sr0
@parm flag bit0= release list memory and exit
*/
static int proc_sys_dev_cdrom_info(char ***list, int *count, int flag)
{
FILE *fp;
char line[1024], fname[1024 + 5], *cpt, *retpt, *list_data;
int maxl= 0, pass, i;
if (*list != NULL) {
if ((*list)[0] != NULL)
free((*list)[0]);
free(*list);
*list = NULL;
*count = 0;
}
if (flag & 1)
return 1;
*count = 0;
fp = fopen("/proc/sys/dev/cdrom/info", "r");
if (fp == NULL)
return 0;
while (1) {
retpt = fgets(line, sizeof(line), fp);
if (retpt == NULL)
break;
if(strncmp(line, "drive name:", 11) == 0)
break;
}
fclose(fp);
if (retpt == NULL)
return 0;
strcpy(fname, "/dev/");
for(pass = 0; pass < 2; pass++) {
*count = 0;
cpt = line + 11;
while (*cpt != 0) {
for(; *cpt == ' ' || *cpt == '\t'; cpt++);
if (*cpt == 0 || *cpt == '\n')
break;
sscanf(cpt, "%s", fname + 5);
if (strlen(fname) > maxl)
maxl = strlen(fname);
if (pass == 1)
strcpy((*list)[*count], fname);
(*count)++;
for(cpt++; *cpt != ' ' && *cpt != '\t'
&& *cpt != 0 && *cpt != '\n'; cpt++);
}
if (pass == 0) {
list_data = calloc(*count + 1, maxl+1);
*list = calloc(*count + 1, sizeof(char *));
if(list_data == NULL || *list == NULL) {
libdax_msgs_submit(libdax_messenger, -1,
0x00000003,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Out of virtual memory", 0, 0);
if (list_data != NULL)
free(list_data);
if (*list != NULL)
free((char *) *list);
return -1;
}
for (i = 0; i <= *count; i++)
(*list)[i] = list_data + i * (maxl + 1);
}
}
return 1;
}
static int add_proc_info_drives(int flag)
{
int ret, list_count, count = 0, i;
char **list= NULL;
ret = proc_sys_dev_cdrom_info(&list, &list_count, 0);
if (ret <= 0)
return ret;
for (i = 0; i < list_count; i++) {
if (burn_drive_is_banned(list[i]))
continue;
ret = fname_enumerate(list[i], 1);
if (ret == 1)
count++;
}
proc_sys_dev_cdrom_info(&list, &list_count, 1); /* free memory */
return 1 + count;
}
#endif /* Libburn_drive_new_deaL */ #endif /* Libburn_drive_new_deaL */
@ -1213,10 +1374,14 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx,
{ {
/* os-linux.h : typedef int burn_drive_enumerator_t; */ /* os-linux.h : typedef int burn_drive_enumerator_t; */
static int sg_limit = 32, ata_limit = 26; static int sg_limit = 32, ata_limit = 26;
int baseno = 0; int baseno = 0, i;
char other_name[80];
if (initialize == -1) if (initialize == -1) {
proc_sys_dev_cdrom_info(&(idx->info_list), &(idx->info_count),
1);
return 0; return 0;
}
sg_select_device_family(); sg_select_device_family();
if (linux_sg_device_family[0] == 0) if (linux_sg_device_family[0] == 0)
@ -1224,30 +1389,56 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx,
if (linux_ata_device_family[0] == 0) if (linux_ata_device_family[0] == 0)
ata_limit = 0; ata_limit = 0;
if (initialize == 1) if (initialize == 1) {
*idx = -1; idx->pos = -1;
(*idx)++; idx->info_count= 0;
if (*idx >= sg_limit) idx->info_list= NULL;
proc_sys_dev_cdrom_info(&(idx->info_list), &(idx->info_count),
0);
}
(idx->pos)++;
if (idx->pos >= sg_limit)
goto next_ata; goto next_ata;
if (adr_size < 10) if (adr_size < 11)
return -1; return -1;
sprintf(adr, linux_sg_device_family, *idx); sprintf(adr, linux_sg_device_family, idx->pos);
/* ts A80702 */
sg_exchange_scd_for_sr(adr, 0); sg_exchange_scd_for_sr(adr, 0);
goto return_1_pre_proc;
return 1;
next_ata:; next_ata:;
baseno += sg_limit; baseno += sg_limit;
if (*idx - baseno >= ata_limit) if (idx->pos - baseno >= ata_limit)
goto next_nothing; goto next_proc_info;
if (adr_size < 9) if (adr_size < 9)
return -1; return -1;
sprintf(adr, linux_ata_device_family, 'a' + (*idx - baseno)); sprintf(adr, linux_ata_device_family, 'a' + (idx->pos - baseno));
return 1; goto return_1_pre_proc;
next_nothing:;
next_proc_info:;
baseno += ata_limit; baseno += ata_limit;
for (i = 0; i < idx->info_count; i++) {
if ((idx->info_list)[i][0] == 0)
continue;
if (baseno == idx->pos) {
if (adr_size < strlen((idx->info_list)[i]) + 1)
return -1;
strcpy(adr, (idx->info_list)[i]);
return 1;
}
baseno++;
}
return 0; return 0;
return_1_pre_proc:;
for (i = 0; i < idx->info_count; i++) {
if (strcmp((idx->info_list)[i], adr) == 0)
(idx->info_list)[i][0] = 0;
if (fname_other_name(adr, other_name, 0) > 0)
if (strcmp((idx->info_list)[i], other_name) == 0)
(idx->info_list)[i][0] = 0;
}
return 1;
} }
@ -1281,13 +1472,15 @@ int scsi_enumerate_drives(void)
return -1; return -1;
if (ret > 0) if (ret > 0)
return 1; return 1;
/* >>> ??? should one rather use /proc/sys/dev/cdrom/info ? */
#endif /* Libburn_drive_new_deaL */ #endif /* Libburn_drive_new_deaL */
sg_enumerate(); sg_enumerate();
ata_enumerate(); ata_enumerate();
#ifdef Libburn_drive_new_deaL
add_proc_info_drives(0);
#endif /* Libburn_drive_new_deaL */
return 1; return 1;
} }
@ -1739,6 +1932,7 @@ int sg_is_enumerable_adr(char *adr)
return 1; return 1;
} }
} }
if (first == 0)
sg_give_next_adr(&idx, fname, sizeof(fname), -1); sg_give_next_adr(&idx, fname, sizeof(fname), -1);
return(0); return(0);
} }