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-solaris.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) 2010 - 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: Solaris uscsi, e.g. for SunOS 5.11
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 <stropts.h>
106 #include <stdio.h>
107 #include <sys/types.h>
108 #include <errno.h>
109 #include <fcntl.h>
110 #include <sys/stat.h>
111 #include <string.h>
112 #include <stdlib.h>
113 #include <dirent.h>
114 
115 #ifdef Libburn_os_has_statvfS
116 #include <sys/statvfs.h>
117 #endif /* Libburn_os_has_stavtfS */
118 
119 #include <volmgt.h>
120 #include <sys/dkio.h>
121 #include <sys/vtoc.h>
122 
123 #include <sys/scsi/impl/uscsi.h>
124 
125 
126 /* The waiting time before eventually retrying a failed SCSI command.
127  Before each retry wait Libburn_sg_linux_retry_incR longer than with
128  the previous one.
129 */
130 #define Libburn_sg_solaris_retry_usleeP 100000
131 #define Libburn_sg_solaris_retry_incR 100000
132 
133 
134 /** PORTING : ------ libburn portable headers and definitions ----- */
135 
136 #include "transport.h"
137 #include "drive.h"
138 #include "sg.h"
139 #include "spc.h"
140 #include "sbc.h"
141 #include "debug.h"
142 #include "toc.h"
143 #include "util.h"
144 #include "init.h"
145 
146 #include "libdax_msgs.h"
147 extern struct libdax_msgs *libdax_messenger;
148 
149 
150 /* is in portable part of libburn */
151 int burn_drive_is_banned(char *device_address);
152 int burn_drive_resolve_link(char *path, char adr[],
153  int *recursion_count, int flag); /* drive.c */
154 
155 /* Whether to log SCSI commands:
156  bit0= log in /tmp/libburn_sg_command_log
157  bit1= log to stderr
158  bit2= flush every line
159 */
160 extern int burn_sg_log_scsi;
161 
162 
163 /* ------------------------------------------------------------------------ */
164 /* PORTING: Private definitions. Port only if needed by public functions. */
165 /* (Public functions are listed below) */
166 /* ------------------------------------------------------------------------ */
167 
168 
169 /* Storage object is in libburn/init.c
170  whether to strive for exclusive access to the drive
171 */
172 extern int burn_sg_open_o_excl;
173 
174 
175 /* ------------------------------------------------------------------------ */
176 /* PORTING: Private functions. Port only if needed by public functions */
177 /* (Public functions are listed below) */
178 /* ------------------------------------------------------------------------ */
179 
180 
181 static int sg_close_drive(struct burn_drive * d)
182 {
183  if (d->fd != -1) {
184  close(d->fd);
185  d->fd = -1;
186  return 1;
187  }
188  return 0;
189 }
190 
191 
192 static int decode_btl_number(char **cpt, int stopper, int *no)
193 {
194  *no = 0;
195  for ((*cpt)++; **cpt != stopper; (*cpt)++) {
196  if (**cpt < '0' || **cpt > '9')
197  return 0;
198  *no = *no * 10 + **cpt - '0';
199  }
200  return 1;
201 }
202 
203 
204 /* Read bus, target, lun from name "cXtYdZs2" or "cXtYdZ/...".
205  Return 0 if name is not of the desired form.
206 */
207 static int decode_btl_solaris(char *name, int *busno, int *tgtno, int *lunno,
208  int flag)
209 {
210  char *cpt, *cpt_mem;
211  int ret;
212 
213  *busno = *tgtno = *lunno = -1;
214  cpt = name;
215  if (*cpt != 'c')
216  return 0;
217  ret = decode_btl_number(&cpt, 't', busno);
218  if (ret <= 0)
219  return ret;
220  ret = decode_btl_number(&cpt, 'd', tgtno);
221  if (ret <= 0)
222  return ret;
223  cpt_mem = cpt;
224  ret = decode_btl_number(&cpt, 's', lunno);
225  if (ret <= 0) {
226  cpt = cpt_mem;
227  ret = decode_btl_number(&cpt, '/', lunno);
228  if (ret <= 0)
229  return ret;
230  return(1);
231  }
232  cpt++;
233  if (*cpt != '2' || *(cpt + 1) != 0)
234  return 0;
235  return 1;
236 }
237 
238 
240 {
241  DIR *dir;
242 
243  idx->dir = NULL;
244  dir = opendir("/dev/rdsk");
245  if (dir == NULL) {
248  "Cannot start device file enumeration. opendir(\"/dev/rdsk\") failed.",
249  errno, 0);
250  return 0;
251  }
252  idx->dir = dir;
253  return 1;
254 }
255 
256 
257 static int sg_solaris_convert_devname(char *path, char **dev_to_open, int flag)
258 {
259  char *sym_name = NULL, *media_name = NULL, *curr_name, *msg = NULL;
260  int ret;
261 
262  BURN_ALLOC_MEM(msg, char, 4096);
263 
264  BURN_FREE_MEM(*dev_to_open);
265  *dev_to_open = NULL;
266  curr_name = path;
267 
268  if (! volmgt_running())
269  goto set_name;
270  sym_name = volmgt_symname(path);
271  sprintf(msg, "Volume Management symbolic name: '%s' -> %s",
272  path, sym_name == NULL ? "NULL" : sym_name);
274  0x00000002,
276  msg, 0, 0);
277  if (sym_name != NULL)
278  media_name = media_findname(sym_name);
279  else
280  media_name = media_findname(path);
281  if (media_name != NULL)
282  curr_name = media_name;
283  sprintf(msg, "Media name: %s -> %s",
284  sym_name == NULL ? path : sym_name,
285  media_name == NULL ? "NULL" : media_name);
287  0x00000002,
289  msg, 0, 0);
290 set_name:
291  BURN_ALLOC_MEM(*dev_to_open, char, strlen(curr_name) + 1);
292  strcpy(*dev_to_open, curr_name);
293  ret = 1;
294 ex:
295  if (media_name != NULL)
296  free(media_name);
297  if (sym_name != NULL)
298  free(sym_name);
299  BURN_FREE_MEM(msg);
300  return(ret);
301 }
302 
303 
305  char adr[], int adr_size, int flag)
306 {
307  int busno, tgtno, lunno, ret, fd = -1, volpath_size = 160, os_errno;
308  char *volpath = NULL, *msg = NULL, *dev_to_open = NULL;
309  struct dirent *entry;
310  struct dk_cinfo cinfo;
311  DIR *dir;
312 
313  BURN_ALLOC_MEM(volpath, char, volpath_size);
314  BURN_ALLOC_MEM(msg, char, 4096);
315 
316  dir = idx->dir;
317  while (1) {
318  errno = 0;
319  entry = readdir(dir);
320  if (entry == NULL) {
321  if (errno) {
323  -1, 0x0002000d,
325  "Cannot enumerate next device. readdir() from \"/dev/rdsk\" failed.",
326  errno, 0);
327  {ret = -1; goto ex;}
328  }
329  break;
330  }
331  if (strlen(entry->d_name) > (size_t) (volpath_size - 11))
332  continue;
333  ret = decode_btl_solaris(entry->d_name,
334  &busno, &tgtno, &lunno, 0);
335  if (ret <= 0)
336  continue; /* not cXtYdZs2 */
337 
338  sprintf(volpath, "/dev/rdsk/%s", entry->d_name);
339  if (burn_drive_is_banned(volpath))
340  continue;
341  ret = sg_solaris_convert_devname(volpath, &dev_to_open, 0);
342  if (ret <= 0)
343  continue;
344  fd = open(dev_to_open, O_RDONLY | O_NDELAY);
345  if (fd < 0) {
346  os_errno = errno;
347  sprintf(msg, "Could not open '%s' , errno = %d",
348  dev_to_open, os_errno);
350  0x00000002,
352  msg, os_errno, 0);
353  continue;
354  }
355  /* See man dkio */
356  ret = ioctl(fd, DKIOCINFO, &cinfo);
357  close(fd);
358  if (ret < 0) {
359  os_errno = errno;
360  sprintf(msg,
361  "ioctl(DKIOCINFO) failed on drive '%s', errno = %d",
362  volpath, os_errno);
364  0x00000002,
366  msg, os_errno, 0);
367  continue;
368  }
369  if (cinfo.dki_ctype != DKC_CDROM) {
370  sprintf(msg,
371  "ioctl(DKIOCINFO) classifies drive '%s' as dki_ctype %ld, not as DKC_CDROM = %ld",
372  volpath, (long int) cinfo.dki_ctype,
373  (long int) DKC_CDROM);
375  0x00000002,
377  msg, 0, 0);
378  continue;
379  }
380  if (adr_size <= (int) strlen(volpath)) {
381  sprintf(msg,
382  "Device path '%s' too long. (Max. %d)",
383  volpath, adr_size - 1);
385  0x00000002,
387  msg, 0, 0);
388  {ret = -1; goto ex;}
389  }
390  strcpy(adr, volpath);
391  sprintf(msg, "Accepted as valid drive '%s'", volpath);
393  0x00000002,
395  msg, 0, 0);
396  {ret = 1; goto ex;}
397  }
398  ret = 0;
399 ex:;
400  BURN_FREE_MEM(dev_to_open);
401  BURN_FREE_MEM(msg);
402  BURN_FREE_MEM(volpath);
403  return ret;
404 }
405 
406 
407 static int end_enum_cXtYdZs2(burn_drive_enumerator_t *idx, int flag)
408 {
409  DIR *dir;
410 
411  dir = idx->dir;
412  if(dir != NULL)
413  closedir(dir);
414  idx->dir = NULL;
415  return 1;
416 }
417 
418 
419 /* ----------------------------------------------------------------------- */
420 /* PORTING: Private functions which contain publicly needed functionality. */
421 /* Their portable part must be performed. So it is probably best */
422 /* to replace the non-portable part and to call these functions */
423 /* in your port, too. */
424 /* ----------------------------------------------------------------------- */
425 
426 
427 /** Wraps a detected drive into libburn structures and hands it over to
428  libburn drive list.
429 */
430 static void enumerate_common(char *fname,
431  int bus_no, int host_no,
432  int channel_no, int target_no, int lun_no)
433 {
434  int ret;
435  struct burn_drive out;
436 
437  /* General libburn drive setup */
438  burn_setup_drive(&out, fname);
439 
440  /* This transport adapter uses SCSI-family commands and models
441  (seems the adapter would know better than its boss, if ever) */
442  ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
443  target_no, lun_no, 0);
444  if (ret <= 0)
445  return;
446 
447  /* PORTING: ------------------- non portable part --------------- */
448 
449  /* Transport adapter is Solaris uscsi */
450  /* Adapter specific handles and data */
451  out.fd = -1;
452 
453  /* PORTING: ---------------- end of non portable part ------------ */
454 
455  /* Adapter specific functions with standardized names */
456  out.grab = sg_grab;
457  out.release = sg_release;
460  /* Finally register drive and inquire drive information */
462 }
463 
464 
465 /* ------------------------------------------------------------------------ */
466 /* PORTING: Public functions. These MUST be ported. */
467 /* ------------------------------------------------------------------------ */
468 
469 
470 /** Returns the id string of the SCSI transport adapter and eventually
471  needed operating system facilities.
472  This call is usable even if sg_initialize() was not called yet. In that
473  case a preliminary constant message might be issued if detailed info is
474  not available yet.
475  @param msg returns id string
476  @param flag unused yet, submit 0
477  @return 1 = success, <=0 = failure
478 */
479 int sg_id_string(char msg[1024], int flag)
480 {
481  sprintf(msg, "internal Solaris uscsi adapter sg-solaris");
482  return 1;
483 }
484 
485 
486 /** Performs global initialization of the SCSI transport adapter and eventually
487  needed operating system facilities. Checks for compatibility of supporting
488  software components.
489  @param msg returns ids and/or error messages of eventual helpers
490  @param flag unused yet, submit 0
491  @return 1 = success, <=0 = failure
492 */
493 int sg_initialize(char msg[1024], int flag)
494 {
495  return sg_id_string(msg, 0);
496 }
497 
498 
499 /** Performs global finalization of the SCSI transport adapter and eventually
500  needed operating system facilities. Releases globally acquired resources.
501  @param flag unused yet, submit 0
502  @return 1 = success, <=0 = failure
503 */
504 int sg_shutdown(int flag)
505 {
506  return 1;
507 }
508 
509 
510 /** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
511  struct burn_drive which are defined in os-*.h.
512  The eventual initialization of those components was made underneath
513  scsi_enumerate_drives().
514  This will be called when a burn_drive gets disposed.
515  @param d the drive to be finalized
516  @param flag unused yet, submit 0
517  @return 1 = success, <=0 = failure
518 */
519 int sg_dispose_drive(struct burn_drive *d, int flag)
520 {
521  return 1;
522 }
523 
524 
525 /** Returns the next index number and the next enumerated drive address.
526  The enumeration has to cover all available and accessible drives. It is
527  allowed to return addresses of drives which are not available but under
528  some (even exotic) circumstances could be available. It is on the other
529  hand allowed, only to hand out addresses which can really be used right
530  in the moment of this call. (This implementation chooses the latter.)
531  @param idx An opaque handle. Make no own theories about it.
532  @param adr Takes the reply
533  @param adr_size Gives maximum size of reply including final 0
534  @param initialize 1 = start new,
535  0 = continue, use no other values for now
536  -1 = finish
537  @return 1 = reply is a valid address , 0 = no further address available
538  -1 = severe error (e.g. adr_size too small)
539 */
541  char adr[], int adr_size, int initialize)
542 {
543  int ret;
544 
545  if (initialize == 1) {
546  ret = start_enum_cXtYdZs2(idx, 0);
547  if (ret <= 0)
548  return ret;
549  } else if (initialize == -1) {
550  ret = end_enum_cXtYdZs2(idx, 0);
551  return 0;
552  }
553  ret = next_enum_cXtYdZs2(idx, adr, adr_size, 0);
554  return ret;
555 }
556 
557 
558 /** Brings all available, not-whitelist-banned, and accessible drives into
559  libburn's list of drives.
560 */
562 {
564  int initialize = 1, ret, i_bus_no = -1, buf_size = 4096;
565  int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
566  char *buf = NULL;
567 
568  BURN_ALLOC_MEM(buf, char, buf_size);
569 
570  while(1) {
571  ret = sg_give_next_adr(&idx, buf, buf_size, initialize);
572  initialize = 0;
573  if (ret <= 0)
574  break;
575  if (burn_drive_is_banned(buf))
576  continue;
577  sg_obtain_scsi_adr(buf, &i_bus_no, &i_host_no,
578  &i_channel_no, &i_target_no, &i_lun_no);
579  enumerate_common(buf,
580  i_bus_no, i_host_no, i_channel_no,
581  i_target_no, i_lun_no);
582  }
583  sg_give_next_adr(&idx, buf, buf_size, -1);
584  ret = 1;
585 ex:;
586  BURN_FREE_MEM(buf);
587  return ret;
588 }
589 
590 
591 /** Tells whether libburn has the given drive in use or exclusively reserved.
592  If it is "open" then libburn will eventually call sg_release() on it when
593  it is time to give up usage and reservation.
594 */
595 /** Published as burn_drive.drive_is_open() */
597 {
598  return (d->fd != -1);
599 }
600 
601 
602 /** Opens the drive for SCSI commands and - if burn activities are prone
603  to external interference on your system - obtains an exclusive access lock
604  on the drive. (Note: this is not physical tray locking.)
605  A drive that has been opened with sg_grab() will eventually be handed
606  over to sg_release() for closing and unreserving.
607 */
608 int sg_grab(struct burn_drive *d)
609 {
610  char *msg = NULL, *dev_to_open = NULL;
611  int os_errno, ret;
612  struct dk_cinfo cinfo;
613 
614  BURN_ALLOC_MEM(msg, char, 4096);
615 
616  if (d->fd != -1) {
617  d->released = 0;
618  {ret = 1; goto ex;}
619  }
620  ret = sg_solaris_convert_devname(d->devname, &dev_to_open, 0);
621  if (ret <= 0)
622  goto ex;
623  d->fd = open(dev_to_open, O_RDONLY | O_NDELAY);
624  if (d->fd == -1) {
625  os_errno = errno;
626  sprintf(msg, "Could not grab drive '%s'",
627  d->devname);
628  if (strcmp(d->devname, dev_to_open))
629  sprintf(msg + strlen(msg), " via '%s'", dev_to_open);
631  0x00020003,
633  msg, os_errno, 0);
634  {ret = 0; goto ex;}
635  }
636  ret = ioctl(d->fd, DKIOCINFO, &cinfo);
637  if (ret < 0) {
638  os_errno = errno;
639  sprintf(msg, "ioctl(DKIOCINFO) failed on drive '%s'",
640  d->devname);
642  0x00000002,
644  msg, os_errno, 0);
645  goto revoke;
646  }
647  if (cinfo.dki_ctype != DKC_CDROM) {
648  sprintf(msg,
649  "ioctl(DKIOCINFO) classifies drive '%s' as dki_ctype %ld, not as DKC_CDROM = %ld",
650  d->devname, (long int) cinfo.dki_ctype,
651  (long int) DKC_CDROM);
653  0x00000002,
655  msg, 0, 0);
656  goto revoke;
657  }
658 
659  /* >>> obtain eventual locks */;
660 
661  d->released = 0;
662  {ret = 1; goto ex;}
663 revoke:;
664  sprintf(msg, "Could not grab drive '%s'. Not a CDROM device.",
665  d->devname);
667  0x00020003,
669  msg, 0, 0);
670  ret = 0;
671 ex:;
672  BURN_FREE_MEM(dev_to_open);
673  BURN_FREE_MEM(msg);
674  return ret;
675 }
676 
677 
678 /** PORTING: Is mainly about the call to sg_close_drive() and whether it
679  implements the demanded functionality.
680 */
681 /** Gives up the drive for SCSI commands and releases eventual access locks.
682  (Note: this is not physical tray locking.)
683 */
684 int sg_release(struct burn_drive *d)
685 {
686  if (d->fd < 0)
687  return 0;
688  sg_close_drive(d);
689  return 0;
690 }
691 
692 
693 /** Sends a SCSI command to the drive, receives reply and evaluates whether
694  the command succeeded or shall be retried or finally failed.
695  Returned SCSI errors shall not lead to a return value indicating failure.
696  The callers get notified by c->error. An SCSI failure which leads not to
697  a retry shall be notified via scsi_notify_error().
698  The Libburn_log_sg_commandS facility might be of help when problems with
699  a drive have to be examined. It shall stay disabled for normal use.
700  @return: 1 success , <=0 failure
701 */
702 int sg_issue_command(struct burn_drive *d, struct command *c)
703 {
704  int i, timeout_ms, ret, key, asc, ascq, done = 0, sense_len;
705  time_t start_time;
706  struct uscsi_cmd cgc;
707  char msg[80];
708  static FILE *fp = NULL;
709 
710  c->error = 0;
711  memset(c->sense, 0, sizeof(c->sense));
712 
713  if (d->fd == -1)
714  return 0;
715 
716  if (burn_sg_log_scsi & 1) {
717  if (fp == NULL) {
718  fp= fopen("/tmp/libburn_sg_command_log", "a");
719  fprintf(fp,
720  "\n-----------------------------------------\n");
721  }
722  }
723  if (burn_sg_log_scsi & 3)
724  scsi_log_cmd(c,fp,0);
725 
726  if (c->timeout > 0)
727  timeout_ms = c->timeout;
728  else
729  timeout_ms = 200000;
730  memset (&cgc, 0, sizeof (struct uscsi_cmd));
731  /* No error messages, no retries,
732  do not execute with other commands, request sense data
733  */
734  cgc.uscsi_flags = USCSI_SILENT | USCSI_DIAGNOSE | USCSI_ISOLATE
735  | USCSI_RQENABLE;
736  cgc.uscsi_timeout = timeout_ms / 1000;
737  cgc.uscsi_cdb = (caddr_t) c->opcode;
738  cgc.uscsi_bufaddr = (caddr_t) c->page->data;
739  if (c->dir == TO_DRIVE) {
740  cgc.uscsi_flags |= USCSI_WRITE;
741  cgc.uscsi_buflen = c->page->bytes;
742  } else if (c->dir == FROM_DRIVE) {
743  cgc.uscsi_flags |= USCSI_READ;
744  if (c->dxfer_len >= 0)
745  cgc.uscsi_buflen = c->dxfer_len;
746  else
747  cgc.uscsi_buflen = BUFFER_SIZE;
748  /* touch page so we can use valgrind */
749  memset(c->page->data, 0, BUFFER_SIZE);
750  } else {
751  cgc.uscsi_buflen = 0;
752  }
753  cgc.uscsi_cdblen = c->oplen;
754  cgc.uscsi_rqlen = sizeof(c->sense);
755  cgc.uscsi_rqbuf = (caddr_t) c->sense;
756 
757  /* ts B90523 : Record effective transfer length request for debugging*/
758  c->dxfer_len = cgc.uscsi_buflen;
759 
760  /* retry-loop */
761  start_time = time(NULL);
762  for(i = 0; !done; i++) {
763 
764  memset(c->sense, 0, sizeof(c->sense));
765  c->start_time = burn_get_time(0);
766 
767  ret = ioctl(d->fd, USCSICMD, &cgc);
768 
769  c->end_time = burn_get_time(0);
770 
771  /* For cgc.uscsi_status see SAM-3 5.3.1, Table 22
772  0 = GOOD , 2 = CHECK CONDITION : Sense Data are delivered
773  8 = BUSY
774  */
775  if (ret != 0 && cgc.uscsi_status != 2) {
776  sprintf(msg,
777  "Failed to transfer command to drive. (uscsi_status = 0x%X)",
778  (unsigned int) cgc.uscsi_status),
780  d->global_index, 0x0002010c,
782  msg, errno, 0);
783  sg_close_drive(d);
784  d->released = 1;
785  d->busy = BURN_DRIVE_IDLE;
786  c->error = 1;
787  return -1;
788  }
789 
790 
791  /* >>> Should replace "18" by realistic sense length.
792  What's about following older remark ?
793  */
794  /* >>> valid sense: cgc.uscsi_rqlen - cgc.uscsi_rqresid */;
795 
796  spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
797  if (key || asc || ascq)
798  sense_len = 18;
799  else
800  sense_len = 0;
801  done = scsi_eval_cmd_outcome(d, c, fp, c->sense, sense_len,
802  start_time, timeout_ms, i, 0);
803  if (d->cancel)
804  done = 1;
805  if (!done)
807 
808  } /* end of retry-loop */
809 
810  return 1;
811 }
812 
813 
814 /** Tries to obtain SCSI address parameters.
815  @return 1 is success , 0 is failure
816 */
817 int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
818  int *target_no, int *lun_no)
819 {
820  int ret;
821 
822  /* Try to guess from path */
823  if (strncmp("/dev/rdsk/", path, 10) == 0) {
824  ret = decode_btl_solaris(path + 10,
825  bus_no, target_no, lun_no, 0);
826  if (ret > 0) {
827  *host_no = *bus_no;
828  *channel_no = 0;
829  return 1;
830  }
831  }
832  *bus_no = *host_no = *channel_no = *target_no = *lun_no = -1;
833 
834  /* >>> Could need a ioctl which gives SCSI numbers */;
835 
836  return (0);
837 }
838 
839 
840 /** Tells whether a text is a persistent address as listed by the enumeration
841  functions.
842 */
843 
844 #ifndef NIX
845 
846 int sg_is_enumerable_adr(char* path)
847 {
848  int ret;
849  int bus_no, target_no, lun_no;
850  struct stat stbuf;
851 
852  if (strncmp("/dev/rdsk/", path, 10) != 0)
853  return 0;
854  ret = decode_btl_solaris(path + 10, &bus_no, &target_no, &lun_no, 0);
855  if (ret <= 0)
856  return 0;
857  if (stat(path, &stbuf) == -1)
858  return 0;
859  return 1;
860 }
861 
862 #else /* ! NIX */
863 
864 int sg_is_enumerable_adr(char* adr)
865 {
867  int initialize = 1, ret;
868  char buf[64];
869 
870  while(1) {
871  ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
872  initialize = 0;
873  if (ret <= 0)
874  break;
875  if (strcmp(adr, buf) == 0) {
876  sg_give_next_adr(&idx, buf, sizeof(buf), -1);
877  return 1;
878  }
879  }
880  sg_give_next_adr(&idx, buf, sizeof(buf), -1);
881  return (0);
882 }
883 #endif /* NIX */
884 
885 
886 
887 
888 /* Return 1 if the given path leads to a regular file or a device that can be
889  fseeked, read, and possibly written with 2 kB granularity.
890 */
891 int burn_os_is_2k_seekrw(char *path, int flag)
892 {
893  struct stat stbuf;
894 
895  if (stat(path, &stbuf) == -1)
896  return 0;
897  if (S_ISREG(stbuf.st_mode))
898  return 1;
899  if (S_ISBLK(stbuf.st_mode))
900  return 1;
901  return 0;
902 }
903 
904 
905 /** Estimate the potential payload capacity of a file address.
906  @param path The address of the file to be examined. If it does not
907  exist yet, then the directory will be inquired.
908  @param bytes The pointed value gets modified, but only if an estimation is
909  possible.
910  @return -2 = cannot perform necessary operations on file object
911  -1 = neither path nor dirname of path exist
912  0 = could not estimate size capacity of file object
913  1 = estimation has been made, bytes was set
914 */
915 int burn_os_stdio_capacity(char *path, off_t write_start, off_t *bytes)
916 {
917  struct stat stbuf;
918  int ret;
919 
920 #ifdef Libburn_os_has_statvfS
921  struct statvfs vfsbuf;
922 #endif
923 
924  char *testpath = NULL, *cpt;
925  off_t add_size = 0;
926 
927  BURN_ALLOC_MEM(testpath, char, 4096);
928 
929  testpath[0] = 0;
930  if (stat(path, &stbuf) == -1) {
931  strcpy(testpath, path);
932  cpt = strrchr(testpath, '/');
933  if(cpt == NULL)
934  strcpy(testpath, ".");
935  else if(cpt == testpath)
936  testpath[1] = 0;
937  else
938  *cpt = 0;
939  if (stat(testpath, &stbuf) == -1)
940  {ret = -1; goto ex;}
941 
942  } else if(S_ISBLK(stbuf.st_mode)) {
943  int open_mode = O_RDONLY, fd;
944 
945  fd = open(path, open_mode);
946  if (fd == -1)
947  {ret = -2; goto ex;}
948  *bytes = lseek(fd, 0, SEEK_END);
949  close(fd);
950  if (*bytes == -1) {
951  *bytes = 0;
952  {ret = 0; goto ex;}
953  }
954 
955  } else if(S_ISREG(stbuf.st_mode)) {
956  add_size = burn_sparse_file_addsize(write_start, &stbuf);
957  strcpy(testpath, path);
958  } else
959  {ret = 0; goto ex;}
960 
961  if (testpath[0]) {
962 
963 #ifdef Libburn_os_has_statvfS
964 
965  if (statvfs(testpath, &vfsbuf) == -1)
966  {ret = -2; goto ex;}
967  *bytes = add_size + ((off_t) vfsbuf.f_frsize) *
968  (off_t) vfsbuf.f_bavail;
969 
970 #else /* Libburn_os_has_statvfS */
971 
972  {ret = 0; goto ex;}
973 
974 #endif /* ! Libburn_os_has_stavtfS */
975 
976  }
977  ret = 1;
978 ex:;
979  BURN_FREE_MEM(testpath);
980  return ret;
981 }
982 
983 
984 /* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
985 
986 #ifdef Libburn_read_o_direcT
987 
988  /* No special O_DIRECT-like precautions are implemented here */
989 
990 #endif /* Libburn_read_o_direcT */
991 
992 
993 int burn_os_open_track_src(char *path, int open_flags, int flag)
994 {
995  int fd;
996 
997  fd = open(path, open_flags);
998  return fd;
999 }
1000 
1001 
1002 void *burn_os_alloc_buffer(size_t amount, int flag)
1003 {
1004  void *buf = NULL;
1005 
1006  buf = calloc(1, amount);
1007  return buf;
1008 }
1009 
1010 
1011 int burn_os_free_buffer(void *buffer, size_t amount, int flag)
1012 {
1013  if (buffer == NULL)
1014  return 0;
1015  free(buffer);
1016  return 1;
1017 }
1018 
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
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_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
#define LIBDAX_MSGS_SEV_FAILURE
Definition: libdax_msgs.h:205
static int sg_close_drive(struct burn_drive *d)
Definition: sg-solaris.c:181
int sg_issue_command(struct burn_drive *d, struct command *c)
Definition: sg-solaris.c:702
void * burn_os_alloc_buffer(size_t amount, int flag)
Definition: sg-solaris.c:1002
static int decode_btl_solaris(char *name, int *busno, int *tgtno, int *lunno, int flag)
Definition: sg-solaris.c:207
int sg_is_enumerable_adr(char *path)
Definition: sg-solaris.c:846
int sg_shutdown(int flag)
Definition: sg-solaris.c:504
int sg_grab(struct burn_drive *d)
Definition: sg-solaris.c:608
static int start_enum_cXtYdZs2(burn_drive_enumerator_t *idx, int flag)
Definition: sg-solaris.c:239
int sg_dispose_drive(struct burn_drive *d, int flag)
Definition: sg-solaris.c:519
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-solaris.c:1011
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-solaris.c:561
int burn_os_open_track_src(char *path, int open_flags, int flag)
Definition: sg-solaris.c:993
static int end_enum_cXtYdZs2(burn_drive_enumerator_t *idx, int flag)
Definition: sg-solaris.c:407
int burn_os_is_2k_seekrw(char *path, int flag)
Definition: sg-solaris.c:891
int burn_sg_open_o_excl
Definition: init.c:53
static int next_enum_cXtYdZs2(burn_drive_enumerator_t *idx, char adr[], int adr_size, int flag)
Definition: sg-solaris.c:304
int burn_os_stdio_capacity(char *path, off_t write_start, off_t *bytes)
Definition: sg-solaris.c:915
static int decode_btl_number(char **cpt, int stopper, int *no)
Definition: sg-solaris.c:192
int sg_initialize(char msg[1024], int flag)
Definition: sg-solaris.c:493
static void enumerate_common(char *fname, int bus_no, int host_no, int channel_no, int target_no, int lun_no)
Definition: sg-solaris.c:430
int burn_sg_log_scsi
Definition: init.c:110
int sg_drive_is_open(struct burn_drive *d)
Definition: sg-solaris.c:596
int sg_release(struct burn_drive *d)
Definition: sg-solaris.c:684
static int sg_solaris_convert_devname(char *path, char **dev_to_open, int flag)
Definition: sg-solaris.c:257
int sg_id_string(char msg[1024], int flag)
Definition: sg-solaris.c:479
int sg_give_next_adr(burn_drive_enumerator_t *idx, char adr[], int adr_size, int initialize)
Definition: sg-solaris.c:540
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, int *target_no, int *lun_no)
Definition: sg-solaris.c:817
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
enum burn_drive_status busy
Definition: transport.h:423
int(* issue_command)(struct burn_drive *, struct command *)
Definition: transport.h:459
int(* release)(struct burn_drive *)
Definition: transport.h:454
unsigned char sense[128]
Definition: transport.h:63
int oplen
Definition: transport.h:60
int dxfer_len
Definition: transport.h:62
double start_time
Definition: transport.h:70
int timeout
Definition: transport.h:68
double end_time
Definition: transport.h:71
int error
Definition: transport.h:65
int dir
Definition: transport.h:61
struct buffer * page
Definition: transport.h:67
unsigned char opcode[16]
Definition: transport.h:59
@ TO_DRIVE
Definition: transport.h:25
@ FROM_DRIVE
Definition: transport.h:25
#define BUFFER_SIZE
Definition: transport.h:21