diff --git a/cdrskin/cdrskin.1 b/cdrskin/cdrskin.1 index c77a9e4..766fdcc 100644 --- a/cdrskin/cdrskin.1 +++ b/cdrskin/cdrskin.1 @@ -2,7 +2,7 @@ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) -.TH CDRSKIN 1 "March 6, 2007" +.TH CDRSKIN 1 "March 14, 2007" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -725,6 +725,13 @@ This is not guaranteed to work with all drivers. Some need nonblocking i/o. 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. .TP +.BI drive_scsi_dev_family= sr | scd | sg +Linux specific: Select a SCSI device file family to be used for drive command +transactions. Normally this is /dev/sgN but on modern kernels it might be +helpful to use drive_scsi_dev_family=sr in order to meet other programs at +a common device file for each drive. On kernel 2.4 this will find no drives. +Device file family /dev/hdX on kernel 2.6 is not affected by this setting. +.TP .BI \--drive_scsi_exclusive Linux specific: Try to exclusively reserve device files /dev/srN, /dev/scdM, /dev/stK of drive. diff --git a/cdrskin/cdrskin.c b/cdrskin/cdrskin.c index 4d170ac..b0c4a2f 100644 --- a/cdrskin/cdrskin.c +++ b/cdrskin/cdrskin.c @@ -131,6 +131,7 @@ or /* Place novelty switch macros here. Move them down to Cdrskin_libburn_from_pykix_svN on version leap */ +#define Cdrskin_libburn_preset_device_familY 1 #endif /* Cdrskin_libburn_0_3_5 */ @@ -1427,9 +1428,14 @@ struct CdrpreskiN { /** Wether to abort when a busy drive is encountered during bus scan */ int abort_on_busy_drive; - /** Wether to try to avoid collisions when opening drives */ + /** Linux specific : Wether to try to avoid collisions when opening drives */ int drive_exclusive; + /** Linux specific : Device file address family to use : + 0=default , 1=sr , 2=scd , 4=sg */ + int drive_scsi_dev_family; + + /** Wether to try to wait for unwilling drives to become willing to open */ int drive_blocking; @@ -1490,6 +1496,7 @@ int Cdrpreskin_new(struct CdrpreskiN **preskin, int flag) o->scan_demands_drive= 0; o->abort_on_busy_drive= 0; o->drive_exclusive= 1; + o->drive_scsi_dev_family= 0; o->drive_blocking= 0; strcpy(o->write_mode_name,"DEFAULT"); @@ -1959,6 +1966,17 @@ set_dev:; } else if(strcmp(argv[i],"--drive_not_exclusive")==0) { o->drive_exclusive= 0; + } else if(strncmp(argv[i],"drive_scsi_dev_family=",22)==0) { + value_pt= argv[i]+22; + if(strcmp(value_pt,"sr")==0) + o->drive_scsi_dev_family= 1; + else if(strcmp(value_pt,"scd")==0) + o->drive_scsi_dev_family= 2; + else if(strcmp(value_pt,"sg")==0) + o->drive_scsi_dev_family= 4; + else + o->drive_scsi_dev_family= 0; + } else if(strcmp(argv[i],"--drive_scsi_exclusive")==0) { o->drive_exclusive= 2; @@ -2011,6 +2029,9 @@ set_dev:; printf(" (might be stalled by a busy hard disk)\n"); printf(" --drive_not_exclusive do not ask kernel to prevent opening\n"); printf(" busy drives. Effect is kernel dependend.\n"); + printf( + " drive_scsi_dev_family= select Linux device\n"); + printf(" file family to be used for (pseudo-)SCSI.\n"); printf( " --drive_scsi_exclusive try to exclusively reserve device files\n"); printf(" /dev/srN, /dev/scdM, /dev/stK of drive.\n"); @@ -5608,6 +5629,16 @@ set_blank:; } else if(strcmp(argv[i],"--drive_not_exclusive")==0) { /* is handled in Cdrpreskin_setup() */; + } else if(strncmp(argv[i],"drive_scsi_dev_family=",22)==0) { + /* is handled in Cdrpreskin_setup() */; + if(skin->verbosity>=Cdrskin_verbose_debuG && + skin->preskin->drive_scsi_dev_family!=0) + ClN(fprintf(stderr,"cdrskin_debug: drive_scsi_dev_family= %d\n", + skin->preskin->drive_scsi_dev_family)); + + } else if(strcmp(argv[i],"--drive_scsi_exclusive")==0) { + /* is handled in Cdrpreskin_setup() */; + } else if(strncmp(argv[i],"-driveropts=",12)==0) { value_pt= argv[i]+12; goto set_driveropts; @@ -6103,10 +6134,14 @@ int Cdrskin_create(struct CdrskiN **o, struct CdrpreskiN **preskin, *exit_value= 0; #ifndef Cdrskin_libburn_no_burn_preset_device_opeN - burn_preset_device_open((*preskin)->drive_exclusive, + burn_preset_device_open((*preskin)->drive_exclusive +#ifdef Cdrskin_libburn_preset_device_familY + | ((*preskin)->drive_scsi_dev_family<<2) +#endif + , (*preskin)->drive_blocking, (*preskin)->abort_on_busy_drive); -#endif +#endif /* ! Cdrskin_libburn_no_burn_preset_device_opeN */ if(strlen((*preskin)->device_adr)>0) { /* disable scan for all others */ ClN(printf( diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 50170ed..98b7d43 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2007.03.12.155600" +#define Cdrskin_timestamP "2007.03.14.133618" diff --git a/libburn/init.c b/libburn/init.c index 432cf0f..25570c2 100644 --- a/libburn/init.c +++ b/libburn/init.c @@ -26,9 +26,18 @@ struct libdax_msgs *libdax_messenger= NULL; int burn_running = 0; -/* ts A60813 : wether to use O_EXCL and/or O_NONBLOCK in libburn/sg.c */ +/* ts A60813 : Linux: wether to use O_EXCL and/or O_NONBLOCK in libburn/sg.c */ int burn_sg_open_o_excl = 1; +/* ts A70314 : Linux: what device family to use : + 0= default family + 1= sr + 2= scd + (3= st) + 4= sg +*/ +int burn_sg_use_family = 0; + /* O_NONBLOCK was hardcoded in enumerate_ata() which i hardly use. For enumerate_sg() it seems ok. So it should stay default mode until enumerate_ata() without O_NONBLOCK @@ -120,7 +129,8 @@ void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy) if (!burn_running) return; - burn_sg_open_o_excl= exclusive; + burn_sg_open_o_excl= exclusive & 3; + burn_sg_use_family= (exclusive >> 2) & 15; burn_sg_open_o_nonblock= !blocking; burn_sg_open_abort_busy= !!abort_on_busy; } diff --git a/libburn/libburn.h b/libburn/libburn.h index 89b28ef..53d820a 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -572,13 +572,20 @@ void burn_set_verbosity(int level); after burn_initialize() and before any bus scan. But not mandatory at all. Parameter value 1 enables a feature, 0 disables. Default is (1,0,0). Have a good reason before you change it. - @param exclusive 1 = Try to open only devices which are not marked as busy + @param exclusive Linux only: + 0 = no attempt to make drive access exclusive. + 1 = Try to open only devices which are not marked as busy and try to mark them busy if opened sucessfully. (O_EXCL) There are kernels which simply don't care about O_EXCL. Some have it off, some have it on, some are switchable. 2 = in case of a SCSI device, also try to open exclusively - the matching /dev/sr, /dev/scd and /dev/st . - 0 = no attempt to make drive access exclusive. + the matching /dev/sr, /dev/scd and /dev/st . + One may select a device SCSI file family by adding + 0 = default family + 4 = /dev/sr%d + 8 = /dev/scd%d + 16 = /dev/sg%d + Do not use other values ! @param blocking Try to wait for drives which do not open immediately but also do not return an error as well. (O_NONBLOCK) This might stall indefinitely with /dev/hdX hard disks. diff --git a/libburn/sg-linux.c b/libburn/sg-linux.c index 50bde11..660d652 100644 --- a/libburn/sg-linux.c +++ b/libburn/sg-linux.c @@ -105,16 +105,9 @@ static int linux_sg_enumerate_debug = 0; address parameters Host, Channel, Id, Lun and also Bus. E.g.: "/dev/sg%d" */ -/* NEW INFO: If hard disks at /dev/sr allow ioctl(CDROM_DRIVE_STATUS), they - are in danger. - If you want it less dangerous: - #undef CDROM_DRIVE_STATUS - but then you might need linux_sg_accept_any_type = 1 which - is _more dangerous_. +/* sr%d is supposed to map only CD-ROM style devices. Additionally a test + with ioctl(CDROM_DRIVE_STATUS) is made to assert that it is such a drive, */ -/* !!! DO NOT SET TO sr%d UNLESS YOU PROTECTED ALL INDISPENSIBLE DEVICES - by chmod -rw . A test wether non-CD devices are properly excluded would - be well needed though. Heroic disks, scanners, etc. wanted !!! */ static char linux_sg_device_family[80] = {"/dev/sg%d"}; @@ -171,9 +164,11 @@ static void enumerate_common(char *fname, int bus_no, int host_no, /* >>> ts A61115 : this needs mending. A Linux aspect shows up in cdrskin. */ /* ts A60813 : storage objects are in libburn/init.c wether to use O_EXCL + what device family to use : 0=default, 1=sr, 2=scd, (3=st), 4=sg wether to use O_NOBLOCK with open(2) on devices wether to take O_EXCL rejection as fatal error */ extern int burn_sg_open_o_excl; +extern int burn_sg_use_family; extern int burn_sg_open_o_nonblock; extern int burn_sg_open_abort_busy; @@ -188,6 +183,21 @@ int mmc_function_spy(char * text); /* (Public functions are listed below) */ /* ------------------------------------------------------------------------ */ +/* This installs (much too often) the device file family if one was + chosen explicitely by burn_preset_device_open() +*/ +void sg_select_device_family(void) +{ + if (burn_sg_use_family == 1) + strcpy(linux_sg_device_family, "/dev/sr%d"); + else if (burn_sg_use_family == 2) + strcpy(linux_sg_device_family, "/dev/scd%d"); + else if (burn_sg_use_family == 3) + strcpy(linux_sg_device_family, "/dev/st%d"); + else if (burn_sg_use_family == 4) + strcpy(linux_sg_device_family, "/dev/sg%d"); +} + static int sgio_test(int fd) { @@ -352,6 +362,7 @@ static int sg_open_scsi_siblings(char *path, int driveno, static char tldev[][81]= {"/dev/sr%d", "/dev/scd%d", "/dev/st%d", "/dev/sg%d", ""}; + sg_select_device_family(); if (linux_sg_device_family[0] == 0) return 1; @@ -482,6 +493,8 @@ static void sg_enumerate(void) int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1; char fname[10]; + sg_select_device_family(); + if (linux_sg_enumerate_debug) fprintf(stderr, "libburn_debug: linux_sg_device_family = %s\n", linux_sg_device_family); @@ -520,6 +533,16 @@ static void sg_enumerate(void) "ioctl(SG_GET_SCSI_ID) failed, errno=%d '%s' , ", errno, strerror(errno)); + if (sgio_test(fd) == -1) { + if (linux_sg_enumerate_debug) + fprintf(stderr, + "FATAL: sgio_test() failed: errno=%d '%s'", + errno, strerror(errno)); + + sg_close_drive_fd(fname, -1, &fd, 0); + continue; + } + #ifdef CDROM_DRIVE_STATUS /* ts A61211 : not widening old acceptance range */ if (strcmp(linux_sg_device_family,"/dev/sg%d") != 0) { @@ -698,6 +721,7 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx, if (initialize == -1) return 0; + sg_select_device_family(); if (linux_sg_device_family[0] == 0) sg_limit = 0; if (linux_ata_device_family[0] == 0)