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-freebsd.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) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
5  Provided under GPL version 2 or later
6  and under FreeBSD license revised, i.e. without advertising clause.
7 */
8 
9 #ifdef HAVE_CONFIG_H
10 #include "../config.h"
11 #endif
12 
13 #include <errno.h>
14 #include <unistd.h>
15 #include <stdio.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <sys/ioctl.h>
20 #include <sys/file.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/poll.h>
24 #include <camlib.h>
25 #include <cam/scsi/scsi_message.h>
26 #include <cam/scsi/scsi_pass.h>
27 
28 #include <err.h> /* XXX */
29 
30 /* ts A70909 */
31 #include <sys/statvfs.h>
32 
33 /* ts B00121 */
34 #include <sys/disk.h> /* DIOCGMEDIASIZE */
35 
36 
37 /* ts B00326 : For use of CAM_PASS_ERR_RECOVER with ahci */
38 #define Libburn_for_freebsd_ahcI yes
39 
40 /* ts B00327 : for debugging of cam_send_cdb() failures
41  # define Libburn_ahci_verbouS yes
42 */
43 
44 /* ts B00327 : Apply CAM_PASS_ERR_RECOVER to drives even if not ahci
45  # define libburn_ahci_style_for_alL yes
46 */
47 
48 
49 #include "transport.h"
50 #include "drive.h"
51 #include "sg.h"
52 #include "spc.h"
53 #include "mmc.h"
54 #include "sbc.h"
55 #include "debug.h"
56 #include "toc.h"
57 #include "util.h"
58 #include "init.h"
59 
60 #include "libdax_msgs.h"
61 extern struct libdax_msgs *libdax_messenger;
62 
64  int fd;
65  union ccb ccb;
66  unsigned int i;
68 };
69 
70 static void enumerate_common(char *fname, int bus_no, int host_no,
71  int channel_no, int target_no, int lun_no);
72 
73 /* ts A51221 */
74 int burn_drive_is_banned(char *device_address);
75 
76 
77 /* ts A60821
78  debug: for tracing calls which might use open drive fds
79  or for catching SCSI usage of emulated drives. */
80 int mmc_function_spy(struct burn_drive *d, char * text);
81 
82 
83 /* ts B00113
84  Whether to log SCSI commands:
85  bit0= log in /tmp/libburn_sg_command_log
86  bit1= log to stderr
87  bit2= flush every line
88 */
89 extern int burn_sg_log_scsi;
90 
91 /* ts B00114 */
92 /* Storage object is in libburn/init.c
93  whether to strive for exclusive access to the drive
94 */
95 extern int burn_sg_open_o_excl;
96 
97 
98 /* ts A91227 */
99 /** Returns the id string of the SCSI transport adapter and eventually
100  needed operating system facilities.
101  This call is usable even if sg_initialize() was not called yet. In that
102  case a preliminary constant message might be issued if detailed info is
103  not available yet.
104  @param msg returns id string
105  @param flag unused yet, submit 0
106  @return 1 = success, <=0 = failure
107 */
108 int sg_id_string(char msg[1024], int flag)
109 {
110  strcpy(msg, "internal FreeBSD CAM adapter sg-freebsd");
111  return 1;
112 }
113 
114 
115 /* ts A91227 */
116 /** Performs global initialization of the SCSI transport adapter and eventually
117  needed operating system facilities. Checks for compatibility supporting
118  software components.
119  @param msg returns ids and/or error messages of eventual helpers
120  @param flag unused yet, submit 0
121  @return 1 = success, <=0 = failure
122 */
123 int sg_initialize(char msg[1024], int flag)
124 {
125  return sg_id_string(msg, 0);
126 }
127 
128 
129 /* ts A91227 */
130 /** Performs global finalization of the SCSI transport adapter and eventually
131  needed operating system facilities. Releases globally acquired resources.
132  @param flag unused yet, submit 0
133  @return 1 = success, <=0 = failure
134 */
135 int sg_shutdown(int flag)
136 {
137  return 1;
138 }
139 
140 
141 /** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
142  struct burn_drive which are defined in os-*.h.
143  The eventual initialization of those components was made underneath
144  scsi_enumerate_drives().
145  This will be called when a burn_drive gets disposed.
146  @param d the drive to be finalized
147  @param flag unused yet, submit 0
148  @return 1 = success, <=0 = failure
149 */
150 int sg_dispose_drive(struct burn_drive *d, int flag)
151 {
152  return 1;
153 }
154 
155 
156 /* ts A61021 : Moved most code from scsi_enumerate_drives under
157  sg_give_next_adr() */
158 /* Some helper functions for scsi_give_next_adr() */
159 
161 {
162  struct burn_drive_enumeration_state *idx;
163  int bufsize;
164 
165  idx = calloc(1, sizeof(*idx));
166  if (idx == NULL) {
167  warnx("cannot allocate memory for enumerator");
168  return -1;
169  }
170  idx->skip_device = 0;
171 
172  if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
173  warn("could not open %s", XPT_DEVICE);
174  free(idx);
175  idx = NULL;
176  return -1;
177  }
178 
179  memset(&(idx->ccb), 0, sizeof(union ccb));
180 
181  idx->ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
182  idx->ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
183  idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
184 
185  idx->ccb.ccb_h.func_code = XPT_DEV_MATCH;
186  bufsize = sizeof(struct dev_match_result) * 100;
187  idx->ccb.cdm.match_buf_len = bufsize;
188  idx->ccb.cdm.matches = (struct dev_match_result *) calloc(1, bufsize);
189  if (idx->ccb.cdm.matches == NULL) {
190  warnx("cannot allocate memory for matches");
191  close(idx->fd);
192  free(idx);
193  return -1;
194  }
195  idx->ccb.cdm.num_matches = 0;
196  idx->i = idx->ccb.cdm.num_matches; /* to trigger buffer load */
197 
198  /*
199  * We fetch all nodes, since we display most of them in the default
200  * case, and all in the verbose case.
201  */
202  idx->ccb.cdm.num_patterns = 0;
203  idx->ccb.cdm.pattern_buf_len = 0;
204 
205  *idx_ = idx;
206 
207  return 1;
208 }
209 
211 {
212  struct burn_drive_enumeration_state *idx = *idx_;
213 
214  if(idx->fd != -1)
215  close(idx->fd);
216 
217  free(idx->ccb.cdm.matches);
218  free(idx);
219 
220  *idx_ = NULL;
221 }
222 
224 {
225  struct burn_drive_enumeration_state *idx = *idx_;
226 
227  /*
228  * We do the ioctl multiple times if necessary, in case there are
229  * more than 100 nodes in the EDT.
230  */
231  if (ioctl(idx->fd, CAMIOCOMMAND, &(idx->ccb)) == -1) {
232  warn("error sending CAMIOCOMMAND ioctl");
233  return -1;
234  }
235 
236  if ((idx->ccb.ccb_h.status != CAM_REQ_CMP)
237  || ((idx->ccb.cdm.status != CAM_DEV_MATCH_LAST)
238  && (idx->ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
239  warnx("got CAM error %#x, CDM error %d\n",
240  idx->ccb.ccb_h.status, idx->ccb.cdm.status);
241  return -1;
242  }
243  return 1;
244 }
245 
246 
247 /** Returns the next index object state and the next enumerated drive address.
248  @param idx An opaque handle. Make no own theories about it.
249  @param adr Takes the reply
250  @param adr_size Gives maximum size of reply including final 0
251  @param initialize 1 = start new,
252  0 = continue, use no other values for now
253  -1 = finish
254  @return 1 = reply is a valid address , 0 = no further address available
255  -1 = severe error (e.g. adr_size too small)
256 */
258  char adr[], int adr_size, int initialize)
259 {
260  struct burn_drive_enumeration_state *idx;
261  int ret;
262 
263  if (initialize == 1) {
264  ret = sg_init_enumerator(idx_);
265  if (ret<=0)
266  return ret;
267  } else if (initialize == -1) {
268  sg_destroy_enumerator(idx_);
269  return 0;
270  }
271 
272  idx = *idx_;
273 
274  do {
275  if (idx->i >= idx->ccb.cdm.num_matches) {
276  ret = sg_next_enumeration_buffer(idx_);
277  if (ret<=0)
278  return -1;
279  idx->i = 0;
280  } else
281  (idx->i)++;
282 
283  while (idx->i < idx->ccb.cdm.num_matches) {
284  switch (idx->ccb.cdm.matches[idx->i].type) {
285  case DEV_MATCH_BUS:
286  break;
287  case DEV_MATCH_DEVICE: {
288  struct device_match_result* result;
289 
290  result = &(idx->ccb.cdm.matches[idx->i].result.device_result);
291  if (result->flags & DEV_RESULT_UNCONFIGURED)
292  idx->skip_device = 1;
293  else
294  idx->skip_device = 0;
295  break;
296  }
297  case DEV_MATCH_PERIPH: {
298  struct periph_match_result* result;
299 
300  result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
301 /* ts B00112 : we really want only "cd" devices.
302 
303  if (idx->skip_device ||
304  strcmp(result->periph_name, "pass") == 0)
305  break;
306 */
307  if (idx->skip_device ||
308  strcmp(result->periph_name, "cd") != 0)
309  break;
310  ret = snprintf(adr, adr_size, "/dev/%s%d",
311  result->periph_name, result->unit_number);
312  if(ret >= adr_size)
313  return -1;
314 
315  /* Found next enumerable address */
316  return 1;
317 
318  }
319  default:
320  /* fprintf(stderr, "unknown match type\n"); */
321  break;
322  }
323  (idx->i)++;
324  }
325  } while ((idx->ccb.ccb_h.status == CAM_REQ_CMP)
326  && (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE));
327 
328  return 0;
329 }
330 
331 
332 int sg_is_enumerable_adr(char* adr)
333 {
335  int ret;
336  char buf[64];
337 
338  ret = sg_init_enumerator(&idx);
339  if (ret <= 0)
340  return 0;
341  while(1) {
342  ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
343  if (ret <= 0)
344  break;
345  if (strcmp(adr, buf) == 0) {
346  sg_destroy_enumerator(&idx);
347  return 1;
348  }
349  }
350  sg_destroy_enumerator(&idx);
351  return (0);
352 }
353 
354 
355 /** Try to obtain SCSI address parameters.
356  @return 1 is success , 0 is failure
357 */
358 int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
359  int *target_no, int *lun_no)
360 {
362  int ret;
363  char buf[64];
364  struct periph_match_result* result;
365 
366  ret = sg_init_enumerator(&idx);
367  if (ret <= 0)
368  return 0;
369  while(1) {
370  ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
371  if (ret <= 0)
372  break;
373  if (strcmp(path, buf) == 0) {
374  result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
375  *bus_no = result->path_id;
376  *host_no = result->path_id;
377  *channel_no = 0;
378  *target_no = result->target_id;
379  *lun_no = result->target_lun;
380  sg_destroy_enumerator(&idx);
381  return 1;
382  }
383  }
384  sg_destroy_enumerator(&idx);
385  return (0);
386 }
387 
388 
389 int sg_close_drive(struct burn_drive * d)
390 {
391  if (d->cam != NULL) {
392  cam_close_device(d->cam);
393  d->cam = NULL;
394  }
395  if (d->lock_fd > 0) {
396  close(d->lock_fd);
397  d->lock_fd = -1;
398  }
399  return 0;
400 }
401 
403 {
404  return (d->cam != NULL);
405 }
406 
408 {
410  int ret;
411  char buf[64];
412  struct periph_match_result* result;
413 
414  ret = sg_init_enumerator(&idx);
415  if (ret <= 0)
416  return 0;
417  while(1) {
418  ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
419  if (ret <= 0)
420  break;
421  if (burn_drive_is_banned(buf))
422  continue;
423  result = &idx->ccb.cdm.matches[idx->i].result.periph_result;
424  enumerate_common(buf, result->path_id, result->path_id,
425  0, result->target_id,
426  result->target_lun);
427  }
428  sg_destroy_enumerator(&idx);
429 
430  return 1;
431 }
432 
433 
434 #ifdef Scsi_freebsd_make_own_enumeratE
435 
436 /* ts A61021: The old version which mixes SCSI and operating system adapter
437 */
438 static void enumerate_common(char *fname, int bus_no, int host_no,
439  int channel_no, int target_no, int lun_no)
440 {
441  struct burn_drive *t;
442  struct burn_drive out;
443 
444  /* Initialize pointers to managed memory */
445  out.devname = NULL;
446  out.idata = NULL;
447  out.mdata = NULL;
448 
449  /* ts A60923 */
450  out.bus_no = bus_no;
451  out.host = host_no;
452  out.id = target_no;
453  out.channel = channel_no;
454  out.lun = lun_no;
455 
456  out.devname = strdup(fname);
457  if (out.devname == NULL)
458  goto could_not_allocate;
459 
460  out.cam = NULL;
461  out.lock_fd = -1;
462  out.is_ahci = 0;
463 
464  out.start_lba= -2000000000;
465  out.end_lba= -2000000000;
466  out.read_atip = mmc_read_atip;
467 
468  out.grab = sg_grab;
469  out.release = sg_release;
470  out.drive_is_open= sg_drive_is_open;
471  out.issue_command = sg_issue_command;
472  out.getcaps = spc_getcaps;
473  out.released = 1;
474  out.status = BURN_DISC_UNREADY;
475 
476  out.eject = sbc_eject;
477  out.load = sbc_load;
478  out.lock = spc_prevent;
479  out.unlock = spc_allow;
480  out.read_disc_info = spc_sense_write_params;
481  out.get_erase_progress = spc_get_erase_progress;
482  out.test_unit_ready = spc_test_unit_ready;
483  out.probe_write_modes = spc_probe_write_modes;
484  out.read_toc = mmc_read_toc;
485  out.write = mmc_write;
486  out.erase = mmc_erase;
487  out.read_cd = mmc_read_cd;
488  out.perform_opc = mmc_perform_opc;
489  out.set_speed = mmc_set_speed;
490  out.send_parameters = spc_select_error_params;
491  out.send_write_parameters = spc_select_write_params;
492  out.send_cue_sheet = mmc_send_cue_sheet;
493  out.sync_cache = mmc_sync_cache;
494  out.get_nwa = mmc_get_nwa;
495  out.close_disc = mmc_close_disc;
496  out.close_session = mmc_close_session;
497  out.close_track_session = mmc_close;
498  out.read_buffer_capacity = mmc_read_buffer_capacity;
499  out.idata = calloc(1, sizeof(struct burn_scsi_inquiry_data));
500  out.idata->valid = 0;
501  out.mdata = calloc(1, sizeof(struct scsi_mode_data));
502  if (out.idata == NULL || out.mdata == NULL) {
503 could_not_allocate:;
504  libdax_msgs_submit(libdax_messenger, -1, 0x00020108,
506  "Could not allocate new drive object", 0, 0);
507  if (out.devname != NULL)
508  free(out.devname);
509  out.devname = NULL;
510  if (out.idata != NULL)
511  free(out.idata);
512  out.idata = NULL;
513  if (out.mdata != NULL)
514  free(out.mdata);
515  out.mdata = NULL;
516  return;
517  }
518  out.mdata->p2a_valid = 0;
519  memset(&out.params, 0, sizeof(struct params));
520  t = burn_drive_register(&out);
521 
522 /* ts A60821
523  <<< debug: for tracing calls which might use open drive fds */
524  mmc_function_spy(NULL, "enumerate_common : -------- doing grab");
525 
526 /* try to get the drive info */
527  if (t->grab(t)) {
528  t->getcaps(t);
529  t->unlock(t);
530  t->released = 1;
531  }
532 
533 /* ts A60821
534  <<< debug: for tracing calls which might use open drive fds */
535  mmc_function_spy(NULL, "enumerate_common : ----- would release ");
536 
537 }
538 
539 #else /* Scsi_freebsd_make_own_enumeratE */
540 
541 /* The new, more concise version of enumerate_common */
542 static void enumerate_common(char *fname, int bus_no, int host_no,
543  int channel_no, int target_no, int lun_no)
544 {
545  int ret;
546  struct burn_drive out;
547 
548  /* General libburn drive setup */
549  burn_setup_drive(&out, fname);
550 
551  /* This transport adapter uses SCSI-family commands and models
552  (seems the adapter would know better than its boss, if ever) */
553  ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
554  target_no, lun_no, 0);
555  if (ret<=0)
556  return;
557 
558  /* Operating system adapter is CAM */
559  /* Adapter specific handles and data */
560  out.cam = NULL;
561  out.lock_fd = -1;
562  out.is_ahci = 0;
563 
564  /* Adapter specific functions */
565  out.grab = sg_grab;
566  out.release = sg_release;
569 
570  /* Finally register drive and inquire drive information */
572 }
573 
574 #endif /* ! Scsi_freebsd_make_own_enumeratE */
575 
576 
577 /* Lock the inode associated to dev_fd and the inode associated to devname.
578  Return OS errno, number of pass device of dev_fd, locked fd to devname,
579  error message.
580  A return value of > 0 means success, <= 0 means failure.
581 */
582 static int freebsd_dev_lock(int dev_fd, char *devname,
583  int *os_errno, int *pass_dev_no, int *lock_fd, char msg[4096],
584  int flag)
585 {
586  int lock_denied = 0, fd_stbuf_valid, name_stbuf_valid, i, pass_l = 100;
587  int max_retry = 3, tries = 0;
588  struct stat fd_stbuf, name_stbuf;
589  char pass_name[16], *lock_name;
590 
591  *os_errno = 0;
592  *pass_dev_no = -1;
593  *lock_fd = -1;
594  msg[0] = 0;
595 
596  fd_stbuf_valid = !fstat(dev_fd, &fd_stbuf);
597 
598  /* Try to find name of pass device by inode number */
599  lock_name = (char *) "effective device";
600  if(fd_stbuf_valid) {
601  for (i = 0; i < pass_l; i++) {
602  sprintf(pass_name, "/dev/pass%d", i);
603  if (stat(pass_name, &name_stbuf) != -1)
604  if(fd_stbuf.st_ino == name_stbuf.st_ino &&
605  fd_stbuf.st_dev == name_stbuf.st_dev)
606  break;
607  }
608  if (i < pass_l) {
609  lock_name = pass_name;
610  *pass_dev_no = i;
611  }
612  }
613 
614  name_stbuf_valid = !stat(devname, &name_stbuf);
615  for (tries= 0; tries <= max_retry; tries++) {
616  lock_denied = flock(dev_fd, LOCK_EX | LOCK_NB);
617  *os_errno = errno;
618  if (lock_denied) {
619  if (errno == EAGAIN && tries < max_retry) {
620  /* <<< debugging
621  fprintf(stderr,
622  "\nlibcdio_DEBUG: EAGAIN pass, tries= %d\n",
623  tries);
624  */
625  usleep(2000000);
626  continue;
627  }
628  sprintf(msg,
629  "Device busy. flock(LOCK_EX) failed on %s of %s",
630  strlen(lock_name) > 2000 || *pass_dev_no < 0 ?
631  "pass device" : lock_name,
632  strlen(devname) > 2000 ? "drive" : devname);
633  return 0;
634  }
635  break;
636  }
637 
638  /*
639  fprintf(stderr, "libburn_DEBUG: flock obtained on %s of %s\n",
640  lock_name, devname);
641  */
642 
643  /* Eventually lock the official device node too */
644  if (fd_stbuf_valid && name_stbuf_valid &&
645  (fd_stbuf.st_ino != name_stbuf.st_ino ||
646  fd_stbuf.st_dev != name_stbuf.st_dev)) {
647 
648  *lock_fd = open(devname, O_RDONLY);
649  if (*lock_fd == 0) {
650  close(*lock_fd);
651  *lock_fd = -1;
652  } if (*lock_fd > 0) {
653  for (tries = 0; tries <= max_retry; tries++) {
654  lock_denied =
655  flock(*lock_fd, LOCK_EX | LOCK_NB);
656  if (lock_denied) {
657  if (errno == EAGAIN &&
658  tries < max_retry) {
659  /* <<< debugging
660  fprintf(stderr,
661  "\nlibcdio_DEBUG: EAGAIN dev, tries= %d\n",
662  tries);
663  */
664 
665  usleep(2000000);
666  continue;
667  }
668  close(*lock_fd);
669  *lock_fd = -1;
670  sprintf(msg,
671  "Device busy. flock(LOCK_EX) failed on %s",
672  strlen(devname) > 4000 ? "drive" : devname);
673  return 0;
674  }
675  break;
676  }
677  }
678 
679 /*
680  fprintf(stderr, "libburn_DEBUG: flock obtained on %s\n",
681  devname);
682 */
683 
684  }
685  return 1;
686 }
687 
688 
689 static int sg_lock(struct burn_drive *d, int flag)
690 {
691  int ret, os_errno, pass_dev_no = -1, flock_fd = -1;
692  char *msg = NULL;
693 
694  BURN_ALLOC_MEM(msg, char, 4096);
695  ret = freebsd_dev_lock(d->cam->fd, d->devname,
696  &os_errno, &pass_dev_no, &flock_fd, msg, 0);
697  if (ret <= 0) {
699  0x00020008,
701  msg, os_errno, 0);
702  sg_close_drive(d);
703  {ret = 0; goto ex;}
704  }
705  if (d->lock_fd > 0)
706  close(d->lock_fd);
707  d->lock_fd = flock_fd;
708  ret = 1;
709 ex:;
710  BURN_FREE_MEM(msg);
711  return ret;
712 }
713 
714 
715 int sg_grab(struct burn_drive *d)
716 {
717  struct cam_device *cam;
718  char path_string[80];
719 
720  if (mmc_function_spy(d, "sg_grab") <= 0)
721  return 0;
722 
723  if (burn_drive_is_open(d)) {
724  d->released = 0;
725  return 1;
726  }
727 
728  cam = cam_open_device(d->devname, O_RDWR);
729  if (cam == NULL) {
731  0x00020003,
733  "Could not grab drive", errno, 0);
734  return 0;
735  }
736  d->cam = cam;
737  if (burn_sg_open_o_excl & 63)
738  if (sg_lock(d, 0) <= 0)
739  return 0;
740  fcntl(cam->fd, F_SETOWN, getpid());
741 
742  cam_path_string(d->cam, path_string, sizeof(path_string));
743 
744 #ifdef Libburn_ahci_verbouS
745  fprintf(stderr, "libburn_EXPERIMENTAL: CAM path = %s\n", path_string);
746 #endif
747 
748  if (strstr(path_string, ":ahcich") != NULL)
749  d->is_ahci = 1;
750  else
751  d->is_ahci = -1;
752 
753  d->released = 0;
754  return 1;
755 }
756 
757 
758 /*
759  non zero return means you still have the drive and it's not
760  in a state to be released? (is that even possible?)
761 */
762 
763 int sg_release(struct burn_drive *d)
764 {
765  if (mmc_function_spy(d, "sg_release") <= 0)
766  return 0;
767 
768  if (d->cam == NULL)
769  return 0;
770 
771  mmc_function_spy(NULL, "sg_release ----------- closing.");
772 
773  sg_close_drive(d);
774  d->released = 1;
775  return 0;
776 }
777 
778 int sg_issue_command(struct burn_drive *d, struct command *c)
779 {
780  int done = 0, err, sense_len = 0, ret, ignore_error, i;
781  int cam_pass_err_recover = 0, key, asc, ascq, timeout_ms;
782  union ccb *ccb;
783  static FILE *fp = NULL;
784  time_t start_time;
785 
786  mmc_function_spy(NULL, "sg_issue_command");
787 
788  c->error = 0;
789  memset(c->sense, 0, sizeof(c->sense));
790 
791  if (d->cam == NULL)
792  return 0;
793  if (burn_sg_log_scsi & 1) {
794  if (fp == NULL) {
795  fp= fopen("/tmp/libburn_sg_command_log", "a");
796  fprintf(fp,
797  "\n-----------------------------------------\n");
798  }
799  }
800  if (burn_sg_log_scsi & 3)
801  scsi_log_cmd(c,fp,0);
802 
803  c->error = 0;
804  if (c->timeout > 0)
805  timeout_ms = c->timeout;
806  else
807  timeout_ms = 200000;
808 
809  ccb = cam_getccb(d->cam);
810  cam_fill_csio(&ccb->csio,
811  1, /* retries */
812  NULL, /* cbfncp */
813  CAM_DEV_QFRZDIS, /* flags */
814  MSG_SIMPLE_Q_TAG, /* tag_action */
815  NULL, /* data_ptr */
816  0, /* dxfer_len */
817  sizeof (ccb->csio.sense_data), /* sense_len */
818  0, /* cdb_len */
819  timeout_ms); /* timeout */
820  switch (c->dir) {
821  case TO_DRIVE:
822  ccb->csio.ccb_h.flags |= CAM_DIR_OUT;
823  break;
824  case FROM_DRIVE:
825  ccb->csio.ccb_h.flags |= CAM_DIR_IN;
826  break;
827  case NO_TRANSFER:
828  ccb->csio.ccb_h.flags |= CAM_DIR_NONE;
829  break;
830  }
831 
832 #ifdef Libburn_for_freebsd_ahcI
833  /* ts B00325 : Advise by Alexander Motin */
834  /* Runs well on 8-STABLE (23 Mar 2003)
835  But on 8-RELEASE cam_send_ccb() returns non-zero with errno 6
836  on eject. Long lasting TEST UNIT READY cycles break with
837  errno 16.
838  */
839 #ifdef Libburn_ahci_style_for_alL
840  {
841 #else
842  if (d->is_ahci > 0) {
843 #endif
844  ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
845  cam_pass_err_recover = 1;
846  }
847 #endif /* Libburn_for_freebsd_ahcI */
848 
849  ccb->csio.cdb_len = c->oplen;
850  memcpy(&ccb->csio.cdb_io.cdb_bytes, &c->opcode, c->oplen);
851 
852  if (c->page) {
853  ccb->csio.data_ptr = c->page->data;
854  if (c->dir == FROM_DRIVE) {
855 
856  /* ts A90430 : Ticket 148 , by jwehle :
857  "On ... FreeBSD 6.4 which has a usb memory reader in
858  addition to a ATAPI DVD burner sg_issue_command
859  will hang while the SCSI bus is being scanned"
860  */
861  if (c->dxfer_len >= 0)
862  ccb->csio.dxfer_len = c->dxfer_len;
863  else
864  ccb->csio.dxfer_len = BUFFER_SIZE;
865 
866 /* touch page so we can use valgrind */
867  memset(c->page->data, 0, BUFFER_SIZE);
868  } else {
869  ccb->csio.dxfer_len = c->page->bytes;
870  }
871  } else {
872  ccb->csio.data_ptr = NULL;
873  ccb->csio.dxfer_len = 0;
874  }
875 
876  /* ts B90523 : Record effective transfer length request for debugging*/
877  c->dxfer_len = ccb->csio.dxfer_len;
878 
879  start_time = time(NULL);
880  for (i = 0; !done; i++) {
881 
882  memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data));
883  memset(c->sense, 0, sizeof(c->sense));
884  c->start_time = burn_get_time(0);
885 
886  err = cam_send_ccb(d->cam, ccb);
887 
888  c->end_time = burn_get_time(0);
889  ignore_error = sense_len = 0;
890  /* ts B00325 : CAM_AUTOSNS_VALID advised by Alexander Motin */
891  if (ccb->ccb_h.status & CAM_AUTOSNS_VALID) {
892  /* ts B00110 */
893  /* Better curb sense_len */
894  sense_len = ccb->csio.sense_len;
895  if (sense_len > (int) sizeof(c->sense))
896  sense_len = sizeof(c->sense);
897  memcpy(c->sense, &ccb->csio.sense_data, sense_len);
898  spc_decode_sense(c->sense, sense_len,
899  &key, &asc, &ascq);
900  if (sense_len >= 14 && cam_pass_err_recover && key)
901  ignore_error = 1;
902  }
903 
904  if (err == -1 && cam_pass_err_recover && ! ignore_error) {
905 
906 #ifdef Libburn_ahci_verbouS
907  fprintf(stderr, "libburn_EXPERIMENTAL: errno = %d . cam_errbuf = '%s'\n", errno, cam_errbuf);
908 #endif
909 
910  if (errno == ENXIO && c->opcode[0] != 0) {
911  /* Operations on empty or ejected tray */
912  /* MEDIUM NOT PRESENT */
913 
914 #ifdef Libburn_ahci_verbouS
915  fprintf(stderr, "libburn_EXPERIMENTAL: Emulating [2,3A,00] MEDIUM NOT PRESENT\n");
916 #endif
917 
918  c->sense[0] = 0x70; /*Fixed format sense data*/
919  c->sense[2] = 0x02;
920  c->sense[12] = 0x3A;
921  c->sense[13] = 0x00;
922  sense_len = 14;
923  ignore_error = 1;
924  } else if (c->opcode[0] == 0 &&
925  (errno == EBUSY || errno == ENXIO)) {
926  /* Timeout of TEST UNIT READY loop */
927  /* Inquiries while tray is being loaded */
928  /*LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE*/
929 
930 #ifdef Libburn_ahci_verbouS
931  fprintf(stderr, "libburn_EXPERIMENTAL: Emulating [2,04,00] LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE\n");
932 #endif
933 
934  c->sense[0] = 0x70; /*Fixed format sense data*/
935  c->sense[2] = 0x02;
936  c->sense[12] = 0x04;
937  c->sense[13] = 0x00;
938  sense_len = 14;
939  ignore_error = 1;
940  } else if (errno == EINVAL) {
941  /* Inappropriate MODE SENSE */
942  /* INVALID FIELD IN CDB */
943 
944 #ifdef Libburn_ahci_verbouS
945  fprintf(stderr, "libburn_EXPERIMENTAL: Emulating [5,24,00] INVALID FIELD IN CDB\n");
946 #endif
947 
948  c->sense[0] = 0x70; /*Fixed format sense data*/
949  c->sense[2] = 0x05;
950  c->sense[12] = 0x24;
951  c->sense[13] = 0x00;
952  sense_len = 14;
953  ignore_error = 1;
954  }
955  }
956 
957  if (err == -1 && !ignore_error) {
959  d->global_index, 0x0002010c,
961  "Failed to transfer command to drive",
962  errno, 0);
963  sg_close_drive(d);
964  d->released = 1;
965  d->busy = BURN_DRIVE_IDLE;
966  c->error = 1;
967  {ret = -1; goto ex;}
968  }
969  /* XXX */
970 
971  if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
972  if (sense_len < 14) {
973  /*LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE*/
974 
975 #ifdef Libburn_ahci_verbouS
976  fprintf(stderr, "libburn_EXPERIMENTAL: CAM_STATUS= %d .Emulating [2,04,00] LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE\n", (ccb->ccb_h.status & CAM_STATUS_MASK));
977 #endif
978 
979  c->sense[0] = 0x70; /*Fixed format sense data*/
980  c->sense[2] = 0x02;
981  c->sense[12] = 0x04;
982  c->sense[13] = 0x00;
983  done = 1;
984  }
985  }
986  done = scsi_eval_cmd_outcome(d, c, fp, c->sense,
987  sense_len, start_time,
988  timeout_ms, i, !!ignore_error);
989  if (d->cancel)
990  done = 1;
991  if (!done)
993  } while (!done);
994  ret = 1;
995 ex:;
996  cam_freeccb(ccb);
997  return ret;
998 }
999 
1000 
1001 /* ts B00115 */
1002 /* Return 1 if the given path leads to a regular file or a device that can be
1003  fseeked, read and eventually written with 2 kB granularity.
1004 */
1005 int burn_os_is_2k_seekrw(char *path, int flag)
1006 {
1007  struct stat stbuf;
1008 #ifdef Libburn_DIOCGMEDIASIZE_ISBLK
1009  int fd, ret;
1010  off_t add_size;
1011 #else
1012  char *spt;
1013  int i, e;
1014 #endif /* ! Libburn_DIOCGMEDIASIZE_ISBLK */
1015 
1016  if (stat(path, &stbuf) == -1)
1017  return 0;
1018  if (S_ISREG(stbuf.st_mode))
1019  return 1;
1020  if (!S_ISCHR(stbuf.st_mode))
1021  return 0;
1022 
1023 #ifdef Libburn_DIOCGMEDIASIZE_ISBLK
1024 
1025  /* If it throws no error with DIOCGMEDIASIZE then it is a
1026  'block device'
1027  */
1028  fd = open(path, O_RDONLY);
1029  if (fd == -1)
1030  return 0;
1031  ret = ioctl(fd, DIOCGMEDIASIZE, &add_size);
1032  close(fd);
1033 
1034  return (ret != -1);
1035 
1036 #else /* Libburn_DIOCGMEDIASIZE_ISBLK */
1037 
1038  spt = strrchr(path, '/');
1039  if (spt == NULL)
1040  spt = path;
1041  else
1042  spt++;
1043  e = strlen(spt);
1044  for (i = strlen(spt) - 1; i > 0; i--)
1045  if (spt[i] >= '0' && spt[i] <= '9')
1046  e = i;
1047  if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
1048  return 1;
1049  if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
1050  return 1;
1051  if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
1052  return 1;
1053  if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
1054  return 1;
1055  if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
1056  return 1;
1057  if (strncmp(spt, "fla", e) == 0) /* Flash drive */
1058  return 1;
1059  return 0;
1060 
1061 #endif /* ! Libburn_DIOCGMEDIASIZE_ISBLK */
1062 
1063 }
1064 
1065 
1066 /* ts A70909 */
1067 /** Estimate the potential payload capacity of a file address.
1068  @param path The address of the file to be examined. If it does not
1069  exist yet, then the directory will be inquired.
1070  @param bytes This value gets modified if an estimation is possible
1071  @return -2 = cannot perform necessary operations on file object
1072  -1 = neither path nor dirname of path exist
1073  0 = could not estimate size capacity of file object
1074  1 = estimation has been made, bytes was set
1075 */
1076 int burn_os_stdio_capacity(char *path, off_t write_start, off_t *bytes)
1077 {
1078  struct stat stbuf;
1079  struct statvfs vfsbuf;
1080  char *testpath = NULL, *cpt;
1081  off_t add_size = 0;
1082  int fd, ret;
1083 
1084  BURN_ALLOC_MEM(testpath, char, 4096);
1085  testpath[0] = 0;
1086  if (stat(path, &stbuf) == -1) {
1087  strcpy(testpath, path);
1088  cpt = strrchr(testpath, '/');
1089  if(cpt == NULL)
1090  strcpy(testpath, ".");
1091  else if(cpt == testpath)
1092  testpath[1] = 0;
1093  else
1094  *cpt = 0;
1095  if (stat(testpath, &stbuf) == -1)
1096  {ret = -1; goto ex;}
1097 
1098 #ifdef Libburn_if_this_was_linuX
1099 
1100  } else if(S_ISBLK(stbuf.st_mode)) {
1101  int open_mode = O_RDWR, fd, ret;
1102  long blocks;
1103 
1104  blocks = *bytes / 512;
1106  open_mode |= O_EXCL;
1107  fd = open(path, open_mode);
1108  if (fd == -1)
1109  {ret = -2; goto ex;}
1110  ret = ioctl(fd, BLKGETSIZE, &blocks);
1111  close(fd);
1112  if (ret == -1)
1113  {ret = -2; goto ex;}
1114  *bytes = ((off_t) blocks) * (off_t) 512;
1115 
1116 #endif /* Libburn_if_this_was_linuX */
1117 
1118 
1119  } else if(S_ISCHR(stbuf.st_mode)) {
1120  fd = open(path, O_RDONLY);
1121  if (fd == -1)
1122  {ret = -2; goto ex;}
1123  ret = ioctl(fd, DIOCGMEDIASIZE, &add_size);
1124  close(fd);
1125  if (ret == -1)
1126  {ret = -2; goto ex;}
1127  *bytes = add_size;
1128  } else if(S_ISREG(stbuf.st_mode)) {
1129  add_size = burn_sparse_file_addsize(write_start, &stbuf);
1130  strcpy(testpath, path);
1131  } else
1132  {ret = 0; goto ex;}
1133 
1134  if (testpath[0]) {
1135  if (statvfs(testpath, &vfsbuf) == -1)
1136  {ret = -2; goto ex;}
1137  *bytes = add_size + ((off_t) vfsbuf.f_frsize) *
1138  (off_t) vfsbuf.f_bavail;
1139  }
1140  ret = 1;
1141 ex:
1142  BURN_FREE_MEM(testpath);
1143  return ret;
1144 }
1145 
1146 
1147 /* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
1148 
1149 #ifdef Libburn_read_o_direcT
1150 
1151  /* No special O_DIRECT-like precautions are implemented here */
1152 
1153 #endif /* Libburn_read_o_direcT */
1154 
1155 
1156 int burn_os_open_track_src(char *path, int open_flags, int flag)
1157 {
1158  int fd;
1159 
1160  fd = open(path, open_flags);
1161  return fd;
1162 }
1163 
1164 
1165 void *burn_os_alloc_buffer(size_t amount, int flag)
1166 {
1167  void *buf = NULL;
1168 
1169  buf = calloc(1, amount);
1170  return buf;
1171 }
1172 
1173 
1174 int burn_os_free_buffer(void *buffer, size_t amount, int flag)
1175 {
1176  if (buffer == NULL)
1177  return 0;
1178  free(buffer);
1179  return 1;
1180 }
1181 
struct burn_drive * burn_drive_register(struct burn_drive *d)
Definition: drive.c:540
int burn_drive_is_open(struct burn_drive *d)
Definition: drive.c:167
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
@ BURN_DISC_UNREADY
Definition: libburn.h:234
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_FATAL
Definition: libdax_msgs.h:217
#define LIBDAX_MSGS_PRIO_HIGH
Definition: libdax_msgs.h:237
#define LIBDAX_MSGS_SEV_SORRY
Definition: libdax_msgs.h:176
void mmc_close_session(struct burn_write_opts *o)
Definition: mmc.c:579
int mmc_read_cd(struct burn_drive *d, int start, int len, int sec_type, int main_ch, const struct burn_read_opts *o, struct buffer *buf, int flag)
Definition: mmc.c:2634
int mmc_read_buffer_capacity(struct burn_drive *d)
Definition: mmc.c:3607
void mmc_read_atip(struct burn_drive *d)
Definition: mmc.c:2320
void mmc_read_toc(struct burn_drive *d)
Definition: mmc.c:1764
void mmc_close_disc(struct burn_write_opts *o)
Definition: mmc.c:558
int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
Definition: mmc.c:454
void mmc_close(struct burn_drive *d, int session, int track)
Definition: mmc.c:603
void mmc_erase(struct burn_drive *d, int fast)
Definition: mmc.c:2729
int mmc_send_cue_sheet(struct burn_drive *d, struct cue_sheet *s)
Definition: mmc.c:331
int mmc_write(struct burn_drive *d, int start, struct buffer *buf)
Definition: mmc.c:929
void mmc_perform_opc(struct burn_drive *d)
Definition: mmc.c:2781
void mmc_set_speed(struct burn_drive *d, int r, int w)
Definition: mmc.c:2905
void mmc_sync_cache(struct burn_drive *d)
Definition: mmc.c:3539
void sbc_eject(struct burn_drive *d)
Definition: sbc.c:80
void sbc_load(struct burn_drive *d)
Definition: sbc.c:55
static void sg_destroy_enumerator(burn_drive_enumerator_t *idx_)
Definition: sg-freebsd.c:210
int sg_issue_command(struct burn_drive *d, struct command *c)
Definition: sg-freebsd.c:778
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-freebsd.c:1165
int sg_close_drive(struct burn_drive *d)
Definition: sg-freebsd.c:389
int sg_is_enumerable_adr(char *adr)
Definition: sg-freebsd.c:332
int sg_shutdown(int flag)
Definition: sg-freebsd.c:135
int sg_grab(struct burn_drive *d)
Definition: sg-freebsd.c:715
static int sg_lock(struct burn_drive *d, int flag)
Definition: sg-freebsd.c:689
int sg_dispose_drive(struct burn_drive *d, int flag)
Definition: sg-freebsd.c:150
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
Definition: sg-freebsd.c:1174
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-freebsd.c:407
int burn_os_open_track_src(char *path, int open_flags, int flag)
Definition: sg-freebsd.c:1156
int sg_give_next_adr(burn_drive_enumerator_t *idx_, char adr[], int adr_size, int initialize)
Definition: sg-freebsd.c:257
int burn_os_is_2k_seekrw(char *path, int flag)
Definition: sg-freebsd.c:1005
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-freebsd.c:1076
static int freebsd_dev_lock(int dev_fd, char *devname, int *os_errno, int *pass_dev_no, int *lock_fd, char msg[4096], int flag)
Definition: sg-freebsd.c:582
static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx_)
Definition: sg-freebsd.c:223
int sg_initialize(char msg[1024], int flag)
Definition: sg-freebsd.c:123
static int sg_init_enumerator(burn_drive_enumerator_t *idx_)
Definition: sg-freebsd.c:160
static void enumerate_common(char *fname, int bus_no, int host_no, int channel_no, int target_no, int lun_no)
Definition: sg-freebsd.c:542
int burn_sg_log_scsi
Definition: init.c:110
int sg_drive_is_open(struct burn_drive *d)
Definition: sg-freebsd.c:402
int sg_release(struct burn_drive *d)
Definition: sg-freebsd.c:763
int sg_id_string(char msg[1024], int flag)
Definition: sg-freebsd.c:108
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, int *target_no, int *lun_no)
Definition: sg-freebsd.c:358
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 spc_get_erase_progress(struct burn_drive *d)
Definition: spc.c:335
int spc_test_unit_ready(struct burn_drive *d)
Definition: spc.c:143
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
void spc_sense_write_params(struct burn_drive *d)
Definition: spc.c:797
void spc_allow(struct burn_drive *d)
Definition: spc.c:436
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
void spc_select_error_params(struct burn_drive *d, const struct burn_read_opts *o)
Definition: spc.c:757
void spc_select_write_params(struct burn_drive *d, struct burn_session *s, int tnum, const struct burn_write_opts *o)
Definition: spc.c:867
void spc_probe_write_modes(struct burn_drive *d)
Definition: spc.c:1054
void spc_getcaps(struct burn_drive *d)
Definition: spc.c:1038
int spc_decode_sense(unsigned char *sense, int senselen, int *key, int *asc, int *ascq)
Definition: spc.c:93
void spc_prevent(struct burn_drive *d)
Definition: spc.c:417
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
void(* unlock)(struct burn_drive *)
Definition: transport.h:471
enum burn_drive_status busy
Definition: transport.h:423
void(* getcaps)(struct burn_drive *)
Definition: transport.h:463
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