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)  

drive.c
Go to the documentation of this file.
1 /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
2 
3 /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
4  Copyright (c) 2006 - 2020 Thomas Schmitt <scdbackup@gmx.net>
5  Provided under GPL version 2 or later.
6 */
7 
8 
9 #ifdef HAVE_CONFIG_H
10 #include "../config.h"
11 #endif
12 
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <signal.h>
18 #include <dirent.h>
19 
20 /* ts A61007 */
21 /* #include <a ssert.h> */
22 
23 #include <stdio.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <pthread.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 
30 /* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
31 #ifndef O_BINARY
32 #define O_BINARY 0
33 #endif
34 
35 #include "libburn.h"
36 #include "init.h"
37 #include "drive.h"
38 #include "transport.h"
39 #include "debug.h"
40 #include "init.h"
41 #include "toc.h"
42 #include "util.h"
43 #include "sg.h"
44 #include "structure.h"
45 
46 /* ts A70107 : to get BE_CANCELLED */
47 #include "error.h"
48 
49 /* ts A70219 : for burn_disc_get_write_mode_demands() */
50 #include "options.h"
51 
52 /* A70225 : to learn about eventual Libburn_dvd_r_dl_multi_no_close_sessioN */
53 #include "write.h"
54 
55 /* A70903 : for burn_scsi_setup_drive() */
56 #include "spc.h"
57 
58 /* A90815 : for mmc_obtain_profile_name() */
59 #include "mmc.h"
60 
61 /* B60730 : for Libburn_do_no_immed_defaulT */
62 #include "os.h"
63 
64 #include "libdax_msgs.h"
65 extern struct libdax_msgs *libdax_messenger;
66 
67 static struct burn_drive drive_array[255];
68 static int drivetop = -1;
69 
70 /* ts A80410 : in init.c */
72 
73 /* ts B10312 : in init.c */
74 extern int burn_drive_role_4_allowed;
75 
76 
77 /* ts A61021 : the unspecific part of sg.c:enumerate_common()
78 */
79 int burn_setup_drive(struct burn_drive *d, char *fname)
80 {
81  d->devname = strdup(fname);
82  memset(&d->params, 0, sizeof(struct params));
83  d->idata = NULL;
84  d->mdata = NULL;
85  d->toc_entry = NULL;
86  d->released = 1;
87  d->stdio_fd = -1;
89  d->erasable = 0;
90  d->current_profile = -1;
91  d->do_stream_recording = 0;
93  d->role_5_nwa = 0;
94 
95 #ifdef Libburn_do_no_immed_defaulT
96  d->do_no_immed = Libburn_do_no_immed_defaulT;
97 #else
98  d->do_no_immed = 0;
99 #endif
100 
101  d->features = NULL;
102  d->drive_serial_number = NULL;
103  d->drive_serial_number_len = -1;
104  d->media_serial_number = NULL;
105  d->media_serial_number_len = -1;
106  return 1;
107 }
108 
109 
110 /* ts A70903 */
112 {
113  if (d->idata != NULL)
114  free((void *) d->idata);
115  d->idata = NULL;
116  if (d->mdata != NULL) {
118  free((void *) d->mdata);
119  }
120  d->mdata = NULL;
121  if(d->toc_entry != NULL)
122  free((void *) d->toc_entry);
123  d->toc_entry = NULL;
124  if (d->devname != NULL)
125  free(d->devname);
126  d->devname = NULL;
127  if (d->stdio_fd >= 0)
128  close (d->stdio_fd);
129  d->stdio_fd = -1;
135  sg_dispose_drive(d, 0);
136 }
137 
138 
139 /* ts A60904 : ticket 62, contribution by elmom */
140 /* splitting former burn_drive_free() (which freed all, into two calls) */
142 {
143  if (d->global_index == -1)
144  return;
145  /* ts A60822 : close open fds before forgetting them */
146  if (d->drive_role == 1)
147  if (burn_drive_is_open(d)) {
148  d->unlock(d);
149  d->release(d);
150  }
152  d->global_index = -1;
153 }
154 
156 {
157  int i;
158 
159  for (i = 0; i < drivetop + 1; i++)
161  drivetop = -1;
162  memset(drive_array, 0, sizeof(drive_array));
163 }
164 
165 
166 /* ts A60822 */
168 {
169  if (d->drive_role != 1)
170  return (d->stdio_fd >= 0);
171  /* ts A61021 : moved decision to sg.c */
172  return d->drive_is_open(d);
173 }
174 
175 
176 /* ts A60906 */
178 {
179  d->busy = BURN_DRIVE_IDLE;
180  return 1;
181 }
182 
183 
184 /* ts A60906 */
186 {
187  return !!d->released;
188 }
189 
190 
191 /* ts A60906 */
192 /** Inquires drive status in respect to degree of app usage.
193  @param return -2 = drive is forgotten
194  -1 = drive is closed (i.e. released explicitly)
195  0 = drive is open, not grabbed (after scan, before 1st grab)
196  1 = drive is grabbed but BURN_DRIVE_IDLE
197  2 = drive is grabbed, synchronous read/write interrupted
198  10 = drive is grabbing (BURN_DRIVE_GRABBING)
199  100 = drive is busy in cancelable state
200  1000 = drive is in non-cancelable state
201  Expect a monotonous sequence of usage severity to emerge in future.
202 */
204 {
205  if(d->global_index < 0)
206  return -2;
207  if(!burn_drive_is_open(d))
208  return -1;
209  if(d->busy == BURN_DRIVE_GRABBING)
210  return 10;
211  if(d->released)
212  return 0;
213  if(d->busy == BURN_DRIVE_IDLE)
214  return 1;
215  if(d->busy == BURN_DRIVE_READING_SYNC ||
217  return 2;
218  if(d->busy == BURN_DRIVE_WRITING ||
222 
223  /* ts A70928 */
224  /* >>> how do i learn whether the writer thread is still
225  alive ? */;
226  /* >>> what to do if writer is dead ?
227  At least sync disc ?*/;
228  return 50;
229  }
230  if(d->busy == BURN_DRIVE_READING) {
231  return 50;
232  }
233  return 1000;
234 }
235 
236 
237 /*
238 void drive_read_lead_in(int dnum)
239 {
240  mmc_read_lead_in(&drive_array[dnum], get_4k());
241 }
242 */
243 unsigned int burn_drive_count(void)
244 {
245  return drivetop + 1;
246 }
247 
248 
249 /* ts A80801 */
250 int burn_drive_is_listed(char *path, struct burn_drive **found, int flag)
251 {
252  int i, ret;
253  char *drive_adr = NULL, *off_adr = NULL;
254 
255  BURN_ALLOC_MEM(drive_adr, char, BURN_DRIVE_ADR_LEN);
256  BURN_ALLOC_MEM(off_adr, char, BURN_DRIVE_ADR_LEN);
257 
258  ret = burn_drive_convert_fs_adr(path, off_adr);
259  if (ret <= 0)
260  strcpy(off_adr, path);
261  for (i = 0; i <= drivetop; i++) {
262  if (drive_array[i].global_index < 0)
263  continue;
264  ret = burn_drive_d_get_adr(&(drive_array[i]), drive_adr);
265  if (ret <= 0)
266  continue;
267  if(strcmp(off_adr, drive_adr) == 0) {
268  if (found != NULL)
269  *found= &(drive_array[i]);
270  {ret= 1; goto ex;}
271  }
272  }
273  ret= 0;
274 ex:;
275  BURN_FREE_MEM(drive_adr);
276  BURN_FREE_MEM(off_adr);
277  return ret;
278 }
279 
280 
281 /* ts A61125 : media status aspects of burn_drive_grab() */
283 {
284 
285  /* ts A61225 : after loading the tray, mode page 2Ah can change */
286  d->getcaps(d);
287 
288  /* ts A61020 : d->status was set to BURN_DISC_BLANK as pure guess */
289 
290  /* ts A71128 : run read_disc_info() for any recognizable profile */
291  if (d->current_profile > 0 || d->current_is_guessed_profile ||
292  (d->mdata->p2a_valid > 0 &&
293  (d->mdata->cdr_write || d->mdata->cdrw_write ||
294  d->mdata->dvdr_write || d->mdata->dvdram_write)) ) {
295  d->read_disc_info(d);
296  } else {
297  if (d->current_profile == -1 || d->current_is_cd_profile)
298  d->read_toc(d);
299 
300  /* ts A70314 , B10712 */
301  if (d->status != BURN_DISC_EMPTY)
303  }
304  return 1;
305 }
306 
307 /* ts B10730 */
308 /* Send a default mode page 05 to CD and DVD-R-oids */
310 {
311  struct burn_write_opts *opts;
312 
313  if (d->sent_default_page_05)
314  return 0;
315  if (!((d->status == BURN_DISC_APPENDABLE ||
316  d->status == BURN_DISC_BLANK) &&
317  (d->current_is_cd_profile || d->current_profile == 0x11 ||
318  d->current_profile == 0x14 || d->current_profile == 0x15)))
319  return 0;
320  opts = burn_write_opts_new(d);
321  if (opts == NULL)
322  return -1;
323  if (d->status == BURN_DISC_APPENDABLE)
326  else
329  d->send_write_parameters(d, NULL, -1, opts);
330  burn_write_opts_free(opts);
331  d->sent_default_page_05 = 1;
332  return 1;
333 }
334 
335 
336 /* ts A70924 */
338 {
339  int fd = -1, i;
340 
341  if (strcmp(adr, "-") == 0)
342  fd = 1;
343  if(strncmp(adr, "/dev/fd/", 8) == 0) {
344  for (i = 8; adr[i]; i++)
345  if (!isdigit(adr[i]))
346  break;
347  if (i> 8 && adr[i] == 0)
348  fd = atoi(adr + 8);
349  }
350  return fd;
351 }
352 
353 /* @param flag bit0= accept read-only files and return 2 in this case
354  bit1= accept write-only files and return 3 in this case
355 */
356 static int burn_drive__is_rdwr(char *fname, int *stat_ret,
357  struct stat *stbuf_ret,
358  off_t *read_size_ret, int flag)
359 {
360  int fd, is_rdwr = 1, ret, getfl_ret, st_ret, mask;
361  struct stat stbuf;
362  off_t read_size = 0;
363 
364  memset(&stbuf, 0, sizeof(struct stat));
366  if (fd >= 0)
367  st_ret = fstat(fd, &stbuf);
368  else
369  st_ret = stat(fname, &stbuf);
370  if (st_ret != -1) {
371  is_rdwr = burn_os_is_2k_seekrw(fname, 0);
372  ret = 1;
373  if (S_ISREG(stbuf.st_mode))
374  read_size = stbuf.st_size;
375  else if (is_rdwr)
376  ret = burn_os_stdio_capacity(fname, 0, &read_size);
377  if (ret <= 0 ||
378  read_size / (off_t) 2048 >= (off_t) 0x7ffffff0)
379  read_size = (off_t) 0x7ffffff0 * (off_t) 2048;
380  }
381 
382  if (is_rdwr && fd >= 0) {
383  getfl_ret = fcntl(fd, F_GETFL);
384 
385 /*
386 fprintf(stderr, "LIBBURN_DEBUG: burn_drive__is_rdwr: getfl_ret = %lX , O_RDWR = %lX , & = %lX , O_RDONLY = %lX\n", (unsigned long) getfl_ret, (unsigned long) O_RDWR, (unsigned long) (getfl_ret & O_RDWR), (unsigned long) O_RDONLY);
387 */
388 
389  mask = O_RDWR | O_WRONLY | O_RDONLY;
390 
391  if (getfl_ret == -1 || (getfl_ret & mask) != O_RDWR)
392  is_rdwr = 0;
393  if ((flag & 1) && getfl_ret != -1 &&
394  (getfl_ret & mask) == O_RDONLY)
395  is_rdwr = 2;
396  if ((flag & 2) && getfl_ret != -1 &&
397  (getfl_ret & mask) == O_WRONLY)
398  is_rdwr = 3;
399  }
400  if (stat_ret != NULL)
401  *stat_ret = st_ret;
402  if (stbuf_ret != NULL)
403  memcpy(stbuf_ret, &stbuf, sizeof(struct stat));
404  if (read_size_ret != NULL)
405  *read_size_ret = read_size;
406  return is_rdwr;
407 }
408 
409 
410 /* flag bit0= ( not needed yet: grab even if it is already grabbed )
411 */
412 int burn_drive_grab_stdio(struct burn_drive *d, int flag)
413 {
414  int stat_ret = -1, is_rdwr, ret;
415  struct stat stbuf;
416  off_t read_size= 0, size= 0;
417  char fd_name[40], *name_pt = NULL;
418 
419  if(d->stdio_fd >= 0) {
420  sprintf(fd_name, "/dev/fd/%d", d->stdio_fd);
421  name_pt = fd_name;
422  } else if (d->devname[0]) {
423  name_pt = d->devname;
424  }
425  if (name_pt != NULL) {
426  /* re-assess d->media_read_capacity and free space */
427  is_rdwr = burn_drive__is_rdwr(name_pt, &stat_ret, &stbuf,
428  &read_size, 1 | 2);
429  /* despite its name : last valid address, not size */
431  read_size / 2048 - !(read_size % 2048);
432  d->mr_capacity_trusted = 1;
433  if ((stat_ret == -1 || is_rdwr) && d->devname[0]) {
434  ret = burn_os_stdio_capacity(d->devname, 0, &size);
435  if (ret > 0)
437  size);
438  }
439  }
440 
441  d->released = 0;
442  d->current_profile = 0xffff;
443  if(d->drive_role == 2 || d->drive_role == 3) {
444  d->status = BURN_DISC_BLANK;
445  } else if(d->drive_role == 4) {
446  if (d->media_read_capacity > 0)
447  d->status = BURN_DISC_FULL;
448  else
449  d->status = BURN_DISC_EMPTY;
450  } else if(d->drive_role == 5) {
451  if (stat_ret != -1 && S_ISREG(stbuf.st_mode) &&
452  stbuf.st_size > 0) {
454  if (stbuf.st_size / (off_t) 2048
455  >= 0x7ffffff0) {
456  d->status = BURN_DISC_FULL;
457  d->role_5_nwa = 0x7ffffff0;
458  } else
459  d->role_5_nwa = stbuf.st_size / 2048 +
460  !!(stbuf.st_size % 2048);
461  } else
462  d->status = BURN_DISC_BLANK;
463  } else {
464  d->status = BURN_DISC_EMPTY;
465  d->current_profile = 0;
466  }
467  d->busy = BURN_DRIVE_IDLE;
468  return 1;
469 }
470 
471 
472 int burn_drive_grab(struct burn_drive *d, int le)
473 {
474  int errcode;
475  /* ts A61125 - B20122 */
476  int ret, sose, signal_action_mem = -1;
477 
478  sose = d->silent_on_scsi_error;
479  if (!d->released) {
481  0x00020189, LIBDAX_MSGS_SEV_FATAL,
483  "Drive is already grabbed by libburn", 0, 0);
484  return 0;
485  }
486  if(d->drive_role != 1) {
487  ret = burn_drive_grab_stdio(d, 0);
488  return ret;
489  }
490 
492  errcode = d->grab(d);
493  if (errcode == 0)
494  return 0;
495 
496  burn_grab_prepare_sig_action(&signal_action_mem, 0);
498 
499  if (le)
500  d->load(d);
501  if (d->cancel || burn_is_aborting(0))
502  {ret = 0; goto ex;}
503 
504  d->lock(d);
505  if (d->cancel || burn_is_aborting(0))
506  {ret = 0; goto ex;}
507 
508  /* ts A61118 */
509  d->start_unit(d);
510  if (d->cancel || burn_is_aborting(0))
511  {ret = 0; goto ex;}
512 
513  /* ts A61202 : gave bit1 of le a meaning */
514  if (!le)
515  d->silent_on_scsi_error = 1;
516  /* ts A61125 : outsourced media state inquiry aspects */
517  ret = burn_drive_inquire_media(d);
518  if (d->cancel || burn_is_aborting(0))
519  {ret = 0; goto ex;}
520 
522  if (d->cancel || burn_is_aborting(0))
523  {ret = 0; goto ex;}
524 
525 ex:;
526  if (d->cancel || burn_is_aborting(0)) {
527  d->unlock(d);
528  d->release(d);
529  }
530  d->silent_on_scsi_error = sose;
531  d->busy = BURN_DRIVE_IDLE;
532  burn_grab_restore_sig_action(signal_action_mem, 0);
533  return ret;
534 }
535 
536 
537 /* ts A71015 */
538 #define Libburn_ticket_62_re_register_is_possiblE 1
539 
541 {
542 #ifdef Libburn_ticket_62_re_register_is_possiblE
543  int i;
544 #endif
545 
546  d->block_types[0] = 0;
547  d->block_types[1] = 0;
548  d->block_types[2] = 0;
549  d->block_types[3] = 0;
550  d->toc_temp = 0;
551  d->nwa = 0;
552  d->alba = 0;
553  d->rlba = 0;
554  d->cancel = 0;
555  d->busy = BURN_DRIVE_IDLE;
556  d->thread_pid = 0;
557  d->thread_pid_valid = 0;
558  memset(&(d->thread_tid), 0, sizeof(d->thread_tid));
559  d->medium_state_changed = 0;
561  d->set_streaming_err = 0;
562  d->toc_entries = 0;
563  d->toc_entry = NULL;
564  d->disc = NULL;
565  d->erasable = 0;
566  d->write_opts = NULL;
567 
568 #ifdef Libburn_ticket_62_re_register_is_possiblE
569  /* ts A60904 : ticket 62, contribution by elmom */
570  /* Not yet accepted because no use case seen yet */
571  /* ts A71015 : xorriso dialog imposes a use case now */
572 
573  /* This is supposed to find an already freed drive struct among
574  all the the ones that have been used before */
575  for (i = 0; i < drivetop + 1; i++)
576  if (drive_array[i].global_index == -1)
577  break;
578  d->global_index = i;
579  memcpy(&drive_array[i], d, sizeof(struct burn_drive));
580  pthread_mutex_init(&drive_array[i].access_lock, NULL);
581  if (drivetop < i)
582  drivetop = i;
583  return &(drive_array[i]);
584 
585 #else /* Libburn_ticket_62_re_register_is_possiblE */
586  /* old A60904 : */
587  /* Still active by default */
588 
589  d->global_index = drivetop + 1;
590  memcpy(&drive_array[drivetop + 1], d, sizeof(struct burn_drive));
591  pthread_mutex_init(&drive_array[drivetop + 1].access_lock, NULL);
592  return &drive_array[++drivetop];
593 
594 #endif /* ! Libburn_ticket_62_re_register_is_possiblE */
595 
596 }
597 
598 
599 /* unregister most recently registered drive */
601 {
602  if(d->global_index != drivetop)
603  return 0;
604  burn_drive_free(d);
605  drivetop--;
606  return 1;
607 }
608 
609 
610 /* ts A61021 : after-setup activities from sg.c:enumerate_common()
611 */
613 {
614  struct burn_drive *t = NULL;
615  char *msg = NULL;
616  int ret;
617 
618  BURN_ALLOC_MEM(msg, char, BURN_DRIVE_ADR_LEN + 160);
619 
620  d->drive_role = 1; /* MMC drive */
621 
622  t = burn_drive_register(d);
623 
624  /* ts A60821 */
625  mmc_function_spy(NULL, "enumerate_common : -------- doing grab");
626 
627  /* try to get the drive info */
628  ret = t->grab(t);
629  if (ret) {
630  t->getcaps(t);
631  t->unlock(t);
632  t->released = 1;
633  } else {
634  /* ts A90602 */
635  d->mdata->p2a_valid = -1;
636  sprintf(msg, "Unable to grab scanned drive %s", d->devname);
638  0x0002016f, LIBDAX_MSGS_SEV_DEBUG,
639  LIBDAX_MSGS_PRIO_LOW, msg, 0, 0);
641  t = NULL;
642  }
643 
644  /* ts A60821 */
645  mmc_function_spy(NULL, "enumerate_common : ----- would release ");
646 
647 ex:
648  BURN_FREE_MEM(msg);
649  return t;
650 }
651 
652 
653 /* ts A61125 : model aspects of burn_drive_release */
654 /* @param flag bit3= do not close d->stdio_fd
655 */
656 int burn_drive_mark_unready(struct burn_drive *d, int flag)
657 {
658  /* ts A61020 : mark media info as invalid */
659  d->start_lba= -2000000000;
660  d->end_lba= -2000000000;
661 
662  /* ts A61202 */
663  d->current_profile = -1;
664  d->current_has_feat21h = 0;
665  d->current_feat2fh_byte4 = -1;
666 
668  if (d->toc_entry != NULL)
669  free(d->toc_entry);
670  d->toc_entry = NULL;
671  d->toc_entries = 0;
672  if (d->write_opts != NULL) {
674  d->write_opts = NULL;
675  }
676  if (d->disc != NULL) {
677  burn_disc_free(d->disc);
678  d->disc = NULL;
679  }
680  if (!(flag & 8)) {
681  if (d->stdio_fd >= 0)
682  close (d->stdio_fd);
683  d->stdio_fd = -1;
684  }
685  return 1;
686 }
687 
688 
689 /* ts A70918 : outsourced from burn_drive_release() and enhanced */
690 /** @param flag bit0-2 = mode : 0=unlock , 1=unlock+eject , 2=leave locked
691  bit3= do not call d->release()
692 */
693 int burn_drive_release_fl(struct burn_drive *d, int flag)
694 {
695  if (d->released) {
696  /* ts A61007 */
698  d->global_index, 0x00020105,
700  "Drive is already released", 0, 0);
701  return 0;
702  }
703 
704  /* ts A61007 */
705  /* ts A60906: one should not assume BURN_DRIVE_IDLE == 0 */
706  /* a ssert(d->busy == BURN_DRIVE_IDLE); */
707  if (d->busy != BURN_DRIVE_IDLE) {
709  d->global_index, 0x00020106,
711  "Drive is busy on attempt to close", 0, 0);
712  return 0;
713  }
714 
715  if (d->drive_role == 1) {
716  if (d->needs_sync_cache)
717  d->sync_cache(d);
718  if ((flag & 7) != 2)
719  d->unlock(d);
720  if ((flag & 7) == 1)
721  d->eject(d);
722  if (!(flag & 8)) {
723  burn_drive_snooze(d, 0);
724  d->release(d);
725  }
726  }
727 
728  d->needs_sync_cache = 0; /* just to be sure */
729 
730  if (d->drive_serial_number != NULL)
732  if (d->media_serial_number != NULL)
736 
737  d->released = 1;
738 
739  /* ts A61125 : outsourced model aspects */
740  burn_drive_mark_unready(d, flag & 8);
741  return 1;
742 }
743 
744 
745 /* API */
746 /* ts A90824
747  @param flag bit0= wake up (else start snoozing)
748 */
749 int burn_drive_snooze(struct burn_drive *d, int flag)
750 {
751  if (d->drive_role != 1)
752  return 0;
753  if (flag & 1)
754  d->start_unit(d);
755  else
756  d->stop_unit(d);
757  return 1;
758 }
759 
760 
761 /* API */
762 void burn_drive_release(struct burn_drive *d, int le)
763 {
764  burn_drive_release_fl(d, !!le);
765 }
766 
767 
768 /* ts B11002 */
769 /* API */
770 int burn_drive_re_assess(struct burn_drive *d, int flag)
771 {
772  int ret, signal_action_mem;
773 
774  if (d->released) {
776  0x00020108,
778  "Drive is not grabbed on burn_drive_re_assess()",
779  0, 0);
780  return 0;
781  }
782  burn_drive_release_fl(d, 2 | 8);
783 
784  if(d->drive_role != 1) {
785  ret = burn_drive_grab_stdio(d, 0);
786  return ret;
787  }
788 
789  burn_grab_prepare_sig_action(&signal_action_mem, 0);
791  ret = burn_drive_inquire_media(d);
793  d->busy = BURN_DRIVE_IDLE;
794  burn_grab_restore_sig_action(signal_action_mem, 0);
795  d->released = 0;
796  return ret;
797 }
798 
799 
800 /* ts A70918 */
801 /* API */
802 int burn_drive_leave_locked(struct burn_drive *d, int flag)
803 {
804  return burn_drive_release_fl(d, 2);
805 }
806 
807 
808 /* ts A61007 : former void burn_wait_all() */
809 /* @param flag bit0= demand freed drives (else released drives) */
811 {
812  int i;
813 
814  for (i = burn_drive_count() - 1; i >= 0; --i) {
815  /* ts A60904 : ticket 62, contribution by elmom */
816  if (drive_array[i].global_index == -1)
817  continue;
818  if (drive_array[i].released && !(flag & 1))
819  continue;
820  return 0;
821  }
822  return 1;
823 }
824 
825 
826 #if 0
827 void burn_wait_all(void)
828 {
829  unsigned int i;
830  int finished = 0;
831  struct burn_drive *d;
832 
833  while (!finished) {
834  finished = 1;
835  d = drive_array;
836  for (i = burn_drive_count(); i > 0; --i, ++d) {
837 
838  /* ts A60904 : ticket 62, contribution by elmom */
839  if (d->global_index==-1)
840  continue;
841 
842  a ssert(d->released);
843  }
844  if (!finished)
845  sleep(1);
846  }
847 }
848 #endif
849 
850 
851 void burn_disc_erase_sync(struct burn_drive *d, int fast)
852 {
853  int ret, was_error = 0;
854 
855  if (d->drive_role == 5) { /* Random access write-only drive */
856  ret = truncate(d->devname, (off_t) 0);
857  if (ret == -1) {
859  0x00020182,
861  "Cannot truncate disk file for pseudo blanking",
862  0, 0);
863  return;
864  }
865  d->role_5_nwa = 0;
866  d->cancel = 0;
867  d->status = BURN_DISC_BLANK;
868  d->busy = BURN_DRIVE_IDLE;
869  d->progress.sector = 0x10000;
870  return;
871  }
872 
873  d->cancel = 0;
874 
875 #ifdef Libburn_reset_progress_asynC
876  /* <<< This is now done in async.c */
877  /* reset the progress */
878  d->progress.session = 0;
879  d->progress.sessions = 1;
880  d->progress.track = 0;
881  d->progress.tracks = 1;
882  d->progress.index = 0;
883  d->progress.indices = 1;
884  d->progress.start_sector = 0;
885  d->progress.sectors = 0x10000;
886  d->progress.sector = 0;
887 #endif /* Libburn_reset_progress_asynC */
888 
889  d->medium_state_changed = 1;
890  d->erase(d, fast);
892 
893 #ifdef Libburn_old_progress_looP
894 
895  /* read the initial 0 stage */
896  while (!d->test_unit_ready(d) && d->get_erase_progress(d) == 0)
897  sleep(1);
898  while ((d->progress.sector = d->get_erase_progress(d)) > 0 ||
899  !d->test_unit_ready(d))
900  sleep(1);
901 
902 #else /* Libburn_old_progress_looP */
903 
904  while (1) {
905 
906  /* >>> ??? ts B60730 : abort if user interrupts ?
907  if (d->cancel)
908  break;
909  */
910 
911  ret = d->get_erase_progress(d);
912  if (ret == -2 || ret > 0)
913  break;
914  if (ret == -3)
915  was_error = 1;
916  sleep(1);
917  }
918  while (1) {
919 
920  /* >>> ??? ts B60730 : abort if user interrupts ?
921  if (d->cancel)
922  break;
923  */
924 
925  ret = d->get_erase_progress(d);
926  if(ret == -2)
927  break;
928  if (ret == -3)
929  was_error = 1;
930  if (ret >= 0)
931  d->progress.sector = ret;
932  sleep(1);
933  }
934 
935 #endif /* ! Libburn_old_progress_looP */
936 
937  d->progress.sector = 0x10000;
938 
939  /* ts A61125 : update media state records */
941  if (d->drive_role == 1 && !d->cancel)
943  d->busy = BURN_DRIVE_IDLE;
944  if (was_error)
945  d->cancel = 1;
946 }
947 
948 /*
949  @param flag: bit0 = fill formatted size with zeros
950  bit1, bit2 , bit4, bit5, bit7 - bit15 are for d->format_unit()
951 */
952 void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
953 {
954  int ret, buf_secs, err, i, stages = 1, pbase, pfill, pseudo_sector;
955  int was_error = 0;
956  off_t num_bufs;
957  char msg[80];
958  struct buffer *buf = NULL, *buf_mem = d->buffer;
959 
960  BURN_ALLOC_MEM(buf, struct buffer, 1);
961 
962 #ifdef Libburn_reset_progress_asynC
963  /* <<< This is now done in async.c */
964  /* reset the progress */
965  d->progress.session = 0;
966  d->progress.sessions = 1;
967  d->progress.track = 0;
968  d->progress.tracks = 1;
969  d->progress.index = 0;
970  d->progress.indices = 1;
971  d->progress.start_sector = 0;
972  d->progress.sectors = 0x10000;
973  d->progress.sector = 0;
974 #endif /* Libburn_reset_progress_asynC */
975 
976  stages = 1 + ((flag & 1) && size > 1024 * 1024);
977  d->cancel = 0;
979  d->medium_state_changed = 1;
980 
981  ret = d->format_unit(d, size, flag & 0xfff6); /* forward bits */
982  if (ret <= 0)
983  d->cancel = 1;
984 
985 #ifdef Libburn_old_progress_looP
986 
987  while (!d->test_unit_ready(d) && d->get_erase_progress(d) == 0)
988  sleep(1);
989  while ((pseudo_sector = d->get_erase_progress(d)) > 0 ||
990  !d->test_unit_ready(d)) {
991  d->progress.sector = pseudo_sector / stages;
992  sleep(1);
993  }
994 
995 #else /* Libburn_old_progress_looP */
996 
997  while (1) {
998  ret = d->get_erase_progress(d);
999  if (ret == -2 || ret > 0)
1000  break;
1001  if (ret == -3)
1002  was_error = 1;
1003  sleep(1);
1004  }
1005  while (1) {
1006  pseudo_sector = d->get_erase_progress(d);
1007  if(pseudo_sector == -2)
1008  break;
1009  if (pseudo_sector == -3)
1010  was_error = 1;
1011  if (pseudo_sector >= 0)
1012  d->progress.sector = pseudo_sector / stages;
1013  sleep(1);
1014  }
1015 
1016 #endif /* ! Libburn_old_progress_looP */
1017 
1018  d->sync_cache(d);
1019 
1020  if (size <= 0)
1021  goto ex;
1022 
1023  /* update media state records */
1026  if (flag & 1) {
1027  /* write size in zeros */;
1028  pbase = 0x8000 + 0x7fff * (stages == 1);
1029  pfill = 0xffff - pbase;
1030  buf_secs = 16; /* Must not be more than 16 */
1031  num_bufs = size / buf_secs / 2048;
1032  if (num_bufs > 0x7fffffff) {
1033  d->cancel = 1;
1034  goto ex;
1035  }
1036 
1037  /* <<< */
1038  sprintf(msg,
1039  "Writing %.f sectors of zeros to formatted media",
1040  (double) num_bufs * (double) buf_secs);
1042  0x00000002,
1044  msg, 0, 0);
1045 
1046  d->buffer = buf;
1047  memset(d->buffer, 0, sizeof(struct buffer));
1048  d->buffer->bytes = buf_secs * 2048;
1049  d->buffer->sectors = buf_secs;
1050  d->busy = BURN_DRIVE_WRITING;
1051  for (i = 0; i < num_bufs; i++) {
1052  d->nwa = i * buf_secs;
1053  err = d->write(d, d->nwa, d->buffer);
1054  if (err == BE_CANCELLED || d->cancel) {
1055  d->cancel = 1;
1056  break;
1057  }
1058  d->progress.sector = pbase
1059  + pfill * ((double) i / (double) num_bufs);
1060  }
1061  d->sync_cache(d);
1062  if (d->current_profile == 0x13 || d->current_profile == 0x1a) {
1063  /* DVD-RW or DVD+RW */
1065  /* CLOSE SESSION, 010b */
1066  d->close_track_session(d, 1, 0);
1067  d->busy = BURN_DRIVE_WRITING;
1068  }
1069  }
1070 ex:;
1071  d->progress.sector = 0x10000;
1072  d->busy = BURN_DRIVE_IDLE;
1073  d->buffer = buf_mem;
1074  if (was_error)
1075  d->cancel = 1;
1076  BURN_FREE_MEM(buf);
1077 }
1078 
1079 
1080 /* ts A70112 API */
1081 int burn_disc_get_formats(struct burn_drive *d, int *status, off_t *size,
1082  unsigned *bl_sas, int *num_formats)
1083 {
1084  int ret;
1085 
1086  *status = 0;
1087  *size = 0;
1088  *bl_sas = 0;
1089  *num_formats = 0;
1090  if (d->drive_role != 1)
1091  return 0;
1092  ret = d->read_format_capacities(d, 0x00);
1093  if (ret <= 0)
1094  return 0;
1095  *status = d->format_descr_type;
1096  *size = d->format_curr_max_size;
1097  *bl_sas = d->format_curr_blsas;
1098  *num_formats = d->num_format_descr;
1099  return 1;
1100 }
1101 
1102 
1103 /* ts A70112 API */
1104 int burn_disc_get_format_descr(struct burn_drive *d, int index,
1105  int *type, off_t *size, unsigned *tdp)
1106 {
1107  *type = 0;
1108  *size = 0;
1109  *tdp = 0;
1110  if (index < 0 || index >= d->num_format_descr)
1111  return 0;
1112  *type = d->format_descriptors[index].type;
1113  *size = d->format_descriptors[index].size;
1114  *tdp = d->format_descriptors[index].tdp;
1115  return 1;
1116 }
1117 
1118 
1120 {
1121  /* ts A61007 */
1122  /* a ssert(!d->released); */
1123  if (d->released) {
1125  d->global_index, 0x00020108,
1127  "Drive is not grabbed on disc status inquiry",
1128  0, 0);
1129  return BURN_DISC_UNGRABBED;
1130  }
1131 
1132  return d->status;
1133 }
1134 
1136 {
1137  return d->erasable;
1138 }
1140  struct burn_progress *p)
1141 {
1142  /* --- Part of asynchronous signal handling --- */
1143  /* This frequently used call may be used to react on messages from
1144  the libburn built-in signal handler.
1145  */
1146 
1147  /* ts B00225 :
1148  If aborting with action 2:
1149  catch control thread after it returned from signal handler.
1150  Let it run burn_abort(4440,...)
1151  */
1153 
1154  /* ts A70928 : inform control thread of signal in sub-threads */
1155  if (burn_builtin_triggered_action < 2 && burn_global_abort_level > 0)
1157  if (burn_builtin_triggered_action < 2 && burn_global_abort_level > 5) {
1158  if (burn_global_signal_handler == NULL)
1159  kill(getpid(), burn_global_abort_signum);
1160  else
1165  }
1166 
1167  /* --- End of asynchronous signal handling --- */
1168 
1169 
1170  if (p != NULL) {
1171  memcpy(p, &(d->progress), sizeof(struct burn_progress));
1172  /* TODO: add mutex */
1173  }
1174  return d->busy;
1175 }
1176 
1177 
1178 int burn_drive_set_stream_recording(struct burn_drive *d, int recmode,
1179  int start, int flag)
1180 {
1181 #ifndef Libburn_force_stream_recordinG
1182  struct burn_feature_descr *descr;
1183 #endif
1184 
1185  if (recmode == 1) {
1186 
1187 #ifdef Libburn_force_stream_recordinG
1188 
1189  d->do_stream_recording = 1;
1190 
1191 #else /* Libburn_force_stream_recordinG */
1192 
1193  d->do_stream_recording = 0;
1194  if (burn_drive_has_feature(d, 0x107, &descr, 0)) {
1195  if ((descr->data[0] & 1) && (descr->flags & 1))
1196  d->do_stream_recording = 1;
1197  }
1198  if (!d->do_stream_recording) {
1200  0x000201ac,
1202  "Drive currently does not offer Stream Recording",
1203  0, 0);
1204  } else if (d->current_profile != 0x12 &&
1205  d->current_profile != 0x41 &&
1206  d->current_profile != 0x43) {
1207  d->do_stream_recording = 0;
1209  0x000201ad,
1211  "Stream Recording suppressed due to medium type",
1212  0, 0);
1213  }
1214 
1215 #endif /* ! Libburn_force_stream_recordinG */
1216 
1217  } else if (recmode == -1) {
1218  d->do_stream_recording = 0;
1219  }
1220  if (d->do_stream_recording)
1221  d->stream_recording_start = start;
1222  else
1223  d->stream_recording_start = 0;
1224  return(1);
1225 }
1226 
1228 {
1229 /* ts B00225 : these mutexes are unnecessary because "= 1" is atomar.
1230  pthread_mutex_lock(&d->access_lock);
1231 */
1232  if (!d->cancel) {
1233  libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
1235  "burn_drive_cancel() was called", 0, 0);
1236  }
1237  d->cancel = 1;
1238 /*
1239  pthread_mutex_unlock(&d->access_lock);
1240 */
1241 }
1242 
1243 
1244 static void strip_spaces(char *str, size_t len)
1245 {
1246  char *tmp, *tmp2;
1247 
1248  /* Remove trailing blanks */
1249  for (tmp = str + len - 1; tmp >= str && (isspace(*tmp) || !*tmp); tmp--)
1250  *tmp = 0;
1251  /* Condense remaining blank intervals to single blanks */
1252  for (tmp = str; tmp < str + len - 1 && *tmp; tmp++) {
1253  if (isspace(*tmp) && isspace(*(tmp + 1))) {
1254  for (tmp2 = tmp + 1; tmp2 < str + len && *tmp2; tmp2++)
1255  *(tmp2 - 1) = *tmp2;
1256  *(tmp2 - 1) = '\0';
1257  tmp--; /* try same first blank again */
1258  }
1259  }
1260 }
1261 
1262 static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
1263 {
1264  struct burn_scsi_inquiry_data *id;
1265  int i, profile;
1266  struct burn_feature_descr *feat;
1267 
1268  /* ts A61007 : now prevented in enumerate_common() */
1269 #if 0
1270  a ssert(d->idata);
1271  a ssert(d->mdata);
1272 #endif
1273 
1274  if(d->idata->valid <= 0)
1275  return 0;
1276 
1277  id = (struct burn_scsi_inquiry_data *)d->idata;
1278 
1279  memcpy(out->vendor, id->vendor, sizeof(id->vendor));
1280  strip_spaces(out->vendor, sizeof(id->vendor));
1281  memcpy(out->product, id->product, sizeof(id->product));
1282  strip_spaces(out->product, sizeof(id->product));
1283  memcpy(out->revision, id->revision, sizeof(id->revision));
1284  strip_spaces(out->revision, sizeof(id->revision));
1285  strncpy(out->location, d->devname, 16);
1286  out->location[16] = '\0';
1287 
1288  if (d->mdata->p2a_valid > 0) {
1289  out->buffer_size = d->mdata->buffer_size;
1290  out->read_dvdram = !!d->mdata->dvdram_read;
1291  out->read_dvdr = !!d->mdata->dvdr_read;
1292  out->read_dvdrom = !!d->mdata->dvdrom_read;
1293  out->read_cdr = !!d->mdata->cdr_read;
1294  out->read_cdrw = !!d->mdata->cdrw_read;
1295  out->write_dvdram = !!d->mdata->dvdram_write;
1296  out->write_dvdr = !!d->mdata->dvdr_write;
1297  out->write_cdr = !!d->mdata->cdr_write;
1298  out->write_cdrw = !!d->mdata->cdrw_write;
1299  out->write_simulate = !!d->mdata->simulate;
1300  out->c2_errors = !!d->mdata->c2_pointers;
1301  } else {
1302  out->buffer_size = out->read_dvdram = out->read_dvdr = 0;
1303  out->read_dvdrom = out->read_cdr = out->read_cdrw = 0;
1304  out->write_dvdram = out->write_dvdr = out->write_cdr = 0;
1305  out->write_cdrw = out->write_simulate = out->c2_errors = 0;
1306  for (i = 0; i < d->num_profiles; i++) {
1307  profile = (d->all_profiles[i * 4] << 8) |
1308  d->all_profiles[i * 4 + 1];
1309  if (profile == 0x09)
1310  out->write_cdr = out->read_cdr = 1;
1311  else if (profile == 0x0a)
1312  out->write_cdrw = out->read_cdrw = 1;
1313  else if (profile == 0x10)
1314  out->read_dvdrom = 1;
1315  else if (profile == 0x11)
1316  out->write_dvdr = out->read_dvdr = 1;
1317  else if (profile == 0x12)
1318  out->write_dvdram = out->read_dvdram = 1;
1319  }
1320 
1321  /* Test Write bit of CD TAO, CD Mastering, DVD-R/-RW Write */
1322  for (i = 0x002D; i <= 0x002F; i++)
1323  if (burn_drive_has_feature(d, i, &feat, 0))
1324  if (feat->data_lenght > 0)
1325  out->write_simulate |=
1326  !!(feat->data[0] & 4);
1327  }
1328 
1329  out->drive = d;
1330 
1331 #ifdef Libburn_dummy_probe_write_modeS
1332 
1333  /* ts A91112 */
1334  /* Set default block types. The call d->probe_write_modes() is quite
1335  obtrusive. It may be performed explicitly by new API call
1336  burn_drive_probe_cd_write_modes().
1337  */
1338  if (out->write_dvdram || out->write_dvdr ||
1339  out->write_cdrw || out->write_cdr) {
1344  } else {
1347  }
1349  out->packet_block_types = 0;
1350 
1351 #else /* Libburn_dummy_probe_write_modeS */
1352 
1353  /* update available block types for burners */
1354  if (out->write_dvdram || out->write_dvdr ||
1355  out->write_cdrw || out->write_cdr)
1356  d->probe_write_modes(d);
1361 
1362 #endif /* ! Libburn_dummy_probe_write_modeS */
1363 
1364  return 1;
1365 }
1366 
1367 
1368 
1369 /* ts A91112 - B00114 API */
1370 /* Probe available CD write modes and block types.
1371 */
1373 {
1374  struct burn_drive *d = dinfo->drive;
1375 
1376  if (d == NULL)
1377  return 0;
1378  if (dinfo->write_dvdram || dinfo->write_dvdr ||
1379  dinfo->write_cdrw || dinfo->write_cdr)
1380  d->probe_write_modes(d);
1385  return 1;
1386 }
1387 
1388 
1389 /* ts A70907 : added parameter flag */
1390 /* @param flag bit0= reset global drive list */
1392  unsigned int *n_drives, int flag)
1393 {
1394  /* ts A70907 :
1395  There seems to have been a misunderstanding about the role of
1396  burn_drive_scan_sync(). It needs no static state because it
1397  is only started once during an asynchronous scan operation.
1398  Its starter, burn_drive_scan(), is the one which ends immediately
1399  and gets called repeatedly. It acts on start of scanning by
1400  calling burn_drive_scan_sync(), returns idle while scanning is
1401  not done and finally removes the worker object which represented
1402  burn_drive_scan_sync().
1403  The scanning itself is not parallel but enumerates sequentially
1404  drive by drive (within scsi_enumerate_drives()).
1405 
1406  I will use "scanned" for marking drives found by previous runs.
1407  It will not be static any more.
1408  */
1409  /* ts A71015 : this makes only trouble : static int scanning = 0; */
1410  /* ts A70907 :
1411  These variables are too small anyway. We got up to 255 drives.
1412  static int scanned = 0, found = 0;
1413  Variable "found" was only set but never read.
1414  */
1415  unsigned char scanned[32];
1416  unsigned count = 0;
1417  int i, ret;
1418 
1419  /* ts A61007 : moved up to burn_drive_scan() */
1420  /* a ssert(burn_running); */
1421 
1422 
1423  /* ts A61007 : test moved up to burn_drive_scan()
1424  burn_wait_all() is obsoleted */
1425 #if 0
1426  /* make sure the drives aren't in use */
1427  burn_wait_all(); /* make sure the queue cleans up
1428  before checking for the released
1429  state */
1430 #endif /* 0 */
1431 
1432  *n_drives = 0;
1433 
1434  /* ts A70907 : whether to scan from scratch or to extend */
1435  for (i = 0; i < (int) sizeof(scanned); i++)
1436  scanned[i] = 0;
1437  if (flag & 1) {
1439  } else {
1440  for (i = 0; i <= drivetop; i++)
1441  if (drive_array[i].global_index >= 0)
1442  scanned[i / 8] |= (1 << (i % 8));
1443  }
1444 
1445  /* refresh the lib's drives */
1446 
1447  /* ts A61115 : formerly sg_enumerate(); ata_enumerate(); */
1449 
1450  count = burn_drive_count();
1451  if (count) {
1452  /* ts A70907 :
1453  Extra array element marks end of array. */
1454  *drives = calloc(count + 1,
1455  sizeof(struct burn_drive_info));
1456  if (*drives == NULL) {
1457  libdax_msgs_submit(libdax_messenger, -1, 0x00000003,
1460  "Out of virtual memory", 0, 0);
1461  return -1;
1462  } else
1463  for (i = 0; i <= (int) count; i++) /* invalidate */
1464  (*drives)[i].drive = NULL;
1465  } else
1466  *drives = NULL;
1467 
1468  for (i = 0; i < (int) count; ++i) {
1469  if (scanned[i / 8] & (1 << (i % 8)))
1470  continue; /* device already scanned by previous run */
1471  if (drive_array[i].global_index < 0)
1472  continue; /* invalid device */
1473 
1474  /* ts A90602 : This old loop is not plausible. See A70907.
1475  while (!drive_getcaps(&drive_array[i],
1476  &(*drives)[*n_drives])) {
1477  sleep(1);
1478  }
1479  */
1480  /* ts A90602 : A single call shall do (rather than a loop) */
1481  ret = drive_getcaps(&drive_array[i], &(*drives)[*n_drives]);
1482  if (ret > 0)
1483  (*n_drives)++;
1484  scanned[i / 8] |= 1 << (i % 8);
1485  }
1486  if (*drives != NULL && *n_drives == 0) {
1487  free ((char *) *drives);
1488  *drives = NULL;
1489  }
1490 
1491  return(1);
1492 }
1493 
1494 /* ts A61001 : internal call */
1495 int burn_drive_forget(struct burn_drive *d, int force)
1496 {
1497  int occup;
1498 
1499  occup = burn_drive_is_occupied(d);
1500 /*
1501  fprintf(stderr, "libburn: experimental: occup == %d\n",occup);
1502 */
1503  if(occup <= -2)
1504  return 2;
1505  if(occup > 0)
1506  if(force < 1)
1507  return 0;
1508  if(occup >= 10)
1509  return 0;
1510 
1511  /* >>> do any drive calming here */;
1512 
1513 
1515  if(occup > 0 && !burn_drive_is_released(d))
1516  burn_drive_release(d,0);
1517  burn_drive_free(d);
1518  return 1;
1519 }
1520 
1521 /* API call */
1522 int burn_drive_info_forget(struct burn_drive_info *info, int force)
1523 {
1524  return burn_drive_forget(info->drive, force);
1525 }
1526 
1527 
1528 void burn_drive_info_free(struct burn_drive_info drive_infos[])
1529 {
1530 #ifndef Libburn_free_all_drives_on_infO
1531  int i;
1532 #endif
1533 
1534 /* ts A60904 : ticket 62, contribution by elmom */
1535 /* clarifying the meaning and the identity of the victim */
1536 
1537  if(drive_infos == NULL)
1538  return;
1539 
1540 #ifndef Libburn_free_all_drives_on_infO
1541 
1542 #ifdef Not_yeT
1543  int new_drivetop;
1544 
1545  /* ts A71015: compute reduced drivetop counter */
1546  new_drivetop = drivetop;
1547  for (i = 0; drive_infos[i].drive != NULL; i++)
1548  if (drive_infos[i].global_index == new_drivetop
1549  && new_drivetop >= 0) {
1550  new_drivetop--;
1551  i = 0;
1552  }
1553 #endif /* Not_yeT */
1554 
1555  /* ts A70907 : Solution for wrong behavior below */
1556  for (i = 0; drive_infos[i].drive != NULL; i++)
1557  burn_drive_free(drive_infos[i].drive);
1558 
1559 #ifdef Not_yeT
1560  drivetop = new_drivetop;
1561 #endif /* Not_yeT */
1562 
1563 #endif /* ! Libburn_free_all_drives_on_infO */
1564 
1565  /* ts A60904 : This looks a bit weird. [ts A70907 : not any more]
1566  burn_drive_info is not the manager of burn_drive but only its
1567  spokesperson. To my knowledge drive_infos from burn_drive_scan()
1568  are not memorized globally. */
1569  free((void *) drive_infos);
1570 
1571 #ifdef Libburn_free_all_drives_on_infO
1572  /* ts A70903 : THIS IS WRONG ! (disabled now)
1573  It endangers multi drive usage.
1574  This call is not entitled to delete all drives, only the
1575  ones of the array which it receives a parameter.
1576 
1577  Problem: It was unclear how many items are listed in drive_infos
1578  Solution: Added a end marker element to any burn_drive_info array
1579  The mark can be recognized by having drive == NULL
1580  */
1582 #endif
1583 }
1584 
1585 
1587 {
1588  /* ts A61022: SIGSEGV on calling this function with blank media */
1589  if(d->disc == NULL)
1590  return NULL;
1591 
1592  d->disc->refcnt++;
1593  return d->disc;
1594 }
1595 
1596 void burn_drive_set_speed(struct burn_drive *d, int r, int w)
1597 {
1598  d->nominal_write_speed = w;
1599  if(d->drive_role != 1)
1600  return;
1601  d->set_speed(d, r, w);
1602 }
1603 
1604 int burn_drive_set_speed_exact(struct burn_drive *d, int r, int w)
1605 {
1606  int sose;
1607 
1608  d->nominal_write_speed = w;
1609  if(d->drive_role != 1)
1610  return 0;
1611  sose = d->silent_on_scsi_error;
1612  d->silent_on_scsi_error = 3;
1613  d->set_streaming_err = 0;
1614  d->set_streaming_exact_bit = 1;
1615  d->set_speed(d, r, w);
1616  d->silent_on_scsi_error = sose;
1617  d->set_streaming_exact_bit = 0;
1618  return !d->set_streaming_err;
1619 }
1620 
1621 /* ts A70711 API function */
1622 int burn_drive_set_buffer_waiting(struct burn_drive *d, int enable,
1623  int min_usec, int max_usec, int timeout_sec,
1624  int min_percent, int max_percent)
1625 {
1626 
1627  if (enable >= 0)
1628  d->wait_for_buffer_free = !!enable;
1629  if (min_usec >= 0)
1630  d->wfb_min_usec = min_usec;
1631  if (max_usec >= 0)
1632  d->wfb_max_usec = max_usec;
1633  if (timeout_sec >= 0)
1634  d->wfb_timeout_sec = timeout_sec;
1635  if (min_percent >= 0) {
1636  if (min_percent < 25 || min_percent > 100)
1637  return 0;
1638  d->wfb_min_percent = min_percent;
1639  }
1640  if (max_percent >= 0) {
1641  if (max_percent < 25 || max_percent > 100)
1642  return 0;
1643  d->wfb_max_percent = max_percent;
1644  }
1645  return 1;
1646 }
1647 
1648 
1649 int burn_drive_reset_simulate(struct burn_drive *d, int simulate)
1650 {
1651  if (d->busy != BURN_DRIVE_IDLE) {
1653  d->global_index, 0x00020140,
1655  "Drive is busy on attempt to write random access",0,0);
1656  return 0;
1657  }
1658  d->do_simulate = !!simulate;
1659  return 1;
1660 }
1661 
1662 
1663 int burn_msf_to_sectors(int m, int s, int f)
1664 {
1665  return (m * 60 + s) * 75 + f;
1666 }
1667 
1668 void burn_sectors_to_msf(int sectors, int *m, int *s, int *f)
1669 {
1670  *m = sectors / (60 * 75);
1671  *s = (sectors - *m * 60 * 75) / 75;
1672  *f = sectors - *m * 60 * 75 - *s * 75;
1673 }
1674 
1676 {
1677  return d->mdata->max_read_speed;
1678 }
1679 
1681 {
1682  return d->mdata->max_write_speed;
1683 }
1684 
1685 /* ts A61021 : New API function */
1687 {
1688  return d->mdata->min_write_speed;
1689 }
1690 
1691 
1692 /* ts A51221 */
1695 
1696 /** Add a device to the list of permissible drives. As soon as some entry is in
1697  the whitelist all non-listed drives are banned from enumeration.
1698  @return 1 success, <=0 failure
1699 */
1700 int burn_drive_add_whitelist(char *device_address)
1701 {
1702  char *new_item;
1704  return 0;
1706  new_item = calloc(1, strlen(device_address) + 1);
1707  if (new_item == NULL)
1708  return -1;
1709  strcpy(new_item, device_address);
1711  return 1;
1712 }
1713 
1714 /** Remove all drives from whitelist. This enables all possible drives. */
1716 {
1717  int i;
1718  for (i = 0; i <= enumeration_whitelist_top; i++)
1719  free(enumeration_whitelist[i]);
1721 }
1722 
1723 int burn_drive_is_banned(char *device_address)
1724 {
1725  int i;
1727  return 0;
1728  for (i = 0; i <= enumeration_whitelist_top; i++)
1729  if (strcmp(enumeration_whitelist[i], device_address) == 0)
1730  return 0;
1731  return 1;
1732 }
1733 
1734 
1735 /* ts A80731 */
1737 {
1738  return enumeration_whitelist_top + 1;
1739 }
1740 
1741 char *burn_drive_whitelist_item(int idx, int flag)
1742 {
1743  if (idx < 0 || idx > enumeration_whitelist_top)
1744  return NULL;
1745  return enumeration_whitelist[idx];
1746 }
1747 
1748 
1749 static int burn_role_by_access(char *fname, int flag)
1750 {
1751 /* We normally need _LARGEFILE64_SOURCE defined by the build system.
1752  Nevertheless the system might use large address integers by default.
1753 */
1754 #ifndef O_LARGEFILE
1755 #define O_LARGEFILE 0
1756 #endif
1757  int fd;
1758 
1759  fd = open(fname, O_RDWR | O_LARGEFILE | O_BINARY);
1760  if (fd != -1) {
1761  close(fd);
1762  return 2;
1763  }
1764  fd = open(fname, O_RDONLY | O_LARGEFILE | O_BINARY);
1765  if (fd != -1) {
1766  close(fd);
1767  return 4;
1768  }
1769  fd = open(fname, O_WRONLY | O_LARGEFILE | O_BINARY);
1770  if (fd != -1) {
1771  close(fd);
1772  return 5;
1773  }
1774  if (flag & 1)
1775  return 0;
1776  return 2;
1777 }
1778 
1779 
1780 /* ts A70903 : Implements adquiration of pseudo drives */
1781 int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
1782 {
1783  int ret = -1, role = 0, fd;
1784  int is_rdwr = 0, stat_ret = -1;
1785  /* divided by 512 it needs to fit into a signed long integer */
1786  off_t size = ((off_t) (512 * 1024 * 1024 - 1) * (off_t) 2048);
1787  off_t read_size = -1;
1788  struct burn_drive *d= NULL, *regd_d;
1789  struct stat stbuf;
1790 
1791  if (fname[0] != 0) {
1792  fd = burn_drive__fd_from_special_adr(fname);
1793  is_rdwr = burn_drive__is_rdwr(fname, &stat_ret, &stbuf,
1794  &read_size, 1 | 2);
1795  if (stat_ret == -1 || is_rdwr) {
1796  ret = burn_os_stdio_capacity(fname, 0, &size);
1797  if (ret == -1) {
1799  0x00020009,
1801  "Neither stdio-path nor its directory exist",
1802  0, 0);
1803  return 0;
1804  } else if (ret == -2) {
1806  0x00020005,
1808  "Failed to open device (a pseudo-drive)",
1809  errno, 0);
1810  return 0;
1811  }
1812  if (fname[0] != 0) {
1813  if (is_rdwr == 2 &&
1815  role = 4;
1816  else if (is_rdwr == 3 &&
1818  role = 5;
1819  else
1820  role = 2;
1821  if (stat_ret != -1 && role == 2 && fd == -1 &&
1822  (burn_drive_role_4_allowed & 3) == 3)
1823  role = burn_role_by_access(fname,
1824  !!(burn_drive_role_4_allowed & 4));
1825  } else
1826  role = 0;
1827  } else {
1828  role = 3;
1829  }
1830  }
1831  d= (struct burn_drive *) calloc(1, sizeof(struct burn_drive));
1832  if (d == NULL)
1833  return 0;
1834  burn_setup_drive(d, fname);
1835  d->status = BURN_DISC_EMPTY;
1836 
1837  d->drive_role = role;
1838  ret = burn_scsi_setup_drive(d, -1, -1, -1, -1, -1, 0);
1839  if (ret <= 0)
1840  goto ex;
1841  regd_d = burn_drive_register(d);
1842  if (regd_d == NULL) {
1843  ret = -1;
1844  goto ex;
1845  }
1846  free((char *) d); /* all sub pointers have been copied to *regd_d */
1847  d = regd_d;
1848  if (d->drive_role >= 2 && d->drive_role <= 5) {
1849  if (d->drive_role == 4) {
1850  if (read_size > 0)
1851  d->status = BURN_DISC_FULL;
1852  else
1853  d->status = BURN_DISC_EMPTY;
1854  d->block_types[BURN_WRITE_TAO] = 0;
1855  d->block_types[BURN_WRITE_SAO] = 0;
1856  } else {
1857  if (d->drive_role == 5 && stat_ret != -1 &&
1858  S_ISREG(stbuf.st_mode) && stbuf.st_size > 0 &&
1859  (burn_drive_role_4_allowed & 8)) {
1861  d->block_types[BURN_WRITE_SAO] = 0;
1862  if (stbuf.st_size / (off_t) 2048
1863  >= 0x7ffffff0) {
1864  d->status = BURN_DISC_FULL;
1865  d->role_5_nwa = 0x7ffffff0;
1866  } else
1867  d->role_5_nwa = stbuf.st_size / 2048 +
1868  !!(stbuf.st_size % 2048);
1869  } else {
1870  d->status = BURN_DISC_BLANK;
1873  d->role_5_nwa = 0;
1874  }
1876  }
1877  d->current_profile = 0xffff; /* MMC for non-compliant drive */
1878  strcpy(d->current_profile_text,"stdio file");
1879  d->current_is_cd_profile = 0;
1881  if (read_size >= 0) {
1882  /* despite its name : last valid address, not size */
1883  d->media_read_capacity =
1884  read_size / 2048 - !(read_size % 2048);
1885  d->mr_capacity_trusted = 1;
1886  }
1888  } else
1889  d->current_profile = 0; /* Drives return this if empty */
1890 
1891  *drive_infos = calloc(2, sizeof(struct burn_drive_info));
1892  if (*drive_infos == NULL)
1893  goto ex;
1894  (*drive_infos)[0].drive = d;
1895  (*drive_infos)[1].drive = NULL; /* End-Of-List mark */
1896  (*drive_infos)[0].tao_block_types = d->block_types[BURN_WRITE_TAO];
1897  (*drive_infos)[0].sao_block_types = d->block_types[BURN_WRITE_SAO];
1898  if (d->drive_role == 2) {
1899  strcpy((*drive_infos)[0].vendor,"YOYODYNE");
1900  strcpy((*drive_infos)[0].product,"WARP DRIVE");
1901  strcpy((*drive_infos)[0].revision,"FX01");
1902  } else if (d->drive_role == 3) {
1903  strcpy((*drive_infos)[0].vendor,"YOYODYNE");
1904  strcpy((*drive_infos)[0].product,"BLACKHOLE");
1905  strcpy((*drive_infos)[0].revision,"FX02");
1906  } else if (d->drive_role == 4) {
1907  strcpy((*drive_infos)[0].vendor,"YOYODYNE");
1908  strcpy((*drive_infos)[0].product,"WARP DRIVE");
1909  strcpy((*drive_infos)[0].revision,"FX03");
1910  } else if (d->drive_role == 5) {
1911  strcpy((*drive_infos)[0].vendor,"YOYODYNE");
1912  strcpy((*drive_infos)[0].product,"WARP DRIVE");
1913  strcpy((*drive_infos)[0].revision,"FX04");
1914  } else {
1915  strcpy((*drive_infos)[0].vendor,"FERENGI");
1916  strcpy((*drive_infos)[0].product,"VAPORWARE");
1917  strcpy((*drive_infos)[0].revision,"0000");
1918  }
1919  d->released = 0;
1920  ret = 1;
1921 ex:;
1922  if (ret <= 0 && d != NULL) {
1924  free((char *) d);
1925  }
1926  return ret;
1927 }
1928 
1929 
1930 /* ts A60823 */
1931 /** Acquire a drive with known persistent address.
1932 */
1933 int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], char* adr,
1934  int load)
1935 {
1936  unsigned int n_drives;
1937  int ret, i;
1938 
1939  /* check whether drive address is already registered */
1940  for (i = 0; i <= drivetop; i++)
1941  if (drive_array[i].global_index >= 0)
1942  if (strcmp(drive_array[i].devname, adr) == 0)
1943  break;
1944  if (i <= drivetop) {
1946  0x0002014b,
1948  "Drive is already registered resp. scanned",
1949  0, 0);
1950  return -1;
1951  }
1952 
1953  if (strncmp(adr, "stdio:", 6) == 0) {
1954  ret = burn_drive_grab_dummy(drive_infos, adr + 6);
1955  return ret;
1956  }
1957 
1960 /*
1961  fprintf(stderr,"libburn: experimental: burn_drive_scan_and_grab(%s)\n",
1962  adr);
1963 */
1964 
1965  /* ts A70907 : now calling synchronously rather than looping */
1966  ret = burn_drive_scan_sync(drive_infos, &n_drives, 0);
1967  if (ret < 0)
1968  return -1;
1969 
1970  if (n_drives == 0)
1971  return 0;
1972 /*
1973  fprintf(stderr, "libburn: experimental: n_drives %d , drivetop %d\n",
1974  n_drives, drivetop);
1975  if (n_drives > 0)
1976  fprintf(stderr, "libburn: experimental: global_index %d\n",
1977  drive_infos[0]->drive->global_index);
1978 */
1979 
1980  ret = burn_drive_grab(drive_infos[0]->drive, load);
1981  if (ret != 1) {
1982  burn_drive_forget(drive_infos[0]->drive, 0);
1983  return -1;
1984  }
1985  return 1;
1986 }
1987 
1988 /* ts A60925 */
1989 /** Simple debug message frontend to libdax_msgs_submit().
1990  If arg is not NULL, then fmt MUST contain exactly one %s and no
1991  other sprintf() %-formatters.
1992 */
1993 int burn_drive_adr_debug_msg(char *fmt, char *arg)
1994 {
1995  int ret;
1996  char *msg = NULL, *msgpt;
1997 
1998  if(libdax_messenger == NULL)
1999  return 0;
2000  if(arg != NULL) {
2001  BURN_ALLOC_MEM(msg, char, 4096);
2002  msgpt = msg;
2003  sprintf(msg, fmt, arg);
2004  } else {
2005  msgpt = fmt;
2006  }
2007  ret = libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
2009  msgpt, 0, 0);
2010 ex:;
2011  BURN_FREE_MEM(msg);
2012  return ret;
2013 }
2014 
2015 /* ts A60923 */ /* ts A70906 : promoted to API */
2016 /** Inquire the persistent address of the given drive. */
2017 int burn_drive_d_get_adr(struct burn_drive *d, char adr[])
2018 {
2019  if (strlen(d->devname) >= BURN_DRIVE_ADR_LEN) {
2021  0x00020110,
2023  "Persistent drive address too long", 0, 0);
2024  return -1;
2025  }
2026  strcpy(adr,d->devname);
2027  return 1;
2028 }
2029 
2030 /* ts A60823 - A60923 */ /* A70906 : Now legacy API call */
2031 /** Inquire the persistent address of the given drive. */
2032 int burn_drive_get_adr(struct burn_drive_info *drive_info, char adr[])
2033 {
2034  int ret;
2035 
2036  ret = burn_drive_d_get_adr(drive_info->drive, adr);
2037  return ret;
2038 }
2039 
2040 
2041 
2042 
2043 /* ts A60922 ticket 33 */
2044 /** Evaluate whether the given address would be enumerated by libburn */
2046 {
2047  return sg_is_enumerable_adr(adr);
2048 }
2049 
2050 #define BURN_DRIVE_MAX_LINK_DEPTH 20
2051 
2052 /* ts A60922 ticket 33 */
2053 /* @param flag bit0= no debug messages
2054  bit1= resolve only links,
2055  do not rely on drive list for resolving via st_rdev
2056 */
2057 int burn_drive_resolve_link(char *path, char adr[], int *recursion_count,
2058  int flag)
2059 {
2060  int ret, link_target_size = 4096;
2061  char *link_target = NULL, *msg = NULL, *link_adr = NULL, *adrpt;
2062  struct stat stbuf;
2063 
2064  BURN_ALLOC_MEM(link_target, char, link_target_size);
2065  BURN_ALLOC_MEM(msg, char, link_target_size + 100);
2066  BURN_ALLOC_MEM(link_adr, char, link_target_size);
2067 
2068  if (flag & 1)
2069  burn_drive_adr_debug_msg("burn_drive_resolve_link( %s )",
2070  path);
2071  if (*recursion_count >= BURN_DRIVE_MAX_LINK_DEPTH) {
2072  if (flag & 1)
2074  "burn_drive_resolve_link aborts because link too deep",
2075  NULL);
2076  {ret = 0; goto ex;}
2077  }
2078  (*recursion_count)++;
2079  ret = readlink(path, link_target, link_target_size);
2080  if (ret == -1) {
2081  if (flag & 1)
2082  burn_drive_adr_debug_msg("readlink( %s ) returns -1",
2083  path);
2084  {ret = 0; goto ex;}
2085  }
2086  if (ret >= link_target_size - 1) {
2087  sprintf(msg,"readlink( %s ) returns %d (too much)", path, ret);
2088  if (flag & 1)
2089  burn_drive_adr_debug_msg(msg, NULL);
2090  {ret = -1; goto ex;}
2091  }
2092  link_target[ret] = 0;
2093  adrpt = link_target;
2094  if (link_target[0] != '/') {
2095  strcpy(link_adr, path);
2096  if ((adrpt = strrchr(link_adr, '/')) != NULL) {
2097  strcpy(adrpt + 1, link_target);
2098  adrpt = link_adr;
2099  } else
2100  adrpt = link_target;
2101  }
2102  if (flag & 2) {
2103  /* Link-only recursion */
2104  if (lstat(adrpt, &stbuf) == -1) {
2105  ;
2106  } else if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
2107  ret = burn_drive_resolve_link(adrpt, adr,
2108  recursion_count, flag);
2109  } else {
2110  strcpy(adr, adrpt);
2111  }
2112  } else {
2113  /* Link and device number recursion */
2114  ret = burn_drive_convert_fs_adr_sub(adrpt, adr,
2115  recursion_count);
2116  sprintf(msg,"burn_drive_convert_fs_adr( %s ) returns %d",
2117  link_target, ret);
2118  }
2119  if (flag & 1)
2120  burn_drive_adr_debug_msg(msg, NULL);
2121 ex:;
2122  BURN_FREE_MEM(link_target);
2123  BURN_FREE_MEM(msg);
2124  BURN_FREE_MEM(link_adr);
2125  return ret;
2126 }
2127 
2128 /* ts A60922 - A61014 ticket 33 */
2129 /* Try to find an enumerated address with the given stat.st_rdev number */
2130 int burn_drive_find_devno(dev_t devno, char adr[])
2131 {
2132  char *fname = NULL, *msg = NULL;
2133  int ret = 0, first = 1, fname_size = 4096;
2134  struct stat stbuf;
2136 
2137  BURN_ALLOC_MEM(fname, char, fname_size);
2138  BURN_ALLOC_MEM(msg, char, fname_size + 100);
2139 
2140  while (1) {
2141  ret = sg_give_next_adr(&enm, fname, fname_size, first);
2142  if(ret <= 0)
2143  break;
2144  first = 0;
2145  ret = stat(fname, &stbuf);
2146  if(ret == -1)
2147  continue;
2148  if(devno != stbuf.st_rdev)
2149  continue;
2150  if(strlen(fname) >= BURN_DRIVE_ADR_LEN)
2151  {ret= -1; goto ex;}
2152 
2153  sprintf(msg, "burn_drive_find_devno( 0x%lX ) found %s",
2154  (long) devno, fname);
2155  burn_drive_adr_debug_msg(msg, NULL);
2156  strcpy(adr, fname);
2157  { ret = 1; goto ex;}
2158  }
2159  ret = 0;
2160 ex:;
2161  if (first == 0)
2162  sg_give_next_adr(&enm, fname, fname_size, -1);
2163  BURN_FREE_MEM(fname);
2164  BURN_FREE_MEM(msg);
2165  return ret;
2166 }
2167 
2168 /* ts A60923 */
2169 /** Try to obtain host,channel,target,lun from path.
2170  @return 1 = success , 0 = failure , -1 = severe error
2171 */
2173  int *bus_no, int *host_no, int *channel_no,
2174  int *target_no, int *lun_no)
2175 {
2176  int ret, i;
2177  char *adr = NULL;
2178 
2179  BURN_ALLOC_MEM(adr, char, BURN_DRIVE_ADR_LEN);
2180 
2181  /* open drives cannot be inquired by sg_obtain_scsi_adr() */
2182  for (i = 0; i < drivetop + 1; i++) {
2183  if (drive_array[i].global_index < 0)
2184  continue;
2185  ret = burn_drive_d_get_adr(&(drive_array[i]),adr);
2186  if (ret < 0)
2187  {ret = 1; goto ex;}
2188  if (ret == 0)
2189  continue;
2190  if (strcmp(adr, path) == 0) {
2191  *host_no = drive_array[i].host;
2192  *channel_no = drive_array[i].channel;
2193  *target_no = drive_array[i].id;
2194  *lun_no = drive_array[i].lun;
2195  *bus_no = drive_array[i].bus_no;
2196  if (*host_no < 0 || *channel_no < 0 ||
2197  *target_no < 0 || *lun_no < 0)
2198  {ret = 0; goto ex;}
2199  {ret = 1; goto ex;}
2200  }
2201  }
2202 
2203  ret = sg_obtain_scsi_adr(path, bus_no, host_no, channel_no,
2204  target_no, lun_no);
2205 ex:;
2206  BURN_FREE_MEM(adr);
2207  return ret;
2208 }
2209 
2210 /* ts A60923 */
2211 int burn_drive_convert_scsi_adr(int bus_no, int host_no, int channel_no,
2212  int target_no, int lun_no, char adr[])
2213 {
2214  char *fname = NULL, *msg = NULL;
2215  int ret = 0, first = 1, i_bus_no = -1, fname_size = 4096;
2216  int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
2218 
2219  BURN_ALLOC_MEM(fname, char, fname_size);
2220  BURN_ALLOC_MEM(msg, char, fname_size + 100);
2221 
2222  sprintf(msg,"burn_drive_convert_scsi_adr( %d,%d,%d,%d,%d )",
2223  bus_no, host_no, channel_no, target_no, lun_no);
2224  burn_drive_adr_debug_msg(msg, NULL);
2225 
2226  while (1) {
2227  ret= sg_give_next_adr(&enm, fname, fname_size, first);
2228  if(ret <= 0)
2229  break;
2230  first = 0;
2231  ret = burn_drive_obtain_scsi_adr(fname, &i_bus_no, &i_host_no,
2232  &i_channel_no, &i_target_no, &i_lun_no);
2233  if(ret <= 0)
2234  continue;
2235  if(bus_no >=0 && i_bus_no != bus_no)
2236  continue;
2237  if(host_no >=0 && i_host_no != host_no)
2238  continue;
2239  if(channel_no >= 0 && i_channel_no != channel_no)
2240  continue;
2241  if(target_no >= 0 && i_target_no != target_no)
2242  continue;
2243  if(lun_no >= 0 && i_lun_no != lun_no)
2244  continue;
2245  if(strlen(fname) >= BURN_DRIVE_ADR_LEN)
2246  { ret = -1; goto ex;}
2248  "burn_drive_convert_scsi_adr() found %s", fname);
2249  strcpy(adr, fname);
2250  { ret = 1; goto ex;}
2251  }
2252  ret = 0;
2253 ex:;
2254  if (first == 0)
2255  sg_give_next_adr(&enm, fname, fname_size, -1);
2256  BURN_FREE_MEM(fname);
2257  BURN_FREE_MEM(msg);
2258  return ret;
2259 }
2260 
2261 /* ts A60922 ticket 33 */
2262 /* Try to find an enumerated address with the same host,channel,target,lun
2263  as path */
2264 int burn_drive_find_scsi_equiv(char *path, char adr[])
2265 {
2266  int ret = 0;
2267  int bus_no, host_no, channel_no, target_no, lun_no;
2268  char msg[4096];
2269 
2270  ret = burn_drive_obtain_scsi_adr(path, &bus_no, &host_no, &channel_no,
2271  &target_no, &lun_no);
2272  if(ret <= 0) {
2273  sprintf(msg,"burn_drive_obtain_scsi_adr( %s ) returns %d",
2274  path, ret);
2275  burn_drive_adr_debug_msg(msg, NULL);
2276  return 0;
2277  }
2278  sprintf(msg, "burn_drive_find_scsi_equiv( %s ) : (%d),%d,%d,%d,%d",
2279  path, bus_no, host_no, channel_no, target_no, lun_no);
2280  burn_drive_adr_debug_msg(msg, NULL);
2281 
2282  ret= burn_drive_convert_scsi_adr(-1, host_no, channel_no, target_no,
2283  lun_no, adr);
2284  return ret;
2285 }
2286 
2287 
2288 /* ts A60922 ticket 33 */
2289 /** Try to convert a given existing filesystem address into a persistent drive
2290  address. */
2291 int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count)
2292 {
2293  int ret;
2294  struct stat stbuf;
2295 
2296  burn_drive_adr_debug_msg("burn_drive_convert_fs_adr( %s )", path);
2297  if (strncmp(path, "stdio:", 6) == 0 ||
2299  if(strlen(path) >= BURN_DRIVE_ADR_LEN)
2300  return -1;
2301  if (strncmp(path, "stdio:", 6) != 0)
2303  "burn_drive_is_enumerable_adr( %s ) is true", path);
2304  strcpy(adr, path);
2305  return 1;
2306  }
2307 
2308  if(lstat(path, &stbuf) == -1) {
2309  burn_drive_adr_debug_msg("lstat( %s ) returns -1", path);
2310  return 0;
2311  }
2312  if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
2313  ret = burn_drive_resolve_link(path, adr, rec_count, 0);
2314  if(ret > 0)
2315  return 1;
2316  burn_drive_adr_debug_msg("link fallback via stat( %s )", path);
2317  if(stat(path, &stbuf) == -1) {
2318  burn_drive_adr_debug_msg("stat( %s ) returns -1",path);
2319  return 0;
2320  }
2321  }
2322  if((stbuf.st_mode&S_IFMT) == S_IFBLK ||
2323  (stbuf.st_mode&S_IFMT) == S_IFCHR) {
2324  ret = burn_drive_find_devno(stbuf.st_rdev, adr);
2325  if(ret > 0)
2326  return 1;
2327  ret = burn_drive_find_scsi_equiv(path, adr);
2328  if(ret > 0)
2329  return 1;
2330  }
2331  burn_drive_adr_debug_msg("Nothing found for %s", path);
2332  return 0;
2333 }
2334 
2335 /* API */
2336 /** Try to convert a given existing filesystem address into a persistent drive
2337  address. */
2338 int burn_drive_convert_fs_adr(char *path, char adr[])
2339 {
2340  int ret, rec_count = 0;
2341 
2342  ret = burn_drive_convert_fs_adr_sub(path, adr, &rec_count);
2343  return ret;
2344 }
2345 
2346 
2347 /* API */
2348 int burn_lookup_device_link(char *dev_adr, char link_adr[],
2349  char *dir_adr, char **ranks, int rank_count, int flag)
2350 {
2351  DIR *dirpt= NULL;
2352  struct dirent *entry;
2353  struct stat link_stbuf;
2354  char *adr= NULL, *namept, *sys_adr= NULL;
2355  int ret, name_rank, found_rank= 0x7fffffff, dirlen, i, rec_count = 0;
2356  static char default_ranks_data[][8] =
2357  {"dvdrw", "cdrw", "dvd", "cdrom", "cd"};
2358  char *default_ranks[5];
2359 
2360  link_adr[0] = 0;
2361  if (ranks == NULL) {
2362  for (i = 0; i < 5; i++)
2363  default_ranks[i] = default_ranks_data[i];
2364  ranks = default_ranks;
2365  rank_count= 5;
2366  }
2367  dirlen= strlen(dir_adr) + 1;
2368  if (strlen(dir_adr) + 1 >= BURN_DRIVE_ADR_LEN) {
2369 
2370  /* >>> Issue warning about oversized directory address */;
2371 
2372  {ret = 0; goto ex;}
2373  }
2374  BURN_ALLOC_MEM(adr, char, BURN_DRIVE_ADR_LEN);
2375  BURN_ALLOC_MEM(sys_adr, char, BURN_DRIVE_ADR_LEN);
2376 
2377  dirpt = opendir(dir_adr);
2378  if (dirpt == NULL)
2379  {ret = 0; goto ex;}
2380  strcpy(adr, dir_adr);
2381  strcat(adr, "/");
2382  namept = adr + strlen(dir_adr) + 1;
2383  while(1) {
2384  entry = readdir(dirpt);
2385  if(entry == NULL)
2386  break;
2387  if (strlen(entry->d_name) + dirlen >= BURN_DRIVE_ADR_LEN)
2388  continue;
2389  strcpy(namept, entry->d_name);
2390  if(lstat(adr, &link_stbuf) == -1)
2391  continue;
2392  if((link_stbuf.st_mode & S_IFMT) != S_IFLNK)
2393  continue;
2394  /* Determine rank and omit uninteresting ones */
2395  for(name_rank= 0; name_rank < rank_count; name_rank++)
2396  if(strncmp(namept, ranks[name_rank],
2397  strlen(ranks[name_rank])) == 0)
2398  break;
2399  /* we look for lowest rank */
2400  if(name_rank >= rank_count ||
2401  name_rank > found_rank ||
2402  (name_rank == found_rank &&
2403  strcmp(namept, link_adr + dirlen) >= 0))
2404  continue;
2405 
2406  /* Does name point to the same device as dev_adr ? */
2407  ret= burn_drive_resolve_link(adr, sys_adr, &rec_count, 2);
2408  if(ret < 0)
2409  goto ex;
2410  if(ret == 0)
2411  continue;
2412  if(strcmp(dev_adr, sys_adr) == 0) {
2413  strcpy(link_adr, adr);
2414  found_rank= name_rank;
2415  }
2416  }
2417  ret= 2;
2418  if(found_rank < 0x7fffffff)
2419  ret= 1;
2420 ex:;
2421  if(dirpt != NULL)
2422  closedir(dirpt);
2423  BURN_FREE_MEM(adr);
2424  BURN_FREE_MEM(sys_adr);
2425  return(ret);
2426 }
2427 
2428 
2429 /** A pacifier function suitable for burn_abort.
2430  @param handle If not NULL, a pointer to a text suitable for printf("%s")
2431 */
2432 int burn_abort_pacifier(void *handle, int patience, int elapsed)
2433 {
2434  char *prefix= "libburn : ";
2435 
2436  if(handle!=NULL)
2437  prefix= handle;
2438  fprintf(stderr,
2439  "\r%sABORT : Waiting for drive to finish ( %d s, %d max)",
2440  (char *) prefix, elapsed, patience);
2441  return(1);
2442 }
2443 
2444 
2445 /* ts B00226 : Outsourced backend of burn_abort()
2446  @param flag bit0= do not call burn_finish()
2447 */
2448 int burn_abort_5(int patience,
2449  int (*pacifier_func)(void *handle, int patience, int elapsed),
2450  void *handle, int elapsed, int flag)
2451 {
2452  int ret, i, occup, still_not_done= 1, pacifier_off= 0, first_round= 1;
2453  unsigned long wait_grain= 100000;
2454  time_t start_time, current_time, pacifier_time, end_time;
2455 
2456 #ifndef NIX
2457  time_t stdio_patience = 3;
2458 #endif
2459 
2460 
2461 /*
2462  fprintf(stderr,
2463  "libburn_EXPERIMENTAL: burn_abort_5(%d,%d)\n", patience, flag);
2464 */
2465 
2466  current_time = start_time = pacifier_time = time(0);
2467  start_time -= elapsed;
2468  end_time = start_time + patience;
2469 
2470  /* >>> ts A71002 : are there any threads at work ?
2471  If not, then one can force abort because the drives will not
2472  change status on their own.
2473  */
2474 
2475  while(current_time < end_time || (patience <= 0 && first_round)) {
2476  still_not_done = 0;
2477 
2478  for(i = 0; i < drivetop + 1; i++) {
2479  occup = burn_drive_is_occupied(&(drive_array[i]));
2480  if(occup == -2)
2481  continue;
2482 
2483  if(drive_array[i].drive_role != 1) {
2484 
2485 #ifdef NIX
2486 
2487  /* ts A90302
2488  <<< this causes a race condition with drive
2489  usage and drive disposal.
2490  */
2492  burn_drive_forget(&(drive_array[i]), 1);
2493  continue;
2494 
2495 #else /* NIX */
2496 
2497  /* ts A90318
2498  >>> but if a pipe breaks then the drive
2499  never gets idle.
2500  So for now with a short patience timespan
2501  and eventually a deliberate memory leak.
2502  */
2503  if (current_time - start_time >
2504  stdio_patience) {
2505  drive_array[i].global_index = -1;
2506  continue;
2507  }
2508 
2509 #endif /* ! NIX */
2510 
2511  }
2512 
2513  if(occup < 10) {
2514  if (!drive_array[i].cancel)
2516  if (drive_array[i].drive_role != 1)
2517  /* occup == -1 comes early */
2518  usleep(1000000);
2519  burn_drive_forget(&(drive_array[i]), 1);
2520  } else if(occup <= 100) {
2521  if (!drive_array[i].cancel)
2523  still_not_done++;
2524  } else if(occup <= 1000) {
2525  still_not_done++;
2526  }
2527  }
2528  first_round = 0;
2529 
2530  if(still_not_done == 0 || patience <= 0)
2531  break;
2532  usleep(wait_grain);
2533  current_time = time(0);
2534  if(current_time>pacifier_time) {
2535  if(pacifier_func != NULL && !pacifier_off) {
2536  ret = (*pacifier_func)(handle, patience,
2537  current_time-start_time);
2538  pacifier_off = (ret <= 0);
2539  }
2540  pacifier_time = current_time;
2541  }
2542  }
2543  if (!(flag & 1))
2544  burn_finish();
2545  return(still_not_done == 0);
2546 }
2547 
2548 
2549 /** Abort any running drive operation and finish libburn.
2550  @param patience Maximum number of seconds to wait for drives to finish
2551  @param pacifier_func Function to produce appeasing messages. See
2552  burn_abort_pacifier() for an example.
2553  @return 1 ok, all went well
2554  0 had to leave a drive in unclean state
2555  <0 severe error, do no use libburn again
2556 */
2557 int burn_abort(int patience,
2558  int (*pacifier_func)(void *handle, int patience, int elapsed),
2559  void *handle)
2560 {
2561  int ret, flg = 0;
2562 
2563  if (patience < 0) {
2564  patience = 0;
2565  flg |= 1;
2566  }
2567  ret = burn_abort_5(patience, pacifier_func, handle, 0, flg);
2568  return ret;
2569 }
2570 
2571 
2572 /* ts A61020 API function */
2574  int *start_lba, int *end_lba, int flag)
2575 {
2576  if (d->start_lba == -2000000000 || d->end_lba == -2000000000)
2577  return 0;
2578  *start_lba = d->start_lba;
2579  *end_lba= d->end_lba;
2580  return 1;
2581 }
2582 
2583 
2584 /* ts A61020 API function */
2586 {
2587  if (d->drive_role == 0)
2588  return 0;
2589  if (d->status != BURN_DISC_UNREADY &&
2591  return 0;
2592  d->status = BURN_DISC_BLANK;
2593  return 1;
2594 }
2595 
2596 /* ts A61106 API function */
2598 {
2599  if (d->drive_role == 0)
2600  return 0;
2601  if (d->status != BURN_DISC_UNREADY &&
2603  return 0;
2604  d->status = BURN_DISC_FULL;
2605  return 1;
2606 }
2607 
2608 /* ts B31110 API function */
2610 {
2611  d->status = BURN_DISC_FULL;
2612  return 1;
2613 }
2614 
2615 /* ts A61021: new API function */
2617 {
2618  if (burn_drive_is_released(d)) {
2620  d->global_index, 0x0002010e,
2622  "Attempt to read ATIP from ungrabbed drive",
2623  0, 0);
2624  return -1;
2625  }
2626  if(d->drive_role != 1)
2627  return 0;
2628  if ((d->current_profile == -1 || d->current_is_cd_profile)
2629  && ((d->mdata->p2a_valid > 0 && d->mdata->cdrw_write) ||
2630  d->current_profile != 0x08)) {
2631  d->read_atip(d);
2632  /* >>> some control of success would be nice :) */
2633  } else {
2634  /* mmc5r03c.pdf 6.26.3.6.3 : ATIP is undefined for non-CD
2635  (and it seems meaningless for non-burners).
2636  ts A90823: Pseudo-CD U3 memory stick stalls with ATIP.
2637  It is !cdrw_write and profile is 0x08.
2638  */
2639  return 0;
2640  }
2641  return 1;
2642 }
2643 
2644 /* ts A61110 : new API function */
2646  int trackno, int *lba, int *nwa)
2647 {
2648  int ret;
2649 
2650  if (burn_drive_is_released(d)) {
2652  d->global_index, 0x0002011b,
2654  "Attempt to read track info from ungrabbed drive",
2655  0, 0);
2656  return -1;
2657  }
2658  if (d->busy != BURN_DRIVE_IDLE) {
2660  d->global_index, 0x0002011c,
2662  "Attempt to read track info from busy drive",
2663  0, 0);
2664  return -1;
2665  }
2666  *lba = *nwa = 0;
2667  if (d->drive_role == 5 && trackno == 0 &&
2668  d->status == BURN_DISC_APPENDABLE) {
2669  *lba = *nwa = d->role_5_nwa;
2670  return 1;
2671  }
2672  if (d->drive_role != 1)
2673  return 0;
2674  if (o != NULL)
2675  d->send_write_parameters(d, NULL, -1, o);
2676  ret = d->get_nwa(d, trackno, lba, nwa);
2677  return ret;
2678 }
2679 
2680 
2681 /* ts A70131 : new API function */
2682 int burn_disc_get_msc1(struct burn_drive *d, int *start)
2683 {
2684  int ret, trackno;
2685 
2686  if (burn_drive_is_released(d)) {
2688  d->global_index, 0x0002011b,
2690  "Attempt to read track info from ungrabbed drive",
2691  0, 0);
2692  return -1;
2693  }
2694  if (d->busy != BURN_DRIVE_IDLE) {
2696  d->global_index, 0x0002011c,
2698  "Attempt to read track info from busy drive",
2699  0, 0);
2700  return -1;
2701  }
2702  *start = 0;
2703  if (d->drive_role != 1)
2704  return 0;
2705  ret = d->read_multi_session_c1(d, &trackno, start);
2706  return ret;
2707 }
2708 
2709 
2710 /* ts A70213 : new API function */
2712  struct burn_write_opts *o)
2713 {
2714  int lba, nwa, ret;
2715  off_t bytes, start_byte = 0;
2716 
2717  if (burn_drive_is_released(d))
2718  return 0;
2719  if (d->busy != BURN_DRIVE_IDLE)
2720  return 0;
2721  if (d->drive_role == 0)
2722  return 0;
2723  if (d->drive_role != 1) {
2724  if (o != NULL)
2725  start_byte = o->start_byte;
2726  ret = burn_os_stdio_capacity(d->devname, start_byte, &bytes);
2727  if (ret != 1)
2728  bytes = d->media_capacity_remaining;
2729  if (bytes <= 0)
2730  bytes = (off_t) (512 * 1024 * 1024 - 1) * (off_t) 2048;
2731  if (bytes != d->media_capacity_remaining)
2733  } else {
2734  if (o != NULL)
2735  d->send_write_parameters(d, NULL, -1, o);
2736  d->get_nwa(d, -1, &lba, &nwa);
2737  }
2738  if (o != NULL) {
2739  if (o->start_byte > 0) {
2741  return 0;
2742  return d->media_capacity_remaining - o->start_byte;
2743  }
2744  }
2745  return d->media_capacity_remaining;
2746 }
2747 
2748 
2749 /* ts A61202 : New API function */
2750 int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80])
2751 {
2752  *pno = d->current_profile;
2753  strcpy(name,d->current_profile_text);
2754  return *pno >= 0;
2755 }
2756 
2757 
2758 /* ts A90815 : New API function */
2759 int burn_drive_get_all_profiles(struct burn_drive *d, int *num_profiles,
2760  int profiles[64], char is_current[64])
2761 {
2762  int i;
2763 
2764  *num_profiles = d->num_profiles;
2765  for (i = 0; i < d->num_profiles; i++) {
2766  profiles[i] = (d->all_profiles[i * 4] << 8) |
2767  d->all_profiles[i * 4 + 1];
2768  is_current[i] = d->all_profiles[i * 4 + 2] & 1;
2769  }
2770  return 1;
2771 }
2772 
2773 
2774 /* ts A90815 : New API function */
2775 int burn_obtain_profile_name(int profile_number, char name[80])
2776 {
2777  strcpy(name, mmc_obtain_profile_name(profile_number));
2778  return(name[0] != 0);
2779 }
2780 
2781 
2782 /* ts A61223 : New API function */
2784 {
2785  return !d->cancel;
2786 }
2787 
2788 
2789 /* ts A61226 */
2791  struct burn_speed_descriptor *prev,
2792  struct burn_speed_descriptor *next, int flag)
2793 {
2794  struct burn_speed_descriptor *o;
2795 
2796  (*s) = o = calloc(1, sizeof(struct burn_speed_descriptor));
2797  if (o == NULL)
2798  return -1;
2799  o->source = 0;
2800  o->profile_loaded = -2;
2801  o->profile_name[0] = 0;
2802  o->wrc = 0;
2803  o->exact = 0;
2804  o->mrw = 0;
2805  o->end_lba = -1;
2806  o->write_speed = 0;
2807  o->read_speed = 0;
2808 
2809  o->prev = prev;
2810  if (prev != NULL) {
2811  next = prev->next;
2812  prev->next = o;
2813  }
2814  o->next = next;
2815  if (next != NULL)
2816  next->prev = o;
2817  return 1;
2818 }
2819 
2820 
2821 /* ts A61226 */
2822 /* @param flag bit0= destroy whole next-chain of descriptors */
2824 {
2825  struct burn_speed_descriptor *next, *o;
2826 
2827  if ((*s) == NULL)
2828  return 0;
2829  if (flag&1)
2830  for (o = (*s); o->prev != NULL; o = o->prev);
2831  else
2832  o = (*s);
2833  next = o->next;
2834  if (next != NULL)
2835  next->prev = o->prev;
2836  if (o->prev != NULL)
2837  o->prev->next = next;
2838  free((char *) (*s));
2839  (*s) = NULL;
2840  if (flag&1)
2841  return burn_speed_descriptor_destroy(&next, flag&1);
2842  return 1;
2843 }
2844 
2845 
2846 /* ts A61226 */
2848  struct burn_speed_descriptor *to, int flag)
2849 {
2850  to->source = from->source;
2851  to->profile_loaded = from->profile_loaded;
2852  strcpy(to->profile_name, from->profile_name);
2853  to->wrc = from->wrc;
2854  to->exact = from->exact;
2855  to->mrw = from->mrw;
2856  to->end_lba = from->end_lba;
2857  to->write_speed = from->write_speed;
2858  to->read_speed = from->read_speed;
2859  return 1;
2860 }
2861 
2862 
2863 /* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */
2865 {
2867  return 1;
2868 }
2869 
2870 
2871 /* ts A61226 : API function */
2873  struct burn_speed_descriptor **speed_list)
2874 {
2875  int ret;
2876  struct burn_speed_descriptor *sd, *csd = NULL;
2877 
2878  (*speed_list) = NULL;
2879  for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
2880  ret = burn_speed_descriptor_new(&csd, NULL, csd, 0);
2881  if (ret <= 0)
2882  return -1;
2883  burn_speed_descriptor_copy(sd, csd, 0);
2884  }
2885  (*speed_list) = csd;
2886  return (csd != NULL);
2887 }
2888 
2889 
2890 /* ts A70713 : API function */
2891 int burn_drive_get_best_speed(struct burn_drive *d, int speed_goal,
2892  struct burn_speed_descriptor **best_descr, int flag)
2893 {
2894  struct burn_speed_descriptor *sd;
2895  int best_speed = 0, best_lba = 0, source= 2, speed;
2896 
2897  if (flag & 2)
2898  source = -1;
2899  if (speed_goal < 0)
2900  best_speed = 2000000000;
2901  *best_descr = NULL;
2902  for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
2903  if (flag & 1)
2904  speed = sd->read_speed;
2905  else
2906  speed = sd->write_speed;
2907  if ((source >= 0 && sd->source != source) ||
2908  speed <= 0)
2909  continue;
2910  if (speed_goal < 0) {
2911  if (speed < best_speed) {
2912  best_speed = speed;
2913  *best_descr = sd;
2914  }
2915  } else if (speed_goal == 0) {
2916  if ((source == 2 && sd->end_lba > best_lba) ||
2917  ((source !=2 || sd->end_lba == best_lba) &&
2918  speed > best_speed)) {
2919  best_lba = sd->end_lba;
2920  best_speed = speed;
2921  *best_descr = sd;
2922  }
2923  } else if (speed <= speed_goal) {
2924  if (speed > best_speed) {
2925  best_speed = speed;
2926  *best_descr = sd;
2927  }
2928  }
2929  }
2930  if (d->current_is_cd_profile && *best_descr == NULL && ! (flag & 2))
2931  /* Mode page 2Ah is deprecated in MMC-5 although all known
2932  burners still support it with CD media. */
2933  return burn_drive_get_best_speed(d, speed_goal, best_descr,
2934  flag | 2);
2935  return (*best_descr != NULL);
2936 }
2937 
2938 
2939 /* ts A61226 : API function */
2941 {
2942  return burn_speed_descriptor_destroy(speed_list, 1);
2943 }
2944 
2945 
2946 /* ts A70203 : API function */
2948  struct burn_multi_caps **caps, int flag)
2949 {
2950  enum burn_disc_status s;
2951  struct burn_multi_caps *o;
2952  int status, num_formats, ret, type, i;
2953  off_t size;
2954  unsigned dummy;
2955 
2956  *caps = NULL;
2957  s = burn_disc_get_status(d);
2958  if(s == BURN_DISC_UNGRABBED)
2959  return -1;
2960  *caps = o = (struct burn_multi_caps *)
2961  calloc(1, sizeof(struct burn_multi_caps));
2962  if(*caps == NULL)
2963  return -1;
2964  /* Default says nothing is available */
2965  o->multi_session = o->multi_track = 0;
2966  o-> start_adr = 0;
2968  o->might_do_tao = o->might_do_sao = o->might_do_raw = 0;
2970  o->selected_write_mode = wt;
2973  o->might_simulate = 0;
2974 
2975  if (d->drive_role == 0 || d->drive_role == 4)
2976  return 0;
2977  if (d->drive_role == 2) {
2978  /* stdio file drive : random access read-write */
2979  o->start_adr = 1;
2980  size = d->media_capacity_remaining;
2981  burn_os_stdio_capacity(d->devname, 0, &size);
2984  o->start_alignment = 2048; /* imposting a drive, not a file */
2985  o->might_do_sao = 4;
2986  o->might_do_tao = 2;
2988  o->might_simulate = 1;
2989  } else if (d->drive_role == 5) {
2990  /* stdio file drive : random access write-only */
2991  o->start_adr = 1;
2992  size = d->media_capacity_remaining;
2993  burn_os_stdio_capacity(d->devname, 0, &size);
2995 
2996  /* >>> start_range_low = file size rounded to 2048 */;
2997 
2999  o->start_alignment = 2048; /* imposting a drive, not a file */
3000  if (s == BURN_DISC_APPENDABLE) {
3001  if (wt == BURN_WRITE_SAO || wt == BURN_WRITE_RAW)
3002  return 0;
3003  o->might_do_sao = 0;
3004  } else
3005  o->might_do_sao = 4;
3006  o->might_do_tao = 2;
3008  o->might_simulate = 1;
3009  } else if (d->drive_role != 1) {
3010  /* stdio file drive : sequential access write-only */
3011  o->might_do_sao = 4;
3012  o->might_do_tao = 2;
3014  o->might_simulate = 1;
3015  } else if (s != BURN_DISC_BLANK && s != BURN_DISC_APPENDABLE) {
3016  return 0;
3017  } else if (s == BURN_DISC_APPENDABLE &&
3018  (wt == BURN_WRITE_SAO || wt == BURN_WRITE_RAW)) {
3019  return 0;
3020  } else if (wt == BURN_WRITE_RAW && !d->current_is_cd_profile) {
3021  return 0;
3022  } else if (d->current_profile == 0x09 || d->current_profile == 0x0a) {
3023  /* CD-R , CD-RW */
3024  if (d->block_types[BURN_WRITE_TAO]) {
3025  o->multi_session = o->multi_track = 1;
3026  o->might_do_tao = 2;
3029  }
3030  if (d->block_types[BURN_WRITE_SAO]) {
3031  o->multi_session = o->multi_track = 1;
3032  o->might_do_sao = 1;
3035  }
3036  if (d->block_types[BURN_WRITE_RAW]) {
3037  o->might_do_raw = 1;
3040  }
3041  if (wt == BURN_WRITE_RAW)
3042  o->multi_session = o->multi_track = 0;
3043  else if(wt == BURN_WRITE_NONE || wt == BURN_WRITE_SAO ||
3044  wt == BURN_WRITE_TAO)
3045  o->might_simulate = !!(d->mdata->p2a_valid > 0 &&
3046  d->mdata->simulate);
3047  } else if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
3048  d->current_profile == 0x15) {
3049  /* DVD-R , sequential DVD-RW , DVD-R/DL Sequential */
3050  if (s == BURN_DISC_BLANK) {
3051  o->might_do_sao = 1;
3053  }
3054  if (d->current_has_feat21h) {
3055 #ifndef Libburn_dvd_r_dl_multi_no_close_sessioN
3056  if (d->current_profile != 0x15)
3057 #endif
3058  o->multi_session = 1;
3059  o->multi_track = 1;
3060  o->might_do_tao = 2;
3062  }
3063  if (wt == BURN_WRITE_SAO)
3064  o->multi_session = o->multi_track = 0;
3065  if (wt == BURN_WRITE_NONE || wt == BURN_WRITE_SAO ||
3066  wt == BURN_WRITE_TAO)
3067  o->might_simulate = 1;
3068  } else if (d->current_profile == 0x12 ||
3069  d->current_profile == 0x13 ||
3070  d->current_profile == 0x1a ||
3071  d->current_profile == 0x43
3072  ) {
3073  /* DVD-RAM, overwritable DVD-RW, DVD+RW, BD-RE */
3074  o->start_adr = 1;
3075  ret = burn_disc_get_formats(d, &status, &size, &dummy,
3076  &num_formats);
3077  if (ret == 1) {
3078  if (status == BURN_FORMAT_IS_FORMATTED)
3079  o->start_range_high = size - 2048;
3080  if (d->current_profile == 0x13) {
3081  o->start_alignment = 32 * 1024;
3082  for (i = 0; i < num_formats; i++) {
3083  ret = burn_disc_get_format_descr(d, i,
3084  &type, &size, &dummy);
3085  if (ret <= 0)
3086  continue;
3087  if (type == 0x13) /* expandable */
3088  break;
3089  }
3090  if (i >= num_formats) /* not expandable */
3091  o->start_range_high -= 32 * 1024;
3092  if (o->start_range_high < 0)
3093  o->start_range_high = 0;
3094  } else {
3095  o->start_alignment = 2 * 1024;
3096  if (d->best_format_size - 2048 >
3097  o->start_range_high)
3098  o->start_range_high =
3099  d->best_format_size - 2048;
3100  }
3101  }
3102  o->might_do_sao = 4;
3103  o->might_do_tao = 2;
3105  } else if (d->current_profile == 0x1b || d->current_profile == 0x2b ||
3106  d->current_profile == 0x41) {
3107  /* DVD+R , DVD+R/DL , BD-R SRM */
3108  o->multi_session = o->multi_track = 1;
3109  o->might_do_tao = 2;
3110  o->might_do_sao = 1;
3112  } else /* unknown media */
3113  return 0;
3114 
3115  if (s == BURN_DISC_APPENDABLE)
3116  o->might_do_sao = o->might_do_raw = 0;
3117 
3118  if (wt == BURN_WRITE_TAO && !o->might_do_tao)
3119  return 0;
3120  else if (wt == BURN_WRITE_SAO && !o->might_do_sao)
3121  return 0;
3122  else if (wt == BURN_WRITE_RAW && !o->might_do_raw)
3123  return 0;
3124  return 1;
3125 }
3126 
3127 
3128 /* ts A70203 : API function */
3130 {
3131  if (*caps == NULL)
3132  return 0;
3133  free((char *) *caps);
3134  *caps = NULL;
3135  return 1;
3136 }
3137 
3138 
3139 /* ts A70207 : evaluate write mode related peculiarities of a disc
3140  @param flag bit0= fill_up_media is active
3141 */
3143  struct burn_write_opts *opts,
3144  struct burn_disc_mode_demands *result, int flag)
3145 {
3146  struct burn_session *session;
3147  struct burn_track *track;
3148  int i, j, mode, unknown_track_sizes = 0, last_track_is_unknown = 0;
3149  enum burn_disc_status s;
3150 
3151 
3152  memset((char *) result, 0, sizeof(struct burn_disc_mode_demands));
3153  if (disc == NULL)
3154  return 2;
3155  s = burn_disc_get_status(opts->drive);
3156  if (s == BURN_DISC_APPENDABLE || disc->sessions > 1)
3157  result->will_append = 1;
3158  if (disc->sessions > 1)
3159  result->multi_session = 1;
3160  for (i = 0; i < disc->sessions; i++) {
3161  session = disc->session[i];
3162  if (session->tracks <= 0)
3163  continue;
3164  mode = session->track[0]->mode;
3165  if (session->tracks > 1)
3166  result->multi_track = 1;
3167  for (j = 0; j < session->tracks; j++) {
3168  track = session->track[j];
3169  if (burn_track_is_open_ended(track)) {
3170  if (burn_track_get_default_size(track) > 0) {
3171  if (result->unknown_track_size == 0)
3172  result->unknown_track_size = 2;
3173  } else
3174  result->unknown_track_size = 1;
3175  unknown_track_sizes++;
3176  last_track_is_unknown = 1;
3177  } else
3178  last_track_is_unknown = 0;
3179  if ((mode & BURN_MODE_BITS) !=
3180  (track->mode & BURN_MODE_BITS))
3181  result->mixed_mode = 1;
3182  if (track->mode & BURN_MODE1) {
3183  result->block_types |= BURN_BLOCK_MODE1;
3184  } else if (track->mode & BURN_AUDIO) {
3185  result->audio = 1;
3186  result->block_types |= BURN_BLOCK_RAW0;
3187  result->exotic_track = 1;
3188  } else {
3189  result->block_types |= opts->block_type;
3190  result->exotic_track = 1;
3191  }
3192  }
3193  }
3194  if (flag&1) {/* fill_up_media will define the size of the last track */
3195  if (unknown_track_sizes == 1 && last_track_is_unknown)
3196  result->unknown_track_size = 0;
3197  }
3198  return (disc->sessions > 0);
3199 }
3200 
3201 
3202 /* ts A70903 : API */
3204 {
3205  return d->drive_role;
3206 }
3207 
3208 
3209 /* ts A70923
3210  Hands out pointers *dpt to directory path and *npt to basename.
3211  Caution: the last '/' in adr gets replaced by a 0.
3212 */
3213 static int burn__split_path(char *adr, char **dpt, char **npt)
3214 {
3215  *dpt = adr;
3216  *npt = strrchr(*dpt, '/');
3217  if (*npt == NULL) {
3218  *npt = *dpt;
3219  *dpt = ".";
3220  return 1;
3221  }
3222  **npt = 0;
3223  if(*npt == *dpt)
3224  *dpt = "/";
3225  (*npt)++;
3226  return 2;
3227 }
3228 
3229 
3230 /* ts A70923 : API */
3231 int burn_drive_equals_adr(struct burn_drive *d1, char *adr2_in, int role2)
3232 {
3233  struct stat stbuf1, stbuf2;
3234  char *adr1 = NULL, *adr2 = adr2_in;
3235  char *conv_adr1 = NULL, *conv_adr2 = NULL;
3236  char *npt1, *dpt1, *npt2, *dpt2;
3237  int role1, stat_ret1, stat_ret2, conv_ret2, exact_role_matters = 0, fd;
3238  int ret;
3239 
3240  BURN_ALLOC_MEM(adr1, char, BURN_DRIVE_ADR_LEN);
3241  BURN_ALLOC_MEM(conv_adr1, char, BURN_DRIVE_ADR_LEN);
3242  BURN_ALLOC_MEM(conv_adr2, char, BURN_DRIVE_ADR_LEN);
3243 
3244  role1 = burn_drive_get_drive_role(d1);
3245  burn_drive_d_get_adr(d1, adr1);
3246  stat_ret1 = stat(adr1, &stbuf1);
3247 
3248  /* If one of the candidate paths depicts an open file descriptor then
3249  its read-write capability decides about its role and the difference
3250  between roles 2 and 3 does matter.
3251  */
3253  if (fd != -1)
3254  exact_role_matters = 1;
3255  if (strncmp(adr2, "stdio:", 6) == 0) {
3256  adr2+= 6;
3257  if (adr2[0] == 0) {
3258  role2 = 0;
3259  } else {
3261  if (fd != -1)
3262  exact_role_matters = 1;
3263  ret = burn_drive__is_rdwr(adr2, NULL, NULL, NULL,
3264  1 | 2);
3265  if (ret == 2 && (burn_drive_role_4_allowed & 1))
3266  role2 = 4;
3267  else if (ret == 3 && (burn_drive_role_4_allowed & 1))
3268  role2 = 5;
3269  else if (ret > 0)
3270  role2 = 2;
3271  else
3272  role2 = 3;
3273  if (fd == -1 &&
3274  role2 == 2 && (burn_drive_role_4_allowed & 3) == 3)
3275  role2 = burn_role_by_access(adr2,
3276  !!(burn_drive_role_4_allowed & 4));
3277  }
3278  }
3279 
3280  if (strlen(adr2) >= BURN_DRIVE_ADR_LEN)
3281  {ret = -1; goto ex;}
3282  stat_ret2 = stat(adr2, &stbuf2);
3283  conv_ret2 = burn_drive_convert_fs_adr(adr2, conv_adr2);
3284 
3285  if (!exact_role_matters) {
3286  /* roles >= 2 have the same name space and object
3287  interpretation */
3288  if (role1 >= 2)
3289  role1 = 2;
3290  if (role2 >= 2)
3291  role2 = 2;
3292  }
3293 
3294  if (strcmp(adr1, adr2) == 0 && role1 == role2)
3295  {ret = 1; goto ex;} /* equal role and address */
3296  if (role1 == 1 && role2 == 1) {
3297  /* MMC drive meets wannabe MMC drive */
3298  if (conv_ret2 <= 0)
3299  {ret = 0; goto ex;} /* no MMC drive at adr2 */
3300  if (strcmp(adr1, conv_adr2) == 0)
3301  {ret = 1; goto ex;} /* equal real MMC drives */
3302  {ret = 0; goto ex;}
3303 
3304  } else if (role1 == 0 || role2 == 0)
3305  {ret = 0; goto ex;} /* one null-drive, one not */
3306 
3307  else if (role1 != 1 && role2 != 1) {
3308  /* pseudo-drive meets file object */
3309 
3310  if (role1 != role2)
3311  {ret = 0; goto ex;}
3312  if (stat_ret1 == -1 || stat_ret2 == -1) {
3313  if (stat_ret1 != -1 || stat_ret2 != -1)
3314  {ret = 0; goto ex;}
3315  /* one address existing, one not */
3316 
3317  /* Two non-existing file objects */
3318 
3319  strcpy(conv_adr1, adr1);
3320  burn__split_path(conv_adr1, &dpt1, &npt1);
3321  strcpy(conv_adr2, adr2);
3322  burn__split_path(conv_adr2, &dpt2, &npt2);
3323  if (strcmp(npt1, npt2))
3324  {ret = 0; goto ex;} /* basenames differ */
3325  stat_ret1= stat(adr1, &stbuf1);
3326  stat_ret2= stat(adr2, &stbuf2);
3327  if (stat_ret1 != stat_ret2)
3328  {ret = 0; goto ex;}
3329  /* one dir existing, one not */
3330 
3331  /* Both directories exist. The basenames are equal.
3332  So the addresses are equal if the directories are
3333  equal.*/
3334  }
3335  if (stbuf1.st_ino == stbuf2.st_ino &&
3336  stbuf1.st_dev == stbuf2.st_dev)
3337  {ret = 1; goto ex;} /* same filesystem object */
3338 
3339  if (S_ISBLK(stbuf1.st_mode) && S_ISBLK(stbuf2.st_mode) &&
3340  stbuf1.st_rdev == stbuf2.st_rdev)
3341  {ret = 1; goto ex;}/* same major,minor device number */
3342  if (S_ISCHR(stbuf1.st_mode) && S_ISCHR(stbuf2.st_mode) &&
3343  stbuf1.st_rdev == stbuf2.st_rdev)
3344  {ret = 1; goto ex;}/* same major,minor device number */
3345 
3346  /* Are both filesystem objects related to the same MMC drive */
3347  if (conv_ret2 <= 0)
3348  {ret = 0; goto ex;} /* no MMC drive at adr2 */
3349  if (burn_drive_convert_fs_adr(adr1, conv_adr1) <= 0)
3350  {ret = 0; goto ex;} /* no MMC drive at adr1 */
3351  if (strcmp(conv_adr1, conv_adr2) == 0)
3352  {ret = 1; goto ex;} /* same MMC drive */
3353 
3354  {ret = 0; goto ex;} /* all filesystem disguises are checked */
3355 
3356  } else if (role1 == 1 && role2 != 1) {
3357  /* MMC drive meets file object */
3358 
3359  if (conv_ret2 <= 0)
3360  {ret = 0; goto ex;} /* no MMC drive at adr2 */
3361  if (strcmp(adr1, conv_adr2) == 0)
3362  {ret = 1; goto ex;} /* same MMC drive */
3363  {ret = 0; goto ex;}
3364 
3365  } else if (role1 != 1 && role2 == 1) {
3366  /* stdio-drive meets wannabe MMC drive */
3367 
3368  if (conv_ret2 <= 0)
3369  {ret = 0; goto ex;} /* no MMC drive at adr2 */
3370  if (burn_drive_convert_fs_adr(adr1, conv_adr1) <= 0)
3371  {ret = 0; goto ex;} /* no MMC drive at adr1 */
3372  if (strcmp(conv_adr1, conv_adr2) == 0)
3373  {ret = 1; goto ex;} /* same MMC drive */
3374  {ret = 0; goto ex;}
3375 
3376  }
3377  ret = 0;
3378 ex:;
3379  BURN_FREE_MEM(adr1);
3380  BURN_FREE_MEM(conv_adr1);
3381  BURN_FREE_MEM(conv_adr2);
3382  return ret;
3383 }
3384 
3385 
3386 int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid,
3387  pthread_t tid)
3388 {
3389  int i;
3390 
3391  for (i = 0; i < drivetop + 1; i++) {
3392 
3393 /*
3394  if (drive_array[i].thread_pid_valid)
3395  fprintf(stderr, "libburn_EXPERIMENTAL : drive %d , thread_pid %d\n", i, drive_array[i].thread_pid);
3396 */
3397 
3398  if (drive_array[i].thread_pid_valid &&
3399  drive_array[i].thread_pid == pid &&
3400  pthread_equal(drive_array[i].thread_tid, tid)) {
3401  *d = &(drive_array[i]);
3402  return 1;
3403  }
3404  }
3405  return 0;
3406 }
3407 
3408 
3409 /* ts A80422 : centralizing this setting for debugging purposes
3410 */
3412 {
3413  if (value / (off_t) 2048 > (off_t) 0x7ffffff0)
3414  value = ((off_t) 0x7ffffff0) * (off_t) 2048;
3415  d->media_capacity_remaining = value;
3416  return 1;
3417 }
3418 
3419 
3420 /* ts A81215 : API */
3421 int burn_get_read_capacity(struct burn_drive *d, int *capacity, int flag)
3422 {
3423  *capacity = d->media_read_capacity +
3424  (d->media_read_capacity != 0x7fffffff);
3425  return (d->media_read_capacity != 0x7fffffff);
3426 }
3427 
3428 
3429 /* ts A90903 : API */
3431  char **product_id, char **media_code1, char **media_code2,
3432  char **book_type, int flag)
3433 {
3434  int ret;
3435 
3436  *product_id = *media_code1 = *media_code2 = *book_type = NULL;
3437  if (burn_drive_get_drive_role(d) != 1)
3438  return 0;
3439  ret = mmc_get_media_product_id(d,
3440  product_id, media_code1, media_code2, book_type,
3441  flag & 1);
3442  return ret;
3443 }
3444 
3445 
3446 /* ts A90909 : API */
3447 /**
3448  @param valid Replies bits which indicate the validity of other reply
3449  parameters or the state of certain CD info bits:
3450  bit0= disc_type valid
3451  bit1= disc_id valid
3452  bit2= bar_code valid
3453  bit3= disc_app_code valid
3454  bit4= Disc is unrestricted (URU bit)
3455  bit5= Disc is nominally erasable (Erasable bit)
3456  This will be set with overwritable media which
3457  libburn normally considers to be unerasable blank.
3458 */
3459 int burn_disc_get_cd_info(struct burn_drive *d, char disc_type[80],
3460  unsigned int *disc_id, char bar_code[9], int *app_code,
3461  int *valid)
3462 {
3463  if (d->disc_type == 0x00) {
3464  strcpy(disc_type, "CD-DA or CD-ROM");
3465  } else if (d->disc_type == 0x10) {
3466  strcpy(disc_type, "CD-I");
3467  } else if (d->disc_type == 0x20) {
3468  strcpy(disc_type, "CD-ROM XA");
3469  } else {
3470  strcpy(disc_type, "undefined");
3471  }
3472  *disc_id = d->disc_id;
3473  memcpy(bar_code, d->disc_bar_code, 8);
3474  bar_code[8]= 0;
3475  *app_code = d->disc_app_code;
3476  *valid = d->disc_info_valid;
3477  return 1;
3478 }
3479 
3480 
3481 /* ts B00924 : API */
3483  int *alloc_blocks, int *free_blocks, int flag)
3484 {
3485  int ret;
3486 
3487  if (burn_drive_get_drive_role(d) != 1)
3488  return 0;
3489  *alloc_blocks = *free_blocks = 0;
3490  ret = mmc_get_bd_spare_info(d, alloc_blocks, free_blocks, 0);
3491  return ret;
3492 }
3493 
3494 
3495 /* ts B10801 : API */
3496 int burn_disc_get_phys_format_info(struct burn_drive *d, int *disk_category,
3497  char **book_name, int *part_version, int *num_layers,
3498  int *num_blocks, int flag)
3499 {
3500  int ret;
3501 
3502  if (burn_drive_get_drive_role(d) != 1)
3503  return 0;
3504  *disk_category = *part_version = *num_layers = *num_blocks = 0;
3505  ret = mmc_get_phys_format_info(d, disk_category, book_name,
3506  part_version, num_layers, num_blocks, 0);
3507  return ret;
3508 }
3509 
3510 
3511 
3512 /* ts B10525 : API */
3514 {
3515  return d->next_track_damaged;
3516 }
3517 
3518 
3519 /* ts B11201 : API */
3520 /* Read the CD-TEXT data from the Lead-in of an Audio CD
3521 */
3523  unsigned char **text_packs, int *num_packs,
3524  int flag)
3525 {
3526  int ret;
3527 
3528  ret = mmc_get_leadin_text(d, text_packs, num_packs, 0);
3529  return ret;
3530 }
3531 
3532 
3533 /* ts B31023 API */
3534 /* Inquire for DVD-RW failure of TAO
3535 */
3537 {
3538  return !!d->was_feat21h_failure;
3539 }
3540 
3541 
3542 /* ts B40106 */
3544  unsigned char *descr, int descr_len, int flag)
3545 {
3546  struct burn_feature_descr *o;
3547 
3548  *new = NULL;
3549  if (descr_len < 4)
3550  return 0;
3551  (*new) = o = calloc(1, sizeof(struct burn_feature_descr));
3552  if (o == NULL)
3553  return -1;
3554  o->feature_code = (descr[0] << 8) | descr[1];
3555  o->flags = descr[2];
3556  if (descr[3] > descr_len - 4)
3557  o->data_lenght = 0;
3558  else
3559  o->data_lenght = descr[3];
3560  o->data = NULL;
3561  o->next = NULL;
3562  if (o->data_lenght > 0) {
3563  o->data = calloc(1, o->data_lenght);
3564  if (o->data == NULL) {
3565  burn_feature_descr_free(new, 0);
3566  return -1;
3567  }
3568  memcpy(o->data, descr + 4, o->data_lenght);
3569  }
3570  return 1;
3571 }
3572 
3573 
3574 /* ts B40106 */
3575 int burn_feature_descr_free(struct burn_feature_descr **descr, int flag)
3576 {
3577  struct burn_feature_descr *o, *next;
3578 
3579  if (*descr == NULL)
3580  return 0;
3581  for (o = *descr; o != NULL; o = next) {
3582  next = o->next;
3583  if (o->data != NULL)
3584  free(o->data);
3585  free((char *) o);
3586  }
3587  *descr = NULL;
3588  return 1;
3589 }
3590 
3591 
3592 /* ts B40107 */
3594  struct burn_feature_descr **descr, int flag)
3595 {
3596  struct burn_feature_descr *o;
3597 
3598  for (o = d->features; o != NULL; o = o->next) {
3599  if (o->feature_code == feature_code) {
3600  if (descr != NULL)
3601  *descr = o;
3602  return 1;
3603  }
3604  }
3605  return 0;
3606 }
3607 
3608 
3609 /* ts B51016 API */
3610 int burn_drive_get_serial_no(struct burn_drive *d, char **sno, int *sno_len)
3611 {
3612  int ret;
3613 
3614  if (*sno != NULL)
3615  BURN_FREE_MEM(*sno);
3616  if (d->drive_serial_number_len > 0)
3617  *sno_len = d->drive_serial_number_len;
3618  else
3619  *sno_len = 0;
3620  BURN_ALLOC_MEM(*sno, char, *sno_len + 1);
3621  if (d->drive_serial_number_len > 0)
3622  memcpy(*sno, d->drive_serial_number, *sno_len);
3623  (*sno)[*sno_len] = 0;
3624  ret = 1;
3625 ex:
3626  return ret;
3627 }
3628 
3629 
3630 /* ts B51016 API */
3631 int burn_drive_get_media_sno(struct burn_drive *d, char **sno, int *sno_len)
3632 {
3633  int ret;
3634 
3635 #ifdef Libburn_enable_scsi_cmd_ABh
3636  struct burn_feature_descr *feat;
3637 #endif
3638 
3639  if (*sno != NULL)
3640  BURN_FREE_MEM(*sno);
3641  *sno = NULL;
3642 
3643  if (d->media_serial_number_len == -1) {
3644 
3645 #ifdef Libburn_enable_scsi_cmd_ABh
3646 
3647  if (burn_drive_has_feature(d, 0x109, &feat, 0))
3648 
3649 #ifndef Libburn_enable_scsi_cmd_ABh_pretend_currenT
3650  if (feat->flags & 1) /* current */
3651 #endif
3652 
3653  spc_read_media_serial_number(d);
3654 
3655 #else
3656  ;
3657 
3658 #endif /* ! Libburn_enable_scsi_cmd_ABh */
3659 
3660  }
3661 
3662  if (d->media_serial_number_len > 0)
3663  *sno_len = d->media_serial_number_len;
3664  else
3665  *sno_len = 0;
3666  BURN_ALLOC_MEM(*sno, char, *sno_len + 1);
3667  if (*sno_len > 0)
3668  memcpy(*sno, d->media_serial_number, *sno_len);
3669  (*sno)[*sno_len] = 0;
3670  ret = 1;
3671 ex:
3672  return ret;
3673 }
3674 
3675 
3677 {
3678  struct burn_feature_descr *feature;
3679 
3680  if (d->current_profile == 0x41)
3681  if (burn_drive_has_feature(d, 0x38, &feature, 0) == 1)
3682  if (feature->flags & 1)
3683  return 1;
3684  return 0;
3685 }
3686 
3687 
3688 int burn_drive_set_immed(struct burn_drive *drive, int enable)
3689 {
3690  drive->do_no_immed = !enable;
3691  return 1;
3692 }
3693 
3694 
3696 {
3697  return !drive->do_no_immed;
3698 }
3699 
3700 
3701 /* ts B90412 , API */
3702 int burn_drive_get_feature(struct burn_drive *d, unsigned int feature_code,
3703  unsigned char *flags,
3704  unsigned char *additional_length,
3705  unsigned char **feature_data,
3706  char **feature_text)
3707 {
3708  int ret, i;
3709  struct burn_feature_descr *descr;
3710 
3711  *flags = 0;
3712  *additional_length = 0;
3713  *feature_data = NULL;
3714  if (feature_text != NULL)
3715  *feature_text = NULL;
3716  if (!burn_drive_has_feature(d, feature_code, &descr, 0))
3717  return 0;
3718  *flags = descr->flags;
3719  *additional_length = descr->data_lenght;
3720  if (*additional_length > 0)
3721  BURN_ALLOC_MEM(*feature_data, unsigned char,
3722  *additional_length);
3723  for (i = 0; i < *additional_length; i++)
3724  (*feature_data)[i] = descr->data[i];
3725 
3726  if (feature_text != NULL) {
3728  *additional_length, *feature_data,
3729  feature_text, 0);
3730  } else {
3731  ret = 1;
3732  }
3733 ex:
3734  return ret;
3735 }
3736 
3737 
3738 /* ts B90412 , API */
3740  int *count, unsigned int **feature_codes)
3741 {
3742  struct burn_feature_descr *o;
3743  int to_alloc;
3744 
3745  *count = 0;
3746  *feature_codes = NULL;
3747  for (o = d->features; o != NULL; o = o->next)
3748  (*count)++;
3749  if (*count == 0)
3750  return;
3751  to_alloc = *count;
3752  *count = 0;
3753  BURN_ALLOC_MEM_VOID(*feature_codes, unsigned int, to_alloc);
3754  for (o = d->features; o != NULL; o = o->next) {
3755  (*feature_codes)[*count] = o->feature_code;
3756  (*count)++;
3757  }
3758 ex:;
3759 }
3760 
int burn_drive_get_all_profiles(struct burn_drive *d, int *num_profiles, int profiles[64], char is_current[64])
Definition: drive.c:2759
int burn_drive_inquire_media(struct burn_drive *d)
Definition: drive.c:282
int burn_drive_unregister(struct burn_drive *d)
Definition: drive.c:600
int burn_drive_adr_debug_msg(char *fmt, char *arg)
Definition: drive.c:1993
void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
Definition: drive.c:952
int burn_drive_get_min_write_speed(struct burn_drive *d)
Definition: drive.c:1686
int burn_feature_descr_free(struct burn_feature_descr **descr, int flag)
Definition: drive.c:3575
int burn_drive_mark_unready(struct burn_drive *d, int flag)
Definition: drive.c:656
int burn_drive_is_released(struct burn_drive *d)
Definition: drive.c:185
#define O_LARGEFILE
static int enumeration_whitelist_top
Definition: drive.c:1694
int burn_drive_grab_stdio(struct burn_drive *d, int flag)
Definition: drive.c:412
int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80])
Definition: drive.c:2750
int burn_disc_read_atip(struct burn_drive *d)
Definition: drive.c:2616
struct burn_drive * burn_drive_register(struct burn_drive *d)
Definition: drive.c:540
int burn_drive_leave_locked(struct burn_drive *d, int flag)
Definition: drive.c:802
int burn_drive_convert_fs_adr(char *path, char adr[])
Definition: drive.c:2338
int burn_drive_get_adr(struct burn_drive_info *drive_info, char adr[])
Definition: drive.c:2032
int burn_drive_reset_simulate(struct burn_drive *d, int simulate)
Definition: drive.c:1649
int burn_disc_get_phys_format_info(struct burn_drive *d, int *disk_category, char **book_name, int *part_version, int *num_layers, int *num_blocks, int flag)
Definition: drive.c:3496
int burn_drive_send_default_page_05(struct burn_drive *d, int flag)
Definition: drive.c:309
void burn_drive_release(struct burn_drive *d, int le)
Definition: drive.c:762
int burn_drive_snooze(struct burn_drive *d, int flag)
Definition: drive.c:749
int burn_disc_get_leadin_text(struct burn_drive *d, unsigned char **text_packs, int *num_packs, int flag)
Definition: drive.c:3522
int burn_drive_is_occupied(struct burn_drive *d)
Definition: drive.c:203
int burn_drive_whitelist_count(void)
Definition: drive.c:1736
int burn_disc_pretend_full(struct burn_drive *d)
Definition: drive.c:2597
#define O_BINARY
Definition: drive.c:32
int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt, struct burn_multi_caps **caps, int flag)
Definition: drive.c:2947
int burn_drive_forget(struct burn_drive *d, int force)
Definition: drive.c:1495
int burn_speed_descriptor_destroy(struct burn_speed_descriptor **s, int flag)
Definition: drive.c:2823
static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
Definition: drive.c:1262
int burn_drive_resolve_link(char *path, char adr[], int *recursion_count, int flag)
Definition: drive.c:2057
void burn_drive_get_feature_codes(struct burn_drive *d, int *count, unsigned int **feature_codes)
Definition: drive.c:3739
static int burn__split_path(char *adr, char **dpt, char **npt)
Definition: drive.c:3213
int burn_disc_get_cd_info(struct burn_drive *d, char disc_type[80], unsigned int *disc_id, char bar_code[9], int *app_code, int *valid)
Definition: drive.c:3459
int burn_drive_force_idle(struct burn_drive *d)
Definition: drive.c:177
int burn_drive_is_banned(char *device_address)
Definition: drive.c:1723
int burn_drive_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, int *target_no, int *lun_no)
Definition: drive.c:2172
int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid, pthread_t tid)
Definition: drive.c:3386
int burn_drive_is_open(struct burn_drive *d)
Definition: drive.c:167
int burn_disc_get_formats(struct burn_drive *d, int *status, off_t *size, unsigned *bl_sas, int *num_formats)
Definition: drive.c:1081
int burn_drive_d_get_adr(struct burn_drive *d, char adr[])
Definition: drive.c:2017
int burn_drive_get_bd_r_pow(struct burn_drive *d)
Definition: drive.c:3676
int burn_drive_convert_scsi_adr(int bus_no, int host_no, int channel_no, int target_no, int lun_no, char adr[])
Definition: drive.c:2211
int burn_disc_get_bd_spare_info(struct burn_drive *d, int *alloc_blocks, int *free_blocks, int flag)
Definition: drive.c:3482
int burn_drive_free_speedlist(struct burn_speed_descriptor **speed_list)
Definition: drive.c:2940
struct libdax_msgs * libdax_messenger
Definition: init.c:42
int burn_drive_release_fl(struct burn_drive *d, int flag)
Definition: drive.c:693
void burn_drive_free_subs(struct burn_drive *d)
Definition: drive.c:111
static struct burn_drive drive_array[255]
Definition: drive.c:67
int burn_drive_scan_sync(struct burn_drive_info *drives[], unsigned int *n_drives, int flag)
Definition: drive.c:1391
char * burn_drive_whitelist_item(int idx, int flag)
Definition: drive.c:1741
int burn_drive_is_listed(char *path, struct burn_drive **found, int flag)
Definition: drive.c:250
int burn_msf_to_sectors(int m, int s, int f)
Definition: drive.c:1663
int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count)
Definition: drive.c:2291
struct burn_drive * burn_drive_finish_enum(struct burn_drive *d)
Definition: drive.c:612
int burn_drive_was_feat21_failure(struct burn_drive *d)
Definition: drive.c:3536
int burn_drive_equals_adr(struct burn_drive *d1, char *adr2_in, int role2)
Definition: drive.c:3231
int burn_disc_pretend_blank(struct burn_drive *d)
Definition: drive.c:2585
static void strip_spaces(char *str, size_t len)
Definition: drive.c:1244
static int burn_drive__is_rdwr(char *fname, int *stat_ret, struct stat *stbuf_ret, off_t *read_size_ret, int flag)
Definition: drive.c:356
int burn_setup_drive(struct burn_drive *d, char *fname)
Definition: drive.c:79
int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
Definition: drive.c:1781
int burn_drive_find_scsi_equiv(char *path, char adr[])
Definition: drive.c:2264
int burn_disc_erasable(struct burn_drive *d)
Definition: drive.c:1135
int burn_drive_get_media_sno(struct burn_drive *d, char **sno, int *sno_len)
Definition: drive.c:3631
enum burn_drive_status burn_drive_get_status(struct burn_drive *d, struct burn_progress *p)
Definition: drive.c:1139
int burn_drive_set_stream_recording(struct burn_drive *d, int recmode, int start, int flag)
Definition: drive.c:1178
int burn_drive_wrote_well(struct burn_drive *d)
Definition: drive.c:2783
int burn_drive_add_whitelist(char *device_address)
Definition: drive.c:1700
off_t burn_disc_available_space(struct burn_drive *d, struct burn_write_opts *o)
Definition: drive.c:2711
int burn_disc_get_format_descr(struct burn_drive *d, int index, int *type, off_t *size, unsigned *tdp)
Definition: drive.c:1104
static int drivetop
Definition: drive.c:68
int burn_drive_info_forget(struct burn_drive_info *info, int force)
Definition: drive.c:1522
int burn_drive_get_speedlist(struct burn_drive *d, struct burn_speed_descriptor **speed_list)
Definition: drive.c:2872
#define BURN_DRIVE_MAX_LINK_DEPTH
Definition: drive.c:2050
int burn_disc_pretend_full_uncond(struct burn_drive *d)
Definition: drive.c:2609
int burn_drive_set_immed(struct burn_drive *drive, int enable)
Definition: drive.c:3688
int burn_abort(int patience, int(*pacifier_func)(void *handle, int patience, int elapsed), void *handle)
Definition: drive.c:2557
int burn_drive_get_drive_role(struct burn_drive *d)
Definition: drive.c:3203
void burn_drive_cancel(struct burn_drive *d)
Definition: drive.c:1227
unsigned int burn_drive_count(void)
Definition: drive.c:243
enum burn_disc_status burn_disc_get_status(struct burn_drive *d)
Definition: drive.c:1119
int burn_disc_free_multi_caps(struct burn_multi_caps **caps)
Definition: drive.c:3129
int burn_speed_descriptor_copy(struct burn_speed_descriptor *from, struct burn_speed_descriptor *to, int flag)
Definition: drive.c:2847
int burn_drive_is_enumerable_adr(char *adr)
Definition: drive.c:2045
int burn_speed_descriptor_new(struct burn_speed_descriptor **s, struct burn_speed_descriptor *prev, struct burn_speed_descriptor *next, int flag)
Definition: drive.c:2790
int burn_drive_re_assess(struct burn_drive *d, int flag)
Definition: drive.c:770
int burn_drive_set_media_capacity_remaining(struct burn_drive *d, off_t value)
Definition: drive.c:3411
int burn_drive_get_feature(struct burn_drive *d, unsigned int feature_code, unsigned char *flags, unsigned char *additional_length, unsigned char **feature_data, char **feature_text)
Definition: drive.c:3702
int burn_abort_5(int patience, int(*pacifier_func)(void *handle, int patience, int elapsed), void *handle, int elapsed, int flag)
Definition: drive.c:2448
int burn_obtain_profile_name(int profile_number, char name[80])
Definition: drive.c:2775
int burn_drive__fd_from_special_adr(char *adr)
Definition: drive.c:337
static char * enumeration_whitelist[255]
Definition: drive.c:1693
void burn_sectors_to_msf(int sectors, int *m, int *s, int *f)
Definition: drive.c:1668
int burn_drives_are_clear(int flag)
Definition: drive.c:810
int burn_disc_next_track_is_damaged(struct burn_drive *d, int flag)
Definition: drive.c:3513
void burn_drive_info_free(struct burn_drive_info drive_infos[])
Definition: drive.c:1528
int burn_abort_pacifier(void *handle, int patience, int elapsed)
Definition: drive.c:2432
int burn_drive_has_feature(struct burn_drive *d, int feature_code, struct burn_feature_descr **descr, int flag)
Definition: drive.c:3593
int burn_drive_grab(struct burn_drive *d, int le)
Definition: drive.c:472
void burn_drive_free_all(void)
Definition: drive.c:155
int burn_drive_get_read_speed(struct burn_drive *d)
Definition: drive.c:1675
void burn_drive_clear_whitelist(void)
Definition: drive.c:1715
int burn_mdata_free_subs(struct scsi_mode_data *m)
Definition: drive.c:2864
int burn_drive_set_speed_exact(struct burn_drive *d, int r, int w)
Definition: drive.c:1604
int burn_get_read_capacity(struct burn_drive *d, int *capacity, int flag)
Definition: drive.c:3421
int burn_disc_get_msc1(struct burn_drive *d, int *start)
Definition: drive.c:2682
static int burn_role_by_access(char *fname, int flag)
Definition: drive.c:1749
struct burn_disc * burn_drive_get_disc(struct burn_drive *d)
Definition: drive.c:1586
int burn_lookup_device_link(char *dev_adr, char link_adr[], char *dir_adr, char **ranks, int rank_count, int flag)
Definition: drive.c:2348
int burn_drive_get_start_end_lba(struct burn_drive *d, int *start_lba, int *end_lba, int flag)
Definition: drive.c:2573
void burn_disc_erase_sync(struct burn_drive *d, int fast)
Definition: drive.c:851
int burn_drive_get_write_speed(struct burn_drive *d)
Definition: drive.c:1680
int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], char *adr, int load)
Definition: drive.c:1933
int burn_drive_get_immed(struct burn_drive *drive)
Definition: drive.c:3695
int burn_disc_get_media_id(struct burn_drive *d, char **product_id, char **media_code1, char **media_code2, char **book_type, int flag)
Definition: drive.c:3430
int burn_drive_probe_cd_write_modes(struct burn_drive_info *dinfo)
Definition: drive.c:1372
int burn_feature_descr_new(struct burn_feature_descr **new, unsigned char *descr, int descr_len, int flag)
Definition: drive.c:3543
int burn_disc_get_write_mode_demands(struct burn_disc *disc, struct burn_write_opts *opts, struct burn_disc_mode_demands *result, int flag)
Definition: drive.c:3142
int burn_drive_get_serial_no(struct burn_drive *d, char **sno, int *sno_len)
Definition: drive.c:3610
int burn_drive_role_4_allowed
Definition: init.c:117
int burn_support_untested_profiles
Definition: init.c:102
int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o, int trackno, int *lba, int *nwa)
Definition: drive.c:2645
int burn_drive_set_buffer_waiting(struct burn_drive *d, int enable, int min_usec, int max_usec, int timeout_sec, int min_percent, int max_percent)
Definition: drive.c:1622
int burn_drive_find_devno(dev_t devno, char adr[])
Definition: drive.c:2130
int burn_drive_get_best_speed(struct burn_drive *d, int speed_goal, struct burn_speed_descriptor **best_descr, int flag)
Definition: drive.c:2891
void burn_drive_free(struct burn_drive *d)
Definition: drive.c:141
void burn_drive_set_speed(struct burn_drive *d, int r, int w)
Definition: drive.c:1596
#define BE_CANCELLED
Definition: error.h:6
int burn_init_catch_on_abort(int flag)
Definition: init.c:568
burn_abort_handler_t burn_global_signal_handler
Definition: init.c:96
int burn_global_abort_signum
Definition: init.c:94
int burn_is_aborting(int flag)
Definition: init.c:559
int burn_grab_restore_sig_action(int signal_action_mem, int flag)
Definition: init.c:603
void burn_finish(void)
Definition: init.c:161
volatile int burn_global_abort_level
Definition: init.c:93
void * burn_global_signal_handle
Definition: init.c:95
int burn_grab_prepare_sig_action(int *signal_action_mem, int flag)
Definition: init.c:587
#define BURN_FREE_MEM(pt)
Definition: init.h:52
#define BURN_ALLOC_MEM(pt, typ, count)
Definition: init.h:40
#define BURN_ALLOC_MEM_VOID(pt, typ, count)
Definition: init.h:46
#define BURN_DRIVE_WHITELIST_LEN
Definition: libburn.h:974
void burn_write_opts_free(struct burn_write_opts *opts)
Definition: options.c:74
@ BURN_BLOCK_SAO
Definition: libburn.h:227
@ BURN_BLOCK_RAW0
Definition: libburn.h:194
@ BURN_BLOCK_MODE1
Definition: libburn.h:202
burn_drive_status
Definition: libburn.h:293
@ BURN_DRIVE_FORMATTING
Definition: libburn.h:325
@ BURN_DRIVE_READING_SYNC
Definition: libburn.h:331
@ BURN_DRIVE_WRITING_LEADIN
Definition: libburn.h:305
@ BURN_DRIVE_WRITING
Definition: libburn.h:303
@ BURN_DRIVE_CLOSING_SESSION
Definition: libburn.h:320
@ BURN_DRIVE_GRABBING
Definition: libburn.h:311
@ BURN_DRIVE_WRITING_LEADOUT
Definition: libburn.h:307
@ BURN_DRIVE_ERASING
Definition: libburn.h:309
@ BURN_DRIVE_WRITING_SYNC
Definition: libburn.h:334
@ BURN_DRIVE_WRITING_PREGAP
Definition: libburn.h:316
@ BURN_DRIVE_READING
Definition: libburn.h:301
@ BURN_DRIVE_IDLE
Definition: libburn.h:295
#define BURN_DRIVE_ADR_LEN
Definition: libburn.h:1041
#define BURN_FORMAT_IS_FORMATTED
Definition: libburn.h:1754
burn_write_types
Definition: libburn.h:138
@ BURN_WRITE_RAW
Definition: libburn.h:180
@ BURN_WRITE_PACKET
Definition: libburn.h:142
@ BURN_WRITE_TAO
Definition: libburn.h:152
@ BURN_WRITE_SAO
Definition: libburn.h:163
@ BURN_WRITE_NONE
Definition: libburn.h:187
#define BURN_MODE_BITS
Definition: libburn.h:79
void burn_disc_free(struct burn_disc *d)
Definition: structure.c:81
burn_disc_status
Definition: libburn.h:232
@ BURN_DISC_UNREADY
Definition: libburn.h:234
@ BURN_DISC_EMPTY
Definition: libburn.h:247
@ BURN_DISC_UNGRABBED
Definition: libburn.h:270
@ BURN_DISC_BLANK
Definition: libburn.h:244
@ BURN_DISC_UNSUITABLE
Definition: libburn.h:275
@ BURN_DISC_APPENDABLE
Definition: libburn.h:254
@ BURN_DISC_FULL
Definition: libburn.h:265
struct burn_write_opts * burn_write_opts_new(struct burn_drive *drive)
Definition: options.c:29
#define BURN_MODE1
Definition: libburn.h:92
#define BURN_AUDIO
Definition: libburn.h:113
int burn_write_opts_set_write_type(struct burn_write_opts *opts, enum burn_write_types write_type, int block_type)
Definition: options.c:138
int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code, int severity, int priority, char *msg_text, int os_errno, int flag)
Definition: libdax_msgs.c:334
#define LIBDAX_MSGS_SEV_DEBUG
Definition: libdax_msgs.h:138
#define LIBDAX_MSGS_PRIO_LOW
Definition: libdax_msgs.h:235
#define LIBDAX_MSGS_SEV_FATAL
Definition: libdax_msgs.h:217
#define LIBDAX_MSGS_SEV_NOTE
Definition: libdax_msgs.h:146
#define LIBDAX_MSGS_PRIO_HIGH
Definition: libdax_msgs.h:237
#define LIBDAX_MSGS_SEV_SORRY
Definition: libdax_msgs.h:176
#define LIBDAX_MSGS_PRIO_ZERO
Definition: libdax_msgs.h:234
#define LIBDAX_MSGS_SEV_FAILURE
Definition: libdax_msgs.h:205
int mmc_function_spy(struct burn_drive *d, char *text)
Definition: mmc.c:267
int mmc_get_phys_format_info(struct burn_drive *d, int *disk_category, char **book_name, int *part_version, int *num_layers, int *num_blocks, int flag)
Definition: mmc.c:5334
int burn_make_feature_text(struct burn_drive *d, unsigned int feature_code, unsigned char flags, unsigned char additional_length, unsigned char *feature_data, char **text, int flag)
Definition: mmc.c:5495
int mmc_get_leadin_text(struct burn_drive *d, unsigned char **text_packs, int *num_packs, int flag)
Definition: mmc.c:2297
int mmc_get_bd_spare_info(struct burn_drive *d, int *alloc_blocks, int *free_blocks, int flag)
Definition: mmc.c:5304
int mmc_get_media_product_id(struct burn_drive *d, char **product_id, char **media_code1, char **media_code2, char **book_type, int flag)
Definition: mmc.c:5121
char * mmc_obtain_profile_name(int profile_number)
Definition: mmc.c:1868
int sg_is_enumerable_adr(char *adr)
Definition: sg-dummy.c:219
int sg_dispose_drive(struct burn_drive *d, int flag)
Definition: sg-dummy.c:105
int scsi_enumerate_drives(void)
Definition: sg-dummy.c:137
int burn_os_is_2k_seekrw(char *path, int flag)
Definition: sg-dummy.c:228
int burn_os_stdio_capacity(char *path, off_t write_start, off_t *bytes)
Definition: sg-dummy.c:252
int sg_give_next_adr(burn_drive_enumerator_t *idx, char adr[], int adr_size, int initialize)
Definition: sg-dummy.c:126
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no, int *target_no, int *lun_no)
Definition: sg-dummy.c:205
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 bytes
Definition: transport.h:54
int sectors
Definition: transport.h:53
int sessions
Definition: structure.h:145
int refcnt
Definition: structure.h:152
struct burn_session ** session
Definition: structure.h:146
char location[17]
Definition: libburn.h:599
unsigned int read_cdr
Definition: libburn.h:613
unsigned int write_simulate
Definition: libburn.h:627
unsigned int write_dvdr
Definition: libburn.h:620
unsigned int read_cdrw
Definition: libburn.h:615
int packet_block_types
Definition: libburn.h:659
unsigned int read_dvdrom
Definition: libburn.h:611
char product[17]
Definition: libburn.h:591
int sao_block_types
Definition: libburn.h:647
int tao_block_types
Definition: libburn.h:641
unsigned int write_cdrw
Definition: libburn.h:624
unsigned int read_dvdr
Definition: libburn.h:609
unsigned int read_dvdram
Definition: libburn.h:607
struct burn_drive * drive
Definition: libburn.h:664
unsigned int write_cdr
Definition: libburn.h:622
int raw_block_types
Definition: libburn.h:653
unsigned int write_dvdram
Definition: libburn.h:618
char revision[5]
Definition: libburn.h:593
unsigned int c2_errors
Definition: libburn.h:630
char vendor[9]
Definition: libburn.h:589
int(* test_unit_ready)(struct burn_drive *d)
Definition: transport.h:519
off_t best_format_size
Definition: transport.h:313
enum burn_disc_status status
Definition: transport.h:204
int nominal_write_speed
Definition: transport.h:411
int was_feat21h_failure
Definition: transport.h:234
int stdio_fd
Definition: transport.h:336
void(* probe_write_modes)(struct burn_drive *d)
Definition: transport.h:520
char current_profile_text[80]
Definition: transport.h:209
int(* grab)(struct burn_drive *)
Definition: transport.h:453
unsigned int wfb_min_percent
Definition: transport.h:415
int media_serial_number_len
Definition: transport.h:269
struct burn_write_opts * write_opts
Definition: transport.h:430
struct burn_progress progress
Definition: transport.h:395
unsigned int wfb_min_usec
Definition: transport.h:412
int num_profiles
Definition: transport.h:216
int current_is_cd_profile
Definition: transport.h:210
int do_stream_recording
Definition: transport.h:286
int disc_info_valid
Definition: transport.h:302
int(* get_erase_progress)(struct burn_drive *)
Definition: transport.h:498
int(* get_nwa)(struct burn_drive *, int trackno, int *lba, int *nwa)
Definition: transport.h:499
unsigned int wfb_max_usec
Definition: transport.h:413
int next_track_damaged
Definition: transport.h:274
struct params params
Definition: transport.h:521
unsigned int disc_id
Definition: transport.h:299
int do_simulate
Definition: transport.h:345
int current_has_feat21h
Definition: transport.h:225
int media_read_capacity
Definition: transport.h:378
int global_index
Definition: transport.h:200
int sent_default_page_05
Definition: transport.h:364
unsigned int format_curr_blsas
Definition: transport.h:311
volatile int released
Definition: transport.h:320
int mr_capacity_trusted
Definition: transport.h:383
struct buffer * buffer
Definition: transport.h:394
int medium_state_changed
Definition: transport.h:443
char * drive_serial_number
Definition: transport.h:263
int current_feat2fh_byte4
Definition: transport.h:259
char * devname
Definition: transport.h:185
off_t format_curr_max_size
Definition: transport.h:310
int toc_entries
Definition: transport.h:524
struct burn_format_descr format_descriptors[32]
Definition: transport.h:317
int block_types[4]
Definition: transport.h:393
int current_is_guessed_profile
Definition: transport.h:213
void(* lock)(struct burn_drive *)
Definition: transport.h:470
unsigned char all_profiles[256]
Definition: transport.h:215
struct burn_feature_descr * features
Definition: transport.h:219
int bus_no
Definition: transport.h:180
struct burn_toc_entry * toc_entry
Definition: transport.h:525
int silent_on_scsi_error
Definition: transport.h:329
char disc_bar_code[9]
Definition: transport.h:300
void(* read_atip)(struct burn_drive *)
Definition: transport.h:466
int disc_type
Definition: transport.h:298
int(* stop_unit)(struct burn_drive *)
Definition: transport.h:477
int(* write)(struct burn_drive *, int, struct buffer *)
Definition: transport.h:468
int set_streaming_exact_bit
Definition: transport.h:449
int role_5_nwa
Definition: transport.h:386
int num_format_descr
Definition: transport.h:316
int(* read_format_capacities)(struct burn_drive *d, int top_wanted)
Definition: transport.h:535
int drive_serial_number_len
Definition: transport.h:264
void(* sync_cache)(struct burn_drive *)
Definition: transport.h:497
struct burn_disc * disc
Definition: transport.h:392
int start_lba
Definition: transport.h:341
int erasable
Definition: transport.h:205
int channel
Definition: transport.h:183
pthread_mutex_t access_lock
Definition: transport.h:202
pid_t thread_pid
Definition: transport.h:433
int(* read_multi_session_c1)(struct burn_drive *d, int *trackno, int *start)
Definition: transport.h:503
volatile int cancel
Definition: transport.h:422
void(* read_disc_info)(struct burn_drive *)
Definition: transport.h:480
void(* send_write_parameters)(struct burn_drive *, struct burn_session *, int tno, const struct burn_write_opts *)
Definition: transport.h:489
int current_profile
Definition: transport.h:208
int disc_app_code
Definition: transport.h:301
int(* start_unit)(struct burn_drive *)
Definition: transport.h:474
void(* eject)(struct burn_drive *)
Definition: transport.h:472
int(* drive_is_open)(struct burn_drive *)
Definition: transport.h:457
void(* unlock)(struct burn_drive *)
Definition: transport.h:471
int needs_sync_cache
Definition: transport.h:281
struct scsi_mode_data * mdata
Definition: transport.h:523
void(* read_toc)(struct burn_drive *)
Definition: transport.h:469
int(* format_unit)(struct burn_drive *d, off_t size, int flag)
Definition: transport.h:531
void(* close_track_session)(struct burn_drive *d, int session, int track)
Definition: transport.h:516
int set_streaming_err
Definition: transport.h:450
int current_is_supported_profile
Definition: transport.h:211
void(* load)(struct burn_drive *)
Definition: transport.h:473
enum burn_drive_status busy
Definition: transport.h:423
unsigned int wfb_timeout_sec
Definition: transport.h:414
int do_no_immed
Definition: transport.h:389
void(* erase)(struct burn_drive *, int)
Definition: transport.h:462
unsigned int wfb_max_percent
Definition: transport.h:416
void(* getcaps)(struct burn_drive *)
Definition: transport.h:463
int thread_pid_valid
Definition: transport.h:434
int stream_recording_start
Definition: transport.h:291
int format_descr_type
Definition: transport.h:309
void(* set_speed)(struct burn_drive *, int, int)
Definition: transport.h:486
off_t media_capacity_remaining
Definition: transport.h:370
int wait_for_buffer_free
Definition: transport.h:410
int drive_role
Definition: transport.h:178
char * media_serial_number
Definition: transport.h:268
struct burn_scsi_inquiry_data * idata
Definition: transport.h:522
int toc_temp
Definition: transport.h:391
pthread_t thread_tid
Definition: transport.h:436
int(* release)(struct burn_drive *)
Definition: transport.h:454
int end_lba
Definition: transport.h:342
unsigned char flags
Definition: transport.h:153
struct burn_feature_descr * next
Definition: transport.h:163
unsigned char * data
Definition: transport.h:161
unsigned char data_lenght
Definition: transport.h:158
unsigned short feature_code
Definition: transport.h:151
unsigned int tdp
Definition: transport.h:143
int current_profile
Definition: libburn.h:3689
int might_simulate
Definition: libburn.h:3697
off_t start_alignment
Definition: libburn.h:3655
off_t start_range_low
Definition: libburn.h:3659
enum burn_write_types selected_write_mode
Definition: libburn.h:3686
off_t start_range_high
Definition: libburn.h:3663
enum burn_write_types advised_write_mode
Definition: libburn.h:3682
int current_is_cd_profile
Definition: libburn.h:3692
int start_sector
Definition: libburn.h:684
int sessions
Definition: libburn.h:672
struct burn_track ** track
Definition: structure.h:130
struct burn_speed_descriptor * next
Definition: libburn.h:760
struct burn_speed_descriptor * prev
Definition: libburn.h:759
char profile_name[80]
Definition: libburn.h:738
int mode
Definition: structure.h:88
enum burn_block_types block_type
Definition: options.h:25
struct burn_drive * drive
Definition: options.h:17
off_t start_byte
Definition: options.h:50
struct burn_speed_descriptor * speed_descriptors
Definition: transport.h:124
int max_write_speed
Definition: transport.h:114
int max_read_speed
Definition: transport.h:112
int min_write_speed
Definition: transport.h:118
off_t burn_track_get_default_size(struct burn_track *t)
Definition: structure.c:629
int burn_track_is_open_ended(struct burn_track *t)
Definition: structure.c:614