xorriso  1.5.4.pl02
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.
  Fossies Dox: xorriso-1.5.4.pl02.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

sg-linux.c
Go to the documentation of this file.
1 /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
2 
3 /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
4  Copyright (c) 2006 - 2020 Thomas Schmitt <scdbackup@gmx.net>
5  Provided under GPL version 2 or later.
6 */
7 
8 
9 
10 /* <<< ts A91112 : experiments to get better speed with USB
11 #define Libburn_sgio_as_growisofS 1
12 */
13 
14 
15 /*
16 
17 This is the main operating system dependent SCSI part of libburn. It implements
18 the transport level aspects of SCSI control and command i/o.
19 
20 Present implementation: GNU/Linux SCSI Generic (sg)
21 
22 
23 PORTING:
24 
25 Porting libburn typically will consist of adding a new operating system case
26 to the following switcher files:
27  os.h Operating system specific libburn definitions and declarations.
28  sg.c Operating system dependent transport level modules.
29 and of deriving the following system specific files from existing examples:
30  os-*.h Included by os.h. You will need some general system knowledge
31  about signals and knowledge about the storage object needs of your
32  transport level module sg-*.c.
33 
34  sg-*.c This source module. You will need special system knowledge about
35  how to detect all potentially available drives, how to open them,
36  eventually how to exclusively reserve them, how to perform
37  SCSI transactions, how to inquire the (pseudo-)SCSI driver.
38  You will not need to care about CD burning, MMC or other high-level
39  SCSI aspects.
40 
41 Said sg-*.c operations are defined by a public function interface, which has
42 to be implemented in a way that provides libburn with the desired services:
43 
44 sg_id_string() returns an id string of the SCSI transport adapter.
45  It may be called before initialization but then may
46  return only a preliminary id.
47 
48 sg_initialize() performs global initialization of the SCSI transport
49  adapter and eventually needed operating system
50  facilities. Checks for compatibility of supporting
51  software components.
52 
53 sg_shutdown() performs global finalizations and releases globally
54  acquired resources.
55 
56 sg_give_next_adr() iterates over the set of potentially useful drive
57  address strings.
58 
59 scsi_enumerate_drives() brings all available, not-whitelist-banned, and
60  accessible drives into libburn's list of drives.
61 
62 sg_dispose_drive() finalizes adapter specifics of struct burn_drive
63  on destruction. Releases resources which were acquired
64  underneath scsi_enumerate_drives().
65 
66 sg_drive_is_open() tells whether libburn has the given drive in use.
67 
68 sg_grab() opens the drive for SCSI commands and ensures
69  undisturbed access.
70 
71 sg_release() closes a drive opened by sg_grab()
72 
73 sg_issue_command() sends a SCSI command to the drive, receives reply,
74  and evaluates whether the command succeeded or shall
75  be retried or finally failed.
76 
77 sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
78 
79 
80 burn_os_is_2k_seekrw() tells whether the given path leads to a file object
81  that can be used in 2 kB granularity by lseek(2) and
82  read(2), and possibly write(2) if not read-only.
83  E.g. a USB stick or a hard disk.
84 
85 burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
86 
87 burn_os_open_track_src() opens a disk file in a way that offers best
88  throughput with file reading and/or SCSI write command
89  transmission.
90 
91 burn_os_alloc_buffer() allocates a memory area that is suitable for file
92  descriptors issued by burn_os_open_track_src().
93  The buffer size may be rounded up for alignment
94  reasons.
95 
96 burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
97 
98 
99 Porting hints are marked by the text "PORTING:".
100 Send feedback to libburn-hackers@pykix.org .
101 
102 Hint: You should also look into sg-freebsd-port.c, which is a younger and
103  in some aspects more straightforward implementation of this interface.
104 
105 */
106 
107 #ifdef HAVE_CONFIG_H
108 #include "../config.h"
109 #endif
110 
111 
112 /** PORTING : ------- OS dependent headers and definitions ------ */
113 
114 #ifdef Libburn_read_o_direcT
115 /* ts B91124:
116  DISABLED, because this spoils multi-track burning of cdrskin by a hard to
117  fix bug in cdrskin/cdrfifo.c
118  DO NOT ENABLE before the wait code in that source file is fixed.
119 */
120 #undef Libburn_read_o_direcT
121 #endif
122 
123 
124 #ifdef Libburn_read_o_direcT
125 # ifndef _GNU_SOURCE
126 # define _GNU_SOURCE
127 # endif
128 #endif /* Libburn_read_o_direcT */
129 
130 #include <errno.h>
131 #include <unistd.h>
132 #include <stdio.h>
133 #include <sys/types.h>
134 #include <sys/stat.h>
135 #include <fcntl.h>
136 #include <sys/ioctl.h>
137 #include <string.h>
138 #include <sys/poll.h>
139 #include <linux/hdreg.h>
140 #include <stdlib.h>
141 #include <sys/utsname.h>
142 #include <scsi/scsi.h>
143 #include <sys/statvfs.h>
144 
145 /* for ioctl(BLKGETSIZE) */
146 #include <linux/fs.h>
147 
148 /* for mmap() */
149 #include <sys/mman.h>
150 
151 
152 #include <scsi/sg.h>
153 /* Values within sg_io_hdr_t indicating success after ioctl(SG_IO) : */
154 /* .host_status : from http://tldp.org/HOWTO/SCSI-Generic-HOWTO/x291.html */
155 #define Libburn_sg_host_oK 0
156 /* .driver_status : from http://tldp.org/HOWTO/SCSI-Generic-HOWTO/x322.html */
157 #define Libburn_sg_driver_oK 0
158 
159 
160 /* ts A61211 : to eventually recognize CD devices on /dev/sr* */
161 #include <limits.h>
162 #include <linux/cdrom.h>
163 
164 
165 /** Indication of the Linux kernel this software is running on */
166 /* -1 = not evaluated , 0 = unrecognizable , 1 = 2.4 , 2 = 2.6 */
167 static int sg_kernel_age = -1;
168 
169 
170 /** PORTING : Device file families for bus scanning and drive access.
171  Both device families must support the following ioctls:
172  SG_IO,
173  SG_GET_SCSI_ID
174  SCSI_IOCTL_GET_BUS_NUMBER
175  SCSI_IOCTL_GET_IDLUN
176  as well as mutual exclusively locking with open(O_EXCL).
177  If a device family is left empty, then it will not be used.
178 
179  To avoid misunderstandings: both families are used via identical
180  transport methods as soon as a device file is accepted as CD drive
181  by the family specific function <family>_enumerate().
182  One difference remains throughout usage: Host,Channel,Id,Lun and Bus
183  address parameters of ATA devices are considered invalid.
184 */
185 
186 /* Set this to 1 in order to get on stderr messages from sg_enumerate() */
188 
189 
190 /* The device file family to use for (emulated) generic SCSI transport.
191  This must be a printf formatter with one single placeholder for int
192  in the range of 0 to 31 . The resulting addresses must provide SCSI
193  address parameters Host, Channel, Id, Lun and also Bus.
194  E.g.: "/dev/sg%d"
195  sr%d is supposed to map only CD-ROM style devices. Additionally a test
196  with ioctl(CDROM_DRIVE_STATUS) is made to assert that it is such a drive,
197  If no such assertion is made, then this adapter performs INQUIRE and
198  looks for first reply byte 0x05.
199 
200  This initial setting may be overridden in sg_select_device_family() by
201  settings made via burn_preset_device_open().
202 */
203 static char linux_sg_device_family[80] = {"/dev/sg%d"};
204 
205 /* Set this to 1 if you want the default linux_sg_device_family chosen
206  depending on kernel release: sg for <2.6 , sr for >=2.6
207 */
208 static int linux_sg_auto_family = 1;
209 
210 
211 /* Set this to 1 in order to accept any TYPE_* (see scsi/scsi.h) */
212 /* But try with 0 first. There is hope via CDROM_DRIVE_STATUS. */
213 /* !!! DO NOT SET TO 1 UNLESS YOU PROTECTED ALL INDISPENSABLE DEVICES
214  chmod -rw !!! */
216 
217 
218 /* The device file family to use for SCSI transport over ATA.
219  This must be a printf formatter with one single placeholder for a
220  _single_ char in the range of 'a' to 'z'. This placeholder _must_ be
221  at the end of the formatter string.
222  E.g. "/dev/hd%c"
223 */
224 static char linux_ata_device_family[80] = {"/dev/hd%c"};
225 
226 /* Set this to 1 in order to get on stderr messages from ata_enumerate()
227 */
229 
230 
231 /** PORTING : ------ libburn portable headers and definitions ----- */
232 
233 #include "libburn.h"
234 #include "transport.h"
235 #include "drive.h"
236 #include "sg.h"
237 #include "spc.h"
238 #include "mmc.h"
239 #include "sbc.h"
240 #include "debug.h"
241 #include "toc.h"
242 #include "util.h"
243 #include "init.h"
244 
245 #include "libdax_msgs.h"
246 extern struct libdax_msgs *libdax_messenger;
247 
248 /* ts A51221 */
249 int burn_drive_is_banned(char *device_address);
250 
251 
252 /* ------------------------------------------------------------------------ */
253 /* PORTING: Private definitions. Port only if needed by public functions. */
254 /* (Public functions are listed below) */
255 /* ------------------------------------------------------------------------ */
256 
257 
258 static void enumerate_common(char *fname, int fd_in, int bus_no, int host_no,
259  int channel_no, int target_no, int lun_no);
260 
261 static int sg_obtain_scsi_adr_fd(char *path, int fd_in,
262  int *bus_no, int *host_no, int *channel_no,
263  int *target_no, int *lun_no);
264 
265 
266 /* ts A60813 : storage objects are in libburn/init.c
267  whether to use O_EXCL with open(2) of devices
268  whether to use fcntl(,F_SETLK,) after open(2) of devices
269  what device family to use : 0=default, 1=sr, 2=scd, (3=st), 4=sg
270  whether to use O_NOBLOCK with open(2) on devices
271  whether to take O_EXCL rejection as fatal error
272 */
273 extern int burn_sg_open_o_excl;
274 extern int burn_sg_fcntl_f_setlk;
275 extern int burn_sg_use_family;
276 extern int burn_sg_open_o_nonblock;
277 extern int burn_sg_open_abort_busy;
278 
279 /* ts A91111 :
280  whether to log SCSI commands:
281  bit0= log in /tmp/libburn_sg_command_log
282  bit1= log to stderr
283  bit2= flush every line
284 */
285 extern int burn_sg_log_scsi;
286 
287 /* ts A60821
288  debug: for tracing calls which might use open drive fds
289  or for catching SCSI usage of emulated drives. */
290 int mmc_function_spy(struct burn_drive *d, char * text);
291 
292 
293 /* ------------------------------------------------------------------------ */
294 /* PORTING: Private functions. Port only if needed by public functions */
295 /* (Public functions are listed below) */
296 /* ------------------------------------------------------------------------ */
297 
298 /* ts A70413 */
299 /* This finds out whether the software is running on kernel >= 2.6
300 */
301 static void sg_evaluate_kernel(void)
302 {
303  struct utsname buf;
304  if (sg_kernel_age >= 0)
305  return;
306 
307  sg_kernel_age = 0;
308  if (uname(&buf) == -1)
309  return;
310  sg_kernel_age = 1;
311  if (strcmp(buf.release, "2.6") >= 0)
312  sg_kernel_age = 2;
313 }
314 
315 
316 /* ts A70314 */
317 /* This installs the device file family if one was chosen explicitly
318  by burn_preset_device_open()
319 */
320 static void sg_select_device_family(void)
321 {
322 
323  /* >>> ??? do we need a mutex here ? */
324  /* >>> (It might be concurrent but is supposed to have always
325  the same effect. Any race condition should be harmless.) */
326 
327  if (burn_sg_use_family == 1)
328  strcpy(linux_sg_device_family, "/dev/sr%d");
329  else if (burn_sg_use_family == 2)
330  strcpy(linux_sg_device_family, "/dev/scd%d");
331  else if (burn_sg_use_family == 3)
332  strcpy(linux_sg_device_family, "/dev/st%d");
333  else if (burn_sg_use_family == 4)
334  strcpy(linux_sg_device_family, "/dev/sg%d");
335  else if (linux_sg_auto_family) {
337  if (sg_kernel_age >= 2)
338  strcpy(linux_sg_device_family, "/dev/sr%d");
339  else
340  strcpy(linux_sg_device_family, "/dev/sg%d");
342  }
343 }
344 
345 
346 /* ts A80701 */
347 /* This cares for the case that no /dev/srNN but only /dev/scdNN exists.
348  A theoretical case which has its complement in SuSE 10.2 having
349  /dev/sr but not /dev/scd.
350 */
351 static int sg_exchange_scd_for_sr(char *fname, int flag)
352 {
353  struct stat stbuf;
354  char scd[17], *msg = NULL;
355 
356  if (burn_sg_use_family != 0 || strncmp(fname, "/dev/sr", 7)!=0 ||
357  strlen(fname)>9 || strlen(fname)<8)
358  return 2;
359  if (fname[7] < '0' || fname[7] > '9')
360  return 2;
361  if (fname [8] != 0 && (fname[7] < '0' || fname[7] > '9'))
362  return 2;
363  if (stat(fname, &stbuf) != -1)
364  return 2;
365  strcpy(scd, "/dev/scd");
366  strcpy(scd + 8, fname + 7);
367  if (stat(scd, &stbuf) == -1)
368  return 2;
369  msg = calloc(strlen(scd) + strlen(fname) + 80, 1);
370  if (msg != NULL) {
371  sprintf(msg, "%s substitutes for non-existent %s", scd, fname);
372  libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
374  msg, 0, 0);
375  free(msg);
376  }
377  strcpy(fname, scd);
378  return 1;
379 }
380 
381 
382 /* ts B11110 */
383 /* This is an early stage version of scsi_log_cmd.
384  >>> It will become obsolete when the /tmp file handler is moved into
385  >>> scsi_log_command().
386  @param flag bit0= data direction is FROM_DRIVE
387 */
388 static int sgio_log_cmd(unsigned char *cmd, int cmd_len, FILE *fp_in, int flag)
389 {
390  FILE *fp = fp_in;
391  int ret = 0;
392  int data_dir = NO_TRANSFER;
393 
394  if (flag & 1)
395  data_dir = FROM_DRIVE;
396 
397  /* >>> ts B11110 : move this into scsi_log_command() */
398  if (fp == NULL && (burn_sg_log_scsi & 1)) {
399  fp= fopen("/tmp/libburn_sg_command_log", "a");
400  if (fp != NULL)
401  fprintf(fp,
402  "\n=========================================\n");
403  }
404 
405  if (fp != NULL)
406  ret = scsi_log_command(cmd, cmd_len, data_dir, NULL, 0,
407  fp, flag);
408  if (fp_in == NULL && fp != NULL)
409  fclose(fp);
410  if (fp == stderr || !(burn_sg_log_scsi & 2))
411  return ret;
412  ret = scsi_log_command(cmd, cmd_len, data_dir, NULL, 0, stderr, 0);
413  return ret;
414 }
415 
416 
417 /* ts B11110 */
418 static int sgio_log_reply(unsigned char *opcode, int data_dir,
419  unsigned char *data, int dxfer_len,
420  void *fp_in, unsigned char sense[18], int sense_len,
421  double duration, int flag)
422 {
423  int ret;
424 
425  ret = scsi_log_reply(opcode, data_dir, data, dxfer_len, fp_in,
426  sense, sense_len, duration, flag);
427  return ret;
428 }
429 
430 
431 static int sgio_test(int fd)
432 {
433  unsigned char test_ops[] = { 0, 0, 0, 0, 0, 0 };
434  sg_io_hdr_t s;
435  int ret;
436  double c_start_time, c_end_time;
437 
438  memset(&s, 0, sizeof(sg_io_hdr_t));
439  s.interface_id = 'S';
440  s.dxfer_direction = SG_DXFER_NONE;
441  s.cmd_len = 6;
442  s.cmdp = test_ops;
443  s.timeout = 12345;
444 
445  sgio_log_cmd(s.cmdp, s.cmd_len, NULL, 0);
446 
447  c_start_time = burn_get_time(0);
448  ret= ioctl(fd, SG_IO, &s);
449  c_end_time = burn_get_time(0);
450 
451  sgio_log_reply(s.cmdp, NO_TRANSFER, NULL, 0, NULL,
452  (unsigned char *) (s.sbp),
453  s.sb_len_wr, c_end_time - c_start_time, 0);
454  return ret;
455 }
456 
457 
458 static int sgio_inquiry_cd_drive(int fd, char *fname)
459 {
460  unsigned char test_ops[] = { 0x12, 0, 0, 0, 36, 0 };
461  sg_io_hdr_t s;
462  struct buffer *buf = NULL;
463  unsigned char *sense = NULL;
464  char *msg = NULL, *msg_pt;
465  int ret = 0, i;
466  double c_start_time, c_end_time;
467 
468  BURN_ALLOC_MEM(buf, struct buffer, 1);
469  BURN_ALLOC_MEM(sense, unsigned char, 128);
470  BURN_ALLOC_MEM(msg, char, strlen(fname) + 1024);
471 
472  memset(&s, 0, sizeof(sg_io_hdr_t));
473  s.interface_id = 'S';
474  s.dxfer_direction = SG_DXFER_FROM_DEV;
475  s.cmd_len = 6;
476  s.cmdp = test_ops;
477  s.mx_sb_len = 32;
478  s.sbp = sense;
479  s.timeout = 30000;
480  s.dxferp = buf;
481  s.dxfer_len = 36;
482  s.usr_ptr = NULL;
483 
484  sgio_log_cmd(s.cmdp, s.cmd_len, NULL, 1);
485 
486  c_start_time = burn_get_time(0);
487  ret = ioctl(fd, SG_IO, &s);
488  c_end_time = burn_get_time(0);
489  if (ret == -1) {
490  sprintf(msg,
491  "INQUIRY on '%s' : ioctl(SG_IO) failed , errno= %d",
492  fname, errno);
493  libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
495  msg, 0, 0);
496  goto ex;
497  }
498 
499  sgio_log_reply(s.cmdp, FROM_DRIVE, buf->data, s.dxfer_len, NULL,
500  (unsigned char *) (s.sbp),
501  s.sb_len_wr, c_end_time - c_start_time, 0);
502 
503  if (s.sb_len_wr > 0 || s.host_status != Libburn_sg_host_oK ||
504  s.driver_status != Libburn_sg_driver_oK) {
505  sprintf(msg, "INQUIRY failed on '%s' : host_status= %hd , driver_status= %hd", fname, s.host_status, s.driver_status);
506  if (s.sb_len_wr > 0) {
507  sprintf(msg + strlen(msg), " , sense data=");
508  msg_pt = msg + strlen(msg);
509  for (i = 0 ; i < s.sb_len_wr; i++)
510  sprintf(msg_pt + i * 3, " %2.2X",
511  ((unsigned char *) (s.sbp))[i]);
512  }
513  libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
515  msg, 0, 0);
516  ret = -1;
517  goto ex;
518  }
519  ret = 0;
520  if (buf->data[0] == 0x5) {
521  /* Peripheral qualifier 0, device type 0x5 = CD/DVD device.
522  SPC-3 tables 82 and 83 */
523  ret = 1;
524  } else {
525  sprintf(msg, "INQUIRY on '%s' : byte 0 = 0x%2.2X",
526  fname, buf->data[0]);
527  libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
529  msg, 0, 0);
530  }
531 
532 ex:;
533  BURN_FREE_MEM(msg);
534  BURN_FREE_MEM(sense);
535  BURN_FREE_MEM(buf);
536  return ret;
537 }
538 
539 
540 /* ts A60924 */
541 static int sg_handle_busy_device(char *fname, int os_errno)
542 {
543  char *msg = NULL;
544  struct stat stbuf;
545  int looks_like_hd= 0, fd, ret;
546 
547  BURN_ALLOC_MEM(msg, char, 4096);
548 
549  /* ts A80713 :
550  check existence of /dev/hdX1 as hint for hard disk rather than CD
551  Hint by Giulio Orsero: check /proc/ide/hdX/media for "disk"
552  */
553  if (strncmp(fname, "/dev/hd", 7)==0) {
554  sprintf(msg, "%s1", fname);
555  if (stat(msg, &stbuf) != -1)
556  looks_like_hd= 1;
557  sprintf(msg, "/proc/ide/hd%c/media", fname[7]);
558  fd = open(msg, O_RDONLY);
559  if (fd != -1) {
560  ret = read(fd, msg, 10);
561  if (ret < 0)
562  ret = 0;
563  msg[ret]= 0;
564  close(fd);
565  if (strncmp(msg, "disk\n", 5) == 0 ||
566  strcmp(msg, "disk") == 0)
567  looks_like_hd= 2;
568  else if (strncmp(msg, "cdrom\n", 6) == 0 ||
569  strcmp(msg, "cdrom") == 0)
570  looks_like_hd= 0;
571  }
572  }
573 
574  /* ts A60814 : i saw no way to do this more nicely */
576  fprintf(stderr,
577  "\nlibburn: FATAL : Application triggered abort on busy device '%s'\n",
578  fname);
579 
580  /* ts A61007 */
581  abort();
582  /* a ssert("drive busy" == "non fatal"); */
583  }
584 
585  /* ts A60924 : now reporting to libdax_msgs */
586  if (looks_like_hd == 2) { /* is surely hard disk */
587  ;
588  } else if (looks_like_hd) {
589  sprintf(msg, "Could not examine busy device '%s'", fname);
590  libdax_msgs_submit(libdax_messenger, -1, 0x0002015a,
592  msg, os_errno, 0);
593  sprintf(msg,
594  "Busy '%s' seems to be a hard disk, as '%s1' exists. But better check.",
595  fname, fname);
596  libdax_msgs_submit(libdax_messenger, -1, 0x0002015b,
598  msg, 0, 0);
599 
600  } else {
601  sprintf(msg, "Cannot open busy device '%s'", fname);
602  libdax_msgs_submit(libdax_messenger, -1, 0x00020001,
604  msg, os_errno, 0);
605  }
606  ret = 1;
607 ex:;
608  BURN_FREE_MEM(msg);
609  return ret;
610 }
611 
612 
613 /* ts A60925 : ticket 74 */
614 static int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry)
615 {
616  int ret, os_errno, sevno= LIBDAX_MSGS_SEV_DEBUG;
617  char *msg = NULL;
618 
619  if(*fd < 0)
620  {ret = 0; goto ex;}
621  BURN_ALLOC_MEM(msg, char, 4096 + 100);
622 
623 #ifdef CDROM_MEDIA_CHANGED_disabled_because_not_helpful
624 #ifdef CDSL_CURRENT
625  /* ts A80217 : wondering whether the os knows about our activities */
626  ret = ioctl(*fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT);
627  sprintf(msg, "ioctl(CDROM_MEDIA_CHANGED) == %d", ret);
628  libdax_msgs_submit(libdax_messenger, driveno, 0x00000002,
630 
631 #ifdef BLKFLSBUF_disabled_because_not_helpful
632  ret = ioctl(*fd, BLKFLSBUF, 0);
633  sprintf(msg, "ioctl(BLKFLSBUF) == %d", ret);
634  os_errno = 0;
635  if(ret == -1)
636  os_errno = errno;
637  libdax_msgs_submit(libdax_messenger, driveno, 0x00000002,
638  LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg, os_errno,0);
639 #endif /* BLKFLSBUF */
640 
641 #endif /* CDSL_CURRENT */
642 #endif /* CDROM_MEDIA_CHANGED */
643 
644  ret = close(*fd);
645  *fd = -1337;
646  if(ret != -1) {
647  /* ts A70409 : DDLP-B */
648  /* >>> release single lock on fname */
649  {ret = 1; goto ex;}
650  }
651  os_errno= errno;
652 
653  sprintf(msg, "Encountered error when closing drive '%s'", fname);
654  if (sorry)
655  sevno = LIBDAX_MSGS_SEV_SORRY;
656  libdax_msgs_submit(libdax_messenger, driveno, 0x00020002,
657  sevno, LIBDAX_MSGS_PRIO_HIGH, msg, os_errno, 0);
658  ret = 0;
659 ex:;
660  BURN_FREE_MEM(msg);
661  return ret;
662 }
663 
664 
665 /* ts A70401 :
666  fcntl() has the unappealing property to work only after open().
667  So libburn will by default use open(O_EXCL) first and afterwards
668  as second assertion will use fcntl(F_SETLK). One lock more should not harm.
669 */
670 static int sg_fcntl_lock(int *fd, char *fd_name, int l_type, int verbose)
671 {
672  struct flock lockthing;
673  char msg[81];
674  int ret;
675 
677  return 1;
678 
679  memset(&lockthing, 0, sizeof(lockthing));
680  lockthing.l_type = l_type;
681  lockthing.l_whence = SEEK_SET;
682  lockthing.l_start = 0;
683  lockthing.l_len = 0;
684 /*
685  fprintf(stderr,"LIBBURN_EXPERIMENTAL: fcntl(%d, F_SETLK, %s)\n",
686  *fd, l_type == F_WRLCK ? "F_WRLCK" : "F_RDLCK");
687 */
688 
689  ret = fcntl(*fd, F_SETLK, &lockthing);
690  if (ret == -1) {
691  if (verbose) {
692  sprintf(msg, "Device busy. Failed to fcntl-lock '%s'",
693  fd_name);
694  libdax_msgs_submit(libdax_messenger, -1, 0x00020008,
696  msg, errno, 0);
697  }
698  close(*fd);
699  *fd = -1;
700 
701  /* ts A70409 : DDLP-B */
702  /* >>> release single lock on fd_name */
703 
704  return(0);
705  }
706  return 1;
707 }
708 
709 
710 /* ts A60926 */
711 /* @param scan_mode 0= open for drivce aquiration
712  1= open for scanning with guessed names
713  2= open for scanning with /proc/sys/dev/cdrom/info names
714 */
715 static int sg_open_drive_fd(char *fname, int scan_mode)
716 {
717  int open_mode = O_RDWR, fd, tries= 0, is_std_adr, report_as_note = 0;
718  char msg[81];
719  struct stat stbuf;
720 
721  /* ts A70409 : DDLP-B */
722  /* >>> obtain single lock on fname */
723 
724  /* ts A60813 - A60927
725  O_EXCL with devices is a non-POSIX feature
726  of Linux kernels. Possibly introduced 2002.
727  Mentioned in "The Linux SCSI Generic (sg) HOWTO" */
729  open_mode |= O_EXCL;
730  /* ts A60813
731  O_NONBLOCK was already hardcoded in ata_ but not in sg_.
732  There must be some reason for this. So O_NONBLOCK is
733  default mode for both now. Disable on own risk.
734  ts B10904: O_NONBLOCK is prescribed by <linux/cdrom.h>
735  ts A70411
736  Switched to O_NDELAY for LKML statement 2007/4/11/141 by Alan Cox:
737  "open() has side effects. The CD layer allows you to open
738  with O_NDELAY if you want to avoid them."
739  */
741  open_mode |= O_NDELAY;
742 
743 /* <<< debugging
744  fprintf(stderr,
745  "\nlibburn: experimental: o_excl= %d , o_nonblock= %d, abort_on_busy= %d\n",
746  burn_sg_open_o_excl,burn_sg_open_o_nonblock,burn_sg_open_abort_busy);
747  fprintf(stderr,
748  "libburn: experimental: O_EXCL= %d , O_NDELAY= %d\n",
749  !!(open_mode&O_EXCL),!!(open_mode&O_NDELAY));
750 */
751 
752 try_open:;
753  fd = open(fname, open_mode);
754  if (fd == -1) {
755 /* <<< debugging
756  fprintf(stderr,
757  "\nlibburn: experimental: fname= %s , errno= %d\n",
758  fname,errno);
759 */
760  if (errno == EBUSY) {
761  tries++;
762 
763 /* <<< debugging
764  fprintf(stderr,
765  "\nlibburn_DEBUG: EBUSY , tries= %d\n", tries);
766 */
767 
768  if (tries < 4) {
769  usleep(2000000);
770  goto try_open;
771  }
772  sg_handle_busy_device(fname, errno);
773  return -1;
774 
775  }
776  sprintf(msg, "Failed to open device '%s'",fname);
777  if (scan_mode) {
778  is_std_adr = (strncmp(fname, "/dev/sr", 7) == 0 ||
779  strncmp(fname, "/dev/scd", 8) == 0);
780  if(scan_mode == 1 && is_std_adr &&
781  stat(fname, &stbuf) != -1)
782  report_as_note = 1;
783  else if(scan_mode == 2 && (!is_std_adr) &&
784  stat(fname, &stbuf) != -1)
785  report_as_note = 1;
786  if (report_as_note)
788  0x0002000e,
790  msg, errno, 0);
791  } else {
792  libdax_msgs_submit(libdax_messenger, -1, 0x00020005,
794  msg, errno, 0);
795  }
796  return -1;
797  }
798  sg_fcntl_lock(&fd, fname, F_WRLCK, 1);
799  return fd;
800 }
801 
802 
803 /* ts A60926 */
804 static int sg_release_siblings(int sibling_fds[],
805  char sibling_fnames[][BURN_OS_SG_MAX_NAMELEN],
806  int *sibling_count)
807 {
808  int i;
809  char msg[81];
810 
811  for(i= 0; i < *sibling_count; i++)
812  sg_close_drive_fd(sibling_fnames[i], -1, &(sibling_fds[i]), 0);
813  if(*sibling_count > 0) {
814  sprintf(msg, "Closed %d O_EXCL scsi siblings", *sibling_count);
815  libdax_msgs_submit(libdax_messenger, -1, 0x00020007,
817  }
818  *sibling_count = 0;
819  return 1;
820 }
821 
822 
823 /* ts C00806 */
824 /** Urges the operating system to re-assess drive and medium state
825 */
826 static int sg_os_revalidate_disc(struct burn_drive *d)
827 {
828 
829 #ifdef Libburn_use_linux_ioctl_simul_changE
830 
831 /* <<< only for compiler tests */
832 #ifndef CDROM_SIMUL_CHANGE
833 /* # def ine CDROM_SIMUL_CHANGE 0x5332 */
834 #endif
835 
836 #ifdef CDROM_SIMUL_CHANGE
837 
838  int fd, ret;
839  long old_blocks, new_blocks;
840  char *msg = NULL;
841 
842  BURN_ALLOC_MEM(msg, char, 161);
843 
844  ret = ioctl(d->fd, BLKGETSIZE, &old_blocks);
845  if (ret == -1)
846  old_blocks = -1;
847 
848  /* Schedule a simulated medium change event.
849  Although the implemented ioctl cannot fail, the kernel might be too
850  old to know it and then throw errors like ENOTTY.
851  */
852  ret = ioctl(d->fd, CDROM_SIMUL_CHANGE, 0);
853  if (ret == -1) {
856  "ioctl(CDROM_SIMUL_CHANGE) failed", errno, 0);
857  ret = 0; goto ex;
858  }
861  "ioctl(CDROM_SIMUL_CHANGE) was performed", 0, 0);
862  /* Try to trigger actual device assessment by a open(2) call */
863  fd = open(d->devname, O_RDONLY | O_NDELAY);
864  if (fd == -1) {
867  "Failed to open device file after ioctl(CDROM_SIMUL_CHANGE)",
868  errno, 0);
869  ret = 0; goto ex;
870  }
871  close(fd);
872  ret = ioctl(d->fd, BLKGETSIZE, &new_blocks);
873  if (ret == -1) {
876  "BLKGETSIZE failed after ioctl(CDROM_SIMUL_CHANGE)",
877  errno, 0);
878  } else if (old_blocks != new_blocks) {
879  sprintf(msg,
880  "BLKGETSIZE indicates size change from %ld to %ld blocks",
881  old_blocks , new_blocks);
884  msg, 0, 0);
885  }
886 ex:
887  BURN_FREE_MEM(msg);
888  return ret;
889 
890 #else /* CDROM_SIMUL_CHANGE */
891 
892  return 0;
893 
894 #endif /* ! CDROM_SIMUL_CHANGE */
895 
896 #else /* Libburn_use_linux_ioctl_simul_changE */
897 
898  return 0;
899 
900 #endif /* ! Libburn_use_linux_ioctl_simul_changE */
901 
902 }
903 
904 
905 /* ts A60926 */
906 static int sg_close_drive(struct burn_drive *d)
907 {
908  int ret;
909 
910  if (!burn_drive_is_open(d))
911  return 0;
912  sg_release_siblings(d->sibling_fds, d->sibling_fnames,
913  &(d->sibling_count));
914  if(d->medium_state_changed > 0)
916  d->medium_state_changed = -1;
917  ret = sg_close_drive_fd(d->devname, d->global_index, &(d->fd), 0);
918  return ret;
919 }
920 
921 
922 /* ts A60926 */
923 static int sg_open_scsi_siblings(char *path, int driveno,
924  int sibling_fds[],
925  char sibling_fnames[][BURN_OS_SG_MAX_NAMELEN],
926  int *sibling_count,
927  int host_no, int channel_no, int id_no, int lun_no)
928 {
929  int tld, i, ret, fd, i_bus_no = -1;
930  int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
931  char *msg = NULL, fname[40];
932  struct stat stbuf;
933  dev_t last_rdev = 0, path_rdev;
934 
935  static char tldev[][20]= {"/dev/sr%d", "/dev/scd%d", "/dev/sg%d", ""};
936  /* ts A70609: removed "/dev/st%d" */
937 
938  if (strlen(path) > BURN_MSGS_MESSAGE_LEN - 160)
939  {ret = 0; goto ex;}
940 
942 
943  if(stat(path, &stbuf) == -1)
944  {ret = 0; goto ex;}
945  path_rdev = stbuf.st_rdev;
946 
948  if (linux_sg_device_family[0] == 0)
949  {ret = 1; goto ex;}
950 
951  if(host_no < 0 || id_no < 0 || channel_no < 0 || lun_no < 0)
952  {ret = 2; goto ex;}
953  if(*sibling_count > 0)
954  sg_release_siblings(sibling_fds, sibling_fnames,
955  sibling_count);
956 
957  for (tld = 0; tldev[tld][0] != 0; tld++) {
958  if (strcmp(tldev[tld], linux_sg_device_family)==0)
959  continue;
960  for (i = 0; i < 32; i++) {
961  sprintf(fname, tldev[tld], i);
962  if(stat(fname, &stbuf) == -1)
963  continue;
964  if (path_rdev == stbuf.st_rdev)
965  continue;
966  if (*sibling_count > 0 && last_rdev == stbuf.st_rdev)
967  continue;
968  ret = sg_obtain_scsi_adr(fname, &i_bus_no, &i_host_no,
969  &i_channel_no, &i_target_no, &i_lun_no);
970  if (ret <= 0)
971  continue;
972  if (i_host_no != host_no || i_channel_no != channel_no)
973  continue;
974  if (i_target_no != id_no || i_lun_no != lun_no)
975  continue;
976 
977  fd = sg_open_drive_fd(fname, 0);
978  if (fd < 0)
979  goto failed;
980 
981  if (*sibling_count>=BURN_OS_SG_MAX_SIBLINGS) {
982  sprintf(msg, "Too many scsi siblings of '%s'",
983  path);
985  driveno, 0x00020006,
987  LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
988  goto failed;
989  }
990  sprintf(msg, "Opened O_EXCL scsi sibling '%s' of '%s'",
991  fname, path);
993  0x00020004,
995  msg, 0, 0);
996  sibling_fds[*sibling_count] = fd;
997  strcpy(sibling_fnames[*sibling_count], fname);
998  (*sibling_count)++;
999  last_rdev= stbuf.st_rdev;
1000  }
1001  }
1002  ret = 1;
1003 ex:;
1004  BURN_FREE_MEM(msg);
1005  return ret;
1006 failed:;
1007  sg_release_siblings(sibling_fds, sibling_fnames, sibling_count);
1008  ret = 0;
1009  goto ex;
1010 }
1011 
1012 
1013 /* ts A80731 */
1014 static int is_ata_drive(char *fname, int fd_in)
1015 {
1016  int fd;
1017  struct hd_driveid tm;
1018 
1019  if (fd_in >= 0)
1020  fd = fd_in;
1021  else
1022  fd = sg_open_drive_fd(fname, 1);
1023  if (fd == -1) {
1025  fprintf(stderr,"open failed, errno=%d '%s'\n",
1026  errno, strerror(errno));
1027  return 0;
1028  }
1029 
1030  memset(&tm, 0, sizeof(tm));
1031  ioctl(fd, HDIO_GET_IDENTITY, &tm);
1032 
1033  /* not atapi */
1034  if (!(tm.config & 0x8000) || (tm.config & 0x4000)) {
1036  fprintf(stderr, "not marked as ATAPI\n");
1037  if (fd_in < 0)
1038  sg_close_drive_fd(fname, -1, &fd, 0);
1039  return 0;
1040  }
1041 
1042  /* if SG_IO fails on an atapi device, we should stop trying to
1043  use hd* devices */
1044  if (sgio_test(fd) == -1) {
1046  fprintf(stderr,
1047  "FATAL: sgio_test() failed: errno=%d '%s'\n",
1048  errno, strerror(errno));
1049  if (fd_in < 0)
1050  sg_close_drive_fd(fname, -1, &fd, 0);
1051  return 0;
1052  }
1053  if (fd_in >= 0)
1054  return 1;
1055  if (sg_close_drive_fd(fname, -1, &fd, 1) <= 0) {
1057  fprintf(stderr,
1058  "cannot close properly, errno=%d '%s'\n",
1059  errno, strerror(errno));
1060  return 0;
1061  }
1062  return 1;
1063 }
1064 
1065 
1066 static int is_scsi_drive(char *fname, int fd_in, int *bus_no, int *host_no,
1067  int *channel_no, int *target_no, int *lun_no)
1068 {
1069  int fd = -1, sid_ret = 0, ret, fail_sev_sorry = 0;
1070  struct sg_scsi_id sid;
1071  int *sibling_fds = NULL, sibling_count= 0;
1072  typedef char burn_sg_sibling_fname[BURN_OS_SG_MAX_NAMELEN];
1073  burn_sg_sibling_fname *sibling_fnames = NULL;
1074 
1075  BURN_ALLOC_MEM(sibling_fds, int, BURN_OS_SG_MAX_SIBLINGS);
1076  BURN_ALLOC_MEM(sibling_fnames, burn_sg_sibling_fname,
1078 
1079  if (fd_in >= 0)
1080  fd = fd_in;
1081  else
1082  fd = sg_open_drive_fd(fname, 1);
1083  if (fd == -1) {
1085  fprintf(stderr, "open failed, errno=%d '%s'\n",
1086  errno, strerror(errno));
1087  {ret = 0; goto ex;}
1088  }
1089  sid_ret = ioctl(fd, SG_GET_SCSI_ID, &sid);
1090  if (sid_ret == -1) {
1091  sid.scsi_id = -1; /* mark SCSI address as invalid */
1093  fprintf(stderr,
1094  "ioctl(SG_GET_SCSI_ID) failed, errno=%d '%s' , ",
1095  errno, strerror(errno));
1096 
1097  if (sgio_test(fd) == -1) {
1099  fprintf(stderr,
1100  "FATAL: sgio_test() failed: errno=%d '%s'",
1101  errno, strerror(errno));
1102 
1103  {ret = 0; goto ex;}
1104  }
1105 
1106 #ifdef CDROM_DRIVE_STATUS
1107  /* http://developer.osdl.org/dev/robustmutexes/
1108  src/fusyn.hg/Documentation/ioctl/cdrom.txt */
1109  sid_ret = ioctl(fd, CDROM_DRIVE_STATUS, 0);
1111  fprintf(stderr,
1112  "ioctl(CDROM_DRIVE_STATUS) = %d , ",
1113  sid_ret);
1114  if (sid_ret != -1 && sid_ret != CDS_NO_INFO)
1115  sid.scsi_type = TYPE_ROM;
1116  else
1117  sid_ret = -1;
1118 #endif /* CDROM_DRIVE_STATUS */
1119 
1120  }
1121 
1122  if (sid_ret == -1) {
1123  /* ts B11109 : Try device type from INQUIRY byte 0 */
1124  if (sgio_inquiry_cd_drive(fd, fname) == 1) {
1125  sid_ret = 0;
1126  sid.scsi_type = TYPE_ROM;
1127  }
1128  }
1129 
1130 
1131 #ifdef SCSI_IOCTL_GET_BUS_NUMBER
1132  /* Hearsay A61005 */
1133  if (ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, bus_no) == -1)
1134  *bus_no = -1;
1135 #endif
1136 
1137  fail_sev_sorry = (sid.scsi_type == TYPE_ROM);
1138  if ( (sid_ret == -1 || sid.scsi_type != TYPE_ROM)
1141  fprintf(stderr, "sid.scsi_type = %d (!= TYPE_ROM)\n",
1142  sid.scsi_type);
1143  {ret = 0; goto ex;}
1144  }
1145 
1146  /* ts A61211 : employ a more general ioctl */
1147  /* ts B11001 : re-use fd */
1148  /* ts B80902 : call unconditionally because host_no differs
1149  between SG_GET_SCSI_ID and SCSI_IOCTL_GET_IDLUN
1150  */
1151  ret = sg_obtain_scsi_adr_fd(fname, fd, bus_no, host_no,
1152  channel_no, target_no, lun_no);
1153  if (ret <= 0) {
1155  fprintf(stderr,
1156  "sg_obtain_scsi_adr_fd() failed\n");
1157  {ret = 0; goto ex;}
1158  }
1159 
1160  /* ts A60927 : trying to do locking with growisofs */
1161  if(burn_sg_open_o_excl>1) {
1162  ret = sg_open_scsi_siblings(
1163  fname, -1, sibling_fds, sibling_fnames,
1164  &sibling_count,
1165  sid.host_no, sid.channel,
1166  sid.scsi_id, sid.lun);
1167  if (ret<=0) {
1169  fprintf(stderr, "cannot lock siblings\n");
1170  sg_handle_busy_device(fname, 0);
1171  {ret = 0; goto ex;}
1172  }
1173  /* the final occupation will be done in sg_grab() */
1174  sg_release_siblings(sibling_fds, sibling_fnames,
1175  &sibling_count);
1176  }
1177  ret = 1;
1178 ex:;
1179  if (fd_in < 0 && fd >= 0) {
1180  if (sg_close_drive_fd(fname, -1, &fd, fail_sev_sorry) <= 0) {
1182  fprintf(stderr,
1183  "cannot close properly, errno=%d '%s'\n",
1184  errno, strerror(errno));
1185  if (ret > 0)
1186  ret = 0;
1187  }
1188  }
1189  BURN_FREE_MEM(sibling_fds);
1190  BURN_FREE_MEM(sibling_fnames);
1191  return ret;
1192 }
1193 
1194 
1195 /* @param flag bit0= do not complain about failure to open /dev/sr /dev/scd */
1196 static int sg_open_for_enumeration(char *fname, int flag)
1197 {
1198  int fd;
1199 
1200  fd = sg_open_drive_fd(fname, 1 + (flag & 1));
1201  if (fd < 0) {
1203  fprintf(stderr, "open failed, errno=%d '%s'\n",
1204  errno, strerror(errno));
1205  return -1;
1206  }
1207  return fd;
1208 }
1209 
1210 
1211 /** Speciality of GNU/Linux: detect non-SCSI ATAPI (EIDE) which will from
1212  then on used used via generic SCSI as is done with (emulated) SCSI drives */
1213 static void ata_enumerate(void)
1214 {
1215  int ret, i, fd = -1;
1216  char fname[10];
1217 
1219  fprintf(stderr, "libburn_debug: linux_ata_device_family = %s\n",
1221 
1222  if (linux_ata_device_family[0] == 0)
1223  return;
1224 
1225  for (i = 0; i < 26; i++) {
1226  sprintf(fname, linux_ata_device_family, 'a' + i);
1228  fprintf(stderr, "libburn_debug: %s : ", fname);
1229 
1230  /* ts A51221 */
1231  if (burn_drive_is_banned(fname)) {
1233  fprintf(stderr, "not in whitelist\n");
1234  continue;
1235  }
1236  fd = sg_open_for_enumeration(fname, 0);
1237  if (fd < 0)
1238  continue;
1239  ret = is_ata_drive(fname, fd);
1240  if (ret < 0)
1241  break;
1242  if (ret == 0)
1243  continue;
1245  fprintf(stderr, "accepting as drive without SCSI address\n");
1246  enumerate_common(fname, fd, -1, -1, -1, -1, -1);
1247  }
1248 }
1249 
1250 
1251 /** Detects (probably emulated) SCSI drives */
1252 static void sg_enumerate(void)
1253 {
1254  int i, ret, fd = -1;
1255  int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1;
1256  char fname[17];
1257 
1259 
1261  fprintf(stderr, "libburn_debug: linux_sg_device_family = %s\n",
1263 
1264  if (linux_sg_device_family[0] == 0)
1265  return;
1266 
1267  for (i = 0; i < 32; i++) {
1268  sprintf(fname, linux_sg_device_family, i);
1269 
1270  /* ts A80702 */
1271  sg_exchange_scd_for_sr(fname, 0);
1272 
1274  fprintf(stderr, "libburn_debug: %s : ", fname);
1275 
1276  /* ts A51221 */
1277  if (burn_drive_is_banned(fname)) {
1279  fprintf(stderr, "not in whitelist\n");
1280  continue;
1281  }
1282  fd = sg_open_for_enumeration(fname, 0);
1283  if (fd < 0)
1284  continue;
1285 
1286  ret = is_scsi_drive(fname, fd, &bus_no, &host_no, &channel_no,
1287  &target_no, &lun_no);
1288  if (ret < 0)
1289  break;
1290  if (ret == 0)
1291  continue;
1293  fprintf(stderr, "accepting as SCSI %d,%d,%d,%d bus=%d\n",
1294  host_no, channel_no, target_no, lun_no, bus_no);
1295  enumerate_common(fname, fd, bus_no, host_no, channel_no,
1296  target_no, lun_no);
1297 
1298  }
1299 }
1300 
1301 
1302 
1303 /* ts A80805 : eventually produce the other official name of a device file */
1304 static int fname_other_name(char *fname, char other_name[80], int flag)
1305 {
1306  if(strncmp(fname, "/dev/sr", 7) == 0 &&
1307  (fname[7] >= '0' && fname[7] <= '9') &&
1308  (fname[8] == 0 ||
1309  (fname[8] >= '0' && fname[8] <= '9' && fname[9] == 0))) {
1310  sprintf(other_name, "/dev/scd%s", fname + 7);
1311  return 1;
1312  }
1313  if(strncmp(fname, "/dev/scd", 8) == 0 &&
1314  (fname[8] >= '0' && fname[8] <= '9') &&
1315  (fname[9] == 0 ||
1316  (fname[9] >= '0' && fname[9] <= '9' && fname[10] == 0))) {
1317  sprintf(other_name, "/dev/sr%s", fname + 8);
1318  return 1;
1319  }
1320  return 0;
1321 }
1322 
1323 
1324 /* ts A80805 */
1325 static int fname_drive_is_listed(char *fname, int flag)
1326 {
1327  char other_fname[80];
1328 
1329  if (burn_drive_is_listed(fname, NULL, 0))
1330  return 1;
1331  if (fname_other_name(fname, other_fname, 0) > 0)
1332  if (burn_drive_is_listed(other_fname, NULL, 0))
1333  return 2;
1334  return 0;
1335 }
1336 
1337 
1338 /* ts A80731 : Directly open the given address.
1339  @param flag bit0= do not complain about missing file
1340  bit1= do not check whether drive is already listed
1341  bit2= do not complain about failure to open /dev/sr /dev/scd
1342 */
1343 static int fname_enumerate(char *fname, int flag)
1344 {
1345  int is_ata= 0, is_scsi= 0, ret, fd = -1;
1346  int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1;
1347  char *msg = NULL;
1348  struct stat stbuf;
1349 
1350  BURN_ALLOC_MEM(msg, char, BURN_DRIVE_ADR_LEN + 80);
1351 
1352  if (!(flag & 2))
1353  if (fname_drive_is_listed(fname, 0))
1354  {ret = 2; goto ex;}
1355  if (stat(fname, &stbuf) == -1) {
1356  sprintf(msg, "File object '%s' not found", fname);
1357  if (!(flag & 1))
1358  libdax_msgs_submit(libdax_messenger, -1, 0x0002000b,
1360  msg, 0, 0);
1361  {ret = -1; goto ex;}
1362  }
1363 
1364  fd = sg_open_for_enumeration(fname, !!(flag & 4));
1365  if (fd < 0)
1366  {ret = 0; goto ex;}
1367  is_ata = is_ata_drive(fname, fd);
1368  if (is_ata < 0)
1369  {ret = -1; goto ex;}
1370  if (!is_ata)
1371  is_scsi = is_scsi_drive(fname, fd, &bus_no, &host_no,
1372  &channel_no, &target_no, &lun_no);
1373  if (is_scsi < 0)
1374  {ret = -1; goto ex;}
1375  if (is_ata == 0 && is_scsi == 0)
1376  {ret = 0; goto ex;}
1377 
1379  fprintf(stderr,
1380  "(single) accepting as SCSI %d,%d,%d,%d bus=%d\n",
1381  host_no, channel_no, target_no, lun_no, bus_no);
1382 
1383  enumerate_common(fname, fd, bus_no, host_no, channel_no,
1384  target_no, lun_no);
1385  ret = 1;
1386 ex:;
1387  BURN_FREE_MEM(msg);
1388  return ret;
1389 }
1390 
1391 
1392 /* ts A80731 : Directly open the given address from a single-item whitlist */
1393 static int single_enumerate(int flag)
1394 {
1395  int ret, wl_count;
1396  char *fname, *msg = NULL;
1397 
1398  wl_count= burn_drive_whitelist_count();
1399  if (wl_count != 1)
1400  {ret = 0; goto ex;}
1401  fname= burn_drive_whitelist_item(0, 0);
1402  if (fname == NULL)
1403  {ret = 0; goto ex;}
1404  ret = fname_enumerate(fname, 2);
1405  if (ret <= 0) {
1406  BURN_ALLOC_MEM(msg, char, BURN_DRIVE_ADR_LEN + 80);
1407  sprintf(msg, "Cannot access '%s' as SG_IO CDROM drive", fname);
1408  libdax_msgs_submit(libdax_messenger, -1, 0x0002000a,
1410  msg, 0, 0);
1411  ret = -1;
1412  }
1413 ex:;
1414  BURN_FREE_MEM(msg);
1415  return ret;
1416 }
1417 
1418 
1419 /* ts A80801 : looking up drives listed in /proc/sys/dev/cdrom/info line like:
1420  drive name: sr1 hdc hda sr0
1421  @parm flag bit0= release list memory and exit
1422 */
1423 static int proc_sys_dev_cdrom_info(char ***list, int *count, int flag)
1424 {
1425  FILE *fp;
1426  char *line = NULL, *fname = NULL, *cpt, *retpt, *list_data;
1427  int maxl= 0, pass, i, line_size = 1024, ret;
1428 
1429  BURN_ALLOC_MEM(line, char, line_size);
1430  BURN_ALLOC_MEM(fname, char, line_size + 5);
1431 
1432  if (*list != NULL) {
1433  if ((*list)[0] != NULL)
1434  free((*list)[0]);
1435  free(*list);
1436  *list = NULL;
1437  *count = 0;
1438  }
1439  if (flag & 1)
1440  {ret = 1; goto ex;}
1441 
1442  *count = 0;
1444  if (sg_kernel_age < 2) /* addresses are not suitable for kernel 2.4 */
1445  {ret = 1; goto ex;}
1446  fp = fopen("/proc/sys/dev/cdrom/info", "r");
1447  if (fp == NULL)
1448  {ret = 0; goto ex;}
1449  while (1) {
1450  retpt = fgets(line, line_size, fp);
1451  if (retpt == NULL)
1452  break;
1453  if(strncmp(line, "drive name:", 11) == 0)
1454  break;
1455  }
1456  fclose(fp);
1457  if (retpt == NULL)
1458  {ret = 0; goto ex;}
1459  strcpy(fname, "/dev/");
1460  for(pass = 0; pass < 2; pass++) {
1461  *count = 0;
1462  cpt = line + 11;
1463  while (*cpt != 0) {
1464  for(; *cpt == ' ' || *cpt == '\t'; cpt++);
1465  if (*cpt == 0 || *cpt == '\n')
1466  break;
1467  sscanf(cpt, "%s", fname + 5);
1468  if ((int) strlen(fname) > maxl)
1469  maxl = strlen(fname);
1470  if (pass == 1)
1471  strcpy((*list)[*count], fname);
1472  (*count)++;
1473  for(cpt++; *cpt != ' ' && *cpt != '\t'
1474  && *cpt != 0 && *cpt != '\n'; cpt++);
1475  }
1476  if (pass == 0) {
1477  list_data = calloc(*count + 1, maxl+1);
1478  *list = calloc(*count + 1, sizeof(char *));
1479  if(list_data == NULL || *list == NULL) {
1481  0x00000003,
1483  "Out of virtual memory", 0, 0);
1484  if (list_data != NULL)
1485  free(list_data);
1486  if (*list != NULL)
1487  free((char *) *list);
1488  {ret = -1; goto ex;}
1489  }
1490  for (i = 0; i <= *count; i++)
1491  (*list)[i] = list_data + i * (maxl + 1);
1492  }
1493  }
1494  ret = 1;
1495 ex:;
1496  BURN_FREE_MEM(line);
1497  BURN_FREE_MEM(fname);
1498  return ret;
1499 }
1500 
1501 
1502 static int add_proc_info_drives(int flag)
1503 {
1504  int ret, list_count, count = 0, i;
1505  char **list= NULL;
1506 
1507  if (burn_sg_use_family != 0)
1508  return(1); /* Looking only for sr , scd , sg */
1509 
1510  ret = proc_sys_dev_cdrom_info(&list, &list_count, 0);
1511  if (ret <= 0)
1512  return ret;
1513  for (i = 0; i < list_count; i++) {
1514  if (burn_drive_is_banned(list[i]))
1515  continue;
1516  ret = fname_enumerate(list[i], 1 | 4);
1517  if (ret == 1)
1518  count++;
1519  }
1520  proc_sys_dev_cdrom_info(&list, &list_count, 1); /* free memory */
1521  return 1 + count;
1522 }
1523 
1524 
1525 /* ts A61115 */
1526 /* ----------------------------------------------------------------------- */
1527 /* PORTING: Private functions which contain publicly needed functionality. */
1528 /* Their portable part must be performed. So it is probably best */
1529 /* to replace the non-portable part and to call these functions */
1530 /* in your port, too. */
1531 /* ----------------------------------------------------------------------- */
1532 
1533 
1534 /** Wraps a detected drive into libburn structures and hands it over to
1535  libburn drive list.
1536 */
1537 /* ts A60923 - A61005 : introduced new SCSI parameters */
1538 /* ts A61021 : moved non os-specific code to spc,sbc,mmc,drive */
1539 static void enumerate_common(char *fname, int fd_in, int bus_no, int host_no,
1540  int channel_no, int target_no, int lun_no)
1541 {
1542  int ret, i;
1543  struct burn_drive out;
1544 
1545  /* General libburn drive setup */
1546  burn_setup_drive(&out, fname);
1547 
1548  /* This transport adapter uses SCSI-family commands and models
1549  (seems the adapter would know better than its boss, if ever) */
1550  ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
1551  target_no, lun_no, 0);
1552  if (ret<=0)
1553  return;
1554 
1555  /* PORTING: ------------------- non portable part --------------- */
1556 
1557  /* Operating system adapter is GNU/Linux Generic SCSI (sg) */
1558  /* Adapter specific handles and data */
1559  out.fd = -1337;
1560  out.sibling_count = 0;
1561  for(i= 0; i<BURN_OS_SG_MAX_SIBLINGS; i++)
1562  out.sibling_fds[i] = -1337;
1563 
1564  /* PORTING: ---------------- end of non portable part ------------ */
1565 
1566  /* Adapter specific functions with standardized names */
1567  out.grab = sg_grab;
1568  out.release = sg_release;
1571  if (fd_in >= 0)
1572  out.fd = fd_in;
1573 
1574  /* Finally register drive and inquire drive information.
1575  out is an invalid copy afterwards. Do not use it for anything.
1576  */
1577  burn_drive_finish_enum(&out);
1578 }
1579 
1580 
1581 /* ts A61115 */
1582 /* ------------------------------------------------------------------------ */
1583 /* PORTING: Public functions. These MUST be ported. */
1584 /* ------------------------------------------------------------------------ */
1585 
1586 
1587 /** Returns the id string of the SCSI transport adapter and eventually
1588  needed operating system facilities.
1589  This call is usable even if sg_initialize() was not called yet. In that
1590  case a preliminary constant message might be issued if detailed info is
1591  not available yet.
1592  @param msg returns id string
1593  @param flag unused yet, submit 0
1594  @return 1 = success, <=0 = failure
1595 */
1596 int sg_id_string(char msg[1024], int flag)
1597 {
1598  strcpy(msg, "internal GNU/Linux SG_IO adapter sg-linux");
1599  return 1;
1600 }
1601 
1602 
1603 /** Performs global initialization of the SCSI transport adapter and eventually
1604  needed operating system facilities. Checks for compatibility supporting
1605  software components.
1606  @param msg returns ids and/or error messages of eventual helpers
1607  @param flag unused yet, submit 0
1608  @return 1 = success, <=0 = failure
1609 */
1610 int sg_initialize(char msg[1024], int flag)
1611 {
1612  return sg_id_string(msg, 0);
1613 }
1614 
1615 
1616 /** Performs global finalization of the SCSI transport adapter and eventually
1617  needed operating system facilities. Releases globally acquired resources.
1618  @param flag unused yet, submit 0
1619  @return 1 = success, <=0 = failure
1620 */
1621 int sg_shutdown(int flag)
1622 {
1623  return 1;
1624 }
1625 
1626 
1627 /** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
1628  struct burn_drive which are defined in os-*.h.
1629  The eventual initialization of those components was made underneath
1630  scsi_enumerate_drives().
1631  This will be called when a burn_drive gets disposed.
1632  @param d the drive to be finalized
1633  @param flag unused yet, submit 0
1634  @return 1 = success, <=0 = failure
1635 */
1636 int sg_dispose_drive(struct burn_drive *d, int flag)
1637 {
1638  return 1;
1639 }
1640 
1641 
1642 /** PORTING:
1643  In this GNU/Linux implementation, this function mirrors the enumeration
1644  done in sg_enumerate and ata_enumerate(). It would be better to base those
1645  functions on this sg_give_next_adr() but the situation is not inviting.
1646 */
1647 /* ts A60922 ticket 33 : called from drive.c */
1648 /** Returns the next index number and the next enumerated drive address.
1649  The enumeration has to cover all available and accessible drives. It is
1650  allowed to return addresses of drives which are not available but under
1651  some (even exotic) circumstances could be available. It is on the other
1652  hand allowed, only to hand out addresses which can really be used right
1653  in the moment of this call. (This implementation chooses the former.)
1654  @param idx An opaque handle. Make no own theories about it.
1655  @param adr Takes the reply
1656  @param adr_size Gives maximum size of reply including final 0
1657  @param initialize 1 = start new,
1658  0 = continue, use no other values for now
1659  -1 = finish
1660  @return 1 = reply is a valid address , 0 = no further address available
1661  -1 = severe error (e.g. adr_size too small)
1662 */
1664  char adr[], int adr_size, int initialize)
1665 {
1666  /* os-linux.h : typedef int burn_drive_enumerator_t; */
1667  static int sg_limit = 32, ata_limit = 26;
1668  int baseno = 0, i;
1669  char other_name[80];
1670 
1671  if (initialize == -1) {
1672  proc_sys_dev_cdrom_info(&(idx->info_list), &(idx->info_count),
1673  1);
1674  return 0;
1675  }
1676 
1678  if (linux_sg_device_family[0] == 0)
1679  sg_limit = 0;
1680  if (linux_ata_device_family[0] == 0)
1681  ata_limit = 0;
1682 
1683  if (initialize == 1) {
1684  idx->pos = -1;
1685  idx->info_count= 0;
1686  idx->info_list= NULL;
1687  proc_sys_dev_cdrom_info(&(idx->info_list), &(idx->info_count),
1688  0);
1689  }
1690  (idx->pos)++;
1691  if (idx->pos >= sg_limit)
1692  goto next_ata;
1693  if (adr_size < 11)
1694  return -1;
1695  sprintf(adr, linux_sg_device_family, idx->pos);
1696 
1697  sg_exchange_scd_for_sr(adr, 0);
1698  goto return_1_pre_proc;
1699 
1700 next_ata:;
1701  baseno += sg_limit;
1702  if (idx->pos - baseno >= ata_limit)
1703  goto next_proc_info;
1704  if (adr_size < 9)
1705  return -1;
1706  sprintf(adr, linux_ata_device_family, 'a' + (idx->pos - baseno));
1707  goto return_1_pre_proc;
1708 
1709 next_proc_info:;
1710  baseno += ata_limit;
1711  if (burn_sg_use_family != 0) /* Only with default enumeration */
1712  return 0;
1713  for (i = 0; i < idx->info_count; i++) {
1714  if ((idx->info_list)[i][0] == 0)
1715  continue;
1716  if (baseno == idx->pos) {
1717  if (adr_size < (int) strlen((idx->info_list)[i]) + 1)
1718  return -1;
1719  strcpy(adr, (idx->info_list)[i]);
1720  return 1;
1721  }
1722  baseno++;
1723  }
1724  return 0;
1725 
1726 return_1_pre_proc:;
1727  for (i = 0; i < idx->info_count; i++) {
1728  if (strcmp((idx->info_list)[i], adr) == 0)
1729  (idx->info_list)[i][0] = 0;
1730  if (fname_other_name(adr, other_name, 0) > 0)
1731  if (strcmp((idx->info_list)[i], other_name) == 0)
1732  (idx->info_list)[i][0] = 0;
1733  }
1734  return 1;
1735 }
1736 
1737 
1738 /** Brings all available, not-whitelist-banned, and accessible drives into
1739  libburn's list of drives.
1740 */
1741 /** PORTING:
1742  If not stricken with an incompletely unified situation like in GNU/Linux
1743  one would rather implement this by a loop calling sg_give_next_adr().
1744  If needed with your sg_give_next_adr() results, do a test for existence
1745  and accessability. If burn activities are prone to external interference
1746  on your system it is also necessary to obtain exclusive access locks on
1747  the drives.
1748  Hand over each accepted drive to enumerate_common() or its replacement
1749  within your port.
1750 
1751  See FreeBSD port sketch sg-freebsd-port.c for such an implementation.
1752 */
1753 /* ts A61115: replacing call to sg-implementation internals from drive.c */
1755 {
1756  int ret;
1757 
1758  /* Direct examination of eventually single whitelisted name */
1759  ret = single_enumerate(0);
1760  if (ret < 0)
1761  return -1;
1762  if (ret > 0)
1763  return 1;
1764 
1765  sg_enumerate();
1766  ata_enumerate();
1768  return 1;
1769 }
1770 
1771 
1772 /** Tells whether libburn has the given drive in use or exclusively reserved.
1773  If it is "open" then libburn will eventually call sg_release() on it when
1774  it is time to give up usage and reservation.
1775 */
1776 /** Published as burn_drive.drive_is_open() */
1778 {
1779  /* a bit more detailed case distinction than needed */
1780  if (d->fd == -1337)
1781  return 0;
1782  if (d->fd < 0)
1783  return 0;
1784  return 1;
1785 }
1786 
1787 
1788 /** Opens the drive for SCSI commands and - if burn activities are prone
1789  to external interference on your system - obtains an exclusive access lock
1790  on the drive. (Note: this is not physical tray locking.)
1791  A drive that has been opened with sg_grab() will eventually be handed
1792  over to sg_release() for closing and unreserving.
1793 */
1794 int sg_grab(struct burn_drive *d)
1795 {
1796  int fd, os_errno= 0, ret;
1797  int max_tries = 3, tries = 0;
1798 
1799  /* ts A60813 */
1800  int open_mode = O_RDWR;
1801 
1802 /* ts A60821
1803  <<< debug: for tracing calls which might use open drive fds */
1804  if (mmc_function_spy(d, "sg_grab") <= 0)
1805  return 0;
1806 
1807 
1808  /* ts A60813 - A60927
1809  O_EXCL with devices is a non-POSIX feature
1810  of Linux kernels. Possibly introduced 2002.
1811  Mentioned in "The Linux SCSI Generic (sg) HOWTO".
1812  */
1814  open_mode |= O_EXCL;
1815 
1816  /* ts A60813
1817  O_NONBLOCK was hardcoded here. So it should stay default mode.
1818  ts A70411
1819  Switched to O_NDELAY for LKML statement 2007/4/11/141
1820  */
1822  open_mode |= O_NDELAY;
1823 
1824  /* ts A60813 - A60822
1825  After enumeration the drive fd is probably still open.
1826  -1337 is the initial value of burn_drive.fd and the value after
1827  release of drive. Unclear why not the official error return
1828  value -1 of open(2) war used. */
1829  if(! burn_drive_is_open(d)) {
1830  char msg[120];
1831 
1832 /* >>> SINGLE_OPEN : This case should be impossible now, since enumeration
1833  transfers the fd from scanning to drive.
1834  So if close-wait-open is desired, then it has to
1835  be done unconditionally.
1836 */
1837 
1838 #ifndef Libburn_udev_wait_useC
1839 #define Libburn_udev_wait_useC 100000
1840 #endif
1841 
1842 #ifndef Libburn_udev_extra_open_cyclE
1843 
1844  if (Libburn_udev_wait_useC > 0) {
1845  /* ts B10921 : workaround for udev which might get
1846  a kernel event from open() and might
1847  remove links if it cannot inspect the
1848  drive. This waiting period shall allow udev
1849  to act after it was woken up by the drive scan
1850  activities.
1851  */
1852  sprintf(msg,
1853  "To avoid collision with udev: Waiting %lu usec before grabbing",
1854  (unsigned long) Libburn_udev_wait_useC);
1855  libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
1857  msg, 0, 0);
1858  usleep(Libburn_udev_wait_useC);
1859  }
1860 
1861 #endif /* Libburn_udev_extra_open_cyclE */
1862 
1863 
1864 try_open:;
1865  /* ts A60821
1866  <<< debug: for tracing calls which might use open drive fds */
1867  mmc_function_spy(NULL, "sg_grab ----------- opening");
1868 
1869  /* ts A70409 : DDLP-B */
1870  /* >>> obtain single lock on d->devname */
1871 
1872  /* ts A60926 */
1873  if(burn_sg_open_o_excl>1) {
1874  fd = -1;
1875  ret = sg_open_scsi_siblings(d->devname,
1876  d->global_index,d->sibling_fds,
1877  d->sibling_fnames,&(d->sibling_count),
1878  d->host, d->channel, d->id, d->lun);
1879  if(ret <= 0)
1880  goto drive_is_in_use;
1881  }
1882  fd = open(d->devname, open_mode);
1883  os_errno = errno;
1884 
1885 #ifdef Libburn_udev_extra_open_cyclE
1886 
1887  /* ts B10920 : workaround for udev which might get
1888  a kernel event from open() and might
1889  remove links if it cannot inspect the
1890  drive.
1891  ts B10921 : this is more obtrusive than above waiting
1892  before open(). The drive scan already has
1893  opened and closed the drive several times.
1894  So it seems to be merely about giving an
1895  opportunity to udev, before long term grabbing
1896  happens.
1897  */
1898  if (fd >= 0 && Libburn_udev_wait_useC > 0) {
1899  close(fd);
1900  sprintf(msg,
1901  "To avoid collision with udev: Waiting %lu usec before re-opening",
1902  (unsigned long) Libburn_udev_wait_useC);
1903  libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
1905  msg, 0, 0);
1906  usleep(Libburn_udev_wait_useC);
1907  fd = open(d->devname, open_mode);
1908  os_errno = errno;
1909  }
1910 #endif /* Libburn_udev_extra_open_cyclE */
1911 
1912  if (fd >= 0) {
1913  sg_fcntl_lock(&fd, d->devname, F_WRLCK, 1);
1914  if (fd < 0)
1915  goto drive_is_in_use;
1916  }
1917  } else
1918  fd= d->fd;
1919 
1920  if (fd >= 0) {
1921  d->fd = fd;
1922  fcntl(fd, F_SETOWN, getpid());
1923  d->released = 0;
1924  return 1;
1925  } else if (errno == EBUSY)
1926  goto drive_is_in_use;
1929  "Could not grab drive", os_errno, 0);
1930  return 0;
1931 
1932 drive_is_in_use:;
1933  tries++;
1934  if (tries < max_tries) {
1935  libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
1937  "Drive is in use. Waiting 2 seconds before re-try",
1938  0, 0);
1939  usleep(2000000);
1940  goto try_open;
1941  }
1943  0x00020003,
1945  "Could not grab drive - already in use", 0, 0);
1946  sg_close_drive(d);
1947  d->fd = -1337;
1948  return 0;
1949 }
1950 
1951 
1952 /** PORTING: Is mainly about the call to sg_close_drive() and whether it
1953  implements the demanded functionality.
1954 */
1955 /** Gives up the drive for SCSI commands and releases eventual access locks.
1956  (Note: this is not physical tray locking.)
1957 */
1958 int sg_release(struct burn_drive *d)
1959 {
1960  /* ts A60821
1961  <<< debug: for tracing calls which might use open drive fds */
1962  if (mmc_function_spy(d, "sg_release") <= 0)
1963  return 0;
1964 
1965  if (d->fd < 1)
1966  return 0;
1967 
1968  /* ts A60821
1969  <<< debug: for tracing calls which might use open drive fds */
1970  mmc_function_spy(NULL, "sg_release ----------- closing");
1971 
1972  sg_close_drive(d);
1973  return 0;
1974 }
1975 
1976 /* @return -1= transport failed, give up drive
1977  0= transport failed, do not retry
1978  1= transport succeeded
1979  2- transport failed, please retry
1980 */
1981 static int evaluate_transport_success(struct burn_drive *d, struct command *c,
1982  FILE *fp,
1983  unsigned short host_status,
1984  unsigned short driver_status)
1985 {
1986  int ret, do_retry= 0, give_up_drive= 0, sev;
1987  char *msg = NULL, *host_problem, *driver_problem, *driver_sugg;
1988 
1989  BURN_ALLOC_MEM(msg, char, 161);
1990 
1991  if ((host_status == Libburn_sg_host_oK &&
1992  (driver_status & 0xf7) == Libburn_sg_driver_oK) || c->error)
1993  {ret = 1; goto ex;} /* No transport problems */
1994 
1995  /* See http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/x291.html */
1996 
1997  switch(host_status) {
1998  case 0x00:
1999  host_problem =
2000  "SG_ERR_DID_OK (No error)";
2001  break; case 0x01:
2002  host_problem =
2003  "SG_ERR_DID_NO_CONNECT (Could not connect before timeout period)";
2004  give_up_drive= 1;
2005  break; case 0x02:
2006  host_problem =
2007  "SG_ERR_DID_BUS_BUSY (Bus stayed busy through time out period)";
2008  break; case 0x03:
2009  host_problem =
2010  "SG_ERR_DID_TIME_OUT (Timed out for miscellaneous reasons)";
2011  break; case 0x04:
2012  host_problem =
2013  "SG_ERR_DID_BAD_TARGET (Bad target, device not responding ?)";
2014  give_up_drive= 1;
2015  break; case 0x05:
2016  host_problem =
2017  "SG_ERR_DID_ABORT (Told to abort)";
2018  break; case 0x06:
2019  host_problem =
2020  "SG_ERR_DID_PARITY (Parity error)";
2021  break; case 0x07:
2022  host_problem =
2023  "SG_ERR_DID_ERROR (Internal error detected in the host adapter)";
2024  give_up_drive= 1;
2025  break; case 0x08:
2026  host_problem =
2027  "SG_ERR_DID_RESET (The SCSI bus or the device have been reset)";
2028  give_up_drive= 1;
2029  break; case 0x09:
2030  host_problem =
2031  "SG_ERR_DID_BAD_INTR (Got an unexpected interrupt)";
2032  break; case 0x0a:
2033  host_problem =
2034  "SG_ERR_DID_PASSTHROUGH (Force command past mid-layer)";
2035  break; case 0x0b:
2036  host_problem =
2037  "SG_ERR_DID_SOFT_ERROR (The low level driver wants a retry)";
2038  do_retry = 1;
2039  break; default:
2040  host_problem =
2041  "? (unknown host_status code)";
2042  }
2043  if (host_status != Libburn_sg_host_oK) {
2044  sprintf(msg, "SCSI command %2.2Xh yielded host problem: ",
2045  (unsigned int) c->opcode[0]);
2046  sprintf(msg+strlen(msg), "0x%x %s",
2047  (unsigned int) host_status, host_problem);
2049  if (do_retry && !give_up_drive)
2050  sev = LIBDAX_MSGS_SEV_NOTE;
2052  0x000201a7, sev, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
2053  strcpy(msg, "Command: ");
2054  if (spc_human_readable_cmd(c, msg + strlen(msg),
2055  160 - strlen(msg), 0) > 0)
2057  0x000201a7, sev, LIBDAX_MSGS_PRIO_HIGH,
2058  msg, 0, 0);
2059  sprintf(msg, "--- SG_IO: host_status= 0x%x %s",
2060  (unsigned int) host_status, host_problem);
2061  scsi_log_message(d, fp, msg, 0);
2062  }
2063 
2064  switch (driver_status & 0x07) {
2065  case 0:
2066  driver_problem = "SG_ERR_DRIVER_OK";
2067  break; case 1:
2068  driver_problem = "SG_ERR_DRIVER_BUSY";
2069  break; case 2:
2070  driver_problem = "SG_ERR_DRIVER_SOFT";
2071  break; case 3:
2072  driver_problem = "SG_ERR_DRIVER_MEDIA";
2073  break; case 4:
2074  driver_problem = "SG_ERR_DRIVER_ERROR";
2075  break; case 5:
2076  driver_problem = "SG_ERR_DRIVER_INVALID";
2077  break; case 6:
2078  driver_problem = "SG_ERR_DRIVER_TIMEOUT";
2079  break; case 7:
2080  driver_problem = "SG_ERR_DRIVER_HARD";
2081  break; default:
2082  driver_problem = "(unknown driver_status code)";
2083  }
2084  switch (driver_status & 0xf0) {
2085  case 0:
2086  driver_sugg = "(no suggestion)";
2087  break; case 0x10:
2088  driver_sugg = "SG_ERR_SUGGEST_RETRY";
2089  do_retry = 1;
2090  break; case 0x20:
2091  driver_sugg = "SG_ERR_SUGGEST_ABORT";
2092  give_up_drive= 1;
2093  break; case 0x30:
2094  driver_sugg = "SG_ERR_SUGGEST_REMAP";
2095  give_up_drive= 1;
2096  break; case 0x40:
2097  driver_sugg = "SG_ERR_SUGGEST_DIE";
2098  give_up_drive= 1;
2099  break; case 0x80:
2100  driver_sugg = "SG_ERR_SUGGEST_SENSE";
2101  break; default:
2102  driver_sugg = "(unknown driver_status suggestion)";
2103  }
2104  if ((driver_status & 0xf7) != Libburn_sg_driver_oK) {
2105  sprintf(msg, "SCSI command %2.2Xh yielded driver problem: ",
2106  (unsigned int) c->opcode[0]);
2107  sprintf(msg+strlen(msg), "driver_status= 0x%x %s / %s",
2108  (unsigned int) driver_status,
2109  driver_problem, driver_sugg);
2111  if (do_retry && !give_up_drive)
2112  sev = LIBDAX_MSGS_SEV_NOTE;
2114  0x000201a8, sev, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
2115  strcpy(msg, "Command: ");
2116  if (spc_human_readable_cmd(c, msg + strlen(msg),
2117  160 - strlen(msg), 0) > 0)
2119  0x000201a8, sev, LIBDAX_MSGS_PRIO_HIGH,
2120  msg, 0, 0);
2121  sprintf(msg, "--- SG_IO: driver_status= 0x%x %s / %s",
2122  (unsigned int) driver_status,
2123  driver_problem, driver_sugg);
2124  scsi_log_message(d, fp, msg, 0);
2125  }
2126 
2127  if (! do_retry)
2128  c->error = 1;
2129  ret = give_up_drive ? -1 : do_retry ? 2 : 0;
2130 ex:;
2131  BURN_FREE_MEM(msg);
2132  return ret;
2133 }
2134 
2135 static void react_on_drive_loss(struct burn_drive *d, struct command *c,
2136  FILE *fp)
2137 {
2138  sg_close_drive(d);
2139  d->released = 1;
2140  d->busy = BURN_DRIVE_IDLE;
2141  d->cancel = 1;
2142  c->error = 1;
2144  d->global_index, 0x000201a6,
2146  "Lost connection to drive", 0, 0);
2147  scsi_log_message(d, fp, "--- SG_IO: Gave up connection to drive", 0);
2148 }
2149 
2150 /** Sends a SCSI command to the drive, receives reply and evaluates whether
2151  the command succeeded or shall be retried or finally failed.
2152  Returned SCSI errors shall not lead to a return value indicating failure.
2153  The callers get notified by c->error. An SCSI failure which leads not to
2154  a retry shall be notified via scsi_notify_error().
2155  @return: 1 success , <=0 failure
2156 */
2157 int sg_issue_command(struct burn_drive *d, struct command *c)
2158 {
2159  int done = 0, no_c_page = 0, i, ret;
2160  int err;
2161  time_t start_time;
2162  sg_io_hdr_t s;
2163  /* ts A61030 */
2164  static FILE *fp= NULL;
2165  char *msg = NULL;
2166 
2167  BURN_ALLOC_MEM(msg, char, 161);
2168 
2169  c->error = 0;
2170  memset(c->sense, 0, sizeof(c->sense));
2171 
2172  /* <<< ts A60821
2173  debug: for tracing calls which might use open drive fds */
2174  sprintf(msg, "sg_issue_command d->fd= %d d->released= %d\n",
2175  d->fd, d->released);
2176  mmc_function_spy(NULL, msg);
2177 
2178  /* >>> ts B11110 : move this into scsi_log_cmd() together with the
2179  static fp */
2180  /* ts A61030 */
2181  if (burn_sg_log_scsi & 1) {
2182  if (fp == NULL) {
2183  fp= fopen("/tmp/libburn_sg_command_log", "a");
2184  fprintf(fp,
2185  "\n-----------------------------------------\n");
2186  }
2187  }
2188 
2189  /* ts A61010 : with no fd there is no chance to send an ioctl */
2190  if (d->fd < 0) {
2191  c->error = 1;
2192  {ret = 0; goto ex;}
2193  }
2194 
2195 
2196  c->error = 0;
2197  memset(&s, 0, sizeof(sg_io_hdr_t));
2198  if (burn_sg_log_scsi & 3)
2199  scsi_log_cmd(c,fp,0);
2200 
2201  s.interface_id = 'S';
2202 
2203 #ifdef Libburn_sgio_as_growisofS
2204  /* ??? ts A91112 : does this speed up USB ? (from growisofs)
2205  --- did not help
2206  */
2207  s.flags = SG_FLAG_DIRECT_IO;
2208 #endif /* Libburn_sgio_as_growisofS */
2209 
2210  if (c->dir == TO_DRIVE)
2211  s.dxfer_direction = SG_DXFER_TO_DEV;
2212  else if (c->dir == FROM_DRIVE)
2213  s.dxfer_direction = SG_DXFER_FROM_DEV;
2214  else if (c->dir == NO_TRANSFER) {
2215  s.dxfer_direction = SG_DXFER_NONE;
2216 
2217  /* ts A61007 */
2218  /* a ssert(!c->page); */
2219  no_c_page = 1;
2220  }
2221  s.cmd_len = c->oplen;
2222  s.cmdp = c->opcode;
2223  s.mx_sb_len = 32;
2224  s.sbp = c->sense;
2225  if (c->timeout > 0)
2226  s.timeout = c->timeout;
2227  else
2228  s.timeout = Libburn_scsi_default_timeouT;
2229  if (c->page && !no_c_page) {
2230  s.dxferp = c->page->data;
2231 
2232 /* # def ine Libburn_debug_dxferP 1 */
2233 #ifdef Libburn_debug_dxferP
2234 
2235  { char text[1024], *content; int i = c->page->bytes;
2236  if (c->dir == FROM_DRIVE) {
2237  for (i = 0; i < c->page->bytes && c->page->data[i] == 0; i++);
2238  content = (i < c->page->bytes) ?
2239  " (some nonzero)" : " (all zero)";
2240  } else {
2241  i = c->page->bytes;
2242  content = "";
2243  }
2244  sprintf(text, "dxferp before = %lx%s",
2245  (unsigned long) s.dxferp, content);
2246  scsi_log_text(text, fp, 0);
2247  }
2248 
2249 #endif
2250 
2251  if (c->dir == FROM_DRIVE) {
2252 
2253  /* ts A70519 : kernel 2.4 usb-storage seems to
2254  expect exact dxfer_len for data
2255  fetching commands.
2256  */
2257  if (c->dxfer_len >= 0)
2258  s.dxfer_len = c->dxfer_len;
2259  else
2260  s.dxfer_len = BUFFER_SIZE;
2261 /* touch page so we can use valgrind */
2262  memset(c->page->data, 0, BUFFER_SIZE);
2263  } else {
2264 
2265  /* ts A61010 */
2266  /* a ssert(c->page->bytes > 0); */
2267  if (c->page->bytes <= 0) {
2268  c->error = 1;
2269  {ret = 0; goto ex;}
2270  }
2271 
2272  s.dxfer_len = c->page->bytes;
2273  }
2274  } else {
2275  s.dxferp = NULL;
2276  s.dxfer_len = 0;
2277  }
2278  s.usr_ptr = c;
2279 
2280  /* ts B90523 : Record effective transfer length request for debugging*/
2281  c->dxfer_len = s.dxfer_len;
2282 
2283  start_time = time(NULL);
2284  for(i = 0; !done; i++) {
2285 
2286  memset(c->sense, 0, sizeof(c->sense));
2287  c->start_time = burn_get_time(0);
2288 
2289  err = ioctl(d->fd, SG_IO, &s);
2290 
2291  c->end_time = burn_get_time(0);
2292 
2293 
2294 #ifdef Libburn_debug_dxferP
2295  if (c->page && !no_c_page) {
2296  char text[1024];
2297  sprintf(text, "dxferp after = %lx",
2298  (unsigned long) s.dxferp);
2299  scsi_log_text(text, fp, 0);
2300  }
2301 
2302 #endif
2303 
2304  /* ts A61010 */
2305  /* a ssert(err != -1); */
2306  if (err == -1) {
2308  d->global_index, 0x0002010c,
2310  "Failed to transfer command to drive",
2311  errno, 0);
2312  sprintf(msg, "--- SG_IO: return= -1 , ");
2313  sprintf(msg + strlen(msg), "errno= %d , ", errno);
2314  sprintf(msg + strlen(msg),
2315  "host_status= 0x%x , driver_status= 0x%x",
2316  (unsigned int) s.host_status,
2317  (unsigned int) s.driver_status);
2318  scsi_log_message(d, fp, msg, 0);
2319 
2321  d->global_index, 0x0002010c,
2323  msg, 0, 0);
2324  sprintf(msg, "Attempted command: ");
2325  spc_human_readable_cmd(c, msg + strlen(msg),
2326  160 - strlen(msg), 0);
2328  d->global_index, 0x0002010c,
2330  msg, 0, 0);
2331 
2332  react_on_drive_loss(d, c, fp);
2333  {ret = -1; goto ex;}
2334  }
2335  done = scsi_eval_cmd_outcome(d, c, fp,
2336  (unsigned char *) (s.sbp),
2337  s.sb_len_wr,
2338  start_time, s.timeout, i, 0);
2339  if (d->cancel)
2340  break;
2341  ret = evaluate_transport_success(d, c, fp,
2342  s.host_status, s.driver_status);
2343  if (ret == -1)
2344  react_on_drive_loss(d, c, fp);
2345  if (ret <= 0)
2346  {ret = -1; goto ex;}
2347  if (d->cancel)
2348  break;
2349  /* if ! done : loop for retry */;
2350  if (!done) {
2351  spc_register_retry(c);
2352  if (burn_sg_log_scsi & 3) {
2353  scsi_log_text("+++ Repeating command", fp, 0);
2354  scsi_log_cmd(c, fp, 0);
2355  }
2356  }
2357  }
2358 
2359  ret = 1;
2360 ex:;
2361  BURN_FREE_MEM(msg);
2362  return ret;
2363 }
2364 
2365 
2366 /* ts B11001 : outsourced from non-static sg_obtain_scsi_adr() */
2367 /** Tries to obtain SCSI address parameters.
2368  @return 1 is success , 0 is failure
2369 */
2370 static int sg_obtain_scsi_adr_fd(char *path, int fd_in,
2371  int *bus_no, int *host_no, int *channel_no,
2372  int *target_no, int *lun_no)
2373 {
2374  int fd, ret, l, open_mode = O_RDONLY;
2375  struct my_scsi_idlun {
2376  int x;
2377  int host_unique_id;
2378  };
2379  struct my_scsi_idlun idlun;
2380 
2381  /* valgrind called idlun uninitialized because it is blind for ioctl */
2382  idlun.x = 0;
2383  idlun.host_unique_id = 0;
2384 
2385  l = strlen(linux_ata_device_family) - 2;
2386  if (l > 0 && strncmp(path, linux_ata_device_family, l) == 0
2387  && path[7] >= 'a' && path[7] <= 'z' && path[8] == 0)
2388  return 0; /* on RIP 14 all hdx return SCSI adr 0,0,0,0 */
2389 
2390  /* ts A70409 : DDLP-B */
2391  /* >>> obtain single lock on path */
2392 
2394  open_mode |= O_NDELAY;
2395  if(burn_sg_open_o_excl) {
2396  /* O_EXCL | O_RDONLY does not work with /dev/sg* on
2397  SuSE 9.0 (kernel 2.4) and SuSE 9.3 (kernel 2.6) */
2398  /* so skip it for now */;
2399  }
2400  if (fd_in >= 0)
2401  fd = fd_in;
2402  else
2403  fd = open(path, open_mode);
2404  if(fd < 0)
2405  return 0;
2406  sg_fcntl_lock(&fd, path, F_RDLCK, 0);
2407  if(fd < 0)
2408  return 0;
2409 
2410 #ifdef SCSI_IOCTL_GET_BUS_NUMBER
2411  /* Hearsay A61005 */
2412  if (ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, bus_no) == -1)
2413  *bus_no = -1;
2414 #endif
2415 
2416  /* http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/scsi_g_idlun.html */
2417  ret = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun);
2418 
2419  if (fd_in < 0)
2420  sg_close_drive_fd(path, -1, &fd, 0);
2421  if (ret == -1)
2422  return(0);
2423  *host_no= (idlun.x>>24)&255;
2424  *channel_no= (idlun.x>>16)&255;
2425  *target_no= (idlun.x)&255;
2426  *lun_no= (idlun.x>>8)&255;
2427 #ifdef SCSI_IOCTL_GET_BUS_NUMBER
2428  if(*bus_no == -1)
2429  *bus_no = 1000 * (*host_no + 1) + *channel_no;
2430 #else
2431  *bus_no= *host_no;
2432 #endif
2433  return 1;
2434 }
2435 
2436 
2437 /* ts A60922 */
2438 /** Tries to obtain SCSI address parameters.
2439  @return 1 is success , 0 is failure
2440 */
2441 int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
2442  int *target_no, int *lun_no)
2443 {
2444  return sg_obtain_scsi_adr_fd(path, -1, bus_no, host_no, channel_no,
2445  target_no, lun_no);
2446 }
2447 
2448 
2449 /* ts A60922 ticket 33 : called from drive.c */
2450 /** Tells whether a text is a persistent address as listed by the enumeration
2451  functions.
2452 */
2453 int sg_is_enumerable_adr(char *adr)
2454 {
2455  char *fname = NULL;
2456  int ret = 0, first = 1, fname_size = 4096;
2458 
2459  BURN_ALLOC_MEM(fname, char, fname_size);
2460  while (1) {
2461  ret= sg_give_next_adr(&idx, fname, fname_size, first);
2462  if(ret <= 0)
2463  break;
2464  first = 0;
2465  if (strcmp(adr, fname) == 0) {
2466  sg_give_next_adr(&idx, fname, fname_size, -1);
2467  {ret = 1; goto ex;}
2468  }
2469  }
2470  ret = 0;
2471 ex:;
2472  if (first == 0)
2473  sg_give_next_adr(&idx, fname, fname_size, -1);
2474  BURN_FREE_MEM(fname);
2475  return ret;
2476 }
2477 
2478 
2479 /* ts B00115 */
2480 /* Return 1 if the given path leads to a regular file or a device that can be
2481  fseeked, read, and possibly written with 2 kB granularity.
2482 */
2483 int burn_os_is_2k_seekrw(char *path, int flag)
2484 {
2485  struct stat stbuf;
2486 
2487  if (stat(path, &stbuf) == -1)
2488  return 0;
2489  if (S_ISREG(stbuf.st_mode))
2490  return 1;
2491  if (S_ISBLK(stbuf.st_mode))
2492  return 1;
2493  return 0;
2494 }
2495 
2496 
2497 /* ts A70909 */
2498 /** Estimate the potential payload capacity of a file address.
2499  @param path The address of the file to be examined. If it does not
2500  exist yet, then the directory will be inquired.
2501  @param bytes The pointed value gets modified, but only if an estimation is
2502  possible.
2503  @return -2 = cannot perform necessary operations on file object
2504  -1 = neither path nor dirname of path exist
2505  0 = could not estimate size capacity of file object
2506  1 = estimation has been made, bytes was set
2507 */
2508 int burn_os_stdio_capacity(char *path, off_t write_start, off_t *bytes)
2509 {
2510  struct stat stbuf;
2511  struct statvfs vfsbuf;
2512  char *testpath = NULL, *cpt;
2513  long blocks;
2514  int open_mode = O_RDONLY, fd, ret;
2515  off_t add_size = 0;
2516 
2517  BURN_ALLOC_MEM(testpath, char, 4096);
2518  testpath[0] = 0;
2519  if (stat(path, &stbuf) == -1) {
2520  strcpy(testpath, path);
2521  cpt = strrchr(testpath, '/');
2522  if(cpt == NULL)
2523  strcpy(testpath, ".");
2524  else if(cpt == testpath)
2525  testpath[1] = 0;
2526  else
2527  *cpt = 0;
2528  if (stat(testpath, &stbuf) == -1)
2529  {ret = -1; goto ex;}
2530  } else if(S_ISBLK(stbuf.st_mode)) {
2531  fd = open(path, open_mode);
2532  if (fd == -1)
2533  {ret = -2; goto ex;}
2534  ret = ioctl(fd, BLKGETSIZE, &blocks);
2535  close(fd);
2536  if (ret == -1)
2537  {ret = -2; goto ex;}
2538  *bytes = ((off_t) blocks) * (off_t) 512;
2539  } else if(S_ISREG(stbuf.st_mode)) {
2540  add_size = burn_sparse_file_addsize(write_start, &stbuf);
2541  strcpy(testpath, path);
2542  } else
2543  {ret = 0; goto ex;}
2544 
2545  if (testpath[0]) {
2546  if (statvfs(testpath, &vfsbuf) == -1)
2547  {ret = -2; goto ex;}
2548  *bytes = add_size + ((off_t) vfsbuf.f_frsize) *
2549  (off_t) vfsbuf.f_bavail;
2550  }
2551 
2552 #ifdef NIX
2553 /* <<< */
2554  fprintf(stderr, "libburn_DEBUG: Faking 4.5 TB of disk space\n");
2555  *bytes = ((off_t) 2415919104) * (off_t) 2048;
2556  if (*bytes / (off_t) 2048 > (off_t) 0x7ffffff0) {
2557  *bytes = ((off_t) 0x7ffffff0) * (off_t) 2048;
2558  fprintf(stderr, "libburn_DEBUG: Reducing disk space to 4 TB - 2 kB\n");
2559  }
2560 /* <<< */
2561 #endif
2562 
2563 
2564  ret = 1;
2565 ex:;
2566  BURN_FREE_MEM(testpath);
2567  return ret;
2568 }
2569 
2570 
2571 /* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
2572 
2573 #ifdef PROT_READ
2574 #ifdef PROT_WRITE
2575 #ifdef MAP_SHARED
2576 #ifdef MAP_ANONYMOUS
2577 #ifdef MAP_FAILED
2578 #define Libburn_linux_do_mmaP 1
2579 #endif
2580 #endif
2581 #endif
2582 #endif
2583 #endif
2584 
2585 #ifdef Libburn_read_o_direcT
2586 #ifdef O_DIRECT
2587 #define Libburn_linux_do_o_direcT 1
2588 #endif
2589 #endif /* Libburn_read_o_direcT */
2590 
2591 
2592 int burn_os_open_track_src(char *path, int open_flags, int flag)
2593 {
2594  int fd;
2595 
2596 #ifdef Libburn_linux_do_o_direcT
2597  libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
2599  "Opening track source with O_DIRECT" , 0, 0);
2600  fd = open(path, open_flags | O_DIRECT);
2601 #else
2602  fd = open(path, open_flags);
2603 #endif
2604  return fd;
2605 }
2606 
2607 
2608 void *burn_os_alloc_buffer(size_t amount, int flag)
2609 {
2610  void *buf = NULL;
2611 
2612 #ifdef Libburn_linux_do_mmaP
2613 
2614  /* >>> check whether size is suitable */;
2615 
2616  libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
2618  "Allocating buffer via mmap()" , 0, 0);
2619  buf = mmap(NULL, amount, PROT_READ | PROT_WRITE,
2620  MAP_SHARED | MAP_ANONYMOUS, -1, (off_t) 0);
2621  if (buf == MAP_FAILED)
2622  buf = NULL;
2623  else
2624  memset(buf, 0, amount);
2625 #else
2626  buf = calloc(1, amount);
2627 #endif /* ! Libburn_linux_do_mmaP */
2628 
2629  return buf;
2630 }
2631 
2632 
2633 int burn_os_free_buffer(void *buffer, size_t amount, int flag)
2634 {
2635  int ret = 0;
2636 
2637  if (buffer == NULL)
2638  return 0;
2639 #ifdef Libburn_linux_do_mmaP
2640  ret = munmap(buffer, amount);
2641 #else
2642  free(buffer);
2643 #endif
2644  return (ret == 0);
2645 }
2646 
int burn_drive_whitelist_count(void)
Definition: drive.c:1736
int burn_drive_is_open(struct burn_drive *d)
Definition: drive.c:167
char * burn_drive_whitelist_item(int idx, int flag)
Definition: drive.c:1741
int burn_drive_is_listed(char *path, struct burn_drive **found, int flag)
Definition: drive.c:250
struct burn_drive * burn_drive_finish_enum(struct burn_drive *d)
Definition: drive.c:612
int burn_setup_drive(struct burn_drive *d, char *fname)
Definition: drive.c:79
#define BURN_FREE_MEM(pt)
Definition: init.h:52
#define BURN_ALLOC_MEM(pt, typ, count)
Definition: init.h:40
double burn_get_time(int flag)
Definition: util.c:354
off_t burn_sparse_file_addsize(off_t write_start, struct stat *stbuf)
Definition: util.c:385
@ BURN_DRIVE_IDLE
Definition: libburn.h:295
#define BURN_DRIVE_ADR_LEN
Definition: libburn.h:1041
#define BURN_MSGS_MESSAGE_LEN
Definition: libburn.h:3896
int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code, int severity, int priority, char *msg_text, int os_errno, int flag)
Definition: libdax_msgs.c:334
#define LIBDAX_MSGS_SEV_DEBUG
Definition: libdax_msgs.h:138
#define LIBDAX_MSGS_PRIO_LOW
Definition: libdax_msgs.h:235
#define LIBDAX_MSGS_SEV_FATAL
Definition: libdax_msgs.h:217
#define LIBDAX_MSGS_SEV_HINT
Definition: libdax_msgs.h:150
#define LIBDAX_MSGS_SEV_NOTE
Definition: libdax_msgs.h:146
#define LIBDAX_MSGS_PRIO_HIGH
Definition: libdax_msgs.h:237
#define LIBDAX_MSGS_SEV_SORRY
Definition: libdax_msgs.h:176
#define LIBDAX_MSGS_SEV_FAILURE
Definition: libdax_msgs.h:205
#define BURN_OS_SG_MAX_NAMELEN
Definition: os-linux.h:68
#define BURN_OS_SG_MAX_SIBLINGS
Definition: os-linux.h:67
static int fname_other_name(char *fname, char other_name[80], int flag)
Definition: sg-linux.c:1304
static int sg_close_drive(struct burn_drive *d)
Definition: sg-linux.c:906
int sg_issue_command(struct burn_drive *d, struct command *c)
Definition: sg-linux.c:2157
int mmc_function_spy(struct burn_drive *d, char *text)
Definition: mmc.c:267
void * burn_os_alloc_buffer(size_t amount, int flag)
Definition: sg-linux.c:2608
int burn_sg_open_abort_busy
Definition: init.c:77
static int linux_sg_accept_any_type
Definition: sg-linux.c:215
int sg_is_enumerable_adr(char *adr)
Definition: sg-linux.c:2453
#define Libburn_sg_driver_oK
Definition: sg-linux.c:157
static void sg_select_device_family(void)
Definition: sg-linux.c:320
int sg_shutdown(int flag)
Definition: sg-linux.c:1621
int sg_grab(struct burn_drive *d)
Definition: sg-linux.c:1794
static int sg_release_siblings(int sibling_fds[], char sibling_fnames[][BURN_OS_SG_MAX_NAMELEN], int *sibling_count)
Definition: sg-linux.c:804
int sg_dispose_drive(struct burn_drive *d, int flag)
Definition: sg-linux.c:1636
static int linux_sg_enumerate_debug
Definition: sg-linux.c:187
static void sg_evaluate_kernel(void)
Definition: sg-linux.c:301
#define Libburn_sg_host_oK
Definition: sg-linux.c:155
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
Definition: sg-linux.c:2633
int burn_drive_is_banned(char *device_address)
Definition: drive.c:1723
static void sg_enumerate(void)
Definition: sg-linux.c:1252
static int sg_open_scsi_siblings(char *path, int driveno, int sibling_fds[], char sibling_fnames[][BURN_OS_SG_MAX_NAMELEN], int *sibling_count, int host_no, int channel_no, int id_no, int lun_no)
Definition: sg-linux.c:923
int burn_sg_fcntl_f_setlk
Definition: init.c:57
static int sg_kernel_age
Definition: sg-linux.c:167
int burn_sg_use_family
Definition: init.c:66
static int linux_ata_enumerate_verbose
Definition: sg-linux.c:228
struct libdax_msgs * libdax_messenger
Definition: init.c:42
int scsi_enumerate_drives(void)
Definition: sg-linux.c:1754
int burn_os_open_track_src(char *path, int open_flags, int flag)
Definition: sg-linux.c:2592
static void ata_enumerate(void)
Definition: sg-linux.c:1213
static int sgio_log_cmd(unsigned char *cmd, int cmd_len, FILE *fp_in, int flag)
Definition: sg-linux.c:388
static int evaluate_transport_success(struct burn_drive *d, struct command *c, FILE *fp, unsigned short host_status, unsigned short driver_status)
Definition: sg-linux.c:1981
int burn_os_is_2k_seekrw(char *path, int flag)
Definition: sg-linux.c:2483
static int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry)
Definition: sg-linux.c:614
int burn_sg_open_o_excl
Definition: init.c:53
static void react_on_drive_loss(struct burn_drive *d, struct command *c, FILE *fp)
Definition: sg-linux.c:2135
static int fname_drive_is_listed(char *fname, int flag)
Definition: sg-linux.c:1325
int burn_os_stdio_capacity(char *path, off_t write_start, off_t *bytes)
Definition: sg-linux.c:2508
#define Libburn_udev_wait_useC
static int is_ata_drive(char *fname, int fd_in)
Definition: sg-linux.c:1014
static int fname_enumerate(char *fname, int flag)
Definition: sg-linux.c:1343
static int sgio_test(int fd)
Definition: sg-linux.c:431
static int single_enumerate(int flag)
Definition: sg-linux.c:1393
int sg_initialize(char msg[1024], int flag)
Definition: sg-linux.c:1610
static int sg_obtain_scsi_adr_fd(char *path, int fd_in, int *bus_no, int *host_no, int *channel_no, int *target_no, int *lun_no)
Definition: sg-linux.c:2370
static int sg_exchange_scd_for_sr(char *fname, int flag)
Definition: sg-linux.c:351
static int sg_handle_busy_device(char *fname, int os_errno)
Definition: sg-linux.c:541
static int sg_open_drive_fd(char *fname, int scan_mode)
Definition: sg-linux.c:715
static int linux_sg_auto_family
Definition: sg-linux.c:208
int burn_sg_log_scsi
Definition: init.c:110
int sg_drive_is_open(struct burn_drive *d)
Definition: sg-linux.c:1777
static int sg_fcntl_lock(int *fd, char *fd_name, int l_type, int verbose)
Definition: sg-linux.c:670
int sg_release(struct burn_drive *d)
Definition: sg-linux.c:1958
static char linux_sg_device_family[80]
Definition: sg-linux.c:203
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)
Definition: sg-linux.c:1066
int burn_sg_open_o_nonblock
Definition: init.c:72
int sg_id_string(char msg[1024], int flag)
Definition: sg-linux.c:1596
static int proc_sys_dev_cdrom_info(char ***list, int *count, int flag)
Definition: sg-linux.c:1423
static char linux_ata_device_family[80]
Definition: sg-linux.c:224
static int sgio_inquiry_cd_drive(int fd, char *fname)
Definition: sg-linux.c:458
static void enumerate_common(char *fname, int fd_in, int bus_no, int host_no, int channel_no, int target_no, int lun_no)
Definition: sg-linux.c:1539
static int sg_os_revalidate_disc(struct burn_drive *d)
Definition: sg-linux.c:826
static int add_proc_info_drives(int flag)
Definition: sg-linux.c:1502
int sg_give_next_adr(burn_drive_enumerator_t *idx, char adr[], int adr_size, int initialize)
Definition: sg-linux.c:1663
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, int *target_no, int *lun_no)
Definition: sg-linux.c:2441
static int sgio_log_reply(unsigned char *opcode, int data_dir, unsigned char *data, int dxfer_len, void *fp_in, unsigned char sense[18], int sense_len, double duration, int flag)
Definition: sg-linux.c:418
static int sg_open_for_enumeration(char *fname, int flag)
Definition: sg-linux.c:1196
int scsi_log_cmd(struct command *c, void *fp_in, int flag)
Definition: spc.c:2002
int spc_human_readable_cmd(struct command *c, char *msg, int msg_max, int flag)
Definition: spc.c:1787
int scsi_log_text(char *text, void *fp_in, int flag)
Definition: spc.c:1984
void spc_register_retry(struct command *c)
Definition: spc.c:1775
int scsi_log_command(unsigned char *opcode, int oplen, int data_dir, unsigned char *data, int bytes, void *fp_in, int flag)
Definition: spc.c:1964
int scsi_log_reply(unsigned char *opcode, int data_dir, unsigned char *data, int dxfer_len, void *fp_in, unsigned char sense[18], int sense_len, double duration, int flag)
Definition: spc.c:2022
int scsi_eval_cmd_outcome(struct burn_drive *d, struct command *c, void *fp, unsigned char *sense, int sense_len, time_t start_time, int timeout_ms, int loop_count, int flag)
Definition: spc.c:2109
int scsi_log_message(struct burn_drive *d, void *fp_in, char *msg, int flag)
Definition: spc.c:2087
int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no, int channel_no, int target_no, int lun_no, int flag)
Definition: spc.c:1213
#define Libburn_scsi_default_timeouT
Definition: spc.h:161
unsigned char data[65536+4096]
Definition: transport.h:52
int bytes
Definition: transport.h:54
int(* grab)(struct burn_drive *)
Definition: transport.h:453
int global_index
Definition: transport.h:200
volatile int released
Definition: transport.h:320
int medium_state_changed
Definition: transport.h:443
char * devname
Definition: transport.h:185
int bus_no
Definition: transport.h:180
int channel
Definition: transport.h:183
volatile int cancel
Definition: transport.h:422
int(* drive_is_open)(struct burn_drive *)
Definition: transport.h:457
enum burn_drive_status busy
Definition: transport.h:423
int(* issue_command)(struct burn_drive *, struct command *)
Definition: transport.h:459
int(* release)(struct burn_drive *)
Definition: transport.h:454
unsigned char sense[128]
Definition: transport.h:63
int oplen
Definition: transport.h:60
int dxfer_len
Definition: transport.h:62
double start_time
Definition: transport.h:70
int timeout
Definition: transport.h:68
double end_time
Definition: transport.h:71
int error
Definition: transport.h:65
int dir
Definition: transport.h:61
struct buffer * page
Definition: transport.h:67
unsigned char opcode[16]
Definition: transport.h:59
@ TO_DRIVE
Definition: transport.h:25
@ FROM_DRIVE
Definition: transport.h:25
@ NO_TRANSFER
Definition: transport.h:25
#define BUFFER_SIZE
Definition: transport.h:21