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-port.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 - 2011 Thomas Schmitt <scdbackup@gmx.net>
5  Provided under GPL version 2 or later.
6 */
7 
8 
9  /* THIS CODE IS NOT FUNCTIONAL YET !!! */
10 
11 
12 /*
13 
14 This is the main operating system dependent SCSI part of libburn. It implements
15 the transport level aspects of SCSI control and command i/o.
16 
17 Present implementation: FreeBSD CAM (untested)
18 
19 
20 PORTING:
21 
22 Porting libburn typically will consist of adding a new operating system case
23 to the following switcher files:
24  os.h Operating system specific libburn definitions and declarations.
25  sg.c Operating system dependent transport level modules.
26 and of deriving the following system specific files from existing examples:
27  os-*.h Included by os.h. You will need some general system knowledge
28  about signals and knowledge about the storage object needs of your
29  transport level module sg-*.c.
30 
31  sg-*.c This source module. You will need special system knowledge about
32  how to detect all potentially available drives, how to open them,
33  eventually how to exclusively reserve them, how to perform
34  SCSI transactions, how to inquire the (pseudo-)SCSI driver.
35  You will not need to care about CD burning, MMC or other high-level
36  SCSI aspects.
37 
38 Said sg-*.c operations are defined by a public function interface, which has
39 to be implemented in a way that provides libburn with the desired services:
40 
41 sg_id_string() returns an id string of the SCSI transport adapter.
42  It may be called before initialization but then may
43  return only a preliminary id.
44 
45 sg_initialize() performs global initialization of the SCSI transport
46  adapter and eventually needed operating system
47  facilities. Checks for compatibility of supporting
48  software components.
49 
50 sg_shutdown() performs global finalizations and releases globally
51  acquired resources.
52 
53 sg_give_next_adr() iterates over the set of potentially useful drive
54  address strings.
55 
56 scsi_enumerate_drives() brings all available, not-whitelist-banned, and
57  accessible drives into libburn's list of drives.
58 
59 sg_dispose_drive() finalizes adapter specifics of struct burn_drive
60  on destruction. Releases resources which were acquired
61  underneath scsi_enumerate_drives().
62 
63 sg_drive_is_open() tells whether libburn has the given drive in use.
64 
65 sg_grab() opens the drive for SCSI commands and ensures
66  undisturbed access.
67 
68 sg_release() closes a drive opened by sg_grab()
69 
70 sg_issue_command() sends a SCSI command to the drive, receives reply,
71  and evaluates whether the command succeeded or shall
72  be retried or finally failed.
73 
74 sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
75 
76 
77 burn_os_is_2k_seekrw() tells whether the given path leads to a file object
78  that can be used in 2 kB granularity by lseek(2),
79  read(2), and possibly write(2) if not read-only.
80  E.g. a USB stick or a hard disk.
81 
82 burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
83 
84 burn_os_open_track_src() opens a disk file in a way that offers best
85  throughput with file reading and/or SCSI write command
86  transmission.
87 
88 burn_os_alloc_buffer() allocates a memory area that is suitable for file
89  descriptors issued by burn_os_open_track_src().
90  The buffer size may be rounded up for alignment
91  reasons.
92 
93 burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
94 
95 
96 Porting hints are marked by the text "PORTING:".
97 Send feedback to libburn-hackers@pykix.org .
98 
99 */
100 
101 #ifdef HAVE_CONFIG_H
102 #include "../config.h"
103 #endif
104 
105 
106 /** PORTING : ------- OS dependent headers and definitions ------ */
107 
108 #include <errno.h>
109 #include <unistd.h>
110 #include <stdio.h>
111 #include <sys/types.h>
112 #include <sys/stat.h>
113 #include <fcntl.h>
114 #include <sys/ioctl.h>
115 #include <stdlib.h>
116 #include <string.h>
117 #include <sys/poll.h>
118 #include <camlib.h>
119 #include <cam/scsi/scsi_message.h>
120 #include <cam/scsi/scsi_pass.h>
121 
122 #include <err.h> /* XXX */
123 
124 
125 /* ts A70909 */
126 #include <sys/statvfs.h>
127 
128 
129 /** PORTING : ------ libburn portable headers and definitions ----- */
130 
131 #include "transport.h"
132 #include "drive.h"
133 #include "sg.h"
134 #include "spc.h"
135 #include "mmc.h"
136 #include "sbc.h"
137 #include "debug.h"
138 #include "toc.h"
139 #include "util.h"
140 
141 #include "libdax_msgs.h"
142 extern struct libdax_msgs *libdax_messenger;
143 
144 
145 /* is in portable part of libburn */
146 int burn_drive_is_banned(char *device_address);
147 
148 
149 
150 /* ------------------------------------------------------------------------ */
151 /* ts A61115: Private functions. Port only if needed by public functions */
152 /* (Public functions are listed below) */
153 /* ------------------------------------------------------------------------ */
154 
155 
156 /* Helper function for scsi_give_next_adr() */
158 {
159  idx->skip_device = 0;
160 
161  if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
162  warn("couldn't open %s", XPT_DEVICE);
163  return -1;
164  }
165 
166  memset(&(idx->ccb), 0, sizeof(union ccb));
167 
168  idx->ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
169  idx->ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
170  idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
171 
172  idx->ccb.ccb_h.func_code = XPT_DEV_MATCH;
173  idx->bufsize = sizeof(struct dev_match_result) * 100;
174  idx->ccb.cdm.match_buf_len = idx->bufsize;
175  idx->ccb.cdm.matches = (struct dev_match_result *)
176  calloc(1, idx->bufsize);
177  if (idx->ccb.cdm.matches == NULL) {
178  warnx("cannot allocate memory for matches");
179  close(idx->fd);
180  return -1;
181  }
182  idx->ccb.cdm.num_matches = 0;
183  idx->i = idx->ccb.cdm.num_matches; /* to trigger buffer load */
184 
185  /*
186  * We fetch all nodes, since we display most of them in the default
187  * case, and all in the verbose case.
188  */
189  idx->ccb.cdm.num_patterns = 0;
190  idx->ccb.cdm.pattern_buf_len = 0;
191 
192  return 1;
193 }
194 
195 
196 /* Helper function for scsi_give_next_adr() */
198 {
199  /*
200  * We do the ioctl multiple times if necessary, in case there are
201  * more than 100 nodes in the EDT.
202  */
203  if (ioctl(idx->fd, CAMIOCOMMAND, &(idx->ccb)) == -1) {
204  warn("error sending CAMIOCOMMAND ioctl");
205  return -1;
206  }
207 
208  if ((idx->ccb.ccb_h.status != CAM_REQ_CMP)
209  || ((idx->ccb.cdm.status != CAM_DEV_MATCH_LAST)
210  && (idx->ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
211  warnx("got CAM error %#x, CDM error %d\n",
212  idx->ccb.ccb_h.status, idx->ccb.cdm.status);
213  return -1;
214  }
215  return 1;
216 }
217 
218 
219 static int sg_close_drive(struct burn_drive * d)
220 {
221  if (d->cam != NULL) {
222  cam_close_device(d->cam);
223  d->cam = NULL;
224  }
225  return 0;
226 }
227 
228 
229 /* ----------------------------------------------------------------------- */
230 /* PORTING: Private functions which contain publicly needed functionality. */
231 /* Their portable part must be performed. So it is probably best */
232 /* to replace the non-portable part and to call these functions */
233 /* in your port, too. */
234 /* ----------------------------------------------------------------------- */
235 
236 
237 /** Wraps a detected drive into libburn structures and hands it over to
238  libburn drive list.
239 */
240 static void enumerate_common(char *fname, int bus_no, int host_no,
241  int channel_no, int target_no, int lun_no)
242 {
243  int ret;
244  struct burn_drive out;
245 
246  /* General libburn drive setup */
247  burn_setup_drive(&out, fname);
248 
249  /* This transport adapter uses SCSI-family commands and models
250  (seems the adapter would know better than its boss, if ever) */
251  ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
252  target_no, lun_no, 0);
253  if (ret<=0)
254  return;
255 
256  /* PORTING: ------------------- non portable part --------------- */
257 
258  /* Operating system adapter is CAM */
259  /* Adapter specific handles and data */
260  out.cam = NULL;
261 
262  /* PORTING: ---------------- end of non portable part ------------ */
263 
264  /* Adapter specific functions with standardized names */
265  out.grab = sg_grab;
266  out.release = sg_release;
269  /* Finally register drive and inquire drive information */
271 }
272 
273 
274 /* ts A61115 */
275 /* ------------------------------------------------------------------------ */
276 /* PORTING: Public functions. These MUST be ported. */
277 /* ------------------------------------------------------------------------ */
278 
279 
280 /** Returns the id string of the SCSI transport adapter and eventually
281  needed operating system facilities.
282  This call is usable even if sg_initialize() was not called yet. In that
283  case a preliminary constant message might be issued if detailed info is
284  not available yet.
285  @param msg returns id string
286  @param flag unused yet, submit 0
287  @return 1 = success, <=0 = failure
288 */
289 int sg_id_string(char msg[1024], int flag)
290 {
291  strcpy(msg, "internal FreeBSD CAM adapter sg-freebsd-port");
292  return 1;
293 }
294 
295 
296 /** Performs global initialization of the SCSI transport adapter and eventually
297  needed operating system facilities. Checks for compatibility supporting
298  software components.
299  @param msg returns ids and/or error messages of eventual helpers
300  @param flag unused yet, submit 0
301  @return 1 = success, <=0 = failure
302 */
303 int sg_initialize(char msg[1024], int flag)
304 {
305  return sg_id_string(msg, 0);
306 }
307 
308 
309 /** Performs global finalization of the SCSI transport adapter and eventually
310  needed operating system facilities. Releases globally acquired resources.
311  @param flag unused yet, submit 0
312  @return 1 = success, <=0 = failure
313 */
314 int sg_shutdown(int flag)
315 {
316  return 1;
317 }
318 
319 
320 /** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
321  struct burn_drive which are defined in os-*.h.
322  The eventual initialization of those components was made underneath
323  scsi_enumerate_drives().
324  This will be called when a burn_drive gets disposed.
325  @param d the drive to be finalized
326  @param flag unused yet, submit 0
327  @return 1 = success, <=0 = failure
328 */
329 int sg_dispose_drive(struct burn_drive *d, int flag)
330 {
331  return 1;
332 }
333 
334 
335 /** Returns the next index number and the next enumerated drive address.
336  The enumeration has to cover all available and accessible drives. It is
337  allowed to return addresses of drives which are not available but under
338  some (even exotic) circumstances could be available. It is on the other
339  hand allowed, only to hand out addresses which can really be used right
340  in the moment of this call. (This implementation chooses the latter.)
341  @param idx An opaque handle. Make no own theories about it.
342  @param adr Takes the reply
343  @param adr_size Gives maximum size of reply including final 0
344  @param initialize 1 = start new,
345  0 = continue, use no other values for now
346  -1 = finish
347  @return 1 = reply is a valid address , 0 = no further address available
348  -1 = severe error (e.g. adr_size too small)
349 */
351  char adr[], int adr_size, int initialize)
352 {
353  int ret;
354 
355  if (initialize == 1) {
356  ret = sg_init_enumerator(idx);
357  if (ret<=0)
358  return ret;
359  } else if (initialize == -1) {
360  if(idx->fd != -1)
361  close(idx->fd);
362  idx->fd = -1;
363  return 0;
364  }
365 
366 
367 try_item:; /* This spaghetti loop keeps the number of tabs small */
368 
369  /* Loop content from old scsi_enumerate_drives() */
370 
371  while (idx->i >= idx->ccb.cdm.num_matches) {
372  ret = sg_next_enumeration_buffer(idx);
373  if (ret<=0)
374  return -1;
375  if (!((idx->ccb.ccb_h.status == CAM_REQ_CMP)
376  && (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE)) )
377  return 0;
378  idx->i = 0;
379  }
380 
381  switch (idx->ccb.cdm.matches[idx->i].type) {
382  case DEV_MATCH_BUS:
383  break;
384  case DEV_MATCH_DEVICE: {
385  struct device_match_result* result;
386 
387  result = &(idx->ccb.cdm.matches[i].result.device_result);
388  if (result->flags & DEV_RESULT_UNCONFIGURED)
389  idx->skip_device = 1;
390  else
391  idx->skip_device = 0;
392  break;
393  }
394  case DEV_MATCH_PERIPH: {
395  struct periph_match_result* result;
396  char buf[64];
397 
398  result = &(idx->ccb.cdm.matches[i].result.periph_result);
399  if (idx->skip_device ||
400  strcmp(result->periph_name, "pass") == 0)
401  break;
402  snprintf(buf, sizeof (buf), "/dev/%s%d",
403  result->periph_name, result->unit_number);
404  if(adr_size <= strlen(buf))
405  return -1;
406  strcpy(adr, buf);
407 
408  /* Found next enumerable address */
409  return 1;
410 
411  }
412  default:
413  /* printf(stderr, "unknown match type\n"); */
414  break;
415  }
416 
417  (idx->i)++;
418  goto try_item; /* Regular function exit is return 1 above */
419 }
420 
421 
422 /** Brings all available, not-whitelist-banned, and accessible drives into
423  libburn's list of drives.
424 */
426 {
428  int initialize = 1, ret;
429  char buf[64];
430 
431  while(1) {
432  ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
433  initialize = 0;
434  if (ret <= 0)
435  break;
436  if (burn_drive_is_banned(buf))
437  continue;
438  enumerate_common(buf, idx.result->path_id, idx.result->path_id,
439  0, idx.result->target_id,
440  idx.result->target_lun);
441  }
442  sg_give_next_adr(&idx, buf, sizeof(buf), -1);
443  return 1;
444 }
445 
446 
447 /** Tells whether libburn has the given drive in use or exclusively reserved.
448  If it is "open" then libburn will eventually call sg_release() on it when
449  it is time to give up usage and reservation.
450 */
451 /** Published as burn_drive.drive_is_open() */
453 {
454  return (d->cam != NULL);
455 }
456 
457 
458 /** Opens the drive for SCSI commands and - if burn activities are prone
459  to external interference on your system - obtains an exclusive access lock
460  on the drive. (Note: this is not physical tray locking.)
461  A drive that has been opened with sg_grab() will eventually be handed
462  over to sg_release() for closing and unreserving.
463 */
464 int sg_grab(struct burn_drive *d)
465 {
466  struct cam_device *cam;
467 
468  if(d->cam != NULL) {
469  d->released = 0;
470  return 1;
471  }
472 
473  cam = cam_open_device(d->devname, O_RDWR);
474  if (cam == NULL) {
476  0x00020003,
478  "Could not grab drive", 0/*os_errno*/, 0);
479  return 0;
480  }
481  d->cam = cam;
482  fcntl(cam->fd, F_SETOWN, getpid());
483  d->released = 0;
484  return 1;
485 }
486 
487 
488 /** PORTING: Is mainly about the call to sg_close_drive() and whether it
489  implements the demanded functionality.
490 */
491 /** Gives up the drive for SCSI commands and releases eventual access locks.
492  (Note: this is not physical tray locking.)
493 */
494 int sg_release(struct burn_drive *d)
495 {
496  if (d->cam == NULL)
497  return 0;
498  sg_close_drive(d);
499  return 0;
500 }
501 
502 
503 /** Sends a SCSI command to the drive, receives reply and evaluates whether
504  the command succeeded or shall be retried or finally failed.
505  Returned SCSI errors shall not lead to a return value indicating failure.
506  The callers get notified by c->error. An SCSI failure which leads not to
507  a retry shall be notified via scsi_notify_error().
508  The Libburn_log_sg_commandS facility might be of help when problems with
509  a drive have to be examined. It shall stay disabled for normal use.
510  @return: 1 success , <=0 failure
511 */
512 int sg_issue_command(struct burn_drive *d, struct command *c)
513 {
514  int done = 0;
515  int err;
516  union ccb *ccb;
517 
518  if (d->cam == NULL) {
519  c->error = 0;
520  return 0;
521  }
522 
523  c->error = 0;
524 
525  ccb = cam_getccb(d->cam);
526  cam_fill_csio(&ccb->csio,
527  1, /* retries */
528  NULL, /* cbfncp */
529  CAM_DEV_QFRZDIS, /* flags */
530  MSG_SIMPLE_Q_TAG, /* tag_action */
531  NULL, /* data_ptr */
532  0, /* dxfer_len */
533  sizeof (ccb->csio.sense_data), /* sense_len */
534  0, /* cdb_len */
535  30*1000); /* timeout */
536  switch (c->dir) {
537  case TO_DRIVE:
538  ccb->csio.ccb_h.flags |= CAM_DIR_OUT;
539  break;
540  case FROM_DRIVE:
541  ccb->csio.ccb_h.flags |= CAM_DIR_IN;
542  break;
543  case NO_TRANSFER:
544  ccb->csio.ccb_h.flags |= CAM_DIR_NONE;
545  break;
546  }
547 
548  ccb->csio.cdb_len = c->oplen;
549  memcpy(&ccb->csio.cdb_io.cdb_bytes, &c->opcode, c->oplen);
550 
551  if (c->page) {
552  ccb->csio.data_ptr = c->page->data;
553  if (c->dir == FROM_DRIVE) {
554  ccb->csio.dxfer_len = BUFFER_SIZE;
555 /* touch page so we can use valgrind */
556  memset(c->page->data, 0, BUFFER_SIZE);
557  } else {
558 
559  /* ts A61115: removed a ssert() */
560  if(c->page->bytes <= 0)
561  return 0;
562 
563  ccb->csio.dxfer_len = c->page->bytes;
564  }
565  } else {
566  ccb->csio.data_ptr = NULL;
567  ccb->csio.dxfer_len = 0;
568  }
569 
570  /* ts B90523 : Record effective transfer length request for debugging*/
571  c->dxfer_len = ccb->csio.dxfer_len;
572 
573  do {
574  memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data));
575  err = cam_send_ccb(d->cam, ccb);
576  if (err == -1) {
578  d->global_index, 0x0002010c,
580  "Failed to transfer command to drive",
581  errno, 0);
582  cam_freeccb(ccb);
583  sg_close_drive(d);
584  d->released = 1;
585  d->busy = BURN_DRIVE_IDLE;
586  c->error = 1;
587  return -1;
588  }
589  /* XXX */
590  memcpy(c->sense, &ccb->csio.sense_data, ccb->csio.sense_len);
591  c->sense_len = ccb->csio.sense_len;
592  if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
593  if (!c->retry) {
594  c->error = 1;
595  cam_freeccb(ccb);
596  return 1;
597  }
598  switch (scsi_error(d, c->sense, 0)) {
599  case RETRY:
600  done = 0;
601  break;
602  case FAIL:
603  done = 1;
604  c->error = 1;
605  break;
606  }
607  } else {
608  done = 1;
609  }
610  if (!done)
612  } while (!done);
613  cam_freeccb(ccb);
614  return 1;
615 }
616 
617 
618 /** Tries to obtain SCSI address parameters.
619  @return 1 is success , 0 is failure
620 */
621 int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
622  int *target_no, int *lun_no)
623 {
625  int initialize = 1, ret;
626  char buf[64];
627  struct periph_match_result* result;
628 
629  while(1) {
630  ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
631  initialize = 0;
632  if (ret <= 0)
633  break;
634  if (strcmp(path, buf) != 0)
635  continue;
636  result = &(idx->ccb.cdm.matches[i].result.periph_result);
637  *bus_no = result->path_id;
638  *host_no = result->path_id;
639  *channel_no = 0;
640  *target_no = result->target_id
641  *lun_no = result->target_lun;
642  sg_give_next_adr(&idx, buf, sizeof(buf), -1);
643  return 1;
644  }
645  sg_give_next_adr(&idx, buf, sizeof(buf), -1);
646  return (0);
647 }
648 
649 
650 /** Tells whether a text is a persistent address as listed by the enumeration
651  functions.
652 */
653 int sg_is_enumerable_adr(char* adr)
654 {
656  int initialize = 1, ret;
657  char buf[64];
658 
659  while(1) {
660  ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
661  initialize = 0;
662  if (ret <= 0)
663  break;
664  if (strcmp(adr, buf) == 0) {
665  sg_give_next_adr(&idx, buf, sizeof(buf), -1);
666  return 1;
667  }
668  }
669  sg_give_next_adr(&idx, buf, sizeof(buf), -1);
670  return (0);
671 }
672 
673 
674 /* ts B00115 */
675 /* Return 1 if the given path leads to a regular file or a device that can be
676  seeked, written, and read with 2 kB granularity.
677 */
678 int burn_os_is_2k_seekrw(char *path, int flag)
679 {
680  struct stat stbuf;
681  char *spt;
682  int i, e;
683 
684  if (stat(path, &stbuf) == -1)
685  return 0;
686  if (S_ISREG(stbuf.st_mode))
687  return 1;
688  if (!S_ISCHR(stbuf.st_mode))
689  return 0;
690  spt = strrchr(path, '/');
691  if (spt == NULL)
692  spt = path;
693  else
694  spt++;
695  e = strlen(spt);
696  for (i = strlen(spt) - 1; i > 0; i--)
697  if (spt[i] >= '0' && spt[i] <= '9')
698  e = i;
699  if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
700  return 1;
701  if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
702  return 1;
703  if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
704  return 1;
705  if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
706  return 1;
707  if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
708  return 1;
709  if (strncmp(spt, "fla", e) == 0) /* Flash drive */
710  return 1;
711  return 0;
712 }
713 
714 
715 /* ts A70909 */
716 /** Estimate the potential payload capacity of a file address.
717  @param path The address of the file to be examined. If it does not
718  exist yet, then the directory will be inquired.
719  @param bytes This value gets modified if an estimation is possible
720  @return -2 = cannot perform necessary operations on file object
721  -1 = neither path nor dirname of path exist
722  0 = could not estimate size capacity of file object
723  1 = estimation has been made, bytes was set
724 */
725 int burn_os_stdio_capacity(char *path, off_t write_start, off_t *bytes)
726 {
727  struct stat stbuf;
728  struct statvfs vfsbuf;
729  char *testpath = NULL, *cpt;
730  off_t add_size = 0;
731  int fd, ret;
732 
733  BURN_ALLOC_MEM(testpath, char, 4096);
734  testpath[0] = 0;
735  if (stat(path, &stbuf) == -1) {
736  strcpy(testpath, path);
737  cpt = strrchr(testpath, '/');
738  if(cpt == NULL)
739  strcpy(testpath, ".");
740  else if(cpt == testpath)
741  testpath[1] = 0;
742  else
743  *cpt = 0;
744  if (stat(testpath, &stbuf) == -1)
745  {ret = -1; goto ex;}
746 
747 #ifdef Libburn_if_this_was_linuX
748 
749  } else if(S_ISBLK(stbuf.st_mode)) {
750  int open_mode = O_RDWR, fd, ret;
751  long blocks;
752 
753  blocks = *bytes / 512;
755  open_mode |= O_EXCL;
756  fd = open(path, open_mode);
757  if (fd == -1)
758  {ret = -2; goto ex;}
759  ret = ioctl(fd, BLKGETSIZE, &blocks);
760  close(fd);
761  if (ret == -1)
762  {ret = -2; goto ex;}
763  *bytes = ((off_t) blocks) * (off_t) 512;
764 
765 #endif /* Libburn_if_this_was_linuX */
766 
767 
768  } else if(S_ISCHR(stbuf.st_mode)) {
769  fd = open(path, O_RDONLY);
770  if (fd == -1)
771  {ret = -2; goto ex;}
772  ret = ioctl(fd, DIOCGMEDIASIZE, &add_size);
773  close(fd);
774  if (ret == -1)
775  {ret = -2; goto ex;}
776  *bytes = add_size;
777  } else if(S_ISREG(stbuf.st_mode)) {
778  add_size = burn_sparse_file_addsize(write_start, &stbuf);
779  strcpy(testpath, path);
780  } else
781  {ret = 0; goto ex;}
782 
783  if (testpath[0]) {
784  if (statvfs(testpath, &vfsbuf) == -1)
785  {ret = -2; goto ex;}
786  *bytes = add_size + ((off_t) vfsbuf.f_frsize) *
787  (off_t) vfsbuf.f_bavail;
788  }
789  ret = 1;
790 ex:
791  BURN_FREE_MEM(testpath);
792  return ret;
793 }
794 
795 
796 /* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
797 
798 #ifdef Libburn_read_o_direcT
799 
800  /* No special O_DIRECT-like precautions are implemented here */
801 
802 #endif /* Libburn_read_o_direcT */
803 
804 
805 int burn_os_open_track_src(char *path, int open_flags, int flag)
806 {
807  int fd;
808 
809  fd = open(path, open_flags);
810  return fd;
811 }
812 
813 
814 void *burn_os_alloc_buffer(size_t amount, int flag)
815 {
816  void *buf = NULL;
817 
818  buf = calloc(1, amount);
819  return buf;
820 }
821 
822 
823 int burn_os_free_buffer(void *buffer, size_t amount, int flag)
824 {
825  if (buffer == NULL)
826  return 0;
827  free(buffer);
828  return 1;
829 }
830 
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
int burn_sg_open_o_excl
Definition: init.c:53
#define BURN_FREE_MEM(pt)
Definition: init.h:52
#define BURN_ALLOC_MEM(pt, typ, count)
Definition: init.h:40
off_t burn_sparse_file_addsize(off_t write_start, struct stat *stbuf)
Definition: util.c:385
@ BURN_DRIVE_IDLE
Definition: libburn.h:295
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
static int sg_close_drive(struct burn_drive *d)
int sg_issue_command(struct burn_drive *d, struct command *c)
void * burn_os_alloc_buffer(size_t amount, int flag)
int sg_is_enumerable_adr(char *adr)
int sg_shutdown(int flag)
int sg_grab(struct burn_drive *d)
int sg_dispose_drive(struct burn_drive *d, int flag)
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
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)
static int sg_init_enumerator(burn_drive_enumerator_t *idx)
int burn_os_open_track_src(char *path, int open_flags, int flag)
int burn_os_is_2k_seekrw(char *path, int flag)
int burn_os_stdio_capacity(char *path, off_t write_start, off_t *bytes)
int sg_initialize(char msg[1024], int flag)
static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx)
static void enumerate_common(char *fname, int bus_no, int host_no, int channel_no, int target_no, int lun_no)
int sg_drive_is_open(struct burn_drive *d)
int sg_release(struct burn_drive *d)
int sg_id_string(char msg[1024], int flag)
int sg_give_next_adr(burn_drive_enumerator_t *idx, char adr[], int adr_size, int initialize)
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, int *target_no, int *lun_no)
void spc_register_retry(struct command *c)
Definition: spc.c:1775
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
enum response scsi_error(struct burn_drive *d, unsigned char *sense, int senselen)
Definition: spc.c:1670
@ RETRY
Definition: spc.h:59
@ FAIL
Definition: spc.h:59
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
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
int retry
Definition: transport.h:66
unsigned char sense[128]
Definition: transport.h:63
int sense_len
Definition: transport.h:64
int oplen
Definition: transport.h:60
int dxfer_len
Definition: transport.h:62
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