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)  

write.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 - 2017 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 <unistd.h>
14 #include <signal.h>
15 
16 /* ts A61009 */
17 /* #include <a ssert.h> */
18 
19 
20 /* ts A61106 : Deliberate defect provocation macros
21  DO NOT DEFINE THESE IF YOU WANT SUCCESSFUL TAO !
22 #define Libburn_experimental_no_close_tracK 1
23 #define Libburn_experimental_no_close_sessioN 1
24 */
25 
26 /* ts A61114 : Highly experimental : try to achieve SAO on appendables
27  THIS DOES NOT WORK YET !
28 #define Libburn_sao_can_appenD 1
29 */
30 
31 #include <sys/types.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include <stdlib.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <sys/stat.h>
39 #include <sys/time.h>
40 
41 /* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
42 #ifndef O_BINARY
43 #define O_BINARY 0
44 #endif
45 
46 #include "error.h"
47 #include "sector.h"
48 #include "libburn.h"
49 #include "drive.h"
50 #include "transport.h"
51 #include "debug.h"
52 #include "init.h"
53 #include "toc.h"
54 #include "util.h"
55 #include "sg.h"
56 #include "write.h"
57 #include "options.h"
58 #include "structure.h"
59 #include "source.h"
60 #include "mmc.h"
61 #include "spc.h"
62 
63 #include "libdax_msgs.h"
64 extern struct libdax_msgs *libdax_messenger;
65 
66 
67 /* ts A91120 : <<< experimental */
68 #ifdef Libburn_mmap_write_buffeR
69 #include <sys/mman.h>
70 #endif
71 
72 
73 /* The maximum output size to be used with CD media. This is also curbed
74  by BURN_OS_TRANSPORT_BUFFER_SIZE. The smaller number gets into effect.
75 */
76 #define Libburn_cd_obS (32 * 1024)
77 
78 /* The size to be used with DVD media.
79 */
80 #define Libburn_dvd_obS (32 * 1024)
81 
82 /* The size to be used with BD-RE media in normal, not streamed mode.
83 */
84 #define Libburn_bd_re_obS (64 * 1024)
85 
86 /* The size to be used with BD-R media in normal, not streamed mode.
87 */
88 #define Libburn_bd_r_obS (64 * 1024)
89 
90 /* The size to be used with BD-RE and BD-R media in streamed mode.
91 */
92 #define Libburn_bd_streamed_obS (64 * 1024)
93 
94 /* The number of retries if write(2) returns a short, non-negative write count.
95 */
96 #define Libburn_stdio_write_retrieS 16
97 
98 
99 static int type_to_ctrl(int mode)
100 {
101  int ctrl = 0;
102 
103  int data = BURN_MODE2 | BURN_MODE1 | BURN_MODE0;
104 
105  if (mode & data) {
106  ctrl |= 4;
107  } else if (mode & BURN_AUDIO) {
108  if (mode & BURN_4CH)
109  ctrl |= 8;
110  if (mode & BURN_PREEMPHASIS)
111  ctrl |= 1;
112  } else
113  /* ts A61008 */
114  /* a ssert(0); */
115  return -1;
116 
117  if (mode & BURN_COPY)
118  ctrl |= 2;
119 
120  return ctrl;
121 }
122 
123 /* only the ctrl nibble is set here (not adr) */
124 /* ts A61009 : removed "static" , reacted on type_to_ctrl() == -1
125  preserved ignorance towards unknown modes (for now) */
126 void type_to_form(int mode, unsigned char *ctladr, int *form)
127 {
128  int ret;
129 
130  ret = type_to_ctrl(mode) << 4;
131  if (ret == -1) {
132  *ctladr = 0xff;
133  *form = -1;
134  return;
135  }
136  *ctladr = ret;
137 
138  if (mode & BURN_AUDIO)
139  *form = 0;
140  if (mode & BURN_MODE0) {
141 
142  /* ts A61009 */
143  /* a ssert(0); */
144  *form = -1;
145  return;
146  }
147 
148  if (mode & BURN_MODE1)
149  *form = 0x10;
150  if (mode & BURN_MODE2) {
151 
152  /* ts A61009 */
153  /* a ssert(0); */ /* XXX someone's gonna want this sometime */
154  *form = -1;
155  return;
156  }
157 
158  if (mode & BURN_MODE_RAW)
159  *form = 0;
160  if (mode & BURN_SUBCODE_P16) /* must be expanded to R96 */
161  *form |= 0x40;
162  if (mode & BURN_SUBCODE_P96)
163  *form |= 0xC0;
164  if (mode & BURN_SUBCODE_R96)
165  *form |= 0x40;
166 }
167 
168 
169 /* ts A71002 : outsourced from burn_write_flush() : no sync cache here */
171 {
172  struct burn_drive *d = o->drive;
173 
174  if (d->buffer->bytes && !d->cancel) {
175  int err;
176  err = d->write(d, d->nwa, d->buffer);
177  if (err == BE_CANCELLED)
178  return 0;
179  /* A61101 */
180  if(track != NULL) {
181  track->writecount += d->buffer->bytes;
182  track->written_sectors += d->buffer->sectors;
183  }
184  /* ts A61119 */
186 
187  d->nwa += d->buffer->sectors;
188  d->buffer->bytes = 0;
189  d->buffer->sectors = 0;
190  }
191  return 1;
192 }
193 
194 
195 int burn_write_flush(struct burn_write_opts *o, struct burn_track *track)
196 {
197  int ret;
198  struct burn_drive *d = o->drive;
199 
200  ret = burn_write_flush_buffer(o, track);
201  if (ret <= 0)
202  return ret;
203  d->sync_cache(d);
204  return 1;
205 }
206 
207 
208 /* ts A71002 : outsourced from burn_write_close_track() */
210  int tnum)
211 {
212  char msg[81];
213  struct burn_drive *d;
214  struct burn_track *t;
215  int todo, step, cancelled, seclen;
216 
217  d = o->drive;
218  t = s->track[tnum];
219 
220  /* ts A61103 : pad up track to minimum size of 600 sectors */
221  if (t->written_sectors < 300) {
222  todo = 300 - t->written_sectors;
223  sprintf(msg,"Padding up track to minimum size (+ %d sectors)",
224  todo);
226  0x0002011a,
228  step = BUFFER_SIZE / 4096; /* shall fit any sector size */
229  seclen = burn_sector_length(t->mode);
230  if (seclen <= 0)
231  seclen = 2048;
232  memset(d->buffer, 0, sizeof(struct buffer));
233  cancelled = d->cancel;
234  for (; todo > 0; todo -= step) {
235  if (step > todo)
236  step = todo;
237  d->buffer->bytes = step*seclen;
238  d->buffer->sectors = step;
239  d->cancel = 0;
240  d->write(d, d->nwa, d->buffer);
241  d->nwa += d->buffer->sectors;
242  t->writecount += d->buffer->bytes;
243  t->written_sectors += d->buffer->sectors;
245  }
246  d->cancel = cancelled;
247  }
248  return 1;
249 }
250 
251 
252 /* ts A61030 */
254  int tnum)
255 {
256  char msg[81];
257  struct burn_drive *d;
258 
259  /* ts A61106 */
260 #ifdef Libburn_experimental_no_close_tracK
261  return 1;
262 #endif
263 
264  d = o->drive;
265 
267 
268  sprintf(msg, "Closing track %2.2d", tnum+1);
271 
272  /* MMC-1 mentions track number 0xFF for "the incomplete track",
273  MMC-3 does not. I tried both. 0xFF was in effect when other
274  bugs finally gave up and made way for readable tracks. */
275  /* ts A70129
276  Probably the right value for appendables is d->last_track_no
277  */
278  d->close_track_session(o->drive, 0, 0xff);
279 
281 
282  return 1;
283 }
284 
285 
286 /* ts A61030 */
288 {
289 
290  /* ts A61106 */
291 #ifdef Libburn_experimental_no_close_sessioN
292  return 1;
293 #endif
294 
297  "Closing session", 0, 0);
298 
299  /* ts A61102 */
301 
302  o->drive->close_track_session(o->drive, 1, 0);
303 
304  /* ts A61102 */
306 
307  return 1;
308 }
309 
310 
311 /* ts A60819, B20101:
312  This is useful only when changes about CD SAO get tested.
313  # define Libburn_write_with_function_print_cuE yes
314 */
315 
316 #ifdef Libburn_write_with_function_print_cuE
317 
318 
319 static char cue_printify(char c)
320 {
321  if (c >= 32 && c < 127)
322  return c;
323  return '#';
324 }
325 
326 
327 static void print_cue(struct cue_sheet *sheet)
328 {
329  int i;
330  unsigned char *unit;
331 
332  printf("\n");
333  printf("ctladr|trno|indx|form|scms| msf | text\n");
334  printf("------+----+----+----+----+----------+--------\n");
335  for (i = 0; i < sheet->count; i++) {
336  unit = sheet->data + 8 * i;
337  if ((unit[0] & 0xf) == 2) {
338  printf(
339  " %1X %1X | | | | | | %c%c%c%c%c%c%c\n",
340  (unit[0] & 0xf0) >> 4, unit[0] & 0xf,
341  cue_printify(unit[1]), cue_printify(unit[2]),
342  cue_printify(unit[3]), cue_printify(unit[4]),
343  cue_printify(unit[5]), cue_printify(unit[6]),
344  unit[7] == 0 ? ' ' : cue_printify(unit[7]));
345  } else if ((unit[0] & 0xf) == 3) {
346  printf(
347  " %1X %1X | %2d | | | | | %c%c%c%c%c%c\n",
348  (unit[0] & 0xf0) >> 4, unit[0] & 0xf,
349  unit[1], cue_printify(unit[2]),
350  cue_printify(unit[3]), cue_printify(unit[4]),
351  cue_printify(unit[5]), cue_printify(unit[6]),
352  cue_printify(unit[7]));
353  } else if (unit[1] > 99) {
354  printf(" %1X %1X |0x%02X| %2d | %02X | %02X |",
355  (unit[0] & 0xf0) >> 4, unit[0] & 0xf,
356  unit[1], unit[2], unit[3], unit[4]);
357  printf(" %02d:%02d:%02d |\n",
358  unit[5], unit[6], unit[7]);
359  } else {
360  printf(" %1X %1X | %2d | %2d | %02X | %02X |",
361  (unit[0] & 0xf0) >> 4, unit[0] & 0xf,
362  unit[1], unit[2], unit[3], unit[4]);
363  printf(" %02d:%02d:%02d |\n",
364  unit[5], unit[6], unit[7]);
365  }
366  }
367  fflush(stdout);
368 }
369 
370 #endif /* Libburn_write_with_print_cuE */
371 
372 
373 /* ts B11226 */
374 static int new_cue(struct cue_sheet *sheet, int number, int flag)
375 {
376  unsigned char *ptr;
377 
378  ptr = realloc(sheet->data, (sheet->count + number) * 8);
379  if (ptr == NULL) {
380  libdax_msgs_submit(libdax_messenger, -1, 0x00020111,
382  "Could not allocate new auxiliary object (cue_sheet->data)",
383  0, 0);
384  return -1;
385  }
386  sheet->data = ptr;
387  sheet->count += number;
388  return 1;
389 }
390 
391 
392 /* ts B11226 : outsourced new_cue() */
393 /** @return 1 = success , <=0 failure */
394 static int add_cue(struct cue_sheet *sheet, unsigned char ctladr,
395  unsigned char tno, unsigned char indx,
396  unsigned char form, unsigned char scms, int lba)
397 {
398  unsigned char *unit;
399  int m, s, f, ret;
400 
401  burn_lba_to_msf(lba, &m, &s, &f);
402 
403  ret = new_cue(sheet, 1, 0);
404  if (ret <= 0)
405  return -1;
406  unit = sheet->data + (sheet->count - 1) * 8;
407  unit[0] = ctladr;
408  unit[1] = tno;
409  unit[2] = indx;
410  unit[3] = form;
411  unit[4] = scms;
412  unit[5] = m;
413  unit[6] = s;
414  unit[7] = f;
415  return 1;
416 }
417 
418 
419 /* ts B11226 */
420 static int add_catalog_cue(struct cue_sheet *sheet, unsigned char catalog[13])
421 {
422  unsigned char *unit;
423  int i, ret;
424 
425  ret = new_cue(sheet, 2, 0);
426  if (ret <= 0)
427  return -1;
428  unit = sheet->data + (sheet->count - 2) * 8;
429  unit[0] = unit[8] = 0x02;
430  for (i = 0; i < 13; i++)
431  unit[1 + (i >= 7) * 8 + (i % 7)] = catalog[i];
432  unit[15] = 0x00;
433  return 1;
434 }
435 
436 
437 /* ts B11226 */
438 static int add_isrc_cue(struct cue_sheet *sheet, unsigned char ctladr, int tno,
439  struct isrc *isrc)
440 {
441  unsigned char *unit;
442  int i, ret;
443  char text[8 + 21]; /* should suffice for 64 bit oversize */
444 
445  ret = new_cue(sheet, 2, 0);
446  if (ret <= 0)
447  return -1;
448  unit = sheet->data + (sheet->count - 2) * 8;
449  unit[0] = unit[8] = (ctladr & 0xf0) | 0x03;
450  unit[1] = unit[9] = tno;
451  unit[2] = isrc->country[0];
452  unit[3] = isrc->country[1];
453  unit[4] = isrc->owner[0];
454  unit[5] = isrc->owner[1];
455  unit[6] = isrc->owner[2];
456  sprintf(text, "%-2.2u%-5.5u", (unsigned int) isrc->year, isrc->serial);
457  sprintf(text, "%-2.2u", (unsigned int) isrc->year);
458  sprintf(text + 2, "%-5.5u", isrc->serial);
459  text[7] = 0;
460  unit[7] = text[0];
461  for (i = 1; i < 7; i++)
462  unit[9 + i] = text[i];
463  return 1;
464 }
465 
466 
467 /* ts A61114: added parameter nwa */
469  struct burn_session *session,
470  int nwa)
471 {
472  int i, m, s, f, form, runtime = -150, ret, track_length;
473  int leadin_form, leadin_start, pregap = 150, postgap;
474  unsigned char ctladr, scms;
475  struct burn_drive *d;
476  struct burn_toc_entry *e;
477  struct cue_sheet *sheet;
478  struct burn_track **tar = session->track;
479  int ntr = session->tracks;
480  int rem = 0;
481 
482 #define Libburn_track_multi_indeX yes
483 
484 #ifdef Libburn_track_multi_indeX
485  int j;
486 #else
487  int pform;
488 #endif
489 
490  if (ntr < 1) {
491  libdax_msgs_submit(libdax_messenger, -1, 0x0002019c,
493  "Session has no defined tracks", 0, 0);
494  return NULL;
495  }
496 
497  d = o->drive;
498 
499 #ifdef Libburn_sao_can_appenD
500  if (d->status == BURN_DISC_APPENDABLE)
501  runtime = nwa-150;
502 #endif
503 
504  sheet = calloc(1, sizeof(struct cue_sheet));
505 
506  /* ts A61009 : react on failures of calloc(), add_cue_sheet()
507  type_to_form() */
508  if (sheet == NULL) {
509  libdax_msgs_submit(libdax_messenger, -1, 0x00020111,
511  "Could not allocate new auxiliary object (cue_sheet)",
512  0, 0);
513  return NULL;
514  }
515 
516  sheet->data = NULL;
517  sheet->count = 0;
518  type_to_form(tar[0]->mode, &ctladr, &form);
519  if (form == -1) {
520  libdax_msgs_submit(libdax_messenger, -1, 0x00020116,
522  "Track mode has unusable value", 0, 0);
523  goto failed;
524  }
525  if (tar[0]->mode & BURN_AUDIO)
526  leadin_form = 0x01;
527  else
528  leadin_form = 0x14;
529  if (o->num_text_packs > 0) {
530  leadin_form |= 0x40;
531  } else {
532  /* Check for CD-TEXT in session. Not the final creation,
533  because the cue sheet content might be needed for CD-TEXT
534  pack type 0x88 "TOC".
535  */
536  if (o->text_packs == NULL) {
537  ret = burn_cdtext_from_session(session, NULL, NULL, 1);
538  if (ret < 0)
539  goto failed;
540  else if (ret > 0)
541  leadin_form |= 0x40;
542  }
543  }
544 
545  if (o->has_mediacatalog)
546  ret = add_catalog_cue(sheet, o->mediacatalog);
547  else if (session->mediacatalog[0])
548  ret = add_catalog_cue(sheet, session->mediacatalog);
549  else
550  ret = 1;
551  if (ret <= 0)
552  goto failed;
553 
554  /* ts B11225
555  MMC-5 6.33.3.15 Data Form of Sub-channel
556  seems to indicate that for leadin_form 0x41 one should announce
557  d->start_lba as start of the leadin (e.g. -12490) and that data
558  block type should 2 or 3 with mode page 05h. But my drives refuse
559  on that.
560  It works with LBA -150 and data block type 0. Shrug.
561  */
562  leadin_start = runtime;
563  ret = add_cue(sheet, (ctladr & 64) | 1, 0, 0, leadin_form, 0,
564  leadin_start);
565  if (ret <= 0)
566  goto failed;
567 
568  d->toc_entries = ntr + 3;
569 
570  /* ts A61009 */
571  /* a ssert(d->toc_entry == NULL); */
572  if (d->toc_entry != NULL) {
573 
574  /* ts A61109 : this happens with appendable CDs
575  >>> Open question: is the existing TOC needed ? */
576 
577  /* ts A61109 : for non-SAO, this sheet is thrown away later */
578  free((char *) d->toc_entry);
579 
580  /*
581  libdax_msgs_submit(libdax_messenger,
582  d->global_index, 0x00020117,
583  LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
584  "toc_entry of drive is already in use", 0, 0);
585  goto failed;
586  */
587  }
588  if (session->firsttrack + ntr - 1 > 99) {
589  libdax_msgs_submit(libdax_messenger, -1, 0x0002019b,
591  "CD track number exceeds 99", 0, 0);
592  goto failed;
593  }
594  session->lasttrack = session->firsttrack + ntr - 1;
595 
596  d->toc_entry = calloc(d->toc_entries, sizeof(struct burn_toc_entry));
597  e = d->toc_entry;
598  e[0].point = 0xA0;
599  if (tar[0]->mode & BURN_AUDIO)
600  e[0].control = TOC_CONTROL_AUDIO;
601  else
602  e[0].control = TOC_CONTROL_DATA;
603  e[0].pmin = session->firsttrack;
604  e[0].psec = o->format;
605  e[0].adr = 1;
606  e[1].point = 0xA1;
607  e[1].pmin = session->lasttrack;
608  e[1].adr = 1;
609  if (tar[ntr - 1]->mode & BURN_AUDIO)
610  e[1].control = TOC_CONTROL_AUDIO;
611  else
612  e[1].control = TOC_CONTROL_DATA;
613  e[2].point = 0xA2;
614  e[2].control = e[1].control;
615  e[2].adr = 1;
616 
617  tar[0]->pregap2 = 1;
618  if (tar[0]->pregap2_size < 150)
619  tar[0]->pregap2_size = 150;
620 
621 #ifndef Libburn_track_multi_indeX
622  pform = form;
623 #endif
624 
625  for (i = 0; i < ntr; i++) {
626 
627  /* ts A70125 :
628  Still not understanding the sense behind linking tracks,
629  i decided to at least enforce the MMC specs' minimum
630  track length.
631  */
632  track_length = burn_track_get_sectors_2(tar[i], 1);
633  if (track_length < 300 && !burn_track_is_open_ended(tar[i])) {
634  track_length = 300;
635  if (!tar[i]->pad)
636  tar[i]->pad = 1;
637  burn_track_set_sectors(tar[i], track_length);
638  }
639 
640  type_to_form(tar[i]->mode, &ctladr, &form);
641  if (tar[i]->mode & BURN_SCMS)
642  scms = 0x80;
643  else
644  scms = 0;
645 
646  if (tar[i]->isrc.has_isrc) {
647  ret = add_isrc_cue(sheet, ctladr,
648  i + session->firsttrack, &(tar[i]->isrc));
649  if (ret <= 0)
650  goto failed;
651  }
652  pregap = 0;
653  if (tar[i]->pregap2)
654  pregap = tar[i]->pregap2_size;
655  postgap = 0;
656  if (tar[i]->postgap) {
657  if (tar[i]->indices >= 99) {
659  0x0002019a, LIBDAX_MSGS_SEV_SORRY,
661  "Post-gap index number exceeds 99",
662  0, 0);
663  goto failed;
664  }
665  if (tar[i]->indices < 2)
666  tar[i]->indices = 2;
667  tar[i]->index[tar[i]->indices] = track_length;
668  postgap = tar[i]->postgap_size;
669  }
670 
671 #ifdef Libburn_track_multi_indeX
672 
673  for(j = 0; j < (tar[i]->indices + !!tar[i]->postgap) || j < 2;
674  j++) {
675  if(tar[i]->index[j] == 0x7fffffff) {
676  if (j > 1)
677  break;
678  if (j == 0 && pregap <= 0)
679  continue;
680  /* force existence of mandatory index */
681  tar[i]->index[j] = 0;
682  } else if (j == 0) {
683  tar[i]->index[j] = 0;
684  } else if (j == 1 && tar[i]->index[0] == 0x7fffffff) {
685  tar[i]->index[j] = 0;
686  }
687 
688  if (j == 1) {
689  tar[i]->entry = &e[3 + i];
690  e[3 + i].point = i + session->firsttrack;
691  burn_lba_to_msf(runtime, &m, &s, &f);
692  e[3 + i].pmin = m;
693  e[3 + i].psec = s;
694  e[3 + i].pframe = f;
695  e[3 + i].adr = 1;
696  e[3 + i].control = type_to_ctrl(tar[i]->mode);
697  }
698 
699  /* >>> ??? else if j == 0 && mode change to -data :
700  Extended pregap */;
701 
702  /* >>> check index with track size */;
703 
704  tar[i]->index[j] += runtime;
705  ret = add_cue(sheet, ctladr | 1,
706  i + session->firsttrack, j, form, scms,
707  tar[i]->index[j]);
708  if (ret <= 0)
709  goto failed;
710  runtime += pregap;
711  pregap = 0;
712  }
713 
714  runtime += track_length + postgap;
715 
716 #else /* Libburn_track_multi_indeX */
717 
718  if (i == 0) {
719  ret = add_cue(sheet, ctladr | 1, session->firsttrack,
720  0, form, 0, runtime);
721  if (ret <= 0)
722  goto failed;
723  runtime += 150;
724  } else if (pform != form) {
725 
726  /* ts A70121 : This seems to be the wrong test. Correct would
727  be to compare tar[]->mode or bit2 of ctladr.
728  */
729 
730  ret = add_cue(sheet, ctladr | 1,
731  i + session->firsttrack, 0, form, scms,
732  runtime);
733  if (ret <= 0)
734  goto failed;
735 
736  runtime += 150;
737 /* XXX fix pregap interval 1 for data tracks */
738 /* ts A60813 silence righteous compiler warning about C++ style comments
739  This is possibly not a comment but rather a trace of Derek Foreman
740  experiments. Thus not to be beautified - but to be preserved rectified.
741 / / if (!(form & BURN_AUDIO))
742 / / tar[i]->pregap1 = 1;
743 */
744 /* ts A70121 : it is unclear why (form & BURN_AUDIO) should prevent pregap1.
745  I believe, correct would be:
746  runtime += 75;
747  tar[i]->pregap1 = 1;
748 
749  The test for pform != form is wrong anyway.
750 
751  Next one has to care for Post-gap: table 555 in mmc5r03c.pdf does not
752  show any although 6.33.3.19 would prescribe some.
753  ts B20111: Table 1 of MMC-1 shows two post-gaps. The first matches the
754  precriptions with SEND CUE SHEET. The second one is riddling.
755  Both are part of a track and occupy the range of the last index
756  of the track. Length is 2 seconds for each.
757 
758  Nobody seems to have ever tested this situation, up to now.
759  It is banned for now in burn_disc_write().
760  Warning have been placed in libburn.h .
761 */
762 
763  tar[i]->pregap2 = 1;
764  }
765 /* XXX HERE IS WHERE WE DO INDICES IN THE CUE SHEET */
766 /* XXX and we should make sure the gaps conform to ecma-130... */
767  tar[i]->entry = &e[3 + i];
768  e[3 + i].point = i + session->firsttrack;
769  burn_lba_to_msf(runtime, &m, &s, &f);
770  e[3 + i].pmin = m;
771  e[3 + i].psec = s;
772  e[3 + i].pframe = f;
773  e[3 + i].adr = 1;
774  e[3 + i].control = type_to_ctrl(tar[i]->mode);
775 
776  ret = add_cue(sheet, ctladr | 1, i + session->firsttrack,
777  1, form, scms, runtime);
778  if (ret <= 0)
779  goto failed;
780 
781  runtime += track_length;
782 
783 #endif /* ! Libburn_track_multi_indeX */
784 
785 
786 /* if we're padding, we'll clear any current shortage.
787  if we're not, we'll slip toc entries by a sector every time our
788  shortage is more than a sector
789 XXX this is untested :)
790 */
791  if (!tar[i]->pad) {
792  rem += burn_track_get_shortage(tar[i]);
793 
794  /* ts A61101 : I doubt that linking would yield a
795  desirable effect. With TAO it is
796  counterproductive in any way.
797  */
798  if (o->write_type == BURN_WRITE_TAO)
799  tar[i]->source->next = NULL;
800  else
801 
802  if (i +1 != ntr)
803  tar[i]->source->next = tar[i+1]->source;
804  } else if (rem) {
805  rem = 0;
806  runtime++;
807  }
808  if (rem > burn_sector_length(tar[i]->mode)) {
809  rem -= burn_sector_length(tar[i]->mode);
810  runtime--;
811  }
812 
813 #ifndef Libburn_track_multi_indeX
814  pform = form;
815 #endif
816 
817  }
818  burn_lba_to_msf(runtime, &m, &s, &f);
819  e[2].pmin = m;
820  e[2].psec = s;
821  e[2].pframe = f;
822 
823  ret = add_cue(sheet, ctladr | 1, 0xAA, 1, leadin_form & 0x3f,
824  0, runtime);
825  if (ret <= 0)
826  goto failed;
827  return sheet;
828 
829 failed:;
830  if (sheet != NULL)
831  free((char *) sheet);
832  return NULL;
833 }
834 
835 int burn_sector_length(int tracktype)
836 {
837  if (tracktype & BURN_AUDIO)
838  return 2352;
839  if (tracktype & BURN_MODE_RAW)
840  return 2352;
841  if (tracktype & BURN_MODE1)
842  return 2048;
843  /* ts A61009 */
844  /* a ssert(0); */
845  return -1;
846 }
847 
848 int burn_subcode_length(int tracktype)
849 {
850  if (tracktype & BURN_SUBCODE_P16)
851  return 16;
852  if ((tracktype & BURN_SUBCODE_P96) || (tracktype & BURN_SUBCODE_R96))
853  return 96;
854  return 0;
855 }
856 
858  struct burn_session *s, int first)
859 {
860  struct burn_drive *d = o->drive;
861  int count;
862 
864 
865  if (first)
866  count = 0 - d->alba - 150;
867  else
868  count = 4500;
869 
870  d->progress.start_sector = d->alba;
871  d->progress.sectors = count;
872  d->progress.sector = 0;
873 
874  while (count != 0) {
875  if (!sector_toc(o, s->track[0]->mode))
876  return 0;
877  count--;
878  d->progress.sector++;
879  }
881  return 1;
882 }
883 
885  int first, unsigned char control, int mode)
886 {
887  struct burn_drive *d = o->drive;
888  int count;
889 
891 
892  d->rlba = -150;
893  if (first)
894  count = 6750;
895  else
896  count = 2250;
897  d->progress.start_sector = d->alba;
898  d->progress.sectors = count;
899  d->progress.sector = 0;
900 
901  while (count != 0) {
902  if (!sector_lout(o, control, mode))
903  return 0;
904  count--;
905  d->progress.sector++;
906  }
908  return 1;
909 }
910 
911 
913  struct burn_session *s,
914  int flag)
915 {
916  int ret, num_packs = 0;
917  unsigned char *text_packs = NULL;
918 
919  ret = burn_cdtext_from_session(s, &text_packs, &num_packs, 0);
920  if (ret > 0) {
921  if (o->text_packs != NULL)
922  free(o->text_packs);
923  o->text_packs = text_packs;
924  o->num_text_packs = num_packs;
925  }
926  return(ret);
927 }
928 
929 
931  struct burn_session *s, int flag)
932 {
933  int ret, i, j, si, lba, sub_cursor = 0, err, write_lba, sectors = 0;
934  int self_made_text_packs = 0;
935  unsigned char *subdata = NULL;
936  struct burn_drive *d = o->drive;
937  struct buffer *buf = NULL;
938  enum burn_drive_status was_busy = o->drive->busy;
939 #ifdef Libburn_debug_cd_texT
940  unsigned char *packs;
941 #endif
942 
943  if (o->num_text_packs <= 0) {
944  if (o->text_packs != NULL)
945  {ret = 1; goto ex;}
946  /* Try to create CD-TEXT from .cdtext_* of session and track */
947  ret = burn_create_text_packs(o, s, 0);
948  self_made_text_packs = 1;
949  if (ret <= 0)
950  goto ex;
951  if (o->num_text_packs <= 0)
952  {ret = 1; goto ex;}
953  }
954 
955  if (!o->no_text_pack_crc_check) {
957  o->num_text_packs, 0);
958  if (ret != 0) {
959  libdax_msgs_submit(libdax_messenger, -1, 0x0002018f,
961  "Program error: CD-TEXT pack CRC mismatch",
962  0, 0);
963  { ret = 0; goto ex; }
964  }
965  }
966 
968 
969 #ifdef Libburn_debug_cd_texT
970  packs = o->text_packs;
971  fprintf(stderr,
972  "libburn_DEBUG: 8 bit CD-TEXT packs to be transmitted:\n");
973  for (i = 0; i < 18 * o->num_text_packs; i += 18) {
974  fprintf(stderr, "%4d :", i / 18);
975  for (j = 0; j < 18; j++) {
976  if (j >= 4 && j <= 15 && packs[i + j] >= 32 &&
977  packs[i + j] <= 126 && packs[i] != 0x88 &&
978  packs[i] != 0x89 && packs[i] != 0x8f)
979  fprintf(stderr, " %c", packs[i + j]);
980  else
981  fprintf(stderr, " %2.2X", packs[i + j]);
982  }
983  fprintf(stderr, "\n");
984  }
985 #endif /* Libburn_debug_cd_texT */
986 
987  /* Chop from 8 bit text pack to 6 bit subchannel */
988  BURN_ALLOC_MEM(subdata, unsigned char, o->num_text_packs * 24);
989  for (i = 0; i < 18 * o->num_text_packs; i += 3) {
990  si = i / 3 * 4;
991  subdata[si + 0] = (o->text_packs[i + 0] >> 2) & 0x3f;
992  subdata[si + 1] = (o->text_packs[i + 0] << 4) & 0x30;
993  subdata[si + 1] |= (o->text_packs[i + 1] >> 4) & 0x0f;
994  subdata[si + 2] = (o->text_packs[i + 1] << 2) & 0x3c;
995  subdata[si + 2] |= (o->text_packs[i + 2] >> 6) & 0x03;
996  subdata[si + 3] = (o->text_packs[i + 2] >> 0) & 0x3f;
997  }
998 
999  /* Start at Lead-in address of ATIP and write blocks up to -150 */
1000  BURN_ALLOC_MEM(buf, struct buffer, 1);
1001  write_lba = d->start_lba;
1002  for (lba = d->start_lba; lba < -150; lba++) {
1003  /* Collect subdata in buf */
1004  for (j = 0; j < 4; j++) {
1005  memcpy(buf->data + buf->bytes,
1006  subdata + sub_cursor * 24, 24);
1007  sub_cursor = (sub_cursor + 1) % o->num_text_packs;
1008  buf->bytes += 24;
1009  }
1010  buf->sectors++;
1011  sectors++;
1012 
1013  /* When full or last sector : perform WRITE */
1014  if (buf->bytes + 96 >= 32768 || lba == -151) {
1015 
1016 #ifdef Libburn_debug_cd_texT
1017  fprintf(stderr,
1018  "libburn_DEBUG: 6 bit data to be transmitted:\n");
1019  for (i = 0; i < buf->bytes; i += 24) {
1020  fprintf(stderr, "%4d :", i / 24);
1021  for (j = 0; j < 24; j++)
1022  fprintf(stderr, " %2.2X",
1023  buf->data[i + j]);
1024  fprintf(stderr, "\n");
1025  }
1026 #endif /* Libburn_debug_cd_texT */
1027 
1028  err = d->write(d, write_lba, buf);
1029  if (err == BE_CANCELLED)
1030  { ret = 0; goto ex; }
1031  write_lba += sectors;
1032  sectors = buf->sectors = buf->bytes = 0;
1033  }
1034  }
1035  ret = 1;
1036 ex:;
1037  if (self_made_text_packs) {
1038  if (o->text_packs != NULL)
1039  free(o->text_packs);
1040  o->text_packs = NULL;
1041  o->num_text_packs = 0;
1042  }
1043  BURN_FREE_MEM(subdata);
1044  BURN_FREE_MEM(buf);
1045  d->busy = was_busy;
1046  return ret;
1047 }
1048 
1049 
1051 {
1052  struct burn_drive *d = o->drive;
1053  int i, ret;
1054 
1055  if (o->write_type == BURN_WRITE_SAO) {
1056  ret = burn_write_leadin_cdtext(o, s, 0);
1057  if (ret <= 0)
1058  goto ex;
1059  }
1060  d->rlba = 0;
1061  for (i = 0; i < s->tracks; i++) {
1062  if (!burn_write_track(o, s, i))
1063  { ret = 0; goto ex; }
1064  }
1065 
1066  /* ts A61103 */
1067  ret = 1;
1068 ex:;
1069  if (o->write_type == BURN_WRITE_TAO)
1071  return ret;
1072 }
1073 
1074 
1075 /* ts A61218 : outsourced from burn_write_track() */
1077  struct burn_session *s, struct burn_track *t,
1078  int tnum, int sectors)
1079 {
1080  struct burn_drive *d = o->drive;
1081 
1082  /* Update progress */
1083 
1084  d->progress.start_sector = d->nwa;
1085 
1086  d->progress.sectors = sectors;
1087  d->progress.sector = 0;
1088 
1089  /* ts A60831: added tnum-line, extended print message on proposal
1090  by bonfire-app@wanadoo.fr in http://libburn.pykix.org/ticket/58 */
1091  d->progress.track = tnum;
1092 
1093  /* ts B20113 */
1094  d->progress.indices = t->indices;
1095  d->progress.index = 0;
1096  if (d->progress.indices > 1)
1097  if (t->index[0] == 0x7fffffff)
1098  d->progress.index = 1;
1099 
1100  /* ts A61102 */
1101  d->busy = BURN_DRIVE_WRITING;
1102 
1103  return 1;
1104 }
1105 
1106 
1108  int tnum)
1109 {
1110  struct burn_track *t = s->track[tnum];
1111  struct burn_drive *d = o->drive;
1112  int i, tmp = 0, open_ended = 0, ret= 0, nwa, lba;
1113  int sectors;
1114  char msg[160];
1115 
1116  d->rlba = -150;
1117 
1118 /* XXX for tao, we don't want the pregaps but still want post? */
1119  if (o->write_type != BURN_WRITE_TAO) {
1120 
1121  /* ts A61102 */
1123 
1124  if (t->pregap1)
1125  d->rlba += 75;
1126  if (t->pregap2)
1127  d->rlba += t->pregap2_size;
1128 
1129  if (t->pregap1) {
1130 
1131  struct burn_track *pt;
1132  /* ts A70121 : Removed pseudo suicidal initializer
1133  = s->track[tnum - 1];
1134  */
1135 
1136  if (tnum == 0) {
1137 
1138  /* ts A70121 : This is not possible because
1139  track 1 cannot have a pregap at all.
1140  MMC-5 6.33.3.2 precribes a mandatory pause
1141  prior to any track 1. Pre-gap is prescribed
1142  for mode changes like audio-to-data.
1143  To set burn_track.pregap1 for track 1 is
1144  kindof a dirty hack.
1145  */
1146 
1147  printf("first track should not have a pregap1\n");
1148  pt = t;
1149  } else
1150  pt = s->track[tnum - 1]; /* ts A70121 */
1151  for (i = 0; i < 75; i++)
1152  if (!sector_pregap(o, t->entry->point,
1153  pt->entry->control, pt->mode))
1154  { ret = 0; goto ex; }
1155  }
1156  if (t->pregap2)
1157  for (i = 0; i < t->pregap2_size; i++)
1158  if (!sector_pregap(o, t->entry->point,
1159  t->entry->control, t->mode))
1160  { ret = 0; goto ex; }
1161 
1162  /* ts B20113 : Flush buffer to avoid influence pregap
1163  on track counter */
1164  ret = sector_write_buffer(d, NULL, 0);
1165  if (ret <= 0)
1166  goto ex;
1167 
1168  } else {
1169  o->control = t->entry->control;
1170  d->send_write_parameters(d, s, tnum, o);
1171 
1172  /* ts A61103 */
1173  ret = d->get_nwa(d, -1, &lba, &nwa);
1174 
1175  /* ts A70213: CD-TAO: eventually expand size of track to max */
1177 
1178  /* <<< */
1179  sprintf(msg,
1180  "TAO pre-track %2.2d : get_nwa(%d)=%d, d=%d , demand=%.f , cap=%.f\n",
1181  tnum+1, nwa, ret, d->nwa,
1182  (double) burn_track_get_sectors_2(t, 1) * 2048.0,
1183  (double) d->media_capacity_remaining);
1185  0x00000002,
1187  msg, 0, 0);
1188 
1189  /* ts A91003 */
1190  if (nwa < d->nwa) {
1192  0x00020173,
1194  "Drive tells NWA smaller than last written address",
1195  0, 0);
1196  d->sync_cache(d);
1197  return 0;
1198  }
1199  d->nwa = nwa;
1200 
1201  }
1202 
1203 /* user data */
1204 
1205  sectors = burn_track_get_sectors_2(t, 1);
1207 
1208  burn_disc_init_track_status(o, s, t, tnum, sectors);
1209 
1210  /* ts A61030 : this cannot happen. tnum is always < s->tracks */
1211  if (tnum == s->tracks)
1212  tmp = sectors > 150 ? 150 : sectors;
1213 
1214  for (i = 0; open_ended || i < sectors - tmp; i++) {
1215 
1216  /* ts A61023 : http://libburn.pykix.org/ticket/14
1217  From time to time inquire drive buffer */
1218  if ((i%64)==0)
1219  d->read_buffer_capacity(d);
1220 
1221  if (!sector_data(o, t, 0))
1222  { ret = 0; goto ex; }
1223 
1224  /* ts A61031 */
1225  if (open_ended) {
1226  d->progress.sectors = sectors = i;
1227  if (burn_track_is_data_done(t))
1228  break;
1229  }
1230 
1231  /* update current progress */
1232  d->progress.sector++;
1233  }
1234  for (; i < sectors; i++) {
1235 
1236  /* ts A61030: program execution never gets to this point */
1237  fprintf(stderr,"LIBBURN_DEBUG: TNUM=%d TRACKS=%d TMP=%d\n",
1238  tnum, s->tracks, tmp);
1239 
1240  /* ts A61023 */
1241  if ((i%64)==0)
1242  d->read_buffer_capacity(d);
1243 
1244  if (!sector_data(o, t, 1))
1245  { ret = 0; goto ex; }
1246 
1247  /* update progress */
1248  d->progress.sector++;
1249  }
1250 
1251  /* ts B20113 : Flush buffer to get buffered bytes assigned to the
1252  track counter */
1253  ret = sector_write_buffer(d, t, 0);
1254  if (ret <= 0)
1255  goto ex;
1256 
1257  if (t->postgap && o->write_type != BURN_WRITE_TAO) {
1258  for (i = 0; i < t->postgap_size; i++)
1259  if (!sector_postgap(o, t->entry->point,
1260  t->entry->control, t->mode))
1261  { ret = 0; goto ex; }
1262  ret = sector_write_buffer(d, NULL, 0);
1263  if (ret <= 0)
1264  goto ex;
1265  }
1266 
1267  /* ts A61103 */
1268  ret = 1;
1269 ex:;
1270  if (d->cancel)
1272  if (o->write_type == BURN_WRITE_TAO) {
1273 
1274  /* ts A71002 */
1275  if (!burn_write_flush_buffer(o, t))
1276  ret = 0;
1277 
1278  /* Ensure that at least 600 kB get written */
1279  burn_write_track_minsize(o, s, tnum);
1280  d->sync_cache(d);
1281 
1282  /* ts A61030 */
1283  /* ts A91003 :
1284  At least in simulation mode this causes NWA=0 for the
1285  next track. cdrecord does not use CLOSE TRACK at all but
1286  ends the tracks by SYNCHRONIZE CACHE alone.
1287  */
1288  /* ts A91202 :
1289  Peng Shao reports that his LG GH22LS30 issues an SCSI error
1290  on CLOSE TRACK even in non-dummy mode. So i better give up
1291  this gesture which seems not be needed by any drive.
1292  if (!o->simulate)
1293  if (burn_write_close_track(o, s, tnum) <= 0)
1294  ret = 0;
1295  */
1296  }
1297  return ret;
1298 }
1299 
1300 /* ts A61009 */
1301 /* @param flag bit1 = do not libdax_msgs_submit() */
1303  int flag)
1304 {
1305  int i, t;
1306  char msg[80];
1307 
1308  for (i = 0; i < disc->sessions; i++)
1309  for (t = 0; t < disc->session[i]->tracks; t++)
1311  o, disc->session[i]->track[t]->mode) != 1)
1312  goto bad_track_mode_found;
1313  return 1;
1314 bad_track_mode_found:;
1315  sprintf(msg, "Unsuitable track mode 0x%x in track %d of session %d",
1316  disc->session[i]->track[t]->mode, i+1, t+1);
1317  if (!(flag & 2))
1318  libdax_msgs_submit(libdax_messenger, -1, 0x0002010a,
1320  msg, 0, 0);
1321  return 0;
1322 }
1323 
1324 
1325 /* ts A61218 : outsourced from burn_disc_write_sync() */
1327  struct burn_disc *disc)
1328 {
1329  struct burn_drive *d = o->drive;
1330  struct burn_track *t = NULL;
1331  int sx, tx, ret;
1332 
1333  d->cancel = 0;
1334 
1335 #ifdef Libburn_reset_progress_asynC
1336  /* <<< This is now done in async.c */
1337  /* init progress before showing the state */
1338  d->progress.session = 0;
1339  d->progress.sessions = disc->sessions;
1340  d->progress.track = 0;
1341  d->progress.tracks = disc->session[0]->tracks;
1342  /* TODO: handle indices */
1343  d->progress.index = 0;
1344  d->progress.indices = disc->session[0]->track[0]->indices;
1345  /* TODO: handle multissession discs */
1346  /* XXX: sectors are only set during write track */
1347  d->progress.start_sector = 0;
1348  d->progress.sectors = 0;
1349  d->progress.sector = 0;
1350  d->progress.track = 0;
1351 #endif /* Libburn_reset_progress_asynC */
1352 
1353  /* ts A61023 */
1354  d->progress.buffer_capacity = 0;
1355  d->progress.buffer_available = 0;
1356  d->progress.buffered_bytes = 0;
1357  d->progress.buffer_min_fill = 0xffffffff;
1358 
1359  /* ts A70711 */
1360  d->pessimistic_buffer_free = 0;
1361  d->pbf_altered = 0;
1362  d->pessimistic_writes = 0;
1363  d->waited_writes = 0;
1364  d->waited_tries = 0;
1365  d->waited_usec = 0;
1366 
1367  /* Set eventual media fill up for last track only */
1368  for (sx = 0; sx < disc->sessions; sx++)
1369  for (tx = 0 ; tx < disc->session[sx]->tracks; tx++) {
1370  t = disc->session[sx]->track[tx];
1371  burn_track_set_fillup(t, 0);
1372  }
1373  if (o->fill_up_media && t != NULL)
1374  burn_track_set_fillup(t, 1);
1375 
1376  d->was_feat21h_failure = 0;
1377  if(d->write_opts != NULL)
1379  ret = burn_write_opts_clone(o, &(d->write_opts), 0);
1380  if (ret <= 0)
1381  return ret;
1382  d->write_retry_count = 0;
1383 
1384  d->busy = BURN_DRIVE_WRITING;
1385 
1386  return 1;
1387 }
1388 
1389 
1390 static int precheck_write_is_audio(struct burn_disc *disc, int flag)
1391 {
1392  struct burn_session **sessions;
1393  int num_sessions, i, j;
1394 
1395  sessions = burn_disc_get_sessions(disc, &num_sessions);
1396  for (i = 0; i < num_sessions; i++)
1397  for (j = 0; j < sessions[i]->tracks; j++)
1398  if (!(sessions[i]->track[j]->mode & BURN_AUDIO))
1399  return 0;
1400  return 1;
1401 }
1402 
1403 
1404 static int precheck_disc_has_cdtext(struct burn_disc *disc, int flag)
1405 {
1406  struct burn_session **sessions;
1407  int num_sessions, i, ret;
1408 
1409  sessions = burn_disc_get_sessions(disc, &num_sessions);
1410  for (i = 0; i < num_sessions; i++) {
1411  ret = burn_cdtext_from_session(sessions[i], NULL, NULL, 1);
1412  if (ret > 0)
1413  return 1;
1414  }
1415  return 0;
1416 }
1417 
1418 
1419 /* ts A70219 : API */
1420 int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc,
1421  char reasons[BURN_REASONS_LEN], int silent)
1422 {
1423  enum burn_write_types wt;
1424  struct burn_drive *d = o->drive;
1425  char *msg = NULL, *reason_pt;
1426  int no_media = 0, ret, has_cdtext, is_bd_pow = 0;
1427 
1428  reason_pt= reasons;
1429  reasons[0] = 0;
1430 
1431  if (d->drive_role == 0 || d->drive_role == 4) {
1432  if (d->drive_role == 0)
1433  sprintf(reasons,
1434  "DRIVE: is a virtual placeholder (null-drive)");
1435  else
1436  sprintf(reasons, "DRIVE: read-only pseudo drive");
1437  no_media = 1;
1438  goto ex;
1439  }
1440 
1441  /* check write mode against write job */
1442  wt = burn_write_opts_auto_write_type(o, disc, reasons, 1);
1443  if (wt == BURN_WRITE_NONE) {
1444  if (strncmp(reasons, "MEDIA: ", 7)==0)
1445  no_media = 1;
1446  goto ex;
1447  }
1448 
1449  sprintf(reasons, "%s: ", d->current_profile_text);
1450  reason_pt= reasons + strlen(reasons);
1451  if (d->status == BURN_DISC_UNSUITABLE)
1452  goto unsuitable_profile;
1453  if (o->num_text_packs > 0) {
1454  has_cdtext = 1;
1455  } else {
1456  has_cdtext = precheck_disc_has_cdtext(disc, 0);
1457  }
1458  if (has_cdtext > 0) {
1459  if (d->current_profile == 0x09 || d->current_profile == 0x0a) {
1460  ret = precheck_write_is_audio(disc, 0);
1461  if (ret <= 0)
1462  strcat(reasons,
1463  "CD-TEXT supported only with pure audio CD media, ");
1464  } else {
1465  strcat(reasons,
1466  "CD-TEXT supported only with CD media, ");
1467  }
1468  }
1469  if (d->drive_role == 2 || d->drive_role == 5 ||
1470  d->current_profile == 0x1a || d->current_profile == 0x12 ||
1471  d->current_profile == 0x43) {
1472  /* DVD+RW , DVD-RAM , BD-RE, emulated drive on stdio file */
1473  if (o->start_byte >= 0 && (o->start_byte % 2048))
1474  strcat(reasons,
1475  "write start address not properly aligned to 2048, ");
1476  } else if (d->current_profile == 0x09 || d->current_profile == 0x0a) {
1477  /* CD-R , CD-RW */
1478  if (!burn_disc_write_is_ok(o, disc, (!!silent) << 1))
1479  strcat(reasons, "unsuitable track mode found, ");
1480  if (o->start_byte >= 0)
1481  strcat(reasons, "write start address not supported, ");
1482  if (o->num_text_packs > 0) {
1483  if (o->write_type != BURN_WRITE_SAO)
1484  strcat(reasons,
1485  "CD-TEXT supported only with write type SAO, ");
1486  if (d->start_lba == -2000000000)
1487  strcat(reasons,
1488  "No Lead-in start address known with CD-TEXT, ");
1489  }
1490  } else if (d->current_profile == 0x13) {
1491  /* DVD-RW Restricted Overwrite */
1492  if (o->start_byte >= 0 && (o->start_byte % 32768))
1493  strcat(reasons,
1494  "write start address not properly aligned to 32k, ");
1495  } else if (d->drive_role == 3 ||
1496  d->current_profile == 0x11 || d->current_profile == 0x14 ||
1497  d->current_profile == 0x15 ||
1498  d->current_profile == 0x1b || d->current_profile == 0x2b ||
1499  d->current_profile == 0x41) {
1500  /* DVD-R* Sequential , DVD+R[/DL] , BD-R,
1501  sequential stdio "drive" */
1502  if (o->start_byte >= 0)
1503  strcat(reasons, "write start address not supported, ");
1504 
1505  is_bd_pow = burn_drive_get_bd_r_pow(d);
1506  if (is_bd_pow && !silent)
1508  0x0002011e,
1510  "Unsuitable media detected: BD-R formatted to POW.",
1511  0, 0);
1512  if (is_bd_pow) {
1513  strcat(reasons,
1514  "unsuitable media formatting POW detected, ");
1515  return 0;
1516  }
1517 
1518  } else {
1519 unsuitable_profile:;
1520  msg = calloc(1, 160);
1521  if (msg != NULL && !silent) {
1522  sprintf(msg,
1523  "Unsuitable media detected. Profile %4.4Xh %s",
1526  0x0002011e,
1528  msg, 0, 0);
1529  }
1530  if (msg != NULL)
1531  free(msg);
1532  strcat(reasons, "no suitable media profile detected, ");
1533  return 0;
1534  }
1535 ex:;
1536  if (reason_pt[0]) {
1537  if (no_media) {
1538  if (!silent)
1540  d->global_index, 0x0002013a,
1542  "No suitable media detected", 0, 0);
1543  return -1;
1544  }
1545  if (!silent)
1547  d->global_index, 0x00020139,
1549  "Write job parameters are unsuitable", 0, 0);
1550  return 0;
1551  }
1552  return 1;
1553 }
1554 
1555 
1556 /* ts A70129 : learned much from dvd+rw-tools-7.0/growisofs_mmc.cpp */
1558  struct burn_session *s, int tnum)
1559 {
1560  struct burn_drive *d = o->drive;
1561  char *msg = NULL;
1562  int ret, lba, nwa;
1563  off_t size;
1564 
1565  BURN_ALLOC_MEM(msg, char, 160);
1566  d->send_write_parameters(d, NULL, -1, o);
1567  ret = d->get_nwa(d, -1, &lba, &nwa);
1568  sprintf(msg,
1569  "DVD pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %d",
1570  tnum+1, nwa, ret, d->nwa);
1573  if (nwa > d->nwa)
1574  d->nwa = nwa;
1575  /* ts A70214 : eventually adjust already expanded size of track */
1577 
1578 #ifdef Libburn_pioneer_dvr_216d_with_opC
1579  fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : num_opc_tables = %d\n", d->num_opc_tables);
1580  if (d->num_opc_tables <= 0 && !o->simulate) {
1581  fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : performing OPC\n");
1582  d->perform_opc(d);
1583  fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : done\n");
1584  }
1585 #endif
1586 
1587 #ifdef Libburn_pioneer_dvr_216d_get_evenT
1588  mmc_get_event(d);
1589 #endif
1590 
1591  if (o->write_type == BURN_WRITE_SAO) { /* DAO */
1592  size = ((off_t) burn_track_get_sectors_2(s->track[tnum], 1))
1593  * (off_t) 2048;
1594 
1595  /* Eventually round track size up to write chunk */
1596  if (o->obs_pad && (size % o->obs))
1597  size += (off_t) (o->obs - (size % o->obs));
1598 
1599  ret = d->reserve_track(d, size);
1600  if (ret <= 0) {
1601  sprintf(msg, "Cannot reserve track of %.f bytes",
1602  (double) size);
1604  0x00020138,
1606  msg, 0, 0);
1607  {ret = 0; goto ex;}
1608  }
1609  }
1610  ret = 1;
1611 ex:;
1612  BURN_FREE_MEM(msg);
1613  return ret;
1614 }
1615 
1616 
1617 /* ts A70226 */
1619  struct burn_session *s, int tnum)
1620 {
1621  struct burn_drive *d = o->drive;
1622  char *msg = NULL;
1623  int ret, lba, nwa;
1624  off_t size;
1625 
1626  BURN_ALLOC_MEM(msg, char, 160);
1627  ret = d->get_nwa(d, -1, &lba, &nwa);
1628  sprintf(msg,
1629  "DVD+R pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %d",
1630  tnum+1, nwa, ret, d->nwa);
1633  if (nwa > d->nwa)
1634  d->nwa = nwa;
1635  /* ts A70214 : eventually adjust already expanded size of track */
1637 
1638  if (o->write_type == BURN_WRITE_SAO &&
1639  ! burn_track_is_open_ended(s->track[tnum])) {
1640  /* Reserve track */
1641  size = ((off_t) burn_track_get_sectors_2(s->track[tnum], 1))
1642  * (off_t) 2048;
1643  if (o->obs_pad) {
1644  /* Round track size up to write chunk size */
1645  /* o->obs should be 32k or 64k already. But 32k
1646  alignment was once performed in d->reserve_track()*/
1647  if (o->obs % 32768)
1648  o->obs += 32768 - (o->obs % 32768);
1649  if (size % o->obs)
1650  size += (off_t) (o->obs - (size % o->obs));
1651  }
1652 
1653  /* <<< Only for now until the first DVD+R succeeded */
1654  if (!o->obs_pad) {
1655  sprintf(msg, "Program error: encountered DVD+R without chunk padding");
1657  0x00000004,
1659  msg, 0, 0);
1660  {ret = 0; goto ex;}
1661  }
1662 
1663  ret = d->reserve_track(d, size);
1664  if (ret <= 0) {
1665  sprintf(msg, "Cannot reserve track of %.f bytes",
1666  (double) size);
1668  0x00020138,
1670  msg, 0, 0);
1671  {ret = 0; goto ex;}
1672  }
1673  }
1674  ret = 1;
1675 ex:;
1676  BURN_FREE_MEM(msg);
1677  return ret;
1678 }
1679 
1680 
1681 /* ts A70129 */
1683 {
1684  struct burn_drive *d = o->drive;
1685  char msg[80];
1686 
1687  /* only with Incremental writing */
1688  if (o->write_type != BURN_WRITE_TAO)
1689  return 2;
1690 
1691  sprintf(msg, "Closing track %2.2d (absolute track number %d)",
1692  tnum + 1, d->last_track_no);
1695 
1697  /* Ignoring tnum here and hoping that d->last_track_no is correct */
1698  d->close_track_session(d, 0, d->last_track_no); /* CLOSE TRACK, 001b */
1699  d->busy = BURN_DRIVE_WRITING;
1700  d->last_track_no++;
1701  return 1;
1702 }
1703 
1704 
1705 /* ts A70229 */
1707 {
1708  struct burn_drive *d = o->drive;
1709  char msg[40 + 80]; /* filltext + profile */
1710 
1711  sprintf(msg, "Finalizing %s ...",
1714  0x00000002,
1716  msg, 0, 0);
1717 
1718  if(d->current_profile == 0x41) { /* BD-R */
1719  /* CLOSE SESSION, 110b, Finalize Disc */
1720  d->close_track_session(d, 3, 0); /* (3<<1)|0 = 6 */
1721  } else {
1722  /* CLOSE SESSION, 101b, Finalize with minimal radius */
1723  d->close_track_session(d, 2, 1); /* (2<<1)|1 = 5 */
1724  }
1725 
1726  sprintf(msg, "... finalizing %s done ",
1729  0x00000002,
1731  msg, 0, 0);
1732 
1733  return 1;
1734 }
1735 
1736 
1737 /* ts A70226 */
1739  int tnum, int is_last_track)
1740 {
1741  struct burn_drive *d = o->drive;
1742  char msg[80];
1743 
1744  sprintf(msg,
1745  "Closing track %2.2d (absolute track and session number %d)",
1746  tnum + 1, d->last_track_no);
1749 
1751  d->close_track_session(d, 0, d->last_track_no); /* CLOSE TRACK, 001b */
1752 
1753  /* Each session becomes a single logical track. So to distinguish them,
1754  it is mandatory to close the session together with each track. */
1755 
1756  if (is_last_track && !o->multi)
1758  else
1759  d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */
1760  d->busy = BURN_DRIVE_WRITING;
1761  d->last_track_no++;
1762  return 1;
1763 }
1764 
1765 
1766 /* <<<
1767 #define Libburn_simplified_dvd_chunk_transactioN 1
1768 */
1769 
1770 #ifdef Libburn_simplified_dvd_chunk_transactioN
1771 
1772 /* ts A91114 : EXPERIMENTAL, NOT COMPLETELY IMPLEMENTED
1773 
1774  Simplified data transmission for DVD. libburn via GNU/Linux USB is 30 %
1775  slower than growisofs or cdrecord when transmitting 32 KB chunks.
1776  With 64 KB chunks it is 20% faster than the competitors.
1777  No heavy CPU load is visible but there might be subtle race conditions in
1778  the USB driver which work better with shorter time gaps between WRITE
1779  commands.
1780 
1781  Insight: It is actually about the interference of track source reading
1782  with SCSI writing via USB. growisofs reads with O_DIRECT into a
1783  mmap()ed buffer. When doing the same, libburn with 32 KB chunks
1784  reaches similar write speed.
1785  On the other hand, 64 KB chunks are 20% faster than that and
1786  are not improved by reading O_DIRECT.
1787 
1788  O_DIRECT is a property of the input fd of struct burn_source.
1789  It can only be done with properly aligned memory and with aligned
1790  read size. Alignment size is file system system specific.
1791  System call
1792  mmap(NULL, (size_t) buffer_size, PROT_READ | PROT_WRITE,
1793  MAP_SHARED | MAP_ANONYMOUS, -1, (off_t) 0);
1794  is supposed to allocate a properly aligned buffer.
1795  64 KB is supposed to be a safe size.
1796  Actually mmap() seems to be the main cause for a positive effect
1797  of O_DIRECT.
1798 
1799  This simplified transmission function did not bring visible benefit.
1800  So for now it is not worth to teach it all applicable details of old
1801  CD sector oriented transmission.
1802 
1803  @return 1= ok, go on , 2= no input with track->open_ended = nothing written
1804  <= 0 = error
1805 */
1806 static int transact_dvd_chunk(struct burn_write_opts *opts,
1807  struct burn_track *track)
1808 {
1809  int curr = 0, valid, err;
1810  struct burn_drive *d = opts->drive;
1811  struct buffer *out = d->buffer;
1812  unsigned char *data = out->data;
1813 
1814 #ifdef Libburn_log_in_and_out_streaM
1815  /* ts A61031 */
1816  static int tee_fd= -1;
1817  if(tee_fd==-1)
1818  tee_fd= open("/tmp/libburn_sg_readin",
1819  O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
1820  S_IRUSR | S_IWUSR);
1821 #endif /* Libburn_log_in_and_out_streaM */
1822 
1823 
1824  /* Read a chunk full of data */
1825 
1826  /* ??? Do we have offset padding ? >>> First produce offset padding */;
1827 
1828  /* <<<< */
1829  if (0 && !track->eos) {
1830  for (curr = 0; curr < opts->obs; curr += 2048) {
1831  if (track->source->read != NULL)
1832  valid = track->source->read(track->source,
1833  data + curr, 2048);
1834  else
1835  valid = track->source->read_xt(track->source,
1836  data + curr, 2048);
1837  if (valid <= 0) {
1838  track->eos = 1;
1839  break;
1840  }
1841  track->sourcecount += valid;
1842 
1843 #ifdef Libburn_log_in_and_out_streaM
1844  if(tee_fd!=-1 && valid>0) {
1845  write(tee_fd, data + curr, valid);
1846  }
1847 #endif /* Libburn_log_in_and_out_streaM */
1848 
1849  }
1850  } else if (!track->eos){
1851  valid = track->source->read(track->source, data, opts->obs);
1852  if (valid <= 0) {
1853  track->eos = 1;
1854  } else {
1855  track->sourcecount += valid;
1856  curr = valid;
1857 
1858 #ifdef Libburn_log_in_and_out_streaM
1859  if(tee_fd!=-1 && valid>0) {
1860  write(tee_fd, data, valid);
1861  }
1862 #endif /* Libburn_log_in_and_out_streaM */
1863  }
1864  }
1865  if (curr == 0 && track->open_ended) {
1866 
1867  /* >>> allow tail padding */;
1868 
1869  return 2;
1870  }
1871  if (curr < opts->obs)
1872  memset(data + curr , 0, opts->obs - curr);
1873 
1874  /* Write chunk */
1875  out->bytes = opts->obs;
1876  out->sectors = out->bytes / 2048;
1877  err = d->write(d, d->nwa, out);
1878  if (err == BE_CANCELLED)
1879  return 0;
1880  track->writecount += out->bytes;
1881  track->written_sectors += out->sectors;
1882  d->progress.buffered_bytes += out->bytes;
1883  d->nwa += out->sectors;
1884  out->bytes = 0;
1885  out->sectors = 0;
1886 
1887  return 1;
1888 }
1889 
1890 #endif /* Libburn_simplified_dvd_chunk_transactioN */
1891 
1892 
1893 /* ts A61218 - A81208 */
1895  struct burn_session *s, int tnum, int is_last_track)
1896 {
1897  struct burn_track *t = s->track[tnum];
1898  struct burn_drive *d = o->drive;
1899  struct buffer *out = d->buffer;
1900  int sectors;
1901  int i, open_ended = 0, ret= 0, is_flushed = 0, track_open = 0;
1902  int first_buf_cap = 0, further_cap = 0, buf_cap_step = 1024;
1903 
1904  /* ts A70213 : eventually expand size of track to max */
1906 
1907  /* ts C00806 : Consider the track state changed by try to open */
1908  d->medium_state_changed = 1;
1909 
1910  if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
1911  d->current_profile == 0x15) {
1912  /* DVD-R, DVD-RW Sequential, DVD-R/DL Sequential */
1913  ret = burn_disc_open_track_dvd_minus_r(o, s, tnum);
1914  if (ret <= 0)
1915  goto ex;
1916  /* Pioneer DVR-216D rev 1.09 hates multiple buffer inquiries
1917  before the drive buffer is full.
1918  */
1919  first_buf_cap = 0;
1920  further_cap = -1;
1921  } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
1922  /* DVD+R , DVD+R/DL */
1923  ret = burn_disc_open_track_dvd_plus_r(o, s, tnum);
1924  if (ret <= 0)
1925  goto ex;
1926  } else if (d->current_profile == 0x41) {
1927  /* BD-R SRM */
1928  ret = burn_disc_open_track_dvd_plus_r(o, s, tnum);
1929  if (ret <= 0)
1930  goto ex;
1931  }
1932  track_open = 1;
1933 
1935  open_ended = burn_track_is_open_ended(t);
1936 
1937  /* (offset padding is done within sector_data()) */
1938 
1939  burn_disc_init_track_status(o, s, t, tnum, sectors);
1940  for (i = 0; open_ended || i < sectors; i++) {
1941 
1942  /* From time to time inquire drive buffer */
1943  /* ts A91110: Eventually avoid to do this more than once
1944  before the drive buffer is full. See above DVD-
1945  */
1946  if (i == first_buf_cap ||
1947  ((i % buf_cap_step) == 0 &&
1948  (i >= further_cap || further_cap < 0))) {
1949  d->read_buffer_capacity(d);
1950  if (further_cap < 0)
1951  further_cap =
1952  d->progress.buffer_capacity / 2048 + 128;
1953  }
1954 
1955 #ifdef Libburn_simplified_dvd_chunk_transactioN
1956 
1957  ret = transact_dvd_chunk(o, t);
1958  if (ret <= 0)
1959  {ret = 0; goto ex;}
1960  i += o->obs / 2048 - 1;
1961  d->progress.sector += o->obs / 2048 - 1;
1962 #else
1963  /* transact a (CD sized) sector */
1964  if (!sector_data(o, t, 0))
1965  { ret = 0; goto ex; }
1966 #endif
1967 
1968  if (open_ended) {
1969  d->progress.sectors = sectors = i;
1970  if (burn_track_is_data_done(t))
1971  break;
1972  }
1973 
1974  /* update current progress */
1975  d->progress.sector++;
1976  }
1977 
1978  /* (tail padding is done in sector_data()) */
1979 
1980  /* Pad up buffer to next full o->obs (usually 32 kB) */
1981  if (o->obs_pad && out->bytes > 0 && out->bytes < o->obs) {
1982  memset(out->data + out->bytes, 0, o->obs - out->bytes);
1983  out->sectors += (o->obs - out->bytes) / 2048;
1984  out->bytes = o->obs;
1985  }
1986  ret = burn_write_flush(o, t);
1987  if (ret <= 0)
1988  goto ex;
1989  is_flushed = 1;
1990 
1991  /* Eventually finalize track */
1992  if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
1993  d->current_profile == 0x15) {
1994  /* DVD-R, DVD-RW Sequential, DVD-R/DL Sequential */
1995  ret = burn_disc_close_track_dvd_minus_r(o, tnum);
1996  if (ret <= 0)
1997  goto ex;
1998  } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
1999  /* DVD+R , DVD+R/DL */
2000  ret = burn_disc_close_track_dvd_plus_r(o, tnum,
2001  is_last_track);
2002  if (ret <= 0)
2003  goto ex;
2004  } else if (d->current_profile == 0x41) {
2005  /* BD-R SRM */
2006  ret = burn_disc_close_track_dvd_plus_r(o, tnum,
2007  is_last_track);
2008  if (ret <= 0)
2009  goto ex;
2010  }
2011  ret = 1;
2012 ex:;
2013  if (d->cancel)
2015  if (track_open && !is_flushed)
2016  d->sync_cache(d); /* burn_write_flush() was not called */
2017  return ret;
2018 }
2019 
2020 
2021 /* ts A61219 */
2023  struct burn_session *s)
2024 {
2025  struct burn_drive *d = o->drive;
2026 
2028  /* This seems to be a quick end : "if (!dvd_compat)" */
2029  /* >>> Stop de-icing (ongoing background format) quickly
2030  by mmc_close() (but with opcode[2]=0).
2031  Wait for unit to get ready.
2032  return 1;
2033  */
2034  /* Else: end eventual background format in a "DVD-RO" compatible way */
2035  d->close_track_session(d, 1, 0); /* same as CLOSE SESSION for CD */
2036  d->busy = BURN_DRIVE_WRITING;
2037  return 1;
2038 }
2039 
2040 
2041 /* ts A61228 */
2043  struct burn_session *s)
2044 {
2045  struct burn_drive *d = o->drive;
2046 
2048  if (d->current_profile == 0x13) {
2049  d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */
2050 
2051  /* ??? under what circumstances to use close functiom 011b
2052  "Finalize disc" ? */
2053 
2054  }
2055  d->busy = BURN_DRIVE_WRITING;
2056  return 1;
2057 }
2058 
2059 
2060 /* ts A70129 : for profile 0x11 DVD-R, 0x14 DVD-RW Seq, 0x15 DVD-R/DL Seq */
2062 {
2063  struct burn_drive *d = o->drive;
2064 
2065  /* only for Incremental writing */
2066  if (o->write_type != BURN_WRITE_TAO)
2067  return 2;
2068 
2069 #ifdef Libburn_dvd_r_dl_multi_no_close_sessioN
2070  if (d->current_profile == 0x15 && o->multi)
2071  return 2;
2072 #endif
2073 
2076  "Closing session", 0, 0);
2077 
2079  d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */
2080  d->busy = BURN_DRIVE_WRITING;
2081  return 1;
2082 }
2083 
2084 
2085 /* ts A61218 */
2087  struct burn_session *s, int is_last_session)
2088 {
2089  int i, ret, multi_mem;
2090  struct burn_drive *d = o->drive;
2091 
2092  /* ts A90108 */
2093  if (d->current_profile == 0x41 && d->status == BURN_DISC_APPENDABLE &&
2094  d->state_of_last_session == 1) {
2095  /* last session on BD-R is still open */;
2096 
2097  /* BR-R were not closed by libburn-0.6.0.pl00 if o->multi==0.
2098  This leads to an unreadable, but recoverable) media state.
2099  Technically they are appendable although the last session
2100  is not readable.
2101 
2102  By default the open session gets closed here before the new
2103  session is written. E.g. after writing a small dummy session
2104  number 2 one can read session 1 and write session 3 which
2105  points to data of session 1.
2106 
2107  For the case that no media with 3 sessions is desired it is
2108  possible to activate the following coarse single-session
2109  closing code:
2110  No new session will be written but calling programs will
2111  report success. Quite misleading.
2112  Activate only if really needed by
2113  # define Libburn_bug_A90108_close_disC yes
2114  */
2115 
2116 
2117 #ifdef Libburn_bug_A90108_close_disC
2118 
2119  /* Close open session and media.
2120  That was the goal of the failed run which led to the
2121  unreadable (but recoverable) media state.
2122 
2123  It is not easy to implement a general close function for
2124  all media types. Therefore this pseudo write code is under
2125  control of #ifdef.
2126  */
2128  0x00020171,
2130  "Closing BD-R with accidentally open session",
2131  0, 0);
2132  d->close_track_session(d, 3, 0); /* CLOSE SESSION, 110b */
2133  d->state_of_last_session = 3; /* mark as complete session */
2134  d->status = BURN_DISC_FULL;
2135  sleep(3); /* The caller might need time to arrange itself */
2136  return 1;
2137 
2138 #else /* Libburn_bug_A90108_close_disC */
2139 
2140  /* This is the default mode.
2141  */
2143  0x00020170,
2145  "Closing open session before writing new one",
2146  0, 0);
2147  d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */
2148  d->state_of_last_session = 3; /* mark as complete session */
2149 
2150 #endif /* ! Libburn_bug_A90108_close_disC */
2151 
2152  }
2153 
2154  for (i = 0; i < s->tracks; i++) {
2155  ret = burn_dvd_write_track(o, s, i,
2156  is_last_session && i == (s->tracks - 1));
2157  if (ret <= 0)
2158  break;
2159  }
2160  if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
2161  d->current_profile == 0x15) {
2162  /* DVD-R , DVD-RW Sequential, DVD-R/DL Sequential */
2163  /* If feature 21h failed on write 0: do not close session */
2164  if (d->was_feat21h_failure != 2) {
2165  multi_mem = o->multi;
2166  if (!is_last_session)
2167  o->multi = 1;
2169  o->multi = multi_mem;
2170  if (ret <= 0)
2171  return 0;
2172  }
2173  } else if (d->current_profile == 0x12 || d->current_profile == 0x43) {
2174  /* DVD-RAM , BD-RE */
2175  /* ??? any finalization needed ? */;
2176  } else if (d->current_profile == 0x13) {
2177  /* DVD-RW restricted overwrite */
2178  if (d->needs_close_session) {
2180  if (ret <= 0)
2181  return 0;
2182  }
2183  } else if (d->current_profile == 0x1a) {
2184  /* DVD+RW */
2185  if (d->needs_close_session) {
2187  if (ret <= 0)
2188  return 0;
2189  }
2190  } else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
2191  /* DVD+R , DVD+R/DL do each track as an own session */;
2192  } else if (d->current_profile == 0x41) {
2193  /* BD-R SRM do each track as an own session */;
2194  }
2195  return 1;
2196 }
2197 
2198 
2199 /* ts A61218 : learned much from dvd+rw-tools-7.0/growisofs_mmc.cpp */
2201  struct burn_disc *disc)
2202 {
2203  struct burn_drive *d = o->drive;
2204  int ret;
2205 
2206  if (d->bg_format_status==0 || d->bg_format_status==1) {
2208  /* start or re-start dvd_plus_rw formatting */
2209  ret = d->format_unit(d, (off_t) 0, 0);
2210  if (ret <= 0)
2211  return 0;
2212  d->busy = BURN_DRIVE_WRITING;
2213  d->needs_close_session = 1;
2214  }
2215 
2216  /* >>> perform OPC if needed */;
2217 
2218  /* >>> ? what else ? */;
2219 
2220  return 1;
2221 }
2222 
2223 
2224 /* ts A61228 : learned much from dvd+rw-tools-7.0/growisofs_mmc.cpp */
2226  struct burn_disc *disc)
2227 {
2228  struct burn_drive *d = o->drive;
2229  char msg[60];
2230  int ret;
2231 
2232  d->nwa = 0;
2233  if (o->start_byte >= 0) {
2234  d->nwa = o->start_byte / 32768; /* align to 32 kB */
2235 
2236  sprintf(msg, "Write start address is %d * 32768", d->nwa);
2238  0x00020127,
2240  msg, 0, 0);
2241 
2242  d->nwa *= 16; /* convert to 2048 block units */
2243  }
2244 
2245 
2246  /* ??? mmc5r03c.pdf 7.5.2 :
2247  "For DVD-RW media ... If a medium is in Restricted overwrite
2248  mode, this mode page shall not be used."
2249 
2250  But growisofs composes a page 5 and sends it.
2251  mmc5r03c.pdf 5.3.16 , table 127 specifies that mode page 5
2252  shall be supported with feature 0026h Restricted Overwrite.
2253  5.3.22 describes a feature 002Ch Rigid Restrictive Overwrite
2254  which seems to apply to DVD-RW and does not mention page 5.
2255 
2256  5.4.14 finally states that profile 0013h includes feature
2257  002Ch rather than 0026h.
2258 
2259  d->send_write_parameters(d, NULL, -1, o);
2260  */
2261 
2263 
2264  /* "quick grow" to at least byte equivalent of d->nwa */
2265  ret = d->format_unit(d, (off_t) d->nwa * (off_t) 2048,
2266  (d->nwa > 0) << 3);
2267  if (ret <= 0)
2268  return 0;
2269 
2270  d->busy = BURN_DRIVE_WRITING;
2271 
2272  /* >>> perform OPC if needed */;
2273 
2274  return 1;
2275 }
2276 
2277 
2278 /* ts A70129 : for DVD-R[W] Sequential Recoding */
2280  struct burn_disc *disc)
2281 {
2282  struct burn_drive *d = o->drive;
2283 
2284  /* most setup is in burn_disc_setup_track_dvd_minus_r() */;
2285 
2286  d->nwa = 0;
2287  return 1;
2288 }
2289 
2290 
2291 /* ts A70226 : for DVD+R , DVD+R/DL */
2293  struct burn_disc *disc)
2294 {
2295  struct burn_drive *d = o->drive;
2296 
2297  /* most setup is in burn_disc_setup_track_dvd_plus_r() */;
2298 
2299  d->nwa = 0;
2300  return 1;
2301 }
2302 
2303 
2304 /* ts A61218 - A70415 */
2306  struct burn_disc *disc)
2307 {
2308  int i, ret, o_end;
2309  off_t default_size = 0;
2310  struct burn_drive *d = o->drive;
2311  struct burn_track *t;
2312  char *msg = NULL;
2313 
2314  BURN_ALLOC_MEM(msg, char, 160);
2315  d->needs_close_session = 0;
2316 
2317  /* buffer flush trigger for sector.c:get_sector() */
2318  o->obs = Libburn_dvd_obS;
2319 
2320  if (d->current_profile == 0x1a || d->current_profile == 0x12 ||
2321  d->current_profile == 0x43) {
2322  /* DVD+RW , DVD-RAM , BD-RE */
2323  ret = 1;
2324  if (d->current_profile == 0x1a)
2325  ret = burn_disc_setup_dvd_plus_rw(o, disc);
2326  if (ret <= 0) {
2327  sprintf(msg,
2328  "Write preparation setup failed for DVD+RW");
2330  0x00020121,
2332  msg, 0, 0);
2333  goto early_failure;
2334  }
2335  d->nwa = 0;
2336  if (o->start_byte >= 0) {
2337  d->nwa = o->start_byte / 2048;
2338  sprintf(msg, "Write start address is %d * 2048",
2339  d->nwa);
2341  0x00020127,
2343  msg, 0, 0);
2344  }
2345  if (o->obs_pad < 2)
2346  o->obs_pad = 0; /* no filling-up of last 32k buffer */
2347  if (d->current_profile == 0x43) /* BD-RE */
2348  o->obs = Libburn_bd_re_obS;
2349  if (d->do_stream_recording) {
2350  if (o->obs_pad < 2)
2351  o->obs_pad = 1;
2352  if (d->current_profile == 0x43) /* BD-RE */
2354  }
2355 
2356  } else if (d->current_profile == 0x13) {
2357  /* DVD-RW Restricted Overwrite */
2358  ret = burn_disc_setup_dvd_minus_rw(o, disc);
2359  if (ret <= 0) {
2360  sprintf(msg,
2361  "Write preparation setup failed for DVD-RW");
2363  0x00020121,
2365  msg, 0, 0);
2366  goto early_failure;
2367  }
2368 
2369  /* _Rigid_ Restricted Overwrite demands this */
2370  o->obs_pad = 1; /* fill-up track's last 32k buffer */
2371 
2372  } else if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
2373  d->current_profile == 0x15) {
2374  /* DVD-R , DVD-RW Sequential , DVD-R/DL Sequential */
2375  t = disc->session[0]->track[0];
2376  o_end = ( burn_track_is_open_ended(t) && !o->fill_up_media );
2378  if (o->write_type == BURN_WRITE_SAO && o_end) {
2379  sprintf(msg, "Activated track default size %.f",
2380  (double) default_size);
2382  d->global_index, 0x0002012e,
2384  msg, 0, 0);
2386  }
2387  /* Whether to fill-up last 32k buffer of track. */
2388  if (o->obs_pad < 2)
2389  o->obs_pad = (o->write_type != BURN_WRITE_SAO);
2390  ret = burn_disc_setup_dvd_minus_r(o, disc);
2391  if (ret <= 0) {
2392  sprintf(msg,
2393  "Write preparation setup failed for DVD-R[W]");
2395  0x00020121,
2397  msg, 0, 0);
2398  goto early_failure;
2399  }
2400 
2401  } else if (d->current_profile == 0x1b || d->current_profile == 0x2b ||
2402  d->current_profile == 0x41) {
2403  /* DVD+R , DVD+R/DL , BD-R SRM */
2404 
2405  /* >>> ts A81208 : with BD-R set o->obs to 64 kB ? */
2406 
2407  t = disc->session[0]->track[0];
2408  o_end = ( burn_track_is_open_ended(t) && !o->fill_up_media );
2410  if (o->write_type == BURN_WRITE_SAO && o_end) {
2411  sprintf(msg, "Activated track default size %.f",
2412  (double) default_size);
2414  d->global_index, 0x0002012e,
2416  msg, 0, 0);
2418  }
2419  ret = burn_disc_setup_dvd_plus_r(o, disc);
2420  if (ret <= 0) {
2421  sprintf(msg, "Write preparation setup failed for %s",
2422  d->current_profile == 0x41 ? "BD-R" : "DVD+R");
2424  0x00020121,
2426  msg, 0, 0);
2427  goto early_failure;
2428  }
2429  /* ??? padding needed ??? cowardly doing it for now */
2430  if (o->obs_pad < 2)
2431  o->obs_pad = 1; /* fill-up track's last obs buffer */
2432  if (d->current_profile == 0x41) /* BD-R */
2433  o->obs = Libburn_bd_r_obS;
2434  if (d->do_stream_recording) {
2435  if (d->current_profile == 0x41) /* BD-R */
2437  }
2438  }
2439 
2440 #ifdef Libburn_dvd_obs_default_64K
2441  o->obs = 64 * 1024;
2442 #endif
2443 
2444  /* <<< test only : Does this increase effective speed with USB ?
2445  ts A90801 : 64kB: speed with 16x DVD-R is 12 rather than 8
2446  128kB: glibc complains about double free
2447  With BURN_OS_TRANSPORT_BUFFER_SIZE
2448  enlarged to 128 MB, the first WRITE fails
2449  with an i/o error.
2450  o->obs = 64 * 1024;
2451  */
2452 
2453  if (o->dvd_obs_override >= 32 * 1024)
2454  o->obs = o->dvd_obs_override;
2455 
2456  if (o->obs > BUFFER_SIZE) {
2457  sprintf(msg, "Chosen write chunk size %d exceeds system dependent buffer size", o->obs);
2459  0x00000002, LIBDAX_MSGS_SEV_DEBUG,
2460  LIBDAX_MSGS_PRIO_ZERO, msg, 0, 0);
2461  o->obs = 32 * 1024; /* This size is required to work */
2462  }
2463 
2464  if (d->do_stream_recording &&
2465  (d->current_profile == 0x43 || d->current_profile == 0x41) &&
2467  /* LG GGW-H20 writes junk with stream recording and obs=32k */
2468  sprintf(msg,
2469  "Stream recording disabled because of small output buffer");
2471  0x00020176, LIBDAX_MSGS_SEV_NOTE,
2472  LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
2473  d->do_stream_recording = 0;
2474  }
2475 
2476  sprintf(msg, "dvd/bd Profile= %2.2Xh , obs= %d , obs_pad= %d",
2477  d->current_profile, o->obs, o->obs_pad);
2480 
2481  for (i = 0; i < disc->sessions; i++) {
2482  /* update progress */
2483  d->progress.session = i;
2484  d->progress.tracks = disc->session[i]->tracks;
2485 
2486  ret = burn_dvd_write_session(o, disc->session[i],
2487  i == (disc->sessions - 1));
2488  if (ret <= 0)
2489  goto ex;
2490 
2491  /* XXX: currently signs an end of session */
2492  d->progress.sector = 0;
2493  d->progress.start_sector = 0;
2494  d->progress.sectors = 0;
2495  }
2496  ret = 1;
2497 ex:;
2498 
2499  /* >>> eventual emergency finalization measures */
2500 
2501  /* update media state records */
2504 
2505  if (d->current_profile == 0x41 && d->complete_sessions >= 300) {
2506  sprintf(msg, "Sequential BD-R media now contains %d sessions. It is likely to soon fail writing.", d->complete_sessions);
2508  0x0002017b, LIBDAX_MSGS_SEV_WARNING,
2509  LIBDAX_MSGS_PRIO_ZERO, msg, 0, 0);
2510  }
2511  BURN_FREE_MEM(msg);
2512  return ret;
2513 early_failure:;
2514  BURN_FREE_MEM(msg);
2515  return 0;
2516 }
2517 
2518 
2519 /* ts A70904 */
2520 int burn_stdio_open_write(struct burn_drive *d, off_t start_byte,
2521  int sector_size, int flag)
2522 {
2523 
2524 /* We normally need _LARGEFILE64_SOURCE defined by the build system.
2525  Nevertheless the system might use large address integers by default.
2526 */
2527 #ifndef O_LARGEFILE
2528 #define O_LARGEFILE 0
2529 #endif
2530 
2531  int fd = -1;
2532  int mode = O_RDWR | O_CREAT | O_LARGEFILE;
2533  char msg[60];
2534  off_t lseek_res;
2535 
2536  if(d->drive_role == 4) {
2538  0x00020181,
2540  "Pseudo-drive is a read-only file. Cannot write.",
2541  0, 0);
2542  return 0;
2543  }
2544  if (d->drive_role == 5 || d->drive_role == 3)
2545  mode = O_WRONLY | O_CREAT | O_LARGEFILE;
2546  if (d->devname[0] == 0) /* null drives should not come here */
2547  return -1;
2549  if (fd >= 0)
2550  fd = dup(fd); /* check validity and make closeable */
2551  else
2552  fd = open(d->devname, mode | O_BINARY,
2553  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
2554  if (fd == -1) {
2556  0x00020005,
2558  "Failed to open device (a pseudo-drive)", errno, 0);
2559  d->cancel = 1;
2560  return -1;
2561  }
2562  if (start_byte < 0)
2563  start_byte = 0;
2564  if (d->drive_role == 2 || d->drive_role == 5) {
2565  lseek_res = lseek(fd, start_byte, SEEK_SET);
2566  if (lseek_res == -1) {
2567  sprintf(msg, "Cannot address start byte %.f",
2568  (double) start_byte);
2570  0x00020147,
2572  msg, errno, 0);
2573  close(fd);
2574  d->cancel = 1;
2575  fd = -1;
2576  }
2577  }
2578  d->nwa = start_byte / sector_size;
2579  return fd;
2580 }
2581 
2582 
2583 /* ts A70904 */
2584 int burn_stdio_read_source(struct burn_source *source, char *buf, int bufsize,
2585  struct burn_write_opts *o, int flag)
2586 {
2587  int count= 0, todo;
2588 
2589  for(todo = bufsize; todo > 0; todo -= count) {
2590  if(source->read!=NULL)
2591  count = source->read(source,
2592  (unsigned char *) (buf + (bufsize - todo)), todo);
2593  else
2594  count = source->read_xt(source,
2595  (unsigned char *) (buf + (bufsize - todo)), todo);
2596  if (count <= 0)
2597  break;
2598  }
2599  return (bufsize - todo);
2600 }
2601 
2602 
2603 /* ts A70904 */
2604 int burn_stdio_write(int fd, char *buf, int count, struct burn_drive *d,
2605  int flag)
2606 {
2607  int ret = 0;
2608  char *msg = NULL;
2609  int todo, done, retries;
2610 
2611  if (d->cancel || count <= 0)
2612  return 0;
2613  if(d->do_simulate)
2614  return 1;
2615 
2616  todo = count;
2617  done = 0;
2618  for (retries = 0; todo > 0 && retries <= Libburn_stdio_write_retrieS;
2619  retries++) {
2620 /*
2621 fprintf(stderr, "libburn_DEBUG: write(%d, %lX, %d)\n",
2622  fd, (unsigned long) buf, count);
2623 */
2624  ret = write(fd, buf + done, todo);
2625  if (ret < 0)
2626  break;
2627  done += ret;
2628  todo -= ret;
2629  }
2630  if (done != count) {
2631  BURN_ALLOC_MEM(msg, char, 160);
2632 
2633  sprintf(msg, "Cannot write desired amount of %d bytes.", count);
2634  if (retries > 1)
2635  sprintf(msg + strlen(msg), " Did %d retries. Last",
2636  retries - 1);
2637  sprintf(msg + strlen(msg), " write(2) returned %d.", ret);
2639  0x00020148,
2641  msg, errno, 0);
2642  d->cancel = 1;
2643  ret = 0; goto ex;
2644  }
2645  ret = 1;
2646 ex:;
2647  BURN_FREE_MEM(msg);
2648  return ret;
2649 }
2650 
2651 
2652 /* ts A70910 : to be used as burn_drive.write(), emulating mmc_write() */
2653 int burn_stdio_mmc_write(struct burn_drive *d, int start, struct buffer *buf)
2654 {
2655  int ret;
2656  off_t start_byte;
2657 
2658  if (d->cancel)
2659  return BE_CANCELLED;
2660  if (d->stdio_fd < 0) {
2662  0x0002017d,
2664  "Invalid file descriptor with stdio pseudo-drive",
2665  0, 0);
2666  d->cancel = 1;
2667  return BE_CANCELLED;
2668  }
2669  if (start != d->nwa) {
2670  char msg[80];
2671 
2672  start_byte = ((off_t) start) *
2673  (off_t) (buf->bytes / buf->sectors);
2674  if (lseek(d->stdio_fd, start_byte, SEEK_SET)==-1) {
2675  sprintf(msg, "Cannot address start byte %.f",
2676  (double) start_byte);
2678  0x00020147,
2680  msg, errno, 0);
2681  d->cancel = 1;
2682  return BE_CANCELLED;
2683  }
2684  d->nwa = start;
2685  }
2686  ret = burn_stdio_write(d->stdio_fd,(char *)buf->data, buf->bytes, d,0);
2687  if (ret <= 0)
2688  return BE_CANCELLED;
2689  d->nwa += buf->sectors;
2690  return 0;
2691 }
2692 
2693 
2694 /* ts A70910 : to be used as burn_drive.write(),
2695  emulating mmc_write() with simulated writing. */
2696 int burn_stdio_mmc_dummy_write(struct burn_drive *d, int start,
2697  struct buffer *buf)
2698 {
2699  if (d->cancel)
2700  return BE_CANCELLED;
2701  d->nwa = start + buf->sectors;
2702  return 0;
2703 }
2704 
2705 
2706 /* ts A70911 */
2707 /* Flush stdio system buffer to physical device.
2708  @param flag bit0= do not report debug message (intermediate sync)
2709  bit1= do fsync(2) unconditionally
2710 */
2711 int burn_stdio_sync_cache(int fd, struct burn_drive *d, int flag)
2712 {
2713  int ret, do_fsync;
2714  char *msg = NULL;
2715 
2716  if (fd < 0) {
2718  0x0002017d,
2720  "Invalid file descriptor with stdio pseudo-drive",
2721  0, 0);
2722  d->cancel = 1;
2723  ret = 0; goto ex;
2724  }
2725  d->needs_sync_cache = 0;
2726  do_fsync = 0;
2727  if (flag & 2)
2728  do_fsync = 1;
2729  else if (d->write_opts != NULL)
2730  do_fsync = (d->write_opts->stdio_fsync_size >= 0);
2731  if (do_fsync) {
2732  if (!(flag & 1))
2733  libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
2735  "syncing cache (stdio fsync)", 0, 0);
2736  ret = fsync(fd);
2737  } else {
2738  ret = 0;
2739  }
2740  if (ret != 0 && errno == EIO) {
2741  BURN_ALLOC_MEM(msg, char, 160);
2742 
2743  sprintf(msg,
2744  "Cannot write desired amount of data. fsync(2) returned %d.",
2745  ret);
2747  0x00020148,
2749  msg, errno, 0);
2750  d->cancel = 1;
2751  ret = 0; goto ex;
2752  }
2753  ret = 1;
2754 ex:;
2755  BURN_FREE_MEM(msg);
2756  return ret;
2757 }
2758 
2759 
2760 /* ts A70911 : to be used as burn_drive.sync_cache(),
2761  emulating mmc_sync_cache() */
2763 {
2764  burn_stdio_sync_cache(d->stdio_fd, d, 0);
2765 }
2766 
2767 
2768 /* ts C00824 : API */
2769 /* Enforces nominal write speed */
2770 int burn_nominal_slowdown(int kb_per_second, int max_corr,
2771  struct timeval *prev_time,
2772  int *us_corr, off_t b_since_prev, int flag)
2773 {
2774  struct timeval tnow;
2775  double to_wait, goal, corr;
2776  int abs_max_corr;
2777 
2778  if (flag & 1) {
2779  gettimeofday(prev_time, NULL);
2780  *us_corr = 0;
2781  return 1;
2782  }
2783  if (kb_per_second <= 0)
2784  return 2;
2785 
2786  if (max_corr < -1.0e9 || max_corr > 1.0e9)
2787  abs_max_corr = 1000000000;
2788  else
2789  abs_max_corr = abs(max_corr);
2790  gettimeofday(&tnow, NULL);
2791  goal = ((double) b_since_prev) / 1000.0 / ((double) kb_per_second) +
2792  ((double) prev_time->tv_sec) +
2793  ((double) prev_time->tv_usec) / 1.0e6 +
2794  ((double) *us_corr) / 1.0e6 ;
2795  to_wait = goal - ((double) tnow.tv_sec) -
2796  ((double) tnow.tv_usec) / 1.0e6;
2797 
2798  /* usleep might be restricted to 999999 microseconds */
2799  while (to_wait > 0.0) {
2800  if (to_wait >= 0.5) {
2801  usleep(500000);
2802  to_wait -= 0.5;
2803  } else if (to_wait >= 0.00001) {
2804  usleep((int) (to_wait * 1000000.0));
2805  to_wait = 0.0;
2806  } else {
2807  to_wait = 0.0;
2808  }
2809  }
2810  gettimeofday(prev_time, NULL);
2811  corr = (goal - ((double) prev_time->tv_sec) -
2812  ((double) prev_time->tv_usec) / 1.0e6) * 1.0e6;
2813  if (corr > abs_max_corr)
2814  *us_corr = abs_max_corr;
2815  else if (corr < -abs_max_corr)
2816  *us_corr = -abs_max_corr;
2817  else
2818  *us_corr = corr;
2819  return 1;
2820 }
2821 
2822 
2823 /* ts A70904 */
2825  int tnum, int flag)
2826 {
2827  int open_ended, bufsize = 16 * 2048, ret, sectors;
2828  struct burn_track *t = s->track[tnum];
2829  struct burn_drive *d = o->drive;
2830  char *buf = NULL;
2831  int i, prev_sync_sector = 0, us_corr = 0, max_corr = 250000;
2832  struct buffer *out = d->buffer;
2833  struct timeval prev_time;
2834 
2835  BURN_ALLOC_MEM(buf, char, bufsize);
2836 
2837  sectors = burn_track_get_sectors_2(t, 1);
2838  burn_disc_init_track_status(o, s, t, tnum, sectors);
2839  open_ended = burn_track_is_open_ended(t);
2840 
2842 
2843  /* attach stdio emulators for mmc_*() functions */
2844  if (o->simulate)
2846  else
2848  d->do_simulate = o->simulate;
2850 
2851  /* initialize */
2853  &prev_time, &us_corr, (off_t) 0, 1);
2854 
2855  for (i = 0; open_ended || i < sectors; i++) {
2856  /* transact a (CD sized) sector */
2857  if (!sector_data(o, t, 0))
2858  {ret= 0; goto ex;}
2859  if (open_ended)
2860  d->progress.sectors = sectors = d->progress.sector;
2861  if (open_ended || t->end_on_premature_eoi) {
2862  if (burn_track_is_data_done(t))
2863  break;
2864  }
2865  d->progress.sector++;
2866  /* Flush to disk from time to time */
2867  if (o->stdio_fsync_size > 0) {
2868  if (d->progress.sector - prev_sync_sector >=
2869  o->stdio_fsync_size) {
2870  if (!o->simulate)
2872  1);
2874  d->nominal_write_speed, max_corr,
2875  &prev_time, &us_corr,
2876  (off_t) (d->progress.sector -
2877  prev_sync_sector) *
2878  (off_t) 2048,
2879  0);
2880  prev_sync_sector = d->progress.sector;
2881  }
2882  } else if ((d->progress.sector % 512) == 0) {
2884  &prev_time, &us_corr, (off_t) (512 * 2048), 0);
2885  }
2886  }
2887 
2888  /* Pad up buffer to next full o->obs (usually 32 kB) */
2889  if (o->obs_pad && out->bytes > 0 && out->bytes < o->obs) {
2890  memset(out->data + out->bytes, 0, o->obs - out->bytes);
2891  out->sectors += (o->obs - out->bytes) / 2048;
2892  out->bytes = o->obs;
2893  }
2894  ret = burn_write_flush(o, t);
2895  ret= 1;
2896 ex:;
2897  if (d->cancel)
2899  if (t->end_on_premature_eoi == 2)
2900  d->cancel = 1;
2901  BURN_FREE_MEM(buf);
2902  return ret;
2903 }
2904 
2905 
2906 /* ts A70904 */
2908  struct burn_disc *disc)
2909 {
2910  int ret;
2911  struct burn_drive *d = o->drive;
2912 
2913  d->needs_close_session = 0;
2914  if (o->obs_pad < 2)
2915  o->obs_pad = 0; /* no filling-up of track's last 32k buffer */
2916  o->obs = 32*1024; /* buffer size */
2917 
2918  if (disc->sessions != 1)
2919  {ret= 0 ; goto ex;}
2920  if (disc->session[0]->tracks != 1)
2921  {ret= 0 ; goto ex;}
2922 
2923  /* update progress */
2924  d->progress.session = 0;
2925  d->progress.tracks = 1;
2926 
2927  /* >>> adjust sector size (2048) to eventual audio or even raw */
2928 
2929  /* >>> ??? ts B11004 : Why this eagerness to close and open ? */
2930 
2931  /* open target file */
2932  if (d->stdio_fd >= 0)
2933  close(d->stdio_fd);
2934  if (d->drive_role == 5 && d->status == BURN_DISC_APPENDABLE &&
2935  o->start_byte < 0)
2936  o->start_byte = d->role_5_nwa * 2048;
2937  d->stdio_fd = burn_stdio_open_write(d, o->start_byte, 2048, 0);
2938  if (d->stdio_fd == -1)
2939  {ret = 0; goto ex;}
2940 
2941  ret = burn_stdio_write_track(o, disc->session[0], 0, 0);
2942  if (ret <= 0)
2943  goto ex;
2944 
2945  /* XXX: currently signs an end of session */
2946  d->progress.sector = 0;
2947  d->progress.start_sector = 0;
2948  d->progress.sectors = 0;
2949  ret = 1;
2950 ex:;
2951 
2952  /* >>> ??? ts B11004 : Why this eagerness to close ? */
2953 
2954  if (d->stdio_fd >= 0)
2955  close(d->stdio_fd);
2956  d->stdio_fd = -1;
2957 
2958  /* update pseudo-media state records by re-grabbing */
2960  burn_drive_grab_stdio(d, 1);
2961 
2962  return ret;
2963 }
2964 
2965 
2967 {
2968  struct cue_sheet *sheet;
2969  struct burn_drive *d = o->drive;
2970  struct buffer *buffer_mem = o->drive->buffer;
2971  struct burn_session *s;
2972  struct burn_track *lt, *t;
2973  int first = 1, i, ret, lba, nwa = 0, multi_mem, stream_recording_start;
2974  off_t default_size;
2975  char msg[80];
2976 
2977 
2978 /* ts A60924 : libburn/message.c gets obsoleted
2979  burn_message_clear_queue();
2980 */
2981 
2982  /* ts A61224 */
2983  burn_disc_init_write_status(o, disc); /* must be done very early */
2984 
2985  /* ts A80412 , A90227 , B90411 */
2986  if (o->do_stream_recording >= 16)
2987  stream_recording_start = o->do_stream_recording;
2988  else
2989  stream_recording_start = 0;
2991  stream_recording_start, 0);
2992 
2993  /* ts A91122 : Get buffer suitable for sources made by
2994  burn_os_open_track_src() */
2995  d->buffer = burn_os_alloc_buffer(sizeof(struct buffer), 0);
2996  if (d->buffer == NULL)
2997  goto fail_wo_sync;
2998 
2999 /* >>> ts A90321
3000 
3001  memset(d->buffer, 0, sizeof(struct buffer));
3002 
3003 fprintf(stderr, "libburn_DEBUG: d->buffer = %lX , size = %d\n",
3004  (unsigned long) d->buffer, (int) sizeof(struct buffer));
3005 
3006 calloc() seems not to have the desired effect. valgrind warns:
3007 ==18251== Syscall param write(buf) points to uninitialised byte(s)
3008 ==18251== at 0x5071DEB: (within /lib64/libpthread-2.5.so)
3009 ==18251== by 0x4723FA: burn_stdio_write (write.c:1850)
3010 ==18251== by 0x4725DC: burn_stdio_mmc_write (write.c:1894)
3011 ==18251== by 0x483B7A: get_sector (sector.c:229)
3012 ==18251== by 0x484F11: sector_data (sector.c:639)
3013 ==18251== by 0x4729FE: burn_stdio_write_track (write.c:2012)
3014 ==18251== by 0x472CF4: burn_stdio_write_sync (write.c:2072)
3015 ==18251== by 0x472E8D: burn_disc_write_sync (write.c:2125) <<< we are here
3016 ==18251== by 0x460254: write_disc_worker_func (async.c:514)
3017 ==18251== by 0x506B09D: start_thread (in /lib64/libpthread-2.5.so)
3018 ==18251== by 0x55484CC: clone (in /lib64/libc-2.5.so)
3019 */
3020 
3021  d->rlba = -150;
3022  d->toc_temp = 9;
3023 
3024  if(d->drive_role == 4) {
3026  0x00020181,
3028  "Pseudo-drive is a read-only file. Cannot write.",
3029  0, 0);
3030  goto fail_wo_sync;
3031  }
3032  /* ts A70904 */
3033  if (d->drive_role != 1) {
3034  ret = burn_stdio_write_sync(o, disc);
3035  if (ret <= 0)
3036  goto fail_wo_sync;
3037  goto ex;
3038  }
3039  /* ts A61218 */
3040  if (! d->current_is_cd_profile) {
3041  ret = burn_dvd_write_sync(o, disc);
3042  if (ret <= 0)
3043  goto fail_wo_sync;
3044  goto ex;
3045  }
3046 
3047  /* ts A70521 : GNU/Linux 2.4 USB audio fails with 64 kiB */
3048  /* ts A80414 : might need 64 kiB for BD-RE streaming */
3049  /* buffer flush trigger for sector.c:get_sector() */
3050  o->obs = Libburn_cd_obS;
3051 
3052  sprintf(msg, "cd Profile= %2.2Xh , obs= %d , obs_pad= %d",
3053  d->current_profile, o->obs, o->obs_pad);
3056 
3057  /* ts A70218 */
3058  if (o->write_type == BURN_WRITE_SAO) {
3059  for (i = 0 ; i < disc->session[0]->tracks; i++) {
3060  t = disc->session[0]->track[i];
3061  if (burn_track_is_open_ended(t)) {
3063  sprintf(msg,
3064  "Activated track default size %.f",
3065  (double) default_size);
3067  d->global_index, 0x0002012e,
3069  LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
3071  }
3072  }
3073  }
3074 
3075 /* Apparently some drives require this command to be sent, and a few drives
3076 return crap. so we send the command, then ignore the result.
3077 */
3078  /* ts A61107 : moved up send_write_parameters because LG GSA-4082B
3079  seems to dislike get_nwa() in advance */
3080  d->alba = d->start_lba; /* ts A61114: this looks senseless */
3081  d->nwa = d->alba;
3082  if (o->write_type == BURN_WRITE_TAO) {
3083  nwa = 0; /* get_nwa() will be called in burn_track() */
3084  } else {
3085  if (disc->sessions > 0)
3086  s = disc->session[0];
3087  else
3088  s = NULL;
3089  d->send_write_parameters(d, s, -1, o);
3090 
3091  ret = d->get_nwa(d, -1, &lba, &nwa);
3092  sprintf(msg,
3093  "SAO|RAW: Inquired nwa: %d , ret= %d , cap=%.f\n",
3094  nwa, ret, (double) d->media_capacity_remaining);
3096  0x00000002,
3098  msg,0, 0);
3099 
3100  /* >>> ts A70212 : CD-DAO/SAO : eventually expand size of last track to maximum */;
3101 
3102  }
3103 
3104  for (i = 0; i < disc->sessions; i++) {
3105  /* update progress */
3106  d->progress.session = i;
3107  d->progress.tracks = disc->session[i]->tracks;
3108 
3109  /* ts A61114: added parameter nwa */
3110  sheet = burn_create_toc_entries(o, disc->session[i], nwa);
3111 
3112  /* ts A61009 */
3113  if (sheet == NULL)
3114  goto fail_wo_sync;
3115 
3116 #ifdef Libburn_write_with_function_print_cuE
3117  print_cue(sheet);
3118  /* goto fail_wo_sync; */
3119 #endif /* Libburn_write_with_function_print_cuE */
3120 
3121  d->medium_state_changed = 1;
3122  ret = 1;
3123  if (o->write_type == BURN_WRITE_SAO)
3124  ret = d->send_cue_sheet(d, sheet);
3125  if (sheet->data != NULL)
3126  free(sheet->data);
3127  free(sheet);
3128  if (ret <= 0)
3129  goto fail_wo_sync;
3130 
3131  /* --- From here on, final sync is needed. --- */
3132 
3133  if (o->write_type == BURN_WRITE_RAW) {
3134  if (!burn_write_leadin(o, disc->session[i], first))
3135  goto fail;
3136  } else {
3137  if (first) {
3138 
3139  /* ts A61030 : 0 made the burner take data. */
3140  /* ts A61103 : Meanwhile d->nwa is updated in
3141  burn_write_track() */
3142  if(o->write_type == BURN_WRITE_TAO) {
3143  d->nwa= d->alba = 0;
3144  } else {
3145 
3146 #ifdef Libburn_sao_can_appenD
3147  /* ts A61114: address for d->write() */
3148  if (d->status == BURN_DISC_APPENDABLE
3149  && o->write_type == BURN_WRITE_SAO) {
3150  d->nwa = d->alba = nwa-150;
3151 
3152  sprintf(msg,
3153  "SAO appendable d->nwa= %d\n", d->nwa);
3155  libdax_messenger, d->global_index, 0x00000002,
3157  msg, 0, 0);
3158 
3159  } else {
3160  d->nwa = -150;
3161  d->alba = -150;
3162  }
3163 #else
3164  d->nwa = -150;
3165  d->alba = -150;
3166 #endif /* ! Libburn_sao_can_appenD */
3167 
3168 
3169  }
3170 
3171  } else {
3172  d->nwa += 4500;
3173  d->alba += 4500;
3174  }
3175  }
3176  multi_mem = o->multi;
3177  if(i < disc->sessions - 1)
3178  o->multi = 1;
3179  ret = burn_write_session(o, disc->session[i]);
3180  o->multi = multi_mem;
3181  if (!ret)
3182  goto fail;
3183 
3184  lt = disc->session[i]->track[disc->session[i]->tracks - 1];
3185  if (o->write_type == BURN_WRITE_RAW) {
3186  if (!burn_write_leadout(o, first, lt->entry->control,
3187  lt->mode))
3188  goto fail;
3189  } else {
3190 
3191  /* ts A61030 */
3192  if (o->write_type != BURN_WRITE_TAO)
3193 
3194  if (!burn_write_flush(o, NULL))
3195  goto fail;
3196 
3197  d->nwa += first ? 6750 : 2250;
3198  d->alba += first ? 6750 : 2250;
3199  }
3200  if (first)
3201  first = 0;
3202 
3203  /* XXX: currently signs an end of session */
3204  d->progress.sector = 0;
3205  d->progress.start_sector = 0;
3206  d->progress.sectors = 0;
3207  }
3208 
3209  /* ts A61030: extended skipping of flush to TAO: session is closed */
3211  if (!burn_write_flush(o, NULL))
3212  goto fail;
3213 
3214  sleep(1);
3215 
3216  /* ts A61125 : update media state records */
3219 
3220  /* ts A61012 : This return was traditionally missing. I suspect this
3221  to have caused Cdrskin_eject() failures */
3222  goto ex;
3223 
3224 fail:
3225  d->sync_cache(d);
3226 fail_wo_sync:;
3227  usleep(500001); /* ts A61222: to avoid a warning from remove_worker()*/
3230  "Burn run failed", 0, 0);
3231  d->cancel = 1;
3232  /* <<< d->busy = BURN_DRIVE_IDLE; */
3233 ex:;
3234  d->do_stream_recording = 0;
3235  if (d->buffer != NULL)
3236  burn_os_free_buffer((char *) d->buffer,
3237  sizeof(struct buffer), 0);
3238  d->buffer = buffer_mem;
3239  if (d->write_opts != NULL) {
3241  d->write_opts = NULL;
3242  }
3243  if (d->write_retry_count > 0) {
3244  sprintf(msg, "WRITE command repetition happened %u times",
3245  d->write_retry_count);
3247  0x000201ad,
3249  msg, 0, 0);
3250  }
3251  return;
3252 }
3253 
3254 /* ts A70811 : API function */
3255 int burn_random_access_write(struct burn_drive *d, off_t byte_address,
3256  char *data, off_t data_count, int flag)
3257 {
3258  int alignment = 0, start, upto, chunksize, err, fd = -1, ret;
3259  int do_close = 0, getfl_ret;
3260  char msg[81], *rpt;
3261  struct buffer *buf = NULL, *buffer_mem = d->buffer;
3262 
3263  BURN_ALLOC_MEM(buf, struct buffer, 1);
3264  if (d->released) {
3266  d->global_index, 0x00020142,
3268  "Drive is not grabbed on random access write", 0, 0);
3269  {ret = 0; goto ex;}
3270  }
3271  if(d->drive_role == 0) {
3273  0x00020146,
3275  "Drive is a virtual placeholder (null-drive)", 0, 0);
3276  {ret = 0; goto ex;}
3277  }
3278  if(d->drive_role == 4) {
3280  0x00020181,
3282  "Pseudo-drive is a read-only file. Cannot write.",
3283  0, 0);
3284  {ret = 0; goto ex;}
3285  }
3286 
3287  if(d->drive_role == 2 || d->drive_role == 5)
3288  alignment = 2 * 1024;
3289  if (d->current_profile == 0x12) /* DVD-RAM */
3290  alignment = 2 * 1024;
3291  if (d->current_profile == 0x13) /* DVD-RW restricted overwrite */
3292  alignment = 32 * 1024;
3293  if (d->current_profile == 0x1a) /* DVD+RW */
3294  alignment = 2 * 1024;
3295  if (d->current_profile == 0x43) /* BD-RE */
3296  alignment = 2 * 1024;
3297  if (alignment == 0) {
3298  sprintf(msg, "Write start address not supported");
3300  0x00020125,
3302  "Write start address not supported", 0, 0);
3303  {ret = 0; goto ex;}
3304  }
3305  if ((byte_address % alignment) != 0) {
3306  sprintf(msg,
3307  "Write start address not properly aligned (%d bytes)",
3308  alignment);
3310  0x00020126,
3312  msg, 0, 0);
3313  {ret = 0; goto ex;}
3314  }
3315  if ((data_count % alignment) != 0) {
3316  sprintf(msg,
3317  "Write data count not properly aligned (%ld bytes)",
3318  (long) alignment);
3320  0x00020141,
3322  msg, 0, 0);
3323  {ret = 0; goto ex;}
3324  }
3325  if (d->busy != BURN_DRIVE_IDLE) {
3327  d->global_index, 0x00020140,
3329  "Drive is busy on attempt to write random access",0,0);
3330  {ret = 0; goto ex;}
3331  }
3332  if (d->drive_role != 1) {
3333  if (d->stdio_fd >= 0) {
3334  /* Avoid to have a read-only fd open */
3335  getfl_ret = fcntl(d->stdio_fd, F_GETFL);
3336  if (((O_RDWR | O_WRONLY | O_RDONLY) & getfl_ret) ==
3337  O_RDONLY) {
3338  close(d->stdio_fd);
3339  d->stdio_fd = -1;
3340  }
3341  }
3342  if (d->stdio_fd >= 0) {
3343  /* Avoid to have two fds open */
3344  fd = d->stdio_fd;
3345  } else {
3346  fd = burn_stdio_open_write(d, byte_address, 2048, 0);
3347  if (fd == -1)
3348  {ret = 0; goto ex;}
3349  do_close = 1;
3350  }
3351  }
3352  d->cancel = 0;
3354  d->buffer = buf;
3355 
3356  start = byte_address / 2048;
3357  upto = start + data_count / 2048;
3358  rpt = data;
3359  for (; start < upto; start += 16) {
3360  chunksize = upto - start;
3361  if (chunksize > 16)
3362  chunksize = 16;
3363  d->buffer->bytes = chunksize * 2048;
3364  memcpy(d->buffer->data, rpt, d->buffer->bytes);
3365  rpt += d->buffer->bytes;
3366  d->buffer->sectors = chunksize;
3367  d->nwa = start;
3368  if(d->do_simulate) {
3369  err = 0;
3370  } else if(d->drive_role == 1) {
3371  err = d->write(d, d->nwa, d->buffer);
3372  } else {
3373  ret = burn_stdio_write(fd, (char *) d->buffer->data,
3374  d->buffer->bytes, d, 0);
3375  err = 0;
3376  if (ret <= 0)
3377  err = BE_CANCELLED;
3378  }
3379  if (err == BE_CANCELLED) {
3380  d->busy = BURN_DRIVE_IDLE;
3381  if(fd >= 0 && do_close)
3382  close(fd);
3383  {ret = -(start * 2048 - byte_address); goto ex;}
3384  }
3385  }
3386 
3387  if(d->drive_role == 1)
3388  d->needs_sync_cache = 1;
3389  if(flag & 1) {
3390  if(d->do_simulate) {
3391  ;
3392  } else if(d->drive_role == 1)
3393  d->sync_cache(d);
3394  else
3395  burn_stdio_sync_cache(fd, d, 2);
3396  d->needs_sync_cache = 0;
3397  }
3398 
3399  if(fd >= 0 && do_close)
3400  close(fd);
3401  d->buffer = buffer_mem;
3402  d->busy = BURN_DRIVE_IDLE;
3403  ret = 1;
3404 ex:
3405  BURN_FREE_MEM(buf);
3406  return ret;
3407 }
3408 
3409 
3410 /* ts B10527 */
3411 /* @param bit0= force close, even if no damage was seen
3412 */
3414 {
3415  struct burn_drive *d;
3416  int ret;
3417  enum burn_drive_status busy;
3418 
3419  d = o->drive;
3420  busy = d->busy;
3421 
3422  if (busy != BURN_DRIVE_IDLE) {
3424  d->global_index, 0x00020106,
3426  "Drive is busy on attempt to close damaged session",
3427  0, 0);
3428  {ret = 0; goto ex;}
3429  }
3430  if (!((d->next_track_damaged & 1) || (flag & 1))) {
3432  d->global_index, 0x00020187,
3434  "Track not marked as damaged. No action taken.",
3435  0, 0);
3436  {ret = 0; goto ex;}
3437  }
3438  d->busy = BURN_DRIVE_WRITING;
3439 
3440  if (d->current_profile == 0x09 || d->current_profile == 0x0a) {
3441  /* Close CD track and session */
3442  o->write_type = BURN_WRITE_TAO; /* no action without TAO */
3443 
3444  /* Send mode page 5 */;
3445  d->send_write_parameters(d, NULL, -1, o);
3446 
3447  ret = burn_write_close_session(o);
3448  if (ret <= 0)
3449  goto ex;
3450 
3451  } else if(d->current_profile == 0x11 || d->current_profile == 0x14) {
3452  /* Close DVD-R[W] track and session */
3453  o->write_type = BURN_WRITE_TAO; /* no action without TAO */
3454 
3455  /* Send mode page 5 */;
3456  d->send_write_parameters(d, NULL, -1, o);
3457 
3459  if (ret <= 0)
3460  goto ex;
3462  if (ret <= 0)
3463  goto ex;
3464 
3465  } else if(d->current_profile == 0x1b || d->current_profile == 0x2b) {
3466  /* Close DVD+R track and session */
3468  if (ret <= 0)
3469  goto ex;
3470 
3471  } else if(d->current_profile == 0x41) {
3472  /* Close BD-R track and session */
3474  if (ret <= 0)
3475  goto ex;
3476 
3477  } else {
3479  d->global_index, 0x00020188,
3481  "Cannot close damaged track on given media type",
3482  0, 0);
3483  {ret = 0; goto ex;}
3484 
3485  }
3486  ret = 1;
3487 ex:;
3488  d->busy = busy;
3489  /* Record with drive that repair was attempted */
3490  d->next_track_damaged &= ~1;
3491  return ret;
3492 }
3493 
3494 
int burn_cdtext_from_session(struct burn_session *s, unsigned char **text_packs, int *num_packs, int flag)
Definition: cdtext.c:359
int burn_cdtext_crc_mismatches(unsigned char *packs, int num_packs, int flag)
Definition: cdtext.c:103
int burn_drive_inquire_media(struct burn_drive *d)
Definition: drive.c:282
int burn_drive_mark_unready(struct burn_drive *d, int flag)
Definition: drive.c:656
int burn_drive_grab_stdio(struct burn_drive *d, int flag)
Definition: drive.c:412
int burn_drive_get_bd_r_pow(struct burn_drive *d)
Definition: drive.c:3676
int burn_drive_set_stream_recording(struct burn_drive *d, int recmode, int start, int flag)
Definition: drive.c:1178
int burn_drive__fd_from_special_adr(char *adr)
Definition: drive.c:337
#define BE_CANCELLED
Definition: error.h:6
#define BURN_FREE_MEM(pt)
Definition: init.h:52
#define BURN_ALLOC_MEM(pt, typ, count)
Definition: init.h:40
#define BURN_REASONS_LEN
Definition: libburn.h:1817
void * burn_os_alloc_buffer(size_t amount, int flag)
Definition: sg-dummy.c:343
void burn_write_opts_free(struct burn_write_opts *opts)
Definition: options.c:74
#define BURN_MODE_RAW
Definition: libburn.h:88
enum burn_write_types burn_write_opts_auto_write_type(struct burn_write_opts *opts, struct burn_disc *disc, char reasons[4096], int flag)
Definition: options.c:313
#define BURN_MODE2
Definition: libburn.h:97
#define BURN_SUBCODE_P16
Definition: libburn.h:121
burn_drive_status
Definition: libburn.h:293
@ BURN_DRIVE_FORMATTING
Definition: libburn.h:325
@ 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_WRITING_LEADOUT
Definition: libburn.h:307
@ BURN_DRIVE_WRITING_SYNC
Definition: libburn.h:334
@ BURN_DRIVE_CLOSING_TRACK
Definition: libburn.h:318
@ BURN_DRIVE_WRITING_PREGAP
Definition: libburn.h:316
@ BURN_DRIVE_IDLE
Definition: libburn.h:295
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
Definition: sg-dummy.c:352
int burn_track_set_size(struct burn_track *t, off_t size)
Definition: structure.c:565
#define BURN_4CH
Definition: libburn.h:115
#define BURN_COPY
Definition: libburn.h:117
#define BURN_SUBCODE_P96
Definition: libburn.h:123
#define BURN_PREEMPHASIS
Definition: libburn.h:119
void burn_lba_to_msf(int lba, int *m, int *s, int *f)
Definition: sector.c:767
#define BURN_SUBCODE_R96
Definition: libburn.h:125
burn_write_types
Definition: libburn.h:138
@ BURN_WRITE_RAW
Definition: libburn.h:180
@ BURN_WRITE_TAO
Definition: libburn.h:152
@ BURN_WRITE_SAO
Definition: libburn.h:163
@ BURN_WRITE_NONE
Definition: libburn.h:187
struct burn_session ** burn_disc_get_sessions(struct burn_disc *d, int *num)
Definition: structure.c:702
#define BURN_SCMS
Definition: libburn.h:133
@ BURN_DISC_UNSUITABLE
Definition: libburn.h:275
@ BURN_DISC_APPENDABLE
Definition: libburn.h:254
@ BURN_DISC_FULL
Definition: libburn.h:265
#define BURN_MODE0
Definition: libburn.h:84
#define BURN_MODE1
Definition: libburn.h:92
#define BURN_AUDIO
Definition: libburn.h:113
int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code, int severity, int priority, char *msg_text, int os_errno, int flag)
Definition: libdax_msgs.c:334
#define LIBDAX_MSGS_SEV_DEBUG
Definition: libdax_msgs.h:138
#define LIBDAX_MSGS_SEV_FATAL
Definition: libdax_msgs.h:217
#define LIBDAX_MSGS_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_SEV_WARNING
Definition: libdax_msgs.h:154
#define LIBDAX_MSGS_PRIO_ZERO
Definition: libdax_msgs.h:234
#define LIBDAX_MSGS_SEV_FAILURE
Definition: libdax_msgs.h:205
void mmc_get_event(struct burn_drive *d)
Definition: mmc.c:651
int burn_write_opts_clone(struct burn_write_opts *from, struct burn_write_opts **to, int flag)
Definition: options.c:83
int sector_postgap(struct burn_write_opts *o, unsigned char tno, unsigned char control, int mode)
Definition: sector.c:517
int sector_write_buffer(struct burn_drive *d, struct burn_track *track, int flag)
Definition: sector.c:238
int sector_pregap(struct burn_write_opts *o, unsigned char tno, unsigned char control, int mode)
Definition: sector.c:496
int sector_lout(struct burn_write_opts *o, unsigned char control, int mode)
Definition: sector.c:703
int sector_headers_is_ok(struct burn_write_opts *o, int mode)
Definition: sector.c:789
int sector_toc(struct burn_write_opts *o, int mode)
Definition: sector.c:476
int sector_data(struct burn_write_opts *o, struct burn_track *t, int psub)
Definition: sector.c:723
int burn_source_cancel(struct burn_source *src)
Definition: source.c:56
unsigned char data[65536+4096]
Definition: transport.h:52
int bytes
Definition: transport.h:54
int sectors
Definition: transport.h:53
int sessions
Definition: structure.h:145
struct burn_session ** session
Definition: structure.h:146
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
char current_profile_text[80]
Definition: transport.h:209
int needs_close_session
Definition: transport.h:278
struct burn_write_opts * write_opts
Definition: transport.h:430
struct burn_progress progress
Definition: transport.h:395
int current_is_cd_profile
Definition: transport.h:210
int do_stream_recording
Definition: transport.h:286
int(* get_nwa)(struct burn_drive *, int trackno, int *lba, int *nwa)
Definition: transport.h:499
int next_track_damaged
Definition: transport.h:274
int do_simulate
Definition: transport.h:345
int global_index
Definition: transport.h:200
volatile int released
Definition: transport.h:320
struct buffer * buffer
Definition: transport.h:394
int medium_state_changed
Definition: transport.h:443
char * devname
Definition: transport.h:185
int toc_entries
Definition: transport.h:524
int last_track_no
Definition: transport.h:360
unsigned int waited_tries
Definition: transport.h:419
struct burn_toc_entry * toc_entry
Definition: transport.h:525
int(* write)(struct burn_drive *, int, struct buffer *)
Definition: transport.h:468
int role_5_nwa
Definition: transport.h:386
int num_opc_tables
Definition: transport.h:296
void(* sync_cache)(struct burn_drive *)
Definition: transport.h:497
unsigned int waited_writes
Definition: transport.h:418
struct burn_disc * disc
Definition: transport.h:392
int start_lba
Definition: transport.h:341
int(* read_buffer_capacity)(struct burn_drive *d)
Definition: transport.h:528
int pbf_altered
Definition: transport.h:409
int(* send_cue_sheet)(struct burn_drive *, struct cue_sheet *)
Definition: transport.h:492
unsigned int write_retry_count
Definition: transport.h:439
unsigned int pessimistic_writes
Definition: transport.h:417
volatile int cancel
Definition: transport.h:422
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 needs_sync_cache
Definition: transport.h:281
int(* reserve_track)(struct burn_drive *d, off_t size)
Definition: transport.h:495
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
unsigned int waited_usec
Definition: transport.h:420
int complete_sessions
Definition: transport.h:348
enum burn_drive_status busy
Definition: transport.h:423
off_t pessimistic_buffer_free
Definition: transport.h:408
off_t media_capacity_remaining
Definition: transport.h:370
int drive_role
Definition: transport.h:178
void(* perform_opc)(struct burn_drive *)
Definition: transport.h:485
int state_of_last_session
Definition: transport.h:350
int bg_format_status
Definition: transport.h:297
int toc_temp
Definition: transport.h:391
off_t buffered_bytes
Definition: libburn.h:702
unsigned buffer_min_fill
Definition: libburn.h:707
int start_sector
Definition: libburn.h:684
unsigned buffer_capacity
Definition: libburn.h:695
int sessions
Definition: libburn.h:672
unsigned buffer_available
Definition: libburn.h:697
unsigned char mediacatalog[14]
Definition: structure.h:140
unsigned char lasttrack
Definition: structure.h:122
struct burn_track ** track
Definition: structure.h:130
unsigned char firsttrack
Definition: structure.h:121
int(* read)(struct burn_source *, unsigned char *buffer, int size)
Definition: libburn.h:493
struct burn_source * next
Definition: libburn.h:540
int(* read_xt)(struct burn_source *, unsigned char *buffer, int size)
Definition: libburn.h:575
Definition: libburn.h:351
unsigned char adr
Definition: libburn.h:355
unsigned char psec
Definition: libburn.h:369
unsigned char pmin
Definition: libburn.h:367
unsigned char point
Definition: libburn.h:361
unsigned char control
Definition: libburn.h:357
unsigned char pframe
Definition: libburn.h:371
struct isrc isrc
Definition: structure.h:105
int open_ended
Definition: structure.h:74
int end_on_premature_eoi
Definition: structure.h:84
int pregap2_size
Definition: structure.h:96
int postgap_size
Definition: structure.h:103
struct burn_source * source
Definition: structure.h:63
unsigned char indices
Definition: structure.h:39
int pregap2
Definition: structure.h:92
int pregap1
Definition: structure.h:90
off_t written_sectors
Definition: structure.h:70
int index[100]
Definition: structure.h:44
int mode
Definition: structure.h:88
int postgap
Definition: structure.h:99
off_t sourcecount
Definition: structure.h:68
off_t writecount
Definition: structure.h:69
off_t default_size
Definition: structure.h:60
struct burn_toc_entry * entry
Definition: structure.h:38
int no_text_pack_crc_check
Definition: options.h:77
int has_mediacatalog
Definition: options.h:80
int fill_up_media
Definition: options.h:53
int do_stream_recording
Definition: options.h:64
struct burn_drive * drive
Definition: options.h:17
int dvd_obs_override
Definition: options.h:68
unsigned char * text_packs
Definition: options.h:75
int num_text_packs
Definition: options.h:76
off_t start_byte
Definition: options.h:50
unsigned int simulate
Definition: options.h:33
unsigned char multi
Definition: options.h:89
enum burn_write_types write_type
Definition: options.h:23
unsigned char mediacatalog[13]
Definition: options.h:81
int stdio_fsync_size
Definition: options.h:72
unsigned char control
Definition: options.h:86
int count
Definition: transport.h:33
unsigned char * data
Definition: transport.h:34
Definition: structure.h:11
unsigned int serial
Definition: structure.h:16
unsigned char year
Definition: structure.h:15
char country[2]
Definition: structure.h:13
char owner[3]
Definition: structure.h:14
int has_isrc
Definition: structure.h:12
off_t burn_track_get_default_size(struct burn_track *t)
Definition: structure.c:629
int burn_track_set_fillup(struct burn_track *t, int fill_up_media)
Definition: structure.c:577
int burn_track_is_data_done(struct burn_track *t)
Definition: structure.c:649
int burn_track_apply_fillup(struct burn_track *t, off_t max_size, int flag)
Definition: structure.c:590
int burn_track_get_shortage(struct burn_track *t)
Definition: structure.c:654
int burn_track_get_sectors_2(struct burn_track *t, int flag)
Definition: structure.c:512
int burn_track_set_sectors(struct burn_track *t, int sectors)
Definition: structure.c:549
int burn_track_is_open_ended(struct burn_track *t)
Definition: structure.c:614
#define TOC_CONTROL_DATA
Definition: toc.h:39
#define TOC_CONTROL_AUDIO
Definition: toc.h:38
#define BUFFER_SIZE
Definition: transport.h:21
int burn_disc_close_session_dvd_minus_rw(struct burn_write_opts *o, struct burn_session *s)
Definition: write.c:2042
int burn_sector_length(int tracktype)
Definition: write.c:835
int burn_disc_init_write_status(struct burn_write_opts *o, struct burn_disc *disc)
Definition: write.c:1326
#define O_LARGEFILE
int burn_dvd_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
Definition: write.c:2305
void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
Definition: write.c:2966
int burn_stdio_sync_cache(int fd, struct burn_drive *d, int flag)
Definition: write.c:2711
int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc, char reasons[4096], int silent)
Definition: write.c:1420
int burn_nominal_slowdown(int kb_per_second, int max_corr, struct timeval *prev_time, int *us_corr, off_t b_since_prev, int flag)
Definition: write.c:2770
int burn_disc_write_is_ok(struct burn_write_opts *o, struct burn_disc *disc, int flag)
Definition: write.c:1302
#define Libburn_cd_obS
Definition: write.c:76
static int add_cue(struct cue_sheet *sheet, unsigned char ctladr, unsigned char tno, unsigned char indx, unsigned char form, unsigned char scms, int lba)
Definition: write.c:394
#define O_BINARY
Definition: write.c:43
int burn_write_leadin(struct burn_write_opts *o, struct burn_session *s, int first)
Definition: write.c:857
#define Libburn_bd_re_obS
Definition: write.c:84
int burn_write_flush_buffer(struct burn_write_opts *o, struct burn_track *track)
Definition: write.c:170
struct libdax_msgs * libdax_messenger
Definition: init.c:42
int burn_dvd_write_track(struct burn_write_opts *o, struct burn_session *s, int tnum, int is_last_track)
Definition: write.c:1894
#define Libburn_dvd_obS
Definition: write.c:80
int burn_disc_close_session_dvd_minus_r(struct burn_write_opts *o)
Definition: write.c:2061
static int burn_create_text_packs(struct burn_write_opts *o, struct burn_session *s, int flag)
Definition: write.c:912
void burn_stdio_mmc_sync_cache(struct burn_drive *d)
Definition: write.c:2762
static int add_isrc_cue(struct cue_sheet *sheet, unsigned char ctladr, int tno, struct isrc *isrc)
Definition: write.c:438
int burn_disc_finalize_dvd_plus_r(struct burn_write_opts *o)
Definition: write.c:1706
int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s, int tnum)
Definition: write.c:253
int burn_write_track_minsize(struct burn_write_opts *o, struct burn_session *s, int tnum)
Definition: write.c:209
int burn_write_close_session(struct burn_write_opts *o)
Definition: write.c:287
int burn_dvd_write_session(struct burn_write_opts *o, struct burn_session *s, int is_last_session)
Definition: write.c:2086
int burn_disc_close_track_dvd_plus_r(struct burn_write_opts *o, int tnum, int is_last_track)
Definition: write.c:1738
static int burn_write_leadin_cdtext(struct burn_write_opts *o, struct burn_session *s, int flag)
Definition: write.c:930
int burn_subcode_length(int tracktype)
Definition: write.c:848
#define Libburn_bd_r_obS
Definition: write.c:88
int burn_disc_close_damaged(struct burn_write_opts *o, int flag)
Definition: write.c:3413
static int precheck_disc_has_cdtext(struct burn_disc *disc, int flag)
Definition: write.c:1404
#define Libburn_bd_streamed_obS
Definition: write.c:92
int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s, int tnum, int flag)
Definition: write.c:2824
int burn_stdio_open_write(struct burn_drive *d, off_t start_byte, int sector_size, int flag)
Definition: write.c:2520
int burn_stdio_write(int fd, char *buf, int count, struct burn_drive *d, int flag)
Definition: write.c:2604
static int type_to_ctrl(int mode)
Definition: write.c:99
int burn_write_track(struct burn_write_opts *o, struct burn_session *s, int tnum)
Definition: write.c:1107
int burn_disc_init_track_status(struct burn_write_opts *o, struct burn_session *s, struct burn_track *t, int tnum, int sectors)
Definition: write.c:1076
int burn_disc_close_track_dvd_minus_r(struct burn_write_opts *o, int tnum)
Definition: write.c:1682
void type_to_form(int mode, unsigned char *ctladr, int *form)
Definition: write.c:126
int burn_stdio_mmc_dummy_write(struct burn_drive *d, int start, struct buffer *buf)
Definition: write.c:2696
int burn_disc_setup_dvd_minus_r(struct burn_write_opts *o, struct burn_disc *disc)
Definition: write.c:2279
int burn_write_session(struct burn_write_opts *o, struct burn_session *s)
Definition: write.c:1050
int burn_random_access_write(struct burn_drive *d, off_t byte_address, char *data, off_t data_count, int flag)
Definition: write.c:3255
int burn_disc_setup_dvd_minus_rw(struct burn_write_opts *o, struct burn_disc *disc)
Definition: write.c:2225
static int add_catalog_cue(struct cue_sheet *sheet, unsigned char catalog[13])
Definition: write.c:420
int burn_disc_setup_dvd_plus_r(struct burn_write_opts *o, struct burn_disc *disc)
Definition: write.c:2292
static int precheck_write_is_audio(struct burn_disc *disc, int flag)
Definition: write.c:1390
int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o, struct burn_session *s, int tnum)
Definition: write.c:1557
int burn_write_flush(struct burn_write_opts *o, struct burn_track *track)
Definition: write.c:195
int burn_write_leadout(struct burn_write_opts *o, int first, unsigned char control, int mode)
Definition: write.c:884
int burn_disc_open_track_dvd_plus_r(struct burn_write_opts *o, struct burn_session *s, int tnum)
Definition: write.c:1618
int burn_disc_setup_dvd_plus_rw(struct burn_write_opts *o, struct burn_disc *disc)
Definition: write.c:2200
static int new_cue(struct cue_sheet *sheet, int number, int flag)
Definition: write.c:374
int burn_disc_close_session_dvd_plus_rw(struct burn_write_opts *o, struct burn_session *s)
Definition: write.c:2022
int burn_stdio_mmc_write(struct burn_drive *d, int start, struct buffer *buf)
Definition: write.c:2653
int burn_stdio_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
Definition: write.c:2907
struct cue_sheet * burn_create_toc_entries(struct burn_write_opts *o, struct burn_session *session, int nwa)
Definition: write.c:468
#define Libburn_stdio_write_retrieS
Definition: write.c:96
int burn_stdio_read_source(struct burn_source *source, char *buf, int bufsize, struct burn_write_opts *o, int flag)
Definition: write.c:2584