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-libcdio.c
Go to the documentation of this file.
1 /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
2 
3 /*
4  Copyright (c) 2009 - 2016 Thomas Schmitt <scdbackup@gmx.net>
5  Provided under GPL version 2 or later.
6 */
7 
8 
9 /*
10 
11 This is the main operating system dependent SCSI part of libburn. It implements
12 the transport level aspects of SCSI control and command i/o.
13 
14 Present implementation: GNU libcdio , for X/Open compliant operating systems
15 
16 
17 PORTING:
18 
19 Porting libburn typically will consist of adding a new operating system case
20 to the following switcher files:
21  os.h Operating system specific libburn definitions and declarations.
22  sg.c Operating system dependent transport level modules.
23 and of deriving the following system specific files from existing examples:
24  os-*.h Included by os.h. You will need some general system knowledge
25  about signals and knowledge about the storage object needs of your
26  transport level module sg-*.c.
27 
28  sg-*.c This source module. You will need special system knowledge about
29  how to detect all potentially available drives, how to open them,
30  eventually how to exclusively reserve them, how to perform
31  SCSI transactions, how to inquire the (pseudo-)SCSI driver.
32  You will not need to care about CD burning, MMC or other high-level
33  SCSI aspects.
34 
35 Said sg-*.c operations are defined by a public function interface, which has
36 to be implemented in a way that provides libburn with the desired services:
37 
38 sg_id_string() returns an id string of the SCSI transport adapter.
39  It may be called before initialization but then may
40  return only a preliminary id.
41 
42 sg_initialize() performs global initialization of the SCSI transport
43  adapter and eventually needed operating system
44  facilities. Checks for compatibility of supporting
45  software components.
46 
47 sg_shutdown() performs global finalizations and releases globally
48  acquired resources.
49 
50 sg_give_next_adr() iterates over the set of potentially useful drive
51  address strings.
52 
53 scsi_enumerate_drives() brings all available, not-whitelist-banned, and
54  accessible drives into libburn's list of drives.
55 
56 sg_dispose_drive() finalizes adapter specifics of struct burn_drive
57  on destruction. Releases resources which were acquired
58  underneath scsi_enumerate_drives().
59 
60 sg_drive_is_open() tells whether libburn has the given drive in use.
61 
62 sg_grab() opens the drive for SCSI commands and ensures
63  undisturbed access.
64 
65 sg_release() closes a drive opened by sg_grab()
66 
67 sg_issue_command() sends a SCSI command to the drive, receives reply,
68  and evaluates whether the command succeeded or shall
69  be retried or finally failed.
70 
71 sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
72 
73 
74 burn_os_is_2k_seekrw() tells whether the given path leads to a file object
75  that can be used in 2 kB granularity by lseek(2),
76  read(2), and possibly write(2) if not read-only..
77  E.g. a USB stick or a hard disk.
78 
79 burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
80 
81 burn_os_open_track_src() opens a disk file in a way that offers best
82  throughput with file reading and/or SCSI write command
83  transmission.
84 
85 burn_os_alloc_buffer() allocates a memory area that is suitable for file
86  descriptors issued by burn_os_open_track_src().
87  The buffer size may be rounded up for alignment
88  reasons.
89 
90 burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
91 
92 Porting hints are marked by the text "PORTING:".
93 Send feedback to libburn-hackers@pykix.org .
94 
95 */
96 
97 #ifdef HAVE_CONFIG_H
98 #include "../config.h"
99 #endif
100 
101 
102 /** PORTING : ------- OS dependent headers and definitions ------ */
103 
104 #include <unistd.h>
105 #include <stdio.h>
106 #include <sys/types.h>
107 #include <errno.h>
108 #include <fcntl.h>
109 #include <sys/stat.h>
110 #include <string.h>
111 #include <stdlib.h>
112 
113 #ifdef Libburn_os_has_statvfS
114 #include <sys/statvfs.h>
115 #endif /* Libburn_os_has_stavtfS */
116 
117 #ifdef __linux
118 /* for ioctl(BLKGETSIZE) */
119 #include <sys/ioctl.h>
120 #include <linux/fs.h>
121 #endif
122 
123 #ifdef __FreeBSD__
124 #define Libburn_is_on_freebsD 1
125 #endif
126 #ifdef __FreeBSD_kernel__
127 #define Libburn_is_on_freebsD 1
128 #endif
129 #ifdef Libburn_is_on_freebsD
130 /* To avoid ATAPI devices */
131 #define Libburn_guess_freebsd_atapi_devicE 1
132 /* To obtain size of disk-like devices */
133 #include <sys/disk.h> /* DIOCGMEDIASIZE */
134 #endif /* Libburn_is_on_freebsD */
135 
136 #define Libburn_guess_freebsd_atapi_devicE 1
137 
138 #ifdef sun
139 #define Libburn_is_on_solariS 1
140 #endif
141 #ifdef __sun
142 #define Libburn_is_on_solariS 1
143 #endif
144 
145 /* Proposal by Rocky Bernstein to avoid macro clashes with cdio_config.h */
146 #define __CDIO_CONFIG_H__ 1
147 
148 #include <cdio/cdio.h>
149 #include <cdio/logging.h>
150 #include <cdio/mmc.h>
151 
152 /* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
153 #ifndef O_BINARY
154 #define O_BINARY 0
155 #endif
156 
157 
158 /* The waiting time before eventually retrying a failed SCSI command.
159  Before each retry wait Libburn_sg_linux_retry_incR longer than with
160  the previous one.
161 */
162 #define Libburn_sg_libcdio_retry_usleeP 100000
163 #define Libburn_sg_libcdio_retry_incR 100000
164 
165 
166 /** PORTING : ------ libburn portable headers and definitions ----- */
167 
168 #include "transport.h"
169 #include "drive.h"
170 #include "sg.h"
171 #include "spc.h"
172 /* collides with symbols of <cdio/mmc.h>
173  #include "mmc.h"
174 */
175 #include "sbc.h"
176 #include "debug.h"
177 #include "toc.h"
178 #include "util.h"
179 #include "init.h"
180 
181 #include "libdax_msgs.h"
182 extern struct libdax_msgs *libdax_messenger;
183 
184 
185 /* is in portable part of libburn */
186 int burn_drive_is_banned(char *device_address);
187 int burn_drive_resolve_link(char *path, char adr[],
188  int *recursion_count, int flag); /* drive.c */
189 
190 /* Whether to log SCSI commands:
191  bit0= log in /tmp/libburn_sg_command_log
192  bit1= log to stderr
193  bit2= flush every line
194 */
195 extern int burn_sg_log_scsi;
196 
197 
198 /* ------------------------------------------------------------------------ */
199 /* PORTING: Private definitions. Port only if needed by public functions. */
200 /* (Public functions are listed below) */
201 /* ------------------------------------------------------------------------ */
202 
203 
204 /* Storage object is in libburn/init.c
205  whether to strive for exclusive access to the drive
206 */
207 extern int burn_sg_open_o_excl;
208 
209 
210 /* ------------------------------------------------------------------------ */
211 /* PORTING: Private functions. Port only if needed by public functions */
212 /* (Public functions are listed below) */
213 /* ------------------------------------------------------------------------ */
214 
215 
216 static int sg_close_drive(struct burn_drive * d)
217 {
218  CdIo_t *p_cdio;
219 
220  if (d->p_cdio != NULL) {
221  p_cdio = (CdIo_t *) d->p_cdio;
222  cdio_destroy(p_cdio);
223  d->p_cdio = NULL;
224  }
225  return 0;
226 }
227 
228 
230  char adr[], int adr_size, int initialize)
231 {
232  char **pos;
233  int count = 0;
234 
235  if (initialize == 1) {
236  idx->pos = idx->ppsz_cd_drives =
237  cdio_get_devices(DRIVER_DEVICE);
238  if (idx->ppsz_cd_drives == NULL)
239  return 0;
240 
241  for (pos = idx->ppsz_cd_drives ; pos != NULL; pos++) {
242  if (*pos == NULL)
243  break;
244  count++;
245  }
246 
247  } else if (initialize == -1) {
248  if (idx->ppsz_cd_drives != NULL)
249  if (*(idx->ppsz_cd_drives) != NULL)
250  cdio_free_device_list(idx->ppsz_cd_drives);
251  idx->ppsz_cd_drives = NULL;
252  }
253 
254 #ifdef Libburn_guess_freebsd_atapi_devicE
255 try_next:;
256 #endif
257 
258  if (idx->pos == NULL)
259  return 0;
260  if (*(idx->pos) == NULL)
261  return 0;
262 
263 #ifdef Libburn_guess_freebsd_atapi_devicE
264  if (strncmp(*(idx->pos), "/dev/acd", 8) == 0) {
265  (idx->pos)++;
266  goto try_next;
267  }
268 #endif
269 
270  if ((ssize_t) strlen(*(idx->pos)) >= adr_size)
271  return -1;
272  strcpy(adr, *(idx->pos));
273  (idx->pos)++;
274  return 1;
275 }
276 
277 
278 /* ----------------------------------------------------------------------- */
279 /* PORTING: Private functions which contain publicly needed functionality. */
280 /* Their portable part must be performed. So it is probably best */
281 /* to replace the non-portable part and to call these functions */
282 /* in your port, too. */
283 /* ----------------------------------------------------------------------- */
284 
285 
286 /** Wraps a detected drive into libburn structures and hands it over to
287  libburn drive list.
288 */
289 static void enumerate_common(char *fname, char *cdio_name,
290  int bus_no, int host_no,
291  int channel_no, int target_no, int lun_no)
292 {
293  int ret;
294  struct burn_drive out;
295 
296  /* General libburn drive setup */
297  burn_setup_drive(&out, fname);
298 
299  /* This transport adapter uses SCSI-family commands and models
300  (seems the adapter would know better than its boss, if ever) */
301  ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
302  target_no, lun_no, 0);
303  if (ret <= 0)
304  return;
305 
306  /* PORTING: ------------------- non portable part --------------- */
307 
308  /* Transport adapter is libcdio */
309  /* Adapter specific handles and data */
310  out.p_cdio = NULL;
311  strcpy(out.libcdio_name, fname);
312  if (strlen(cdio_name) < sizeof(out.libcdio_name))
313  strcpy(out.libcdio_name, cdio_name);
314 
315  /* PORTING: ---------------- end of non portable part ------------ */
316 
317  /* Adapter specific functions with standardized names */
318  out.grab = sg_grab;
319  out.release = sg_release;
322  /* Finally register drive and inquire drive information */
324 }
325 
326 
327 /* ------------------------------------------------------------------------ */
328 /* PORTING: Public functions. These MUST be ported. */
329 /* ------------------------------------------------------------------------ */
330 
331 
332 /** Returns the id string of the SCSI transport adapter and eventually
333  needed operating system facilities.
334  This call is usable even if sg_initialize() was not called yet. In that
335  case a preliminary constant message might be issued if detailed info is
336  not available yet.
337  @param msg returns id string
338  @param flag unused yet, submit 0
339  @return 1 = success, <=0 = failure
340 */
341 int sg_id_string(char msg[1024], int flag)
342 {
343  char *version_text;
344 
345  sprintf(msg, "sg-libcdio h%d with libcdio ", LIBCDIO_VERSION_NUM);
346 
347  #if LIBCDIO_VERSION_NUM < 83
348 
349 LIBBURN_MISCONFIGURATION = 0;
350 INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_cdio_version_dot_h_TOO_OLD__NEED_libcdio_VERSION_NUM_83 = 0;
351 LIBBURN_MISCONFIGURATION_ = 0;
352 
353  #endif /* LIBCDIO_VERSION_NUM < 83 */
354 
355  version_text = (char *) cdio_version_string;
356  strncat(msg, version_text, 800);
357  return 1;
358 }
359 
360 
361 /** Performs global initialization of the SCSI transport adapter and eventually
362  needed operating system facilities. Checks for compatibility of supporting
363  software components.
364  @param msg returns ids and/or error messages of eventual helpers
365  @param flag unused yet, submit 0
366  @return 1 = success, <=0 = failure
367 */
368 int sg_initialize(char msg[1024], int flag)
369 {
370  int cdio_ver;
371  char *msg_pt;
372 
373  cdio_loglevel_default = CDIO_LOG_ASSERT;
374 
375  msg[0] = 0;
376  sg_id_string(msg, 0);
377  cdio_ver = libcdio_version_num;
378  libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
380  msg , 0, 0);
381  if (cdio_ver < LIBCDIO_VERSION_NUM) {
382  strcat(msg, " ---> ");
383  msg_pt = msg + strlen(msg);
384  sprintf(msg_pt,
385  "libcdio TOO OLD: numeric version %d , need at least %d",
386  cdio_ver, LIBCDIO_VERSION_NUM);
388  0x00000002,
390  msg_pt, 0, 0);
391  return 0;
392  }
393  return 1;
394 }
395 
396 
397 /** Performs global finalization of the SCSI transport adapter and eventually
398  needed operating system facilities. Releases globally acquired resources.
399  @param flag unused yet, submit 0
400  @return 1 = success, <=0 = failure
401 */
402 int sg_shutdown(int flag)
403 {
404  return 1;
405 }
406 
407 
408 /** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
409  struct burn_drive which are defined in os-*.h.
410  The eventual initialization of those components was made underneath
411  scsi_enumerate_drives().
412  This will be called when a burn_drive gets disposed.
413  @param d the drive to be finalized
414  @param flag unused yet, submit 0
415  @return 1 = success, <=0 = failure
416 */
417 int sg_dispose_drive(struct burn_drive *d, int flag)
418 {
419  return 1;
420 }
421 
422 
423 /** Returns the next index number and the next enumerated drive address.
424  The enumeration has to cover all available and accessible drives. It is
425  allowed to return addresses of drives which are not available but under
426  some (even exotic) circumstances could be available. It is on the other
427  hand allowed, only to hand out addresses which can really be used right
428  in the moment of this call. (This implementation chooses the latter.)
429  @param idx An opaque handle. Make no own theories about it.
430  @param adr Takes the reply
431  @param adr_size Gives maximum size of reply including final 0
432  @param initialize 1 = start new,
433  0 = continue, use no other values for now
434  -1 = finish
435  @return 1 = reply is a valid address , 0 = no further address available
436  -1 = severe error (e.g. adr_size too small)
437 */
439  char adr[], int adr_size, int initialize)
440 {
441  int ret, recursion_count = 0, path_size = 4096;
442  char *path = NULL;
443 #ifdef Libburn_is_on_solariS
444  int l;
445 #endif
446  BURN_ALLOC_MEM(path, char, path_size);
447 
448  ret = sg_give_next_adr_raw(idx, adr, adr_size, initialize);
449  if (ret <= 0)
450  goto ex;
451  if ((ssize_t) strlen(adr) >= path_size)
452  goto ex;
453 
454 #ifdef Libburn_is_on_solariS
455  /* >>> provisory : preserve Solaris /dev/rdsk/cXtYdZs2 addresses */
456  l = strlen(adr);
457  if (l >= 18)
458  if (strncmp(adr, "/dev/rdsk/c", 11) == 0 && adr[11] >= '0' &&
459  adr[11] <= '9' && strcmp(adr + (l - 2), "s2") == 0)
460  {ret = 1; goto ex;}
461 #endif /* Libburn_is_on_solariS */
462 
463  ret = burn_drive_resolve_link(adr, path, &recursion_count, 2);
464  if(ret > 0 && (ssize_t) strlen(path) < adr_size)
465  strcpy(adr, path);
466  ret = (ret >= 0);
467 ex:
468  BURN_FREE_MEM(path);
469  return ret;
470 }
471 
472 
473 /** Brings all available, not-whitelist-banned, and accessible drives into
474  libburn's list of drives.
475 */
477 {
479  int initialize = 1, ret, i_bus_no = -1, recursion_count = 0;
480  int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
481  int buf_size = 4096;
482  char *buf = NULL, *target = NULL;
483 #ifdef Libburn_is_on_solariS
484  int l;
485 #endif
486 
487  BURN_ALLOC_MEM(buf, char, buf_size);
488  BURN_ALLOC_MEM(target, char, buf_size);
489 
490  while(1) {
491  ret = sg_give_next_adr_raw(&idx, buf, buf_size, initialize);
492  initialize = 0;
493  if (ret <= 0)
494  break;
495  ret = 1;
496 
497 #ifdef Libburn_is_on_solariS
498  /* >>> provisory : preserve Solaris /dev/rdsk/cXtYdZs2 */
499  l = strlen(buf);
500  if (l >= 18)
501  if (strncmp(buf, "/dev/rdsk/c", 11) == 0 &&
502  buf[11] >= '0' && buf[11] <= '9' &&
503  strcmp(buf + (l - 2), "s2") == 0)
504  ret = 0;
505 #endif /* Libburn_is_on_solariS */
506 
507  if (ret == 1) {
508  ret = burn_drive_resolve_link(buf, target,
509  &recursion_count,2);
510  }
511  if (ret <= 0)
512  strcpy(target, buf);
513  if (burn_drive_is_banned(target))
514  continue;
515  sg_obtain_scsi_adr(buf, &i_bus_no, &i_host_no,
516  &i_channel_no, &i_target_no, &i_lun_no);
517  enumerate_common(target, buf,
518  i_bus_no, i_host_no, i_channel_no,
519  i_target_no, i_lun_no);
520  }
521  sg_give_next_adr(&idx, buf, buf_size, -1);
522  ret = 1;
523 ex:;
524  BURN_FREE_MEM(buf);
525  BURN_FREE_MEM(target);
526  return ret;
527 }
528 
529 
530 /** Tells whether libburn has the given drive in use or exclusively reserved.
531  If it is "open" then libburn will eventually call sg_release() on it when
532  it is time to give up usage and reservation.
533 */
534 /** Published as burn_drive.drive_is_open() */
536 {
537  return (d->p_cdio != NULL);
538 }
539 
540 
541 /** Opens the drive for SCSI commands and - if burn activities are prone
542  to external interference on your system - obtains an exclusive access lock
543  on the drive. (Note: this is not physical tray locking.)
544  A drive that has been opened with sg_grab() will eventually be handed
545  over to sg_release() for closing and unreserving.
546 */
547 int sg_grab(struct burn_drive *d)
548 {
549  CdIo_t *p_cdio;
550  char *am_eff, *msg = NULL, *am_wanted;
551  int os_errno, second_try = 0, ret;
552 
553  if (d->p_cdio != NULL) {
554  d->released = 0;
555  {ret = 1; goto ex;}
556  }
557  if (d->libcdio_name[0] == 0) /* just to be sure it is initialized */
558  strcpy(d->libcdio_name, d->devname);
559  am_wanted = (burn_sg_open_o_excl & 63) ? "MMC_RDWR_EXCL" : "MMC_RDWR";
560 try_to_open:;
561  p_cdio = cdio_open_am(d->libcdio_name, DRIVER_DEVICE, am_wanted);
562  if (p_cdio == NULL) {
563  BURN_ALLOC_MEM(msg, char, 4096);
564  os_errno = errno;
565  sprintf(msg, "Could not grab drive '%s'", d->devname);
567  0x00020003,
569  msg, os_errno, 0);
570  {ret = 0; goto ex;}
571  }
572  am_eff = (char *) cdio_get_arg(p_cdio, "access-mode");
573  if (strncmp(am_eff, "MMC_RDWR", 8) != 0) {
574  cdio_destroy(p_cdio);
575  if (!second_try) {
576  am_wanted = (burn_sg_open_o_excl & 63) ?
577  "MMC_RDWR" : "MMC_RDWR_EXCL";
578  second_try = 1;
579  goto try_to_open;
580  }
582  0x00020003,
584  "libcdio provides no MMC_RDWR access mode", 0, 0);
585  {ret = 0; goto ex;}
586  }
587 
588  d->p_cdio = p_cdio;
589  d->released = 0;
590  ret = 1;
591 ex:;
592  BURN_FREE_MEM(msg);
593  return ret;
594 }
595 
596 
597 /** PORTING: Is mainly about the call to sg_close_drive() and whether it
598  implements the demanded functionality.
599 */
600 /** Gives up the drive for SCSI commands and releases eventual access locks.
601  (Note: this is not physical tray locking.)
602 */
603 int sg_release(struct burn_drive *d)
604 {
605  if (d->p_cdio == NULL)
606  return 0;
607  sg_close_drive(d);
608  return 0;
609 }
610 
611 
612 /** Sends a SCSI command to the drive, receives reply and evaluates whether
613  the command succeeded or shall be retried or finally failed.
614  Returned SCSI errors shall not lead to a return value indicating failure.
615  The callers get notified by c->error. An SCSI failure which leads not to
616  a retry shall be notified via scsi_notify_error().
617  The Libburn_log_sg_commandS facility might be of help when problems with
618  a drive have to be examined. It shall stay disabled for normal use.
619  @return: 1 success , <=0 failure
620 */
621 int sg_issue_command(struct burn_drive *d, struct command *c)
622 {
623  int sense_valid = 0, i, timeout_ms, sense_len;
624  int key = 0, asc = 0, ascq = 0, done = 0;
625  time_t start_time;
626  driver_return_code_t i_status;
627  unsigned int dxfer_len;
628  static FILE *fp = NULL;
629  mmc_cdb_t cdb = {{0, }};
630  cdio_mmc_direction_t e_direction;
631  CdIo_t *p_cdio;
632  cdio_mmc_request_sense_t *sense_pt = NULL;
633 
634  c->error = 0;
635  memset(c->sense, 0, sizeof(c->sense));
636 
637  if (d->p_cdio == NULL) {
638  return 0;
639  }
640  p_cdio = (CdIo_t *) d->p_cdio;
641  if (burn_sg_log_scsi & 1) {
642  if (fp == NULL) {
643  fp= fopen("/tmp/libburn_sg_command_log", "a");
644  fprintf(fp,
645  "\n-----------------------------------------\n");
646  }
647  }
648  if (burn_sg_log_scsi & 3)
649  scsi_log_cmd(c,fp,0);
650 
651  memcpy(cdb.field, c->opcode, c->oplen);
652  if (c->dir == TO_DRIVE) {
653  dxfer_len = c->page->bytes;
654  e_direction = SCSI_MMC_DATA_WRITE;
655  } else if (c->dir == FROM_DRIVE) {
656  if (c->dxfer_len >= 0)
657  dxfer_len = c->dxfer_len;
658  else
659  dxfer_len = BUFFER_SIZE;
660  e_direction = SCSI_MMC_DATA_READ;
661  /* touch page so we can use valgrind */
662  memset(c->page->data, 0, BUFFER_SIZE);
663  } else {
664  dxfer_len = 0;
665  e_direction = SCSI_MMC_DATA_NONE;
666  }
667 
668  /* ts B90523 : Record effective transfer length request for debugging*/
669  c->dxfer_len = dxfer_len;
670 
671  /* retry-loop */
672  start_time = time(NULL);
673  if (c->timeout > 0)
674  timeout_ms = c->timeout;
675  else
676  timeout_ms = 200000;
677  for(i = 0; !done; i++) {
678 
679  memset(c->sense, 0, sizeof(c->sense));
680  c->start_time = burn_get_time(0);
681 
682  i_status = mmc_run_cmd(p_cdio, timeout_ms, &cdb, e_direction,
683  dxfer_len, c->page->data);
684 
685  c->end_time = burn_get_time(0);
686  sense_valid = mmc_last_cmd_sense(p_cdio, &sense_pt);
687  if (sense_valid >= 18) {
688  memcpy(c->sense, (unsigned char *) sense_pt,
689  (size_t) sense_valid >= sizeof(c->sense) ?
690  sizeof(c->sense) : (size_t) sense_valid );
691  spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
692  } else
693  key = asc = ascq = 0;
694  if (sense_pt != NULL)
695  free(sense_pt);
696 
697 /* Regrettably mmc_run_cmd() does not clearly distinguish between transport
698  failure and SCSI error reply.
699  This reaction here would be for transport failure:
700 
701  if (i_status != 0 && i_status != DRIVER_OP_ERROR) {
702  libdax_msgs_submit(libdax_messenger,
703  d->global_index, 0x0002010c,
704  LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
705  "Failed to transfer command to drive",
706  errno, 0);
707  sg_close_drive(d);
708  d->released = 1;
709  d->busy = BURN_DRIVE_IDLE;
710  c->error = 1;
711  return -1;
712  }
713 */
714 
715  if ((!sense_valid) || (key == 0 && asc == 0 && ascq == 0)) {
716  memset(c->sense, 0, sizeof(c->sense));
717  if (i_status != 0) { /* set dummy sense */
718  /*LOGICAL UNIT NOT READY,
719  CAUSE NOT REPORTABLE*/
720  c->sense[0] = 0x70; /*Fixed format sense data*/
721  c->sense[2] = 0x02;
722  c->sense[12] = 0x04;
723  done = 1;
724  }
725  }
726  if (key || asc || ascq)
727  sense_len = 18;
728  else
729  sense_len = 0;
730  done = scsi_eval_cmd_outcome(d, c, fp, c->sense, sense_len,
731  start_time, timeout_ms, i, 0);
732  if (d->cancel)
733  done = 1;
734  if (!done)
736 
737  } /* end of retry-loop */
738 
739  return 1;
740 }
741 
742 
743 /** Tries to obtain SCSI address parameters.
744  @return 1 is success , 0 is failure
745 */
746 int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
747  int *target_no, int *lun_no)
748 {
749  CdIo_t *p_cdio;
750  char *tuple;
751 
752  *bus_no = *host_no = *channel_no = *target_no = *lun_no = -1;
753 
754  p_cdio = cdio_open(path, DRIVER_DEVICE);
755  if (p_cdio == NULL)
756  return 0;
757 
758  /* Try whether a bus,host,channel,target,lun address tuple is
759  available */
760  tuple = (char *) cdio_get_arg(p_cdio, "scsi-tuple");
761  if (tuple != NULL) if (tuple[0]) {
762  sscanf(tuple, "%d,%d,%d,%d,%d",
763  bus_no, host_no, channel_no, target_no, lun_no);
764  }
765 
766  cdio_destroy(p_cdio);
767  return (*bus_no >= 0);
768 }
769 
770 
771 /** Tells whether a text is a persistent address as listed by the enumeration
772  functions.
773 */
774 int sg_is_enumerable_adr(char* adr)
775 {
777  int initialize = 1, ret;
778  char buf[64];
779 
780  while(1) {
781  ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
782  initialize = 0;
783  if (ret <= 0)
784  break;
785  if (strcmp(adr, buf) == 0) {
786  sg_give_next_adr(&idx, buf, sizeof(buf), -1);
787  return 1;
788  }
789  }
790  sg_give_next_adr(&idx, buf, sizeof(buf), -1);
791  return (0);
792 }
793 
794 
795 #ifdef __FreeBSD__
796 #define Libburn_guess_block_devicE 1
797 #endif
798 #ifdef __FreeBSD_kernel__
799 #define Libburn_guess_block_devicE 1
800 #endif
801 
802 #ifdef Libburn_guess_block_devicE
803 
804 /* ts B00115 */
805 /* The FreeBSD implementation of burn_os_is_2k_seekrw().
806  On FreeBSD there are no block devices.
807 */
808 static int freebsd_is_2k_seekrw(char *path, int flag)
809 {
810  struct stat stbuf;
811  char *spt;
812  int i, e;
813 
814  if (stat(path, &stbuf) == -1)
815  return 0;
816  if (S_ISREG(stbuf.st_mode))
817  return 1;
818  if (!S_ISCHR(stbuf.st_mode))
819  return 0;
820  spt = strrchr(path, '/');
821  if (spt == NULL)
822  spt = path;
823  else
824  spt++;
825  e = strlen(spt);
826  for (i = strlen(spt) - 1; i > 0; i--)
827  if (spt[i] >= '0' && spt[i] <= '9')
828  e = i;
829  if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
830  return 1;
831  if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
832  return 1;
833  if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
834  return 1;
835  if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
836  return 1;
837  if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
838  return 1;
839  if (strncmp(spt, "fla", e) == 0) /* Flash drive */
840  return 1;
841  return 0;
842 }
843 
844 #endif /* Libburn_guess_block_devicE */
845 
846 
847 /* Return 1 if the given path leads to a regular file or a device that can be
848  fseeked, read, and possibly written with 2 kB granularity.
849 */
850 int burn_os_is_2k_seekrw(char *path, int flag)
851 {
852 #ifdef Libburn_guess_block_devicE
853  return freebsd_is_2k_seekrw(path, flag);
854 #else
855  struct stat stbuf;
856 
857  if (stat(path, &stbuf) == -1)
858  return 0;
859  if (S_ISREG(stbuf.st_mode))
860  return 1;
861  if (S_ISBLK(stbuf.st_mode))
862  return 1;
863  return 0;
864 #endif /* ! Libburn_guess_block_devicE */
865 }
866 
867 
868 /** Estimate the potential payload capacity of a file address.
869  @param path The address of the file to be examined. If it does not
870  exist yet, then the directory will be inquired.
871  @param bytes The pointed value gets modified, but only if an estimation is
872  possible.
873  @return -2 = cannot perform necessary operations on file object
874  -1 = neither path nor dirname of path exist
875  0 = could not estimate size capacity of file object
876  1 = estimation has been made, bytes was set
877 */
878 int burn_os_stdio_capacity(char *path, off_t write_start, off_t *bytes)
879 {
880  struct stat stbuf;
881 
882 #ifdef Libburn_os_has_statvfS
883  struct statvfs vfsbuf;
884 #endif
885 
886  char *testpath = NULL, *cpt;
887  off_t add_size = 0;
888  int ret;
889 
890  BURN_ALLOC_MEM(testpath, char, 4096);
891  testpath[0] = 0;
892  if (stat(path, &stbuf) == -1) {
893  strcpy(testpath, path);
894  cpt = strrchr(testpath, '/');
895  if(cpt == NULL)
896  strcpy(testpath, ".");
897  else if(cpt == testpath)
898  testpath[1] = 0;
899  else
900  *cpt = 0;
901  if (stat(testpath, &stbuf) == -1)
902  {ret = -1; goto ex;}
903 
904 #ifdef __linux
905 
906  /* GNU/Linux specific determination of block device size */
907  } else if(S_ISBLK(stbuf.st_mode)) {
908  int open_mode = O_RDONLY | O_BINARY, fd;
909  long blocks;
910 
911  blocks = *bytes / 512;
912  fd = open(path, open_mode);
913  if (fd == -1)
914  {ret = -2; goto ex;}
915  ret = ioctl(fd, BLKGETSIZE, &blocks);
916  close(fd);
917  if (ret == -1)
918  {ret = -2; goto ex;}
919  *bytes = ((off_t) blocks) * (off_t) 512;
920 
921 #endif /* __linux */
922 
923 #ifdef Libburn_is_on_freebsD
924 
925  } else if(S_ISCHR(stbuf.st_mode)) {
926  int fd;
927 
928  fd = open(path, O_RDONLY | O_BINARY);
929  if (fd == -1)
930  {ret = -2; goto ex;}
931  ret = ioctl(fd, DIOCGMEDIASIZE, &add_size);
932  close(fd);
933  if (ret == -1)
934  {ret = -2; goto ex;}
935  *bytes = add_size;
936 
937 #endif /* Libburn_is_on_freebsD */
938 
939 #ifdef Libburn_is_on_solariS
940 
941  } else if(S_ISBLK(stbuf.st_mode)) {
942  int open_mode = O_RDONLY | O_BINARY, fd;
943 
944  fd = open(path, open_mode);
945  if (fd == -1)
946  {ret = -2; goto ex;}
947  *bytes = lseek(fd, 0, SEEK_END);
948  close(fd);
949  if (*bytes == -1) {
950  *bytes = 0;
951  {ret = 0; goto ex;}
952  }
953 
954 #endif /* Libburn_is_on_solariS */
955 
956  } else if(S_ISREG(stbuf.st_mode)) {
957  add_size = burn_sparse_file_addsize(write_start, &stbuf);
958  strcpy(testpath, path);
959  } else
960  {ret = 0; goto ex;}
961 
962  if (testpath[0]) {
963 
964 #ifdef Libburn_os_has_statvfS
965 
966  if (statvfs(testpath, &vfsbuf) == -1)
967  {ret = -2; goto ex;}
968  *bytes = add_size + ((off_t) vfsbuf.f_frsize) *
969  (off_t) vfsbuf.f_bavail;
970 
971 #else /* Libburn_os_has_statvfS */
972 
973  {ret = 0; goto ex;}
974 
975 #endif /* ! Libburn_os_has_stavtfS */
976 
977  }
978  ret = 1;
979 ex:;
980  BURN_FREE_MEM(testpath);
981  return ret;
982 }
983 
984 
985 /* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
986 
987 #ifdef Libburn_read_o_direcT
988 
989  /* No special O_DIRECT-like precautions are implemented here */
990 
991 #endif /* Libburn_read_o_direcT */
992 
993 
994 int burn_os_open_track_src(char *path, int open_flags, int flag)
995 {
996  int fd;
997 
998  fd = open(path, open_flags | O_BINARY);
999  return fd;
1000 }
1001 
1002 
1003 void *burn_os_alloc_buffer(size_t amount, int flag)
1004 {
1005  void *buf = NULL;
1006 
1007  buf = calloc(1, amount);
1008  return buf;
1009 }
1010 
1011 
1012 int burn_os_free_buffer(void *buffer, size_t amount, int flag)
1013 {
1014  if (buffer == NULL)
1015  return 0;
1016  free(buffer);
1017  return 1;
1018 }
1019 
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
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_HIGH
Definition: libdax_msgs.h:237
#define LIBDAX_MSGS_SEV_SORRY
Definition: libdax_msgs.h:176
static int sg_close_drive(struct burn_drive *d)
Definition: sg-libcdio.c:216
int sg_issue_command(struct burn_drive *d, struct command *c)
Definition: sg-libcdio.c:621
void * burn_os_alloc_buffer(size_t amount, int flag)
Definition: sg-libcdio.c:1003
int sg_is_enumerable_adr(char *adr)
Definition: sg-libcdio.c:774
int sg_shutdown(int flag)
Definition: sg-libcdio.c:402
int sg_grab(struct burn_drive *d)
Definition: sg-libcdio.c:547
int sg_dispose_drive(struct burn_drive *d, int flag)
Definition: sg-libcdio.c:417
#define O_BINARY
Definition: sg-libcdio.c:154
int burn_drive_resolve_link(char *path, char adr[], int *recursion_count, int flag)
Definition: drive.c:2057
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
Definition: sg-libcdio.c:1012
int burn_drive_is_banned(char *device_address)
Definition: drive.c:1723
struct libdax_msgs * libdax_messenger
Definition: init.c:42
int scsi_enumerate_drives(void)
Definition: sg-libcdio.c:476
int burn_os_open_track_src(char *path, int open_flags, int flag)
Definition: sg-libcdio.c:994
int burn_os_is_2k_seekrw(char *path, int flag)
Definition: sg-libcdio.c:850
int burn_sg_open_o_excl
Definition: init.c:53
int burn_os_stdio_capacity(char *path, off_t write_start, off_t *bytes)
Definition: sg-libcdio.c:878
int sg_initialize(char msg[1024], int flag)
Definition: sg-libcdio.c:368
int burn_sg_log_scsi
Definition: init.c:110
static int sg_give_next_adr_raw(burn_drive_enumerator_t *idx, char adr[], int adr_size, int initialize)
Definition: sg-libcdio.c:229
int sg_drive_is_open(struct burn_drive *d)
Definition: sg-libcdio.c:535
int sg_release(struct burn_drive *d)
Definition: sg-libcdio.c:603
static void enumerate_common(char *fname, char *cdio_name, int bus_no, int host_no, int channel_no, int target_no, int lun_no)
Definition: sg-libcdio.c:289
int sg_id_string(char msg[1024], int flag)
Definition: sg-libcdio.c:341
int sg_give_next_adr(burn_drive_enumerator_t *idx, char adr[], int adr_size, int initialize)
Definition: sg-libcdio.c:438
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, int *target_no, int *lun_no)
Definition: sg-libcdio.c:746
int scsi_log_cmd(struct command *c, void *fp_in, int flag)
Definition: spc.c:2002
void spc_register_retry(struct command *c)
Definition: spc.c:1775
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 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
int spc_decode_sense(unsigned char *sense, int senselen, int *key, int *asc, int *ascq)
Definition: spc.c:93
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
char * devname
Definition: transport.h:185
int bus_no
Definition: transport.h:180
volatile int cancel
Definition: transport.h:422
int(* drive_is_open)(struct burn_drive *)
Definition: transport.h:457
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
#define BUFFER_SIZE
Definition: transport.h:21