"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "libburn/sg-linux.c" between
xorriso-1.5.2.tar.gz and xorriso-1.5.4.tar.gz

About: GNU xorriso creates, loads, manipulates and writes ISO 9660 filesystem images with Rock Ridge extensions. It is suitable for incremental data backup and for production of bootable ISO 9660 images. GNU xorriso is a statical compilation of the libraries libburn, libisofs, libisoburn, and libjte.

sg-linux.c  (xorriso-1.5.2):sg-linux.c  (xorriso-1.5.4)
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2019 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2020 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
/* <<< ts A91112 : experiments to get better speed with USB /* <<< ts A91112 : experiments to get better speed with USB
#define Libburn_sgio_as_growisofS 1 #define Libburn_sgio_as_growisofS 1
*/ */
/* /*
This is the main operating system dependent SCSI part of libburn. It implements This is the main operating system dependent SCSI part of libburn. It implements
skipping to change at line 49 skipping to change at line 49
sg_id_string() returns an id string of the SCSI transport adapter. sg_id_string() returns an id string of the SCSI transport adapter.
It may be called before initialization but then may It may be called before initialization but then may
return only a preliminary id. return only a preliminary id.
sg_initialize() performs global initialization of the SCSI transport sg_initialize() performs global initialization of the SCSI transport
adapter and eventually needed operating system adapter and eventually needed operating system
facilities. Checks for compatibility of supporting facilities. Checks for compatibility of supporting
software components. software components.
sg_shutdown() performs global finalizations and releases golbally sg_shutdown() performs global finalizations and releases globally
acquired resources. acquired resources.
sg_give_next_adr() iterates over the set of potentially useful drive sg_give_next_adr() iterates over the set of potentially useful drive
address strings. address strings.
scsi_enumerate_drives() brings all available, not-whitelist-banned, and scsi_enumerate_drives() brings all available, not-whitelist-banned, and
accessible drives into libburn's list of drives. accessible drives into libburn's list of drives.
sg_dispose_drive() finalizes adapter specifics of struct burn_drive sg_dispose_drive() finalizes adapter specifics of struct burn_drive
on destruction. Releases resources which were acquired on destruction. Releases resources which were acquired
underneath scsi_enumerate_drives(). underneath scsi_enumerate_drives().
sg_drive_is_open() tells wether libburn has the given drive in use. sg_drive_is_open() tells whether libburn has the given drive in use.
sg_grab() opens the drive for SCSI commands and ensures sg_grab() opens the drive for SCSI commands and ensures
undisturbed access. undisturbed access.
sg_release() closes a drive opened by sg_grab() sg_release() closes a drive opened by sg_grab()
sg_issue_command() sends a SCSI command to the drive, receives reply, sg_issue_command() sends a SCSI command to the drive, receives reply,
and evaluates wether the command succeeded or shall and evaluates whether the command succeeded or shall
be retried or finally failed. be retried or finally failed.
sg_obtain_scsi_adr() tries to obtain SCSI address parameters. sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
burn_os_is_2k_seekrw() tells whether the given path leads to a file object burn_os_is_2k_seekrw() tells whether the given path leads to a file object
that can be used in 2 kB granularity by lseek(2) and that can be used in 2 kB granularity by lseek(2) and
read(2), and possibly write(2) if not read-only. read(2), and possibly write(2) if not read-only.
E.g. a USB stick or a hard disk. E.g. a USB stick or a hard disk.
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives. burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
skipping to change at line 108 skipping to change at line 108
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "../config.h" #include "../config.h"
#endif #endif
/** PORTING : ------- OS dependent headers and definitions ------ */ /** PORTING : ------- OS dependent headers and definitions ------ */
#ifdef Libburn_read_o_direcT #ifdef Libburn_read_o_direcT
/* ts B91124:
DISABLED, because this spoils multi-track burning of cdrskin by a hard to
fix bug in cdrskin/cdrfifo.c
DO NOT ENABLE before the wait code in that source file is fixed.
*/
#undef Libburn_read_o_direcT
#endif
#ifdef Libburn_read_o_direcT
# ifndef _GNU_SOURCE # ifndef _GNU_SOURCE
# define _GNU_SOURCE # define _GNU_SOURCE
# endif # endif
#endif /* Libburn_read_o_direcT */ #endif /* Libburn_read_o_direcT */
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
skipping to change at line 204 skipping to change at line 213
/* The device file family to use for SCSI transport over ATA. /* The device file family to use for SCSI transport over ATA.
This must be a printf formatter with one single placeholder for a This must be a printf formatter with one single placeholder for a
_single_ char in the range of 'a' to 'z'. This placeholder _must_ be _single_ char in the range of 'a' to 'z'. This placeholder _must_ be
at the end of the formatter string. at the end of the formatter string.
E.g. "/dev/hd%c" E.g. "/dev/hd%c"
*/ */
static char linux_ata_device_family[80] = {"/dev/hd%c"}; static char linux_ata_device_family[80] = {"/dev/hd%c"};
/* Set this to 1 in order to get on stderr messages from ata_enumerate() /* Set this to 1 in order to get on stderr messages from ata_enumerate()
*/ */
static int linux_ata_enumerate_verbous = 0; static int linux_ata_enumerate_verbose = 0;
/** PORTING : ------ libburn portable headers and definitions ----- */ /** PORTING : ------ libburn portable headers and definitions ----- */
#include "libburn.h" #include "libburn.h"
#include "transport.h" #include "transport.h"
#include "drive.h" #include "drive.h"
#include "sg.h" #include "sg.h"
#include "spc.h" #include "spc.h"
#include "mmc.h" #include "mmc.h"
#include "sbc.h" #include "sbc.h"
skipping to change at line 270 skipping to change at line 279
debug: for tracing calls which might use open drive fds debug: for tracing calls which might use open drive fds
or for catching SCSI usage of emulated drives. */ or for catching SCSI usage of emulated drives. */
int mmc_function_spy(struct burn_drive *d, char * text); int mmc_function_spy(struct burn_drive *d, char * text);
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/* PORTING: Private functions. Port only if needed by public functions */ /* PORTING: Private functions. Port only if needed by public functions */
/* (Public functions are listed below) */ /* (Public functions are listed below) */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/* ts A70413 */ /* ts A70413 */
/* This finds out wether the software is running on kernel >= 2.6 /* This finds out whether the software is running on kernel >= 2.6
*/ */
static void sg_evaluate_kernel(void) static void sg_evaluate_kernel(void)
{ {
struct utsname buf; struct utsname buf;
if (sg_kernel_age >= 0) if (sg_kernel_age >= 0)
return; return;
sg_kernel_age = 0; sg_kernel_age = 0;
if (uname(&buf) == -1) if (uname(&buf) == -1)
return; return;
sg_kernel_age = 1; sg_kernel_age = 1;
if (strcmp(buf.release, "2.6") >= 0) if (strcmp(buf.release, "2.6") >= 0)
sg_kernel_age = 2; sg_kernel_age = 2;
} }
/* ts A70314 */ /* ts A70314 */
/* This installs the device file family if one was chosen explicitely /* This installs the device file family if one was chosen explicitly
by burn_preset_device_open() by burn_preset_device_open()
*/ */
static void sg_select_device_family(void) static void sg_select_device_family(void)
{ {
/* >>> ??? do we need a mutex here ? */ /* >>> ??? do we need a mutex here ? */
/* >>> (It might be concurrent but is supposed to have always /* >>> (It might be concurrent but is supposed to have always
the same effect. Any race condition should be harmless.) */ the same effect. Any race condition should be harmless.) */
if (burn_sg_use_family == 1) if (burn_sg_use_family == 1)
skipping to change at line 354 skipping to change at line 363
free(msg); free(msg);
} }
strcpy(fname, scd); strcpy(fname, scd);
return 1; return 1;
} }
/* ts B11110 */ /* ts B11110 */
/* This is an early stage version of scsi_log_cmd. /* This is an early stage version of scsi_log_cmd.
>>> It will become obsolete when the /tmp file handler is moved into >>> It will become obsolete when the /tmp file handler is moved into
>>> scsi_log_command(). >>> scsi_log_command().
@param flag bit0= data direction is FROM_DRIVE
*/ */
static int sgio_log_cmd(unsigned char *cmd, int cmd_len, FILE *fp_in, int flag) static int sgio_log_cmd(unsigned char *cmd, int cmd_len, FILE *fp_in, int flag)
{ {
FILE *fp = fp_in; FILE *fp = fp_in;
int ret = 0; int ret = 0;
int data_dir = NO_TRANSFER;
if (flag & 1)
data_dir = FROM_DRIVE;
/* >>> ts B11110 : move this into scsi_log_command() */ /* >>> ts B11110 : move this into scsi_log_command() */
if (fp == NULL && (burn_sg_log_scsi & 1)) { if (fp == NULL && (burn_sg_log_scsi & 1)) {
fp= fopen("/tmp/libburn_sg_command_log", "a"); fp= fopen("/tmp/libburn_sg_command_log", "a");
if (fp != NULL) if (fp != NULL)
fprintf(fp, fprintf(fp,
"\n=========================================\n"); "\n=========================================\n");
} }
if (fp != NULL) if (fp != NULL)
ret = scsi_log_command(cmd, cmd_len, NO_TRANSFER, NULL, 0, ret = scsi_log_command(cmd, cmd_len, data_dir, NULL, 0,
fp, flag); fp, flag);
if (fp_in == NULL && fp != NULL) if (fp_in == NULL && fp != NULL)
fclose(fp); fclose(fp);
if (fp == stderr || !(burn_sg_log_scsi & 2))
return ret;
ret = scsi_log_command(cmd, cmd_len, data_dir, NULL, 0, stderr, 0);
return ret; return ret;
} }
/* ts B11110 */ /* ts B11110 */
static int sgio_log_reply(unsigned char *opcode, int data_dir, static int sgio_log_reply(unsigned char *opcode, int data_dir,
unsigned char *data, int dxfer_len, unsigned char *data, int dxfer_len,
void *fp_in, unsigned char sense[18], int sense_len, void *fp_in, unsigned char sense[18], int sense_len,
double duration, int flag) double duration, int flag)
{ {
int ret; int ret;
skipping to change at line 441 skipping to change at line 458
s.dxfer_direction = SG_DXFER_FROM_DEV; s.dxfer_direction = SG_DXFER_FROM_DEV;
s.cmd_len = 6; s.cmd_len = 6;
s.cmdp = test_ops; s.cmdp = test_ops;
s.mx_sb_len = 32; s.mx_sb_len = 32;
s.sbp = sense; s.sbp = sense;
s.timeout = 30000; s.timeout = 30000;
s.dxferp = buf; s.dxferp = buf;
s.dxfer_len = 36; s.dxfer_len = 36;
s.usr_ptr = NULL; s.usr_ptr = NULL;
sgio_log_cmd(s.cmdp, s.cmd_len, NULL, 0); sgio_log_cmd(s.cmdp, s.cmd_len, NULL, 1);
c_start_time = burn_get_time(0); c_start_time = burn_get_time(0);
ret = ioctl(fd, SG_IO, &s); ret = ioctl(fd, SG_IO, &s);
c_end_time = burn_get_time(0); c_end_time = burn_get_time(0);
if (ret == -1) { if (ret == -1) {
sprintf(msg, sprintf(msg,
"INQUIRY on '%s' : ioctl(SG_IO) failed , errno= %d", "INQUIRY on '%s' : ioctl(SG_IO) failed , errno= %d",
fname, errno); fname, errno);
libdax_msgs_submit(libdax_messenger, -1, 0x00000002, libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
skipping to change at line 624 skipping to change at line 641
ex:; ex:;
BURN_FREE_MEM(msg); BURN_FREE_MEM(msg);
return ret; return ret;
} }
/* ts A70401 : /* ts A70401 :
fcntl() has the unappealing property to work only after open(). fcntl() has the unappealing property to work only after open().
So libburn will by default use open(O_EXCL) first and afterwards 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. as second assertion will use fcntl(F_SETLK). One lock more should not harm.
*/ */
static int sg_fcntl_lock(int *fd, char *fd_name, int l_type, int verbous) static int sg_fcntl_lock(int *fd, char *fd_name, int l_type, int verbose)
{ {
struct flock lockthing; struct flock lockthing;
char msg[81]; char msg[81];
int ret; int ret;
if (!burn_sg_fcntl_f_setlk) if (!burn_sg_fcntl_f_setlk)
return 1; return 1;
memset(&lockthing, 0, sizeof(lockthing)); memset(&lockthing, 0, sizeof(lockthing));
lockthing.l_type = l_type; lockthing.l_type = l_type;
lockthing.l_whence = SEEK_SET; lockthing.l_whence = SEEK_SET;
lockthing.l_start = 0; lockthing.l_start = 0;
lockthing.l_len = 0; lockthing.l_len = 0;
/* /*
fprintf(stderr,"LIBBURN_EXPERIMENTAL: fcntl(%d, F_SETLK, %s)\n", fprintf(stderr,"LIBBURN_EXPERIMENTAL: fcntl(%d, F_SETLK, %s)\n",
*fd, l_type == F_WRLCK ? "F_WRLCK" : "F_RDLCK"); *fd, l_type == F_WRLCK ? "F_WRLCK" : "F_RDLCK");
*/ */
ret = fcntl(*fd, F_SETLK, &lockthing); ret = fcntl(*fd, F_SETLK, &lockthing);
if (ret == -1) { if (ret == -1) {
if (verbous) { if (verbose) {
sprintf(msg, "Device busy. Failed to fcntl-lock '%s'", sprintf(msg, "Device busy. Failed to fcntl-lock '%s'",
fd_name); fd_name);
libdax_msgs_submit(libdax_messenger, -1, 0x00020008, libdax_msgs_submit(libdax_messenger, -1, 0x00020008,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, errno, 0); msg, errno, 0);
} }
close(*fd); close(*fd);
*fd = -1; *fd = -1;
/* ts A70409 : DDLP-B */ /* ts A70409 : DDLP-B */
skipping to change at line 774 skipping to change at line 791
sg_close_drive_fd(sibling_fnames[i], -1, &(sibling_fds[i]), 0); sg_close_drive_fd(sibling_fnames[i], -1, &(sibling_fds[i]), 0);
if(*sibling_count > 0) { if(*sibling_count > 0) {
sprintf(msg, "Closed %d O_EXCL scsi siblings", *sibling_count); sprintf(msg, "Closed %d O_EXCL scsi siblings", *sibling_count);
libdax_msgs_submit(libdax_messenger, -1, 0x00020007, libdax_msgs_submit(libdax_messenger, -1, 0x00020007,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, msg, 0,0); LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, msg, 0,0);
} }
*sibling_count = 0; *sibling_count = 0;
return 1; return 1;
} }
/* ts C00806 */
/** Urges the operating system to re-assess drive and medium state
*/
static int sg_os_revalidate_disc(struct burn_drive *d)
{
#ifdef Libburn_use_linux_ioctl_simul_changE
/* <<< only for compiler tests */
#ifndef CDROM_SIMUL_CHANGE
/* # def ine CDROM_SIMUL_CHANGE 0x5332 */
#endif
#ifdef CDROM_SIMUL_CHANGE
int fd, ret;
long old_blocks, new_blocks;
char *msg = NULL;
BURN_ALLOC_MEM(msg, char, 161);
ret = ioctl(d->fd, BLKGETSIZE, &old_blocks);
if (ret == -1)
old_blocks = -1;
/* Schedule a simulated medium change event.
Although the implemented ioctl cannot fail, the kernel might be too
old to know it and then throw errors like ENOTTY.
*/
ret = ioctl(d->fd, CDROM_SIMUL_CHANGE, 0);
if (ret == -1) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x02, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"ioctl(CDROM_SIMUL_CHANGE) failed", errno, 0);
ret = 0; goto ex;
}
libdax_msgs_submit(libdax_messenger, d->global_index,
0x02, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"ioctl(CDROM_SIMUL_CHANGE) was performed", 0, 0);
/* Try to trigger actual device assessment by a open(2) call */
fd = open(d->devname, O_RDONLY | O_NDELAY);
if (fd == -1) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x02, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"Failed to open device file after ioctl(CDROM_SIMUL_CHANGE)",
errno, 0);
ret = 0; goto ex;
}
close(fd);
ret = ioctl(d->fd, BLKGETSIZE, &new_blocks);
if (ret == -1) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x02, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"BLKGETSIZE failed after ioctl(CDROM_SIMUL_CHANGE)",
errno, 0);
} else if (old_blocks != new_blocks) {
sprintf(msg,
"BLKGETSIZE indicates size change from %ld to %ld blocks",
old_blocks , new_blocks);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x02, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
}
ex:
BURN_FREE_MEM(msg);
return ret;
#else /* CDROM_SIMUL_CHANGE */
return 0;
#endif /* ! CDROM_SIMUL_CHANGE */
#else /* Libburn_use_linux_ioctl_simul_changE */
return 0;
#endif /* ! Libburn_use_linux_ioctl_simul_changE */
}
/* ts A60926 */ /* ts A60926 */
static int sg_close_drive(struct burn_drive *d) static int sg_close_drive(struct burn_drive *d)
{ {
int ret; int ret;
if (!burn_drive_is_open(d)) if (!burn_drive_is_open(d))
return 0; return 0;
sg_release_siblings(d->sibling_fds, d->sibling_fnames, sg_release_siblings(d->sibling_fds, d->sibling_fnames,
&(d->sibling_count)); &(d->sibling_count));
if(d->medium_state_changed > 0)
sg_os_revalidate_disc(d);
d->medium_state_changed = -1;
ret = sg_close_drive_fd(d->devname, d->global_index, &(d->fd), 0); ret = sg_close_drive_fd(d->devname, d->global_index, &(d->fd), 0);
return ret; return ret;
} }
/* ts A60926 */ /* ts A60926 */
static int sg_open_scsi_siblings(char *path, int driveno, static int sg_open_scsi_siblings(char *path, int driveno,
int sibling_fds[], int sibling_fds[],
char sibling_fnames[][BURN_OS_SG_MAX_NAMELEN], char sibling_fnames[][BURN_OS_SG_MAX_NAMELEN],
int *sibling_count, int *sibling_count,
int host_no, int channel_no, int id_no, int lun_no) int host_no, int channel_no, int id_no, int lun_no)
skipping to change at line 888 skipping to change at line 989
static int is_ata_drive(char *fname, int fd_in) static int is_ata_drive(char *fname, int fd_in)
{ {
int fd; int fd;
struct hd_driveid tm; struct hd_driveid tm;
if (fd_in >= 0) if (fd_in >= 0)
fd = fd_in; fd = fd_in;
else else
fd = sg_open_drive_fd(fname, 1); fd = sg_open_drive_fd(fname, 1);
if (fd == -1) { if (fd == -1) {
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr,"open failed, errno=%d '%s'\n", fprintf(stderr,"open failed, errno=%d '%s'\n",
errno, strerror(errno)); errno, strerror(errno));
return 0; return 0;
} }
memset(&tm, 0, sizeof(tm)); memset(&tm, 0, sizeof(tm));
ioctl(fd, HDIO_GET_IDENTITY, &tm); ioctl(fd, HDIO_GET_IDENTITY, &tm);
/* not atapi */ /* not atapi */
if (!(tm.config & 0x8000) || (tm.config & 0x4000)) { if (!(tm.config & 0x8000) || (tm.config & 0x4000)) {
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, "not marked as ATAPI\n"); fprintf(stderr, "not marked as ATAPI\n");
if (fd_in < 0) if (fd_in < 0)
sg_close_drive_fd(fname, -1, &fd, 0); sg_close_drive_fd(fname, -1, &fd, 0);
return 0; return 0;
} }
/* if SG_IO fails on an atapi device, we should stop trying to /* if SG_IO fails on an atapi device, we should stop trying to
use hd* devices */ use hd* devices */
if (sgio_test(fd) == -1) { if (sgio_test(fd) == -1) {
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, fprintf(stderr,
"FATAL: sgio_test() failed: errno=%d '%s'\n", "FATAL: sgio_test() failed: errno=%d '%s'\n",
errno, strerror(errno)); errno, strerror(errno));
if (fd_in < 0) if (fd_in < 0)
sg_close_drive_fd(fname, -1, &fd, 0); sg_close_drive_fd(fname, -1, &fd, 0);
return 0; return 0;
} }
if (fd_in >= 0) if (fd_in >= 0)
return 1; return 1;
if (sg_close_drive_fd(fname, -1, &fd, 1) <= 0) { if (sg_close_drive_fd(fname, -1, &fd, 1) <= 0) {
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, fprintf(stderr,
"cannot close properly, errno=%d '%s'\n", "cannot close properly, errno=%d '%s'\n",
errno, strerror(errno)); errno, strerror(errno));
return 0; return 0;
} }
return 1; return 1;
} }
static int is_scsi_drive(char *fname, int fd_in, int *bus_no, int *host_no, static int is_scsi_drive(char *fname, int fd_in, int *bus_no, int *host_no,
int *channel_no, int *target_no, int *lun_no) int *channel_no, int *target_no, int *lun_no)
skipping to change at line 1063 skipping to change at line 1164
return ret; return ret;
} }
/* @param flag bit0= do not complain about failure to open /dev/sr /dev/scd */ /* @param flag bit0= do not complain about failure to open /dev/sr /dev/scd */
static int sg_open_for_enumeration(char *fname, int flag) static int sg_open_for_enumeration(char *fname, int flag)
{ {
int fd; int fd;
fd = sg_open_drive_fd(fname, 1 + (flag & 1)); fd = sg_open_drive_fd(fname, 1 + (flag & 1));
if (fd < 0) { if (fd < 0) {
if (linux_sg_enumerate_debug || linux_ata_enumerate_verbous) if (linux_sg_enumerate_debug || linux_ata_enumerate_verbose)
fprintf(stderr, "open failed, errno=%d '%s'\n", fprintf(stderr, "open failed, errno=%d '%s'\n",
errno, strerror(errno)); errno, strerror(errno));
return -1; return -1;
} }
return fd; return fd;
} }
/** Speciality of GNU/Linux: detect non-SCSI ATAPI (EIDE) which will from /** Speciality of GNU/Linux: detect non-SCSI ATAPI (EIDE) which will from
then on used used via generic SCSI as is done with (emulated) SCSI drives */ then on used used via generic SCSI as is done with (emulated) SCSI drives */
static void ata_enumerate(void) static void ata_enumerate(void)
{ {
int ret, i, fd = -1; int ret, i, fd = -1;
char fname[10]; char fname[10];
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, "libburn_debug: linux_ata_device_family = %s\n", fprintf(stderr, "libburn_debug: linux_ata_device_family = %s\n",
linux_ata_device_family); linux_ata_device_family);
if (linux_ata_device_family[0] == 0) if (linux_ata_device_family[0] == 0)
return; return;
for (i = 0; i < 26; i++) { for (i = 0; i < 26; i++) {
sprintf(fname, linux_ata_device_family, 'a' + i); sprintf(fname, linux_ata_device_family, 'a' + i);
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, "libburn_debug: %s : ", fname); fprintf(stderr, "libburn_debug: %s : ", fname);
/* ts A51221 */ /* ts A51221 */
if (burn_drive_is_banned(fname)) { if (burn_drive_is_banned(fname)) {
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, "not in whitelist\n"); fprintf(stderr, "not in whitelist\n");
continue; continue;
} }
fd = sg_open_for_enumeration(fname, 0); fd = sg_open_for_enumeration(fname, 0);
if (fd < 0) if (fd < 0)
continue; continue;
ret = is_ata_drive(fname, fd); ret = is_ata_drive(fname, fd);
if (ret < 0) if (ret < 0)
break; break;
if (ret == 0) if (ret == 0)
continue; continue;
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, "accepting as drive without SCSI address\n"); fprintf(stderr, "accepting as drive without SCSI address\n");
enumerate_common(fname, fd, -1, -1, -1, -1, -1); enumerate_common(fname, fd, -1, -1, -1, -1, -1);
} }
} }
/** Detects (probably emulated) SCSI drives */ /** Detects (probably emulated) SCSI drives */
static void sg_enumerate(void) static void sg_enumerate(void)
{ {
int i, ret, fd = -1; int i, ret, fd = -1;
int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1; int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1;
skipping to change at line 1614 skipping to change at line 1715
return -1; return -1;
if (ret > 0) if (ret > 0)
return 1; return 1;
sg_enumerate(); sg_enumerate();
ata_enumerate(); ata_enumerate();
add_proc_info_drives(0); add_proc_info_drives(0);
return 1; return 1;
} }
/** Tells wether libburn has the given drive in use or exclusively reserved. /** Tells whether libburn has the given drive in use or exclusively reserved.
If it is "open" then libburn will eventually call sg_release() on it when If it is "open" then libburn will eventually call sg_release() on it when
it is time to give up usage and reservation. it is time to give up usage and reservation.
*/ */
/** Published as burn_drive.drive_is_open() */ /** Published as burn_drive.drive_is_open() */
int sg_drive_is_open(struct burn_drive * d) int sg_drive_is_open(struct burn_drive * d)
{ {
/* a bit more detailed case distinction than needed */ /* a bit more detailed case distinction than needed */
if (d->fd == -1337) if (d->fd == -1337)
return 0; return 0;
if (d->fd < 0) if (d->fd < 0)
skipping to change at line 1667 skipping to change at line 1768
O_NONBLOCK was hardcoded here. So it should stay default mode. O_NONBLOCK was hardcoded here. So it should stay default mode.
ts A70411 ts A70411
Switched to O_NDELAY for LKML statement 2007/4/11/141 Switched to O_NDELAY for LKML statement 2007/4/11/141
*/ */
if(burn_sg_open_o_nonblock) if(burn_sg_open_o_nonblock)
open_mode |= O_NDELAY; open_mode |= O_NDELAY;
/* ts A60813 - A60822 /* ts A60813 - A60822
After enumeration the drive fd is probably still open. After enumeration the drive fd is probably still open.
-1337 is the initial value of burn_drive.fd and the value after -1337 is the initial value of burn_drive.fd and the value after
relase of drive. Unclear why not the official error return release of drive. Unclear why not the official error return
value -1 of open(2) war used. */ value -1 of open(2) war used. */
if(! burn_drive_is_open(d)) { if(! burn_drive_is_open(d)) {
char msg[120]; char msg[120];
/* >>> SINGLE_OPEN : This case should be impossible now, since enumeration /* >>> SINGLE_OPEN : This case should be impossible now, since enumeration
transfers the fd from scanning to drive. transfers the fd from scanning to drive.
So if close-wait-open is desired, then it has to So if close-wait-open is desired, then it has to
be done unconditionally. be done unconditionally.
*/ */
skipping to change at line 1790 skipping to change at line 1891
} }
libdax_msgs_submit(libdax_messenger, d->global_index, libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020003, 0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Could not grab drive - already in use", 0, 0); "Could not grab drive - already in use", 0, 0);
sg_close_drive(d); sg_close_drive(d);
d->fd = -1337; d->fd = -1337;
return 0; return 0;
} }
/** PORTING: Is mainly about the call to sg_close_drive() and wether it /** PORTING: Is mainly about the call to sg_close_drive() and whether it
implements the demanded functionality. implements the demanded functionality.
*/ */
/** Gives up the drive for SCSI commands and releases eventual access locks. /** Gives up the drive for SCSI commands and releases eventual access locks.
(Note: this is not physical tray locking.) (Note: this is not physical tray locking.)
*/ */
int sg_release(struct burn_drive *d) int sg_release(struct burn_drive *d)
{ {
/* ts A60821 /* ts A60821
<<< debug: for tracing calls which might use open drive fds */ <<< debug: for tracing calls which might use open drive fds */
if (mmc_function_spy(d, "sg_release") <= 0) if (mmc_function_spy(d, "sg_release") <= 0)
skipping to change at line 1988 skipping to change at line 2089
d->busy = BURN_DRIVE_IDLE; d->busy = BURN_DRIVE_IDLE;
d->cancel = 1; d->cancel = 1;
c->error = 1; c->error = 1;
libdax_msgs_submit(libdax_messenger, libdax_msgs_submit(libdax_messenger,
d->global_index, 0x000201a6, d->global_index, 0x000201a6,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Lost connection to drive", 0, 0); "Lost connection to drive", 0, 0);
scsi_log_message(d, fp, "--- SG_IO: Gave up connection to drive", 0); scsi_log_message(d, fp, "--- SG_IO: Gave up connection to drive", 0);
} }
/** Sends a SCSI command to the drive, receives reply and evaluates wether /** Sends a SCSI command to the drive, receives reply and evaluates whether
the command succeeded or shall be retried or finally failed. the command succeeded or shall be retried or finally failed.
Returned SCSI errors shall not lead to a return value indicating failure. Returned SCSI errors shall not lead to a return value indicating failure.
The callers get notified by c->error. An SCSI failure which leads not to The callers get notified by c->error. An SCSI failure which leads not to
a retry shall be notified via scsi_notify_error(). a retry shall be notified via scsi_notify_error().
@return: 1 success , <=0 failure @return: 1 success , <=0 failure
*/ */
int sg_issue_command(struct burn_drive *d, struct command *c) int sg_issue_command(struct burn_drive *d, struct command *c)
{ {
int done = 0, no_c_page = 0, i, ret; int done = 0, no_c_page = 0, i, ret;
int err; int err;
skipping to change at line 2216 skipping to change at line 2317
int *bus_no, int *host_no, int *channel_no, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no) int *target_no, int *lun_no)
{ {
int fd, ret, l, open_mode = O_RDONLY; int fd, ret, l, open_mode = O_RDONLY;
struct my_scsi_idlun { struct my_scsi_idlun {
int x; int x;
int host_unique_id; int host_unique_id;
}; };
struct my_scsi_idlun idlun; struct my_scsi_idlun idlun;
/* valgrind called idlun unitialized because it is blind for ioctl */ /* valgrind called idlun uninitialized because it is blind for ioctl */
idlun.x = 0; idlun.x = 0;
idlun.host_unique_id = 0; idlun.host_unique_id = 0;
l = strlen(linux_ata_device_family) - 2; l = strlen(linux_ata_device_family) - 2;
if (l > 0 && strncmp(path, linux_ata_device_family, l) == 0 if (l > 0 && strncmp(path, linux_ata_device_family, l) == 0
&& path[7] >= 'a' && path[7] <= 'z' && path[8] == 0) && path[7] >= 'a' && path[7] <= 'z' && path[8] == 0)
return 0; /* on RIP 14 all hdx return SCSI adr 0,0,0,0 */ return 0; /* on RIP 14 all hdx return SCSI adr 0,0,0,0 */
/* ts A70409 : DDLP-B */ /* ts A70409 : DDLP-B */
/* >>> obtain single lock on path */ /* >>> obtain single lock on path */
skipping to change at line 2283 skipping to change at line 2384
@return 1 is success , 0 is failure @return 1 is success , 0 is failure
*/ */
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no) int *target_no, int *lun_no)
{ {
return sg_obtain_scsi_adr_fd(path, -1, bus_no, host_no, channel_no, return sg_obtain_scsi_adr_fd(path, -1, bus_no, host_no, channel_no,
target_no, lun_no); target_no, lun_no);
} }
/* ts A60922 ticket 33 : called from drive.c */ /* ts A60922 ticket 33 : called from drive.c */
/** Tells wether a text is a persistent address as listed by the enumeration /** Tells whether a text is a persistent address as listed by the enumeration
functions. functions.
*/ */
int sg_is_enumerable_adr(char *adr) int sg_is_enumerable_adr(char *adr)
{ {
char *fname = NULL; char *fname = NULL;
int ret = 0, first = 1, fname_size = 4096; int ret = 0, first = 1, fname_size = 4096;
burn_drive_enumerator_t idx; burn_drive_enumerator_t idx;
BURN_ALLOC_MEM(fname, char, fname_size); BURN_ALLOC_MEM(fname, char, fname_size);
while (1) { while (1) {
 End of changes. 32 change blocks. 
26 lines changed or deleted 127 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)