--- growisofs_orig.c 2006-09-27 11:41:19.000000000 +0200 +++ growisofs_sglock.c 2006-09-30 16:42:32.000000000 +0200 @@ -2368,6 +2368,18 @@ int builtin_dd (int infd,int outfd,off64 int fd = open64 (ioctl_device,O_RDONLY|O_NONBLOCK|O_EXCL); struct stat64 sb,sc; + /* ts A60927 - A60930 */ + /* Trying to protect growisofs burn runs from being spoiled by + cdrskin -scanbus or other cdrskin operations on the same drive. + Also trying to avoid blocking problems within cdrskin. + */ + void try_to_lock_linux_sg(char *ioctl_device); + + /* A use-the-force-luke to disable this locking attempt + might be a wise precaution against unexpected problems */ + if (i == 3) + try_to_lock_linux_sg(ioctl_device); + if (fd<0) { if (errno==EBUSY) { if (i==0) @@ -2638,6 +2650,27 @@ int main (int argc, char *argv[]) int alleged_next_session=-1; unsigned int new_size; + + /* ts A60930 */ + if(strcmp(argv[0], "-umount") != 0 && strcmp(argv[0], "-eject") != 0) { + fprintf(stderr, + "NOTE: This is an experimental version tsA60930 of growisofs 7.0 !\n"); + fprintf(stderr, + "NOTE: Code changes made by Thomas Schmitt \n"); + fprintf(stderr, + "NOTE: in order to protect growisofs from cdrskin interference.\n"); + fprintf(stderr, + "NOTE: In case of aborts after \"Locking experiment :\"\n"); + fprintf(stderr, + "NOTE: or \":-( unable to locate /dev/sgN\" please report to\n"); + fprintf(stderr, + "NOTE: libburn-hackers@pykix.org or scdbackup@gmx.net\n"); + fprintf(stderr, + "NOTE: and then better switch back to Andy Polyakov's original.\n"); + fprintf(stderr, "\n"); + } + + argv0 = argv[0]; #if defined(__unix) || defined(__unix__) #if !defined(I_KNOW_ALL_ABOUT_SUDO) @@ -3317,3 +3350,131 @@ int main (int argc, char *argv[]) set_errno(0); exit (0); } + +#ifdef __linux + +/* ts A60927 - A60930 */ +/* Rather than to change the build system, i include the new functions + here. This is for simplicity only and not an implementation proposal. +*/ + +#include + +/** Try to obtain SCSI address parameters. + http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/scsi_g_idlun.html + @return 1 is success , 0 is failure +*/ +int obtain_linux_scsi_adr(char *path, + int *host_no, int *channel_no, + int *id_no, int *lun_no) +{ + int ret, fd; + struct my_scsi_idlun { + int x; + int host_unique_id; + }; + struct my_scsi_idlun idlun; + + fd = open(path, O_RDONLY | O_NONBLOCK); + if(fd < 0) + return(0); + ret= ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun); + close(fd); + if (ret == -1) + return(0); /* ( but success does not necessarily mean SCSI) */ + *host_no= (idlun.x>>24)&255; + *channel_no= (idlun.x>>16)&255; + *id_no= (idlun.x)&255; + *lun_no= (idlun.x>>8)&255; + return(1); +} + + +/** Try to find /dev/sgN with same SCSI address parameters as device_path. + @param device_path The file system adress of the (block) device file. + @param sg_path The return buffer. It should provide 16 bytes memory. + @return 1 on success, + 0 if no SCSI addresses could be obtained, + -1 if no matching /dev/sg could be found but /dev/sg existed +*/ +int obtain_linux_sg_path(char *device_path, char sg_path[]) +{ + int ret, i, dev_sg_exists = 0; + int host_no, channel_no, id_no, lun_no; + int sg_host_no, sg_channel_no, sg_id_no, sg_lun_no; + char path[16]; + struct stat stbuf; + + ret = obtain_linux_scsi_adr(device_path, + &host_no, &channel_no, &id_no, &lun_no); + if(ret <= 0) + return(0); + for(i= 0; i < 32; i++) { + sprintf(path, "/dev/sg%d", i); + if(stat(path, &stbuf) == -1) + continue; + dev_sg_exists = 1; + ret = obtain_linux_scsi_adr(path, + &sg_host_no, &sg_channel_no, &sg_id_no, &sg_lun_no); + if(ret <= 0) + continue; + if(sg_host_no != host_no) + continue; + if(sg_channel_no != channel_no) + continue; + if(sg_id_no != id_no) + continue; + if(sg_lun_no != lun_no) + continue; + strcpy(sg_path, path); + return(1); + } + return(-dev_sg_exists); +} + + +/* Trying to protect growisofs burn runs from being spoiled by + cdrskin -scanbus or cdrskin operations on the same drive. + Also trying to avoid blocking problems within cdrskin. + + This either detects no problem or it exits (FATAL_START(errno)). +*/ +void try_to_lock_linux_sg(char *ioctl_device) +{ + int fd_sg = -2, ret; + char sg_devname[16]; + + fprintf (stderr,"Locking experiment : ioctl_device is '%s'\n", + ioctl_device); + + sg_devname[0]= 0; + if ( ( ( strncmp (ioctl_device, "/dev/sr", 7) == 0 + && isdigit(ioctl_device[7]) ) || + ( strncmp (ioctl_device, "/dev/scd", 8) == 0 + && isdigit(ioctl_device[8]) ) + ) ) { + ret = obtain_linux_sg_path(ioctl_device, sg_devname); + if (ret == -1) /* There are sg but not the desired one */ + fprintf (stderr, + ":-( unable to locate /dev/sgN of %s: " + "Other program active on drive ?\n", + ioctl_device), + exit (FATAL_START(errno)); + } + if (sg_devname[0] == 0) + return; + fd_sg = open64 (sg_devname, O_RDWR|O_NONBLOCK|O_EXCL); + if (fd_sg >= 0) + + fprintf(stderr,"Locking experiment : aquired lock on '%s'\n", + sg_devname); + + else if(errno == EBUSY) + fprintf (stderr,":-( unable to O_EXCL %s: " + "Other burn program active on drive ?\n", + sg_devname), + exit (FATAL_START(errno)); +} + +#endif /* __linux , ts A60927 - A60930 */ +