From 12a2be8d864bce346f00000b57fdb4aa0b4d35df Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Wed, 30 Dec 2009 15:40:10 +0000 Subject: [PATCH] Making use of new libcdio capability to obtain SCSI address tuple on Linux --- cdrskin/cdrskin_timestamp.h | 2 +- libburn/drive.c | 47 ++++++++++++++++----- libburn/sg-libcdio.c | 83 +++++++++++++++---------------------- 3 files changed, 71 insertions(+), 61 deletions(-) diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 4b97c60..ea2a029 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2009.12.29.224506" +#define Cdrskin_timestamP "2009.12.30.154140" diff --git a/libburn/drive.c b/libburn/drive.c index 17623a9..823b663 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -1560,14 +1560,23 @@ int burn_drive_is_enumerable_adr(char *adr) #define BURN_DRIVE_MAX_LINK_DEPTH 20 /* ts A60922 ticket 33 */ -int burn_drive_resolve_link(char *path, char adr[], int *recursion_count) +/* @param flag bit0= no debug messages + bit1= resolve only links, + do not rely on drive list for resolving via st_rdev +*/ +int burn_drive_resolve_link(char *path, char adr[], int *recursion_count, + int flag) { int ret; char link_target[4096], msg[4096+100], link_adr[4096], *adrpt; + struct stat stbuf; - burn_drive_adr_debug_msg("burn_drive_resolve_link( %s )", path); + if (flag & 1) + burn_drive_adr_debug_msg("burn_drive_resolve_link( %s )", + path); if (*recursion_count >= BURN_DRIVE_MAX_LINK_DEPTH) { - burn_drive_adr_debug_msg( + if (flag & 1) + burn_drive_adr_debug_msg( "burn_drive_resolve_link aborts because link too deep", NULL); return 0; @@ -1575,12 +1584,15 @@ int burn_drive_resolve_link(char *path, char adr[], int *recursion_count) (*recursion_count)++; ret = readlink(path, link_target, sizeof(link_target)); if (ret == -1) { - burn_drive_adr_debug_msg("readlink( %s ) returns -1", path); + if (flag & 1) + burn_drive_adr_debug_msg("readlink( %s ) returns -1", + path); return 0; } if (ret >= sizeof(link_target) - 1) { sprintf(msg,"readlink( %s ) returns %d (too much)", path, ret); - burn_drive_adr_debug_msg(msg, NULL); + if (flag & 1) + burn_drive_adr_debug_msg(msg, NULL); return -1; } link_target[ret] = 0; @@ -1593,10 +1605,25 @@ int burn_drive_resolve_link(char *path, char adr[], int *recursion_count) } else adrpt = link_target; } - ret = burn_drive_convert_fs_adr_sub(adrpt, adr, recursion_count); - sprintf(msg,"burn_drive_convert_fs_adr( %s ) returns %d", - link_target, ret); - burn_drive_adr_debug_msg(msg, NULL); + if (flag & 2) { + /* Link-only recursion */ + if (lstat(adrpt, &stbuf) == -1) { + ; + } else if((stbuf.st_mode & S_IFMT) == S_IFLNK) { + ret = burn_drive_resolve_link(adrpt, adr, + recursion_count, flag); + } else { + strcpy(adr, adrpt); + } + } else { + /* Link and device number recursion */ + ret = burn_drive_convert_fs_adr_sub(adrpt, adr, + recursion_count); + sprintf(msg,"burn_drive_convert_fs_adr( %s ) returns %d", + link_target, ret); + } + if (flag & 1) + burn_drive_adr_debug_msg(msg, NULL); return ret; } @@ -1770,7 +1797,7 @@ int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count) return 0; } if((stbuf.st_mode & S_IFMT) == S_IFLNK) { - ret = burn_drive_resolve_link(path, adr, rec_count); + ret = burn_drive_resolve_link(path, adr, rec_count, 0); if(ret > 0) return 1; burn_drive_adr_debug_msg("link fallback via stat( %s )", path); diff --git a/libburn/sg-libcdio.c b/libburn/sg-libcdio.c index 7263dad..0f7bbc2 100644 --- a/libburn/sg-libcdio.c +++ b/libburn/sg-libcdio.c @@ -131,7 +131,8 @@ extern struct libdax_msgs *libdax_messenger; /* is in portable part of libburn */ int burn_drive_is_banned(char *device_address); - +int burn_drive_resolve_link(char *path, char adr[], + int *recursion_count, int flag); /* drive.c */ /* Whether to log SCSI commands: bit0= log in /tmp/libburn_sg_command_log @@ -175,11 +176,21 @@ static int sg_close_drive(struct burn_drive * d) static int sg_give_next_adr_raw(burn_drive_enumerator_t *idx, char adr[], int adr_size, int initialize) { + char **pos; + int count = 0; + if (initialize == 1) { idx->pos = idx->ppsz_cd_drives = cdio_get_devices(DRIVER_DEVICE); if (idx->ppsz_cd_drives == NULL) return 0; + + for (pos = idx->ppsz_cd_drives ; pos != NULL; pos++) { + if (*pos == NULL) + break; + count++; + } + } else if (initialize == -1) { if (*(idx->ppsz_cd_drives) != NULL) cdio_free_device_list(idx->ppsz_cd_drives); @@ -197,47 +208,6 @@ static int sg_give_next_adr_raw(burn_drive_enumerator_t *idx, } -/* Resolve eventual softlink, E.g. /dev/cdrom . */ -static int sg_resolve_link(char *in_path, char target[], int target_size, - int flag) -{ - int i, max_link_depth = 100, ret; - char path[4096], link_target[4096]; - struct stat stbuf; - - if (strlen(in_path) >= sizeof(path)) { - if (strlen(in_path) >= target_size) - return -1; - strcpy(target, path); - return 1; - } - strcpy(path, in_path); - - /* (burn_drive_resolve_link() relies on a completed drive list and - cannot be used here) */ - for (i= 0; i < max_link_depth; i++) { - if (lstat(path, &stbuf) == -1) { - strcpy(path, in_path); - break; /* dead link */ - } - if ((stbuf.st_mode & S_IFMT) != S_IFLNK) - break; /* found target */ - ret = readlink(path, link_target, sizeof(link_target)); - if (ret == -1) { - strcpy(path, in_path); - break; /* unreadable link pointer */ - } - strcpy(path, link_target); - } - if (i >= max_link_depth) /* endless link loop */ - strcpy(path, in_path); - if (strlen(path) >= target_size) - return -1; - strcpy(target, path); - return 1; -} - - /* ----------------------------------------------------------------------- */ /* PORTING: Private functions which contain publicly needed functionality. */ /* Their portable part must be performed. So it is probably best */ @@ -399,7 +369,7 @@ int sg_dispose_drive(struct burn_drive *d, int flag) int sg_give_next_adr(burn_drive_enumerator_t *idx, char adr[], int adr_size, int initialize) { - int ret; + int ret, recursion_count = 0; char path[4096]; ret = sg_give_next_adr_raw(idx, adr, adr_size, initialize); @@ -408,8 +378,8 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx, if (strlen(adr) >= sizeof(path)) return ret; strcpy(path, adr); - ret = sg_resolve_link(path, adr, adr_size, 0); - return ret; + ret = burn_drive_resolve_link(path, adr, &recursion_count, 2); + return (ret >= 0); } @@ -419,7 +389,7 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx, int scsi_enumerate_drives(void) { burn_drive_enumerator_t idx; - int initialize = 1, ret, i_bus_no = -1; + int initialize = 1, ret, i_bus_no = -1, recursion_count = 0; int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1; char buf[4096], target[4096]; @@ -428,7 +398,7 @@ int scsi_enumerate_drives(void) initialize = 0; if (ret <= 0) break; - ret = sg_resolve_link(buf, target, sizeof(target), 0); + ret = burn_drive_resolve_link(buf, target, &recursion_count,2); if (ret <= 0) strcpy(target, buf); if (burn_drive_is_banned(target)) @@ -653,11 +623,24 @@ ex:; int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, int *target_no, int *lun_no) { - - /* >>> any chance to get them from libcdio ? */; + CdIo_t *p_cdio; + char *tuple; *bus_no = *host_no = *channel_no = *target_no = *lun_no = -1; - return (0); + + p_cdio = cdio_open(path, DRIVER_DEVICE); + if (p_cdio == NULL) + return 0; + + /* Try whether a Linux address tuple is available */ + tuple = (char *) cdio_get_arg(p_cdio, "scsi-tuple-linux"); + if (tuple != NULL) if (tuple[0]) { + sscanf(tuple, "%d,%d,%d,%d,%d", + bus_no, host_no, channel_no, target_no, lun_no); + } + + cdio_destroy(p_cdio); + return (*bus_no >= 0); }