[Debburn-devel] Re: Bug#390353: wodim: Writng to CD fails with "permission denied" on hard disk's sg device

Eduard Bloch edi at gmx.de
Sat Sep 30 21:24:08 UTC 2006


#include <hallo.h>
* Eduard Bloch [Sat, Sep 30 2006, 09:32:19PM]:
> #include <hallo.h>
> * Graham [Sat, Sep 30 2006, 01:16:46PM]:
> > Package: wodim
> > Version: 5:1.0~pre4-1.1
> > 
> > Writing a CD fails on my system. It looks like another problem caused
> > by cdrecord trying to open devices that it doesn't need to; see also
> > my bug report #370603, which covers the "-scanbus" case.
> 
> That was a different case. "-scanbus" had no option to skip busy/failed
> devices. "wodim" should work in that case and just skip the unuseable
> devices.

Ok, Graham is right it was not a big deal to reproduce it. The current
code does inded break when a device could not be opened because of
permission problems when libscg scans (to build its list of "intuitive"
SCSI addresses). We had already two cludges to work around this problems,
one was from Andreas Metzler to not scan over all devices when the user
already specified a device name, and another from me to stop looping
forever when exclusiv open fails. However, the last part was only used
conditionaly for atapi devices. With SCSI (eg. a mixture of usb-attached
harddisks and external recorder which I just used), it fails: -scanbus
runs well (because of the endless looping prevention) but opening fails.

Now, I rewrote the code a bit more and ask for comments. It consolidates
the previous workarounds. I consider adding it to the stable branch RSN,
most likely for pre5.


Index: libscg/scsi-linux-sg.c
===================================================================
--- libscg/scsi-linux-sg.c	(Revision 351)
+++ libscg/scsi-linux-sg.c	(Arbeitskopie)
@@ -242,25 +242,21 @@
 #endif
 LOCAL	void	sg_settimeout	__PR((int f, int timeout));
 
-int    sg_open_excl    __PR((char *device, int mode, int quickAndQuiet));
+int    sg_open_excl    __PR((char *device, int mode));
 
 int
-sg_open_excl(device, mode, quickAndQuiet)
+sg_open_excl(device, mode)
        char    *device;
        int     mode;
-       int quickAndQuiet;
 {
        int f;
        int i;
        f = open(device, mode|O_EXCL);
-       if(!quickAndQuiet)
-          for (i = 0; (i < 10) && (f == -1 && (errno == EACCES || errno == EBUSY)); i++) {
-             fprintf(stderr, "Error trying to open %s exclusively (%s)... retrying in 1 second.\n", device, strerror(errno));
-             usleep(1000000 + 100000.0 * rand()/(RAND_MAX+1.0));
-             f = open(device, mode|O_EXCL);
-          }
-       if (f == -1 && errno != EACCES && errno != EBUSY) {
-           f = open(device, mode);
+       // try to reopen locked/busy devices up to five times
+       for (i = 0; (i < 5) && (f == -1 && errno == EBUSY); i++) {
+	       fprintf(stderr, "Error trying to open %s exclusively (%s)... %s\n", device, strerror(errno), (i<5)?"retrying in 1 second.":"");
+	       usleep(1000000 + 100000.0 * rand()/(RAND_MAX+1.0));
+	       f = open(device, mode|O_EXCL);
        }
        return f;
 }
@@ -448,7 +444,7 @@
 	if (use_ata) for (i=2*busno+tgt >= 0 ? 2*busno+tgt:0; i <= 25; i++) {
 		js_snprintf(devname, sizeof (devname), "/dev/hd%c", i+'a');
 					/* O_NONBLOCK is dangerous */
-		f = sg_open_excl(devname, O_RDWR | O_NONBLOCK, 1);
+		f = sg_open_excl(devname, O_RDWR | O_NONBLOCK);
 		if (f < 0) {
 			/*
 			 * Set up error string but let us clear it later
@@ -489,7 +485,7 @@
 	if (nopen == 0) for (i = 0; i < 32; i++) {
 		js_snprintf(devname, sizeof (devname), "/dev/sg%d", i);
 					/* O_NONBLOCK is dangerous */
-		f = sg_open_excl(devname, O_RDWR | O_NONBLOCK, 0);
+		f = sg_open_excl(devname, O_RDWR | O_NONBLOCK);
 		if (f < 0) {
 			/*
 			 * Set up error string but let us clear it later
@@ -498,6 +494,8 @@
 			if (scgp->errstr)
 				js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
 							"Cannot open '/dev/sg*'");
+			if(errno == EACCES || errno==EPERM)
+				continue;
 			if (errno != ENOENT && errno != ENXIO && errno != ENODEV) {
 				if (scgp->errstr)
 					js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
@@ -518,7 +516,7 @@
 	if (nopen == 0) for (i = 0; i <= 25; i++) {
 		js_snprintf(devname, sizeof (devname), "/dev/sg%c", i+'a');
 					/* O_NONBLOCK is dangerous */
-		f = sg_open_excl(devname, O_RDWR | O_NONBLOCK, 0);
+		f = sg_open_excl(devname, O_RDWR | O_NONBLOCK);
 		if (f < 0) {
 			/*
 			 * Set up error string but let us clear it later
@@ -527,6 +525,8 @@
 			if (scgp->errstr)
 				js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
 							"Cannot open '/dev/sg*'");
+			if(errno == EACCES || errno==EPERM)
+				continue;
 			if (errno != ENOENT && errno != ENXIO && errno != ENODEV) {
 				if (scgp->errstr)
 					js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
@@ -570,7 +570,7 @@
 			 */
 		}
 					/* O_NONBLOCK is dangerous */
-		f = sg_open_excl(device, O_RDWR | O_NONBLOCK, 0);
+		f = sg_open_excl(device, O_RDWR | O_NONBLOCK);
 /*		if (f < 0 && errno == ENOENT)*/
 /*			goto openpg;*/
 

-- 
<Getty> HA! Ich habs <klatsch> Ich Idiot



More information about the Debburn-devel mailing list