diff --git a/cdrskin/cdrskin.c b/cdrskin/cdrskin.c index 004a60e..8bf4b87 100644 --- a/cdrskin/cdrskin.c +++ b/cdrskin/cdrskin.c @@ -164,12 +164,12 @@ or #define Cdrskin_libburn_versioN "0.2.3" #define Cdrskin_libburn_from_pykix_svN 1 #define Cdrskin_libburn_has_is_enumerablE 1 +#define Cdrskin_libburn_has_convert_fs_adR 1 #endif #ifndef Cdrskin_libburn_versioN #define Cdrskin_libburn_versioN "0.2.3" #define Cdrskin_libburn_from_pykix_svN 1 -#define Cdrskin_libburn_has_is_enumerablE 1 #endif #ifdef Cdrskin_libburn_from_pykix_svN @@ -1388,10 +1388,14 @@ return: 2 end program run (--help) */ { - int i,k,ret,bragg_with_audio= 0; + int i,ret,bragg_with_audio= 0; char *value_pt,link_adr[Cdrskin_strleN+1]; + +#ifndef Cdrskin_libburn_has_convert_fs_adR + int k; char link_target[Cdrskin_strleN+1]; struct stat stbuf; +#endif #ifndef Cdrskin_extra_leaN if(argc>1) @@ -1752,7 +1756,7 @@ final_checks:; "cdrskin: HINT : to run cdrskin under your normal user identity.\n"); fprintf(stderr, "cdrskin: HINT : Option --allow_setuid disables this safety check.\n"); - ret= 0; + ret= 0; goto ex; } if(strlen(o->raw_device_adr)>0 && !o->no_whitelist) { @@ -1792,12 +1796,27 @@ dev_too_long:; } if(!o->no_follow_links) { strcpy(link_adr,o->device_adr); + +#ifdef Cdrskin_libburn_has_convert_fs_adR + + ret = burn_drive_convert_fs_adr(link_adr,o->device_adr); + if(ret<0) { + fprintf(stderr, + "cdrskin: NOTE : Please inform libburn-hackers@pykix.org about:\n"); + fprintf(stderr, + " burn_drive_convert_fs_adr() returned %d\n",ret); + } + +#else + while(lstat(link_adr,&stbuf)!=-1) { if(Cdrpreskin__is_enumerable_adr(link_adr,0)) break; if((stbuf.st_mode&S_IFMT)!=S_IFLNK) break; ret= readlink(link_adr,link_target,Cdrskin_strleN+1); + if(ret==-1) + goto after_resolving_links; if(ret>=Cdrskin_strleN) { link_too_long:; fprintf(stderr, @@ -1816,8 +1835,15 @@ link_too_long:; goto link_too_long; strcpy(o->device_adr,link_adr); } + +#endif /* Cdrskin_libburn_has_convert_fs_adR */ + } +#ifndef Cdrskin_libburn_has_convert_fs_adR +after_resolving_links:; +#endif } + ret= 1; ex:; #ifndef Cdrskin_extra_leaN diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index fa18d47..6c05117 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2006.09.21.194006" +#define Cdrskin_timestamP "2006.09.22.170220" diff --git a/libburn/drive.c b/libburn/drive.c index 01332d3..0c6ad10 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -1,5 +1,7 @@ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ +#include +#include #include #include #include @@ -670,3 +672,111 @@ int burn_drive_is_enumerable_adr(char *adr) return sg_is_enumerable_adr(adr); } +/* ts A60922 ticket 33 */ +/* Try to find an enumerated address with the given stat.st_rdev number */ +int burn_drive_resolve_link(char *path, char adr[]) +{ + int ret; + char link_target[4096]; + + +fprintf(stderr,"libburn experimental: burn_drive_resolve_link( %s )\n",path); + + ret = readlink(path, link_target, sizeof(link_target)); + if(ret == -1) { + +fprintf(stderr,"libburn experimental: readlink( %s ) returns -1\n",path); + + return 0; + } + if(ret >= sizeof(link_target) - 1) { + +fprintf(stderr,"libburn experimental: readlink( %s ) returns %d (too much)\n",path,ret); + + return -1; + } + link_target[ret] = 0; + ret = burn_drive_convert_fs_adr(link_target, adr); + +fprintf(stderr,"libburn experimental: burn_drive_convert_fs_adr( %s ) returns %d\n",link_target,ret); + + return ret; +} + +/* ts A60922 ticket 33 */ +/* Try to find an enumerated address with the given stat.st_rdev number */ +int burn_drive_find_devno(dev_t devno, char adr[]) +{ + char fname[4096]; + int i, ret = 0, first = 1; + struct stat stbuf; + + while (1) { + ret= sg_give_next_adr(&i, fname, sizeof(fname), first); + if(ret <= 0) + break; + first = 0; + ret = stat(fname, &stbuf); + if(ret == -1) + continue; + if(devno != stbuf.st_rdev) + continue; + if(strlen(fname) >= BURN_DRIVE_ADR_LEN) + return -1; + +fprintf(stderr,"libburn experimental: burn_drive_find_devno( 0x%llX ) found %s\n", (long long) devno, fname); + + strcpy(adr, fname); + return 1; + } + return 0; +} + +/* ts A60922 ticket 33 */ +/** Try to convert a given existing filesystem address into a persistent drive + address. */ +int burn_drive_convert_fs_adr(char *path, char adr[]) +{ + int ret; + struct stat stbuf; + +fprintf(stderr,"libburn experimental: burn_drive_convert_fs_adr( %s )\n",path); + + if(burn_drive_is_enumerable_adr(path)) { + if(strlen(path) >= BURN_DRIVE_ADR_LEN) + return -1; + +fprintf(stderr,"libburn experimental: burn_drive_is_enumerable_adr( %s ) is true\n",path); + + strcpy(adr, path); + return 1; + } + + if(lstat(path, &stbuf) == -1) { + +fprintf(stderr,"libburn experimental: lstat( %s ) returns -1\n",path); + + return 0; + } + if((stbuf.st_mode & S_IFMT) == S_IFLNK) { + ret = burn_drive_resolve_link(path, adr); + if(ret > 0) + return 1; + } + if((stbuf.st_mode&S_IFMT) == S_IFBLK || + (stbuf.st_mode&S_IFMT) == S_IFCHR) { + ret = burn_drive_find_devno(stbuf.st_rdev, adr); + if(ret > 0) + return 1; + + /* >>> if SCSI device : + try to find enumerated device with same Bus,Target,Lun + */; + + } + +fprintf(stderr,"libburn experimental: Nothing found for %s \n",path); + + return 0; +} + diff --git a/libburn/libburn.h b/libburn/libburn.h index 52182a3..d648be8 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -584,6 +584,16 @@ int burn_drive_get_adr(struct burn_drive_info *drive_info, char adr[]); @return 1 means yes, 0 means no */ int burn_drive_is_enumerable_adr(char *adr); +/* ts A60922 ticket 33 */ +/** Try to convert a given existing filesystem address into a persistent drive + address. + @param path The address of an existing file system object + @param adr An application provided array of at least BURN_DRIVE_ADR_LEN + characters size. The persistent address gets copied to it. + @return 1 = success , 0 = failure , -1 = severe error +*/ +int burn_drive_convert_fs_adr(char *path, char adr[]); + /** Grab a drive. This must be done before the drive can be used (for reading, writing, etc). diff --git a/libburn/sg.c b/libburn/sg.c index d4e352c..1827a54 100644 --- a/libburn/sg.c +++ b/libburn/sg.c @@ -58,23 +58,59 @@ static int sgio_test(int fd) /* ts A60922 ticket 33 */ +/** Returns the next index number and the next enumerated drive address. + @param idx An opaque number handle. Make no own theories about it. + @param adr Takes the reply + @param adr_size Gives maximum size of reply including final 0 + @param initialize 1 = start new, 0 = continue, use no other values for now + @return 1 = reply is a valid address , 0 = no further address available + -1 = severe error (e.g. adr_size too small) +*/ +int sg_give_next_adr(int *idx, char adr[], int adr_size, int initialize) +{ + static int sg_limit = 32, ata_limit = 26; + int baseno = 0; + + if (initialize == 1) + *idx = -1; + (*idx)++; + if (*idx >= sg_limit) + goto next_ata; + if (adr_size < 10) + return -1; + sprintf(adr, "/dev/sg%d", *idx); + return 1; +next_ata:; + baseno += sg_limit; + if (*idx - baseno >= ata_limit) + goto next_nothing; + if (adr_size < 9) + return -1; + sprintf(adr, "/dev/hd%c", 'a' + (*idx - baseno)); + return 1; +next_nothing:; + baseno += ata_limit; + return 0; +} + int sg_is_enumerable_adr(char *adr) { - char fname[10]; - int i; + char fname[4096]; + int i, ret = 0, first = 1; - for (i = 0; i < 26; i++) { - sprintf(fname, "/dev/hd%c", 'a' + i); + while (1) { + ret= sg_give_next_adr(&i, fname, sizeof(fname), first); + if(ret <= 0) + break; +/* <<< + fprintf(stderr,"libburn experimental: idx %d : %s\n",i,fname); +*/ + first = 0; if (strcmp(adr, fname) == 0) return 1; + } - for (i = 0; i < 32; i++) { - sprintf(fname, "/dev/sg%d", i); - if (strcmp(adr, fname) == 0) - return 1; - - } - return 0; + return(0); } diff --git a/libburn/sg.h b/libburn/sg.h index 03666a9..afb5687 100644 --- a/libburn/sg.h +++ b/libburn/sg.h @@ -10,6 +10,7 @@ enum response { RETRY, FAIL }; /* ts A60922 ticket 33 */ +int sg_give_next_adr(int *idx, char adr[], int adr_size, int initialize); int sg_is_enumerable_adr(char *adr); void sg_enumerate(void);