diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index a9a1bec..22ff28f 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2007.04.10.144840" +#define Cdrskin_timestamP "2007.04.13.171347" diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index e00e881..a6fcb49 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -300,9 +300,10 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x00020002 (SORRY,HIGH) = Encountered error when closing drive 0x00020003 (SORRY,HIGH) = Could not grab drive 0x00020004 (NOTE,HIGH) = Opened O_EXCL scsi sibling - 0x00020005 (FATAL,HIGH) = Failed to open device + 0x00020005 (SORRY,HIGH) = Failed to open device 0x00020006 (FATAL,HIGH) = Too many scsi siblings 0x00020007 (NOTE,HIGH) = Closed O_EXCL scsi siblings + 0x00020008 (SORRY,HIGH) = Device busy. Failed to fcntl-lock General library operations: @@ -365,7 +366,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x00020138 (FATAL,HIGH) = Cannot reserve track 0x00020139 (SORRY,HIGH) = Write job parameters are unsuitable 0x0002013a (FATAL,HIGH) = No suitable media detected - 0x0002013b (FATAL,HIGH) = Failed to fcntl-lock device + 0x0002013b 0x0002013c (SORRY,HIGH) = Malformed capabilities page 2Ah received libdax_audioxtr: diff --git a/libburn/sg-linux.c b/libburn/sg-linux.c index b72c109..7f3e122 100644 --- a/libburn/sg-linux.c +++ b/libburn/sg-linux.c @@ -79,6 +79,11 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and #include +/** Indication of the Linux kernel this software is running on */ +/* -1 = not evaluated , 0 = unrecognizable , 1 = 2.4 , 2 = 2.6 */ +static int sg_kernel_age = -1; + + /** PORTING : Device file families for bus scanning and drive access. Both device families must support the following ioctls: SG_IO, @@ -191,6 +196,24 @@ int mmc_function_spy(char * text); /* (Public functions are listed below) */ /* ------------------------------------------------------------------------ */ +/* ts A70413 */ +/* This finds out wether the software is running on kernel >= 2.6 +*/ +static void sg_evaluate_kernel(void) +{ + struct utsname buf; + if (sg_kernel_age >= 0) + return; + + sg_kernel_age = 0; + if (uname(&buf) == -1) + return; + sg_kernel_age = 1; + if (strcmp(buf.release, "2.6") >= 0) + sg_kernel_age = 2; +} + + /* ts A70314 */ /* This installs the device file family if one was chosen explicitely by burn_preset_device_open() @@ -211,13 +234,8 @@ static void sg_select_device_family(void) else if (burn_sg_use_family == 4) strcpy(linux_sg_device_family, "/dev/sg%d"); else if (linux_sg_auto_family) { - int use_sr_family = 0; - struct utsname buf; - - if (uname(&buf) != -1) - if (strcmp(buf.release, "2.6") >= 0) - use_sr_family = 1; - if (use_sr_family) + sg_evaluate_kernel(); + if (sg_kernel_age >= 2) strcpy(linux_sg_device_family, "/dev/sr%d"); else strcpy(linux_sg_device_family, "/dev/sg%d"); @@ -277,7 +295,7 @@ static int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry) ret = close(*fd); *fd = -1337; if(ret != -1) { - /* ts A70409 : DDLP */ + /* ts A70409 : DDLP-B */ /* >>> release single lock on fname */ return 1; } @@ -297,7 +315,7 @@ static int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry) So libburn will by default use open(O_EXCL) first and afterwards as second assertion will use fcntl(F_SETLK). One lock more should not harm. */ -static int sg_fcntl_lock(int *fd, char *fd_name) +static int sg_fcntl_lock(int *fd, char *fd_name, int l_type, int verbous) { struct flock lockthing; char msg[81]; @@ -307,23 +325,28 @@ static int sg_fcntl_lock(int *fd, char *fd_name) return 1; memset(&lockthing, 0, sizeof(lockthing)); - lockthing.l_type = F_WRLCK; + lockthing.l_type = l_type; lockthing.l_whence = SEEK_SET; lockthing.l_start = 0; lockthing.l_len = 0; /* - fprintf(stderr,"LIBBURN_EXPERIMENTAL: fcntl(%d, F_SETLK, )\n", *fd); + fprintf(stderr,"LIBBURN_EXPERIMENTAL: fcntl(%d, F_SETLK, %s)\n", + *fd, l_type == F_WRLCK ? "F_WRLCK" : "F_RDLCK"); */ + ret = fcntl(*fd, F_SETLK, &lockthing); if (ret == -1) { - sprintf(msg, "Failed to fcntl-lock device '%s'",fd_name); - libdax_msgs_submit(libdax_messenger, -1, 0x00020005, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + if (verbous) { + sprintf(msg, "Device busy. Failed to fcntl-lock '%s'", + fd_name); + libdax_msgs_submit(libdax_messenger, -1, 0x00020008, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, msg, errno, 0); + } close(*fd); *fd = -1; - /* ts A70409 : DDLP */ + /* ts A70409 : DDLP-B */ /* >>> release single lock on fd_name */ return(0); @@ -338,7 +361,7 @@ static int sg_open_drive_fd(char *fname, int scan_mode) int open_mode = O_RDWR, fd; char msg[81]; - /* ts A70409 : DDLP */ + /* ts A70409 : DDLP-B */ /* >>> obtain single lock on fname */ /* ts A60813 - A60927 @@ -350,17 +373,22 @@ static int sg_open_drive_fd(char *fname, int scan_mode) /* ts A60813 O_NONBLOCK was already hardcoded in ata_ but not in sg_. There must be some reason for this. So O_NONBLOCK is - default mode for both now. Disable on own risk. */ + default mode for both now. Disable on own risk. + ts A70411 + Switched to O_NDELAY for LKML statement 2007/4/11/141 by Alan Cox: + "open() has side effects. The CD layer allows you to open + with O_NDELAY if you want to avoid them." + */ if(burn_sg_open_o_nonblock) - open_mode |= O_NONBLOCK; + open_mode |= O_NDELAY; /* <<< debugging fprintf(stderr, "\nlibburn: experimental: o_excl= %d , o_nonblock= %d, abort_on_busy= %d\n", burn_sg_open_o_excl,burn_sg_open_o_nonblock,burn_sg_open_abort_busy); fprintf(stderr, - "libburn: experimental: O_EXCL= %d , O_NONBLOCK= %d\n", - !!(open_mode&O_EXCL),!!(open_mode&O_NONBLOCK)); + "libburn: experimental: O_EXCL= %d , O_NDELAY= %d\n", + !!(open_mode&O_EXCL),!!(open_mode&O_NDELAY)); */ fd = open(fname, open_mode); @@ -379,11 +407,11 @@ static int sg_open_drive_fd(char *fname, int scan_mode) return -1; sprintf(msg, "Failed to open device '%s'",fname); libdax_msgs_submit(libdax_messenger, -1, 0x00020005, - LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, msg, errno, 0); return -1; } - sg_fcntl_lock(&fd, fname); + sg_fcntl_lock(&fd, fname, F_WRLCK, 1); return fd; } @@ -909,9 +937,12 @@ int sg_grab(struct burn_drive *d) open_mode |= O_EXCL; /* ts A60813 - O_NONBLOCK was hardcoded here. So it should stay default mode. */ + O_NONBLOCK was hardcoded here. So it should stay default mode. + ts A70411 + Switched to O_NDELAY for LKML statement 2007/4/11/141 + */ if(burn_sg_open_o_nonblock) - open_mode |= O_NONBLOCK; + open_mode |= O_NDELAY; /* ts A60813 - A60822 After enumeration the drive fd is probably still open. @@ -924,7 +955,7 @@ int sg_grab(struct burn_drive *d) <<< debug: for tracing calls which might use open drive fds */ mmc_function_spy("sg_grab ----------- opening"); - /* ts A70409 : DDLP */ + /* ts A70409 : DDLP-B */ /* >>> obtain single lock on d->devname */ /* ts A60926 */ @@ -940,8 +971,11 @@ int sg_grab(struct burn_drive *d) fd = open(d->devname, open_mode); os_errno = errno; - if (fd >= 0) - sg_fcntl_lock(&fd, d->devname); + if (fd >= 0) { + sg_fcntl_lock(&fd, d->devname, F_WRLCK, 1); + if (fd < 0) + goto drive_is_in_use; + } } else fd= d->fd; @@ -1155,27 +1189,33 @@ ex:; int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, int *target_no, int *lun_no) { - int fd, ret, l, open_mode = O_RDWR | O_NONBLOCK; + int fd, ret, l, open_mode = O_RDONLY; struct my_scsi_idlun { int x; int host_unique_id; }; struct my_scsi_idlun idlun; + l = strlen(linux_ata_device_family) - 2; if (l > 0 && strncmp(path, linux_ata_device_family, l) == 0 && path[7] >= 'a' && path[7] <= 'z' && path[8] == 0) return 0; /* on RIP 14 all hdx return SCSI adr 0,0,0,0 */ - /* ts A70409 : DDLP */ + /* ts A70409 : DDLP-B */ /* >>> obtain single lock on path */ - if(burn_sg_open_o_excl) - open_mode |= O_EXCL; + if(burn_sg_open_o_nonblock) + open_mode |= O_NDELAY; + if(burn_sg_open_o_excl) { + /* O_EXCL | O_RDONLY does not work with /dev/sg* on + SuSE 9.0 (kernel 2.4) and SuSE 9.3 (kernel 2.6) */ + /* so skip it for now */; + } fd = open(path, open_mode); if(fd < 0) return 0; - sg_fcntl_lock(&fd, path); + sg_fcntl_lock(&fd, path, F_RDLCK, 0); if(fd < 0) return 0;