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)  

file.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 
14 #include <stdlib.h>
15 #include <sys/types.h>
16 #include <stdio.h>
17 #include <errno.h>
18 #include <string.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <time.h>
23 #include <pthread.h>
24 
25 /* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
26 #ifndef O_BINARY
27 #define O_BINARY 0
28 #endif
29 
30 #include "source.h"
31 #include "libburn.h"
32 #include "file.h"
33 #include "async.h"
34 #include "init.h"
35 #include "util.h"
36 
37 #include "libdax_msgs.h"
38 extern struct libdax_msgs *libdax_messenger;
39 
40 
41 /* main channel data can be padded on read, but 0 padding the subs will make
42 an unreadable disc */
43 
44 
45 /* This is a generic OS oriented function wrapper which compensates
46  shortcomings of read() in respect to a guaranteed amount of return data.
47  See man 2 read , paragraph "RETURN VALUE".
48 */
49 static int read_full_buffer(int fd, unsigned char *buffer, int size)
50 {
51  int ret,summed_ret = 0;
52 
53  /* make safe against partial buffer returns */
54  while (1) {
55  ret = read(fd, buffer + summed_ret, size - summed_ret);
56  if (ret <= 0)
57  break;
58  summed_ret += ret;
59  if (summed_ret >= size)
60  break;
61  }
62  if (ret < 0) /* error encountered. abort immediately */
63  return ret;
64  return summed_ret;
65 }
66 
67 
68 static int file_read(struct burn_source *source,
69  unsigned char *buffer,
70  int size)
71 {
72  struct burn_source_file *fs = source->data;
73 
74  return read_full_buffer(fs->datafd, buffer, size);
75 }
76 
77 static int file_read_sub(struct burn_source *source,
78  unsigned char *buffer,
79  int size)
80 {
81  struct burn_source_file *fs = source->data;
82 
83  return read_full_buffer(fs->subfd, buffer, size);
84 }
85 
86 static void file_free(struct burn_source *source)
87 {
88  struct burn_source_file *fs = source->data;
89 
90  close(fs->datafd);
91  if (source->read_sub)
92  close(fs->subfd);
93  free(fs);
94 }
95 
96 static off_t file_size(struct burn_source *source)
97 {
98  struct stat buf;
99  struct burn_source_file *fs = source->data;
100 
101  if (fs->fixed_size > 0)
102  return fs->fixed_size;
103  if (fstat(fs->datafd, &buf) != 0)
104  return (off_t) 0;
105  if ((buf.st_mode & S_IFMT) != S_IFREG)
106  return (off_t) 0;
107  return (off_t) buf.st_size;
108 }
109 
110 
111 /* ts A70125 */
112 static int file_set_size(struct burn_source *source, off_t size)
113 {
114  struct burn_source_file *fs = source->data;
115 
116  fs->fixed_size = size;
117  return 1;
118 }
119 
120 
121 struct burn_source *burn_file_source_new(const char *path, const char *subpath)
122 {
123  struct burn_source_file *fs;
124  struct burn_source *src;
125  int fd1 = -1, fd2 = -1;
126 
127  if (!path)
128  return NULL;
129  fd1 = open(path, O_RDONLY | O_BINARY);
130  if (fd1 == -1)
131  return NULL;
132  if (subpath != NULL) {
133  fd2 = open(subpath, O_RDONLY | O_BINARY);
134  if (fd2 == -1) {
135  close(fd1);
136  return NULL;
137  }
138  }
139  fs = calloc(1, sizeof(struct burn_source_file));
140 
141  /* ts A70825 */
142  if (fs == NULL) {
143 failure:;
144  close(fd1);
145  if (fd2 >= 0)
146  close(fd2);
147  return NULL;
148  }
149 
150  fs->datafd = fd1;
151  fs->subfd = fd2;
152 
153  /* ts A70125 */
154  fs->fixed_size = 0;
155 
156  src = burn_source_new();
157 
158  /* ts A70825 */
159  if (src == NULL) {
160  free((char *) fs);
161  goto failure;
162  }
163 
164  src->read = file_read;
165  if (subpath)
166  src->read_sub = file_read_sub;
167 
168  src->get_size = file_size;
169  src->set_size = file_set_size;
170  src->free_data = file_free;
171  src->data = fs;
172  return src;
173 }
174 
175 
176 /* ts A70126 : removed class burn_source_fd in favor of burn_source_file */
177 
178 struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size)
179 {
180  struct burn_source_file *fs;
181  struct burn_source *src;
182 
183  if (datafd == -1)
184  return NULL;
185  fs = burn_alloc_mem(sizeof(struct burn_source_file), 1, 0);
186  if (fs == NULL) /* ts A70825 */
187  return NULL;
188  fs->datafd = datafd;
189  fs->subfd = subfd;
190  fs->fixed_size = size;
191 
192  src = burn_source_new();
193 
194  /* ts A70825 */
195  if (src == NULL) {
196  free((char *) fs);
197  return NULL;
198  }
199 
200  src->read = file_read;
201  if(subfd != -1)
202  src->read_sub = file_read_sub;
203  src->get_size = file_size;
204  src->set_size = file_set_size;
205  src->free_data = file_free;
206  src->data = fs;
207  return src;
208 }
209 
210 
211 /* ts A71003 */
212 /* ------------------------------ fifo --------------------------- */
213 
214 /* The fifo mechanism consists of a burn_source proxy which is here,
215  a thread management team which is located in async.c,
216  and a synchronous shoveller which is here.
217 */
218 
219 static int fifo_sleep(int flag)
220 {
221  static unsigned long sleeptime = 50000; /* 50 ms */
222 
223  usleep(sleeptime);
224  return 0;
225 }
226 
227 
228 static int fifo_read(struct burn_source *source,
229  unsigned char *buffer,
230  int size)
231 {
232  struct burn_source_fifo *fs = source->data;
233  int ret, todo, rpos, bufsize, diff, counted = 0;
234 
235  if (fs->end_of_consumption) {
236  /* ??? msg: reading has been ended already */;
237  return 0;
238  }
239  if (fs->is_started == 0) {
240  ret = burn_fifo_start(source, 0);
241  if (ret <= 0) {
242  libdax_msgs_submit(libdax_messenger, -1, 0x00020152,
244  "Cannot start fifo thread", 0, 0);
245  fs->end_of_consumption = 1;
246  return -1;
247  }
248  fs->is_started = 1;
249  }
250  if (size == 0)
251  return 0;
252 
253  /* Reading from the ring buffer */
254 
255  /* This needs no mutex because each volatile variable has one thread
256  which may write and the other which only reads and is aware of
257  volatility.
258  The feeder of the ringbuffer is in burn_fifo_source_shoveller().
259  */
260  todo = size;
261  bufsize = fs->chunksize * fs->chunks;
262  while (todo > 0) {
263  /* readpos is not volatile here , writepos is volatile */
264  rpos = fs->buf_readpos;
265  while (rpos == fs->buf_writepos) {
266  if (fs->end_of_input)
267  break;
268  if (fs->input_error) {
269  if (todo < size) /* deliver partial buffer */
270  break;
271  fs->end_of_consumption = 1;
273  0x00020154,
275  "Forwarded input error ends output", 0, 0);
276  return -1;
277  }
278  if (!counted)
279  fs->empty_counter++;
280  counted = 1;
281  fifo_sleep(0);
282  }
283  diff = fs->buf_writepos - rpos; /* read volatile only once */
284  if (diff == 0)
285  break;
286  if (diff > 0)
287  /* diff bytes are available */;
288  else
289  /* at least (bufsize - rpos) bytes are available */
290  diff = bufsize - rpos;
291  if (diff > todo)
292  diff = todo;
293  memcpy(buffer, fs->buf+(size-todo)+rpos, diff);
294  fs->buf_readpos += diff;
295  if (fs->buf_readpos >= bufsize)
296  fs->buf_readpos = 0;
297  todo -= diff;
298  }
299  if (size - todo <= 0)
300  fs->end_of_consumption = 1;
301  else
302  fs->out_counter += size - todo;
303 
304 /*
305  fprintf(stderr,
306  "libburn_EXPERIMENTAL: read= %d , pos= %d , out_count= %.f\n",
307  (size - todo), fs->buf_readpos, (double) fs->out_counter);
308 */
309 
310  fs->get_counter++;
311  return (size - todo);
312 }
313 
314 
315 static off_t fifo_get_size(struct burn_source *source)
316 {
317  struct burn_source_fifo *fs = source->data;
318 
319  return fs->inp->get_size(fs->inp);
320 }
321 
322 
323 static int fifo_set_size(struct burn_source *source, off_t size)
324 {
325  struct burn_source_fifo *fs = source->data;
326 
327  return fs->inp->set_size(fs->inp, size);
328 }
329 
330 
331 static void fifo_free(struct burn_source *source)
332 {
333  struct burn_source_fifo *fs = source->data;
334  int wait_count;
335  static int wait_max = 30, wait_usleep = 100000;
336 
337  burn_fifo_abort(fs, 0);
338  for (wait_count = 0; wait_count <= wait_max; wait_count++) {
339  if (fs->thread_is_valid <= 0)
340  break;
341  if (wait_count < wait_max)
342  usleep(wait_usleep);
343  }
344  if (wait_count > wait_max) {
345  /* The shoveler thread might still be active. If so, it would
346  use invalid or inappropriate memory if the fifo would be
347  disposed now. A memory and resource leak is the better
348  option here.
349  */
351  0x000201ab,
354  "Leaving burn_source_fifo object undisposed because it is possibly stuck but alive",
355  0, 0);
356  return;
357  }
358 
359  if (fs->inp != NULL)
360  burn_source_free(fs->inp);
361 
362  if (fs->buf != NULL)
364  ((size_t) fs->chunksize) * (size_t) fs->chunks, 0);
365  free((char *) fs);
366 }
367 
368 
369 int burn_fifo_source_shoveller(struct burn_source *source, int flag)
370 {
371  struct burn_source_fifo *fs = source->data;
372  int ret, bufsize, diff, wpos, rpos, trans_end, free_bytes, fill;
373  int counted;
374  char *bufpt;
375  pthread_t thread_handle_storage;
376 
377  fs->thread_handle= &thread_handle_storage;
378  *((pthread_t *) fs->thread_handle)= pthread_self();
379  fs->thread_pid = getpid();
380  fs->thread_is_valid = 1;
381 
382  /* Lock was obtained by async.c:add_worker() */
384 
385  bufsize = fs->chunksize * fs->chunks;
386  while (!fs->end_of_consumption) {
387  if (fs->do_abort)
388  goto emergency_exit;
389 
390  /* wait for enough buffer space available */
391  wpos = fs->buf_writepos;
392  counted = 0;
393  while (1) {
394  if (fs->do_abort)
395  goto emergency_exit;
396  rpos = fs->buf_readpos;
397  diff = rpos - wpos;
398  trans_end = 0;
399  if (diff == 0)
400  free_bytes = bufsize - 1;
401  else if (diff > 0)
402  free_bytes = diff - 1;
403  else {
404  free_bytes = (bufsize - wpos) + rpos - 1;
405  if (bufsize - wpos < fs->inp_read_size)
406  trans_end = 1;
407  }
408  if (free_bytes >= fs->inp_read_size)
409  break;
410  if (!counted)
411  fs->full_counter++;
412  counted = 1;
413  fifo_sleep(0);
414  }
415 
416  fill = bufsize - free_bytes - 1;
417  if (fill < fs->total_min_fill)
418  fs->total_min_fill = fill;
419  if (fill < fs->interval_min_fill)
420  fs->interval_min_fill = fill;
421 
422  /* prepare the receiving memory */
423  bufpt = fs->buf + wpos;
424  if (trans_end) {
425  bufpt = burn_os_alloc_buffer(
426  (size_t) fs->inp_read_size, 0);
427  if (bufpt == NULL) {
429  0x00000003,
431  "Out of virtual memory", 0, 0);
432  fs->input_error = ENOMEM;
433  break;
434  }
435  }
436 
437  /* Obtain next chunk */
438  if (fs->do_abort)
439  goto emergency_exit;
440  if (fs->inp->read != NULL)
441  ret = fs->inp->read(fs->inp,
442  (unsigned char *) bufpt, fs->inp_read_size);
443  else
444  ret = fs->inp->read_xt( fs->inp,
445  (unsigned char *) bufpt, fs->inp_read_size);
446  if (ret == 0) {
447 
448  /* >>> ??? ts B00326 */
449  /* >>> report EOF of fifo input and fs->in_counter */;
450 
451  break; /* EOF */
452  } else if (ret < 0) {
453  libdax_msgs_submit(libdax_messenger, -1, 0x00020153,
455  "Read error on fifo input", errno, 0);
456  fs->input_error = errno;
457  if(errno == 0)
458  fs->input_error = EIO;
459  break;
460  }
461  fs->in_counter += ret;
462  fs->put_counter++;
463 
464  /* activate read chunk */
465  if (fs->do_abort)
466  goto emergency_exit;
467  if (ret > fs->inp_read_size)
468  /* beware of ill custom burn_source */
469  ret = fs->inp_read_size;
470  if (trans_end) {
471  /* copy to end of buffer */
472  memcpy(fs->buf + wpos, bufpt, bufsize - wpos);
473  /* copy to start of buffer */
474  memcpy(fs->buf, bufpt + (bufsize - wpos),
475  fs->inp_read_size - (bufsize - wpos));
476  burn_os_free_buffer(bufpt, (size_t) fs->inp_read_size,
477  0);
478  if (ret >= bufsize - wpos)
479  fs->buf_writepos = ret - (bufsize - wpos);
480  else
481  fs->buf_writepos += ret;
482  } else if (fs->buf_writepos + ret == bufsize)
483  fs->buf_writepos = 0;
484  else
485  fs->buf_writepos += ret;
486 
487 /*
488  fprintf(stderr, "[%2.2d%%] ",
489  (int) (100.0 - 100.0 * ((double) free_bytes) /
490  (double) bufsize));
491  fprintf(stderr,
492  "libburn_EXPERIMENTAL: writepos= %d ,in_count = %.f\n",
493  fs->buf_writepos, (double) fs->in_counter);
494 */
495  }
496  if (!fs->end_of_consumption)
497  fs->end_of_input = 1;
498 
499  /* wait for end of reading by consumer */;
500  while (fs->buf_readpos != fs->buf_writepos && !fs->end_of_consumption) {
501  if (fs->do_abort)
502  goto emergency_exit;
503  fifo_sleep(0);
504  }
505 
506  /* destroy ring buffer */;
507  if (!fs->end_of_consumption)
508  fs->end_of_consumption = 2; /* Claim stop of consumption */
509 
510  /* This is not prone to race conditions because either the consumer
511  indicated hangup by fs->end_of_consumption = 1 or the consumer set
512  fs->buf_readpos to a value indicating the buffer is empty.
513  So in both cases the consumer is aware that reading is futile
514  or even fatal.
515  */
516  if(fs->buf != NULL)
518  ((size_t) fs->chunksize) * (size_t) fs->chunks, 0);
519  fs->buf = NULL;
520 
521 emergency_exit:;
523  fs->thread_handle= NULL;
524  fs->thread_is_valid = 0;
526  return (fs->input_error == 0);
527 }
528 
529 
530 int burn_fifo_cancel(struct burn_source *source)
531 {
532  int ret;
533  struct burn_source_fifo *fs = source->data;
534 
535  ret = burn_source_cancel(fs->inp);
536  return ret;
537 }
538 
539 /*
540  @param flag bit0= allow larger read chunks
541 */
543  int chunksize, int chunks, int flag)
544 {
545  struct burn_source_fifo *fs;
546  struct burn_source *src;
547 
548  if (((double) chunksize) * ((double) chunks) > 1024.0*1024.0*1024.0) {
549  libdax_msgs_submit(libdax_messenger, -1, 0x00020155,
551  "Desired fifo buffer too large (> 1GB)", 0, 0);
552  return NULL;
553  }
554  if (chunksize < 1 || chunks < 2) {
555  libdax_msgs_submit(libdax_messenger, -1, 0x00020156,
557  "Desired fifo buffer too small", 0, 0);
558  return NULL;
559  }
560  fs = burn_alloc_mem(sizeof(struct burn_source_fifo), 1, 0);
561  if (fs == NULL)
562  return NULL;
563  fs->is_started = 0;
564  fs->thread_handle = NULL;
565  fs->thread_pid = 0;
566  fs->thread_is_valid = 0;
567  fs->do_abort = 0;
568  fs->inp = NULL; /* set later */
569  if (flag & 1)
570  fs->inp_read_size = 32 * 1024;
571  else
572  fs->inp_read_size = chunksize;
573  fs->chunksize = chunksize;
574  fs->chunks = chunks;
575  fs->buf = NULL;
576  fs->buf_writepos = fs->buf_readpos = 0;
577  fs->end_of_input = 0;
578  fs->input_error = 0;
579  fs->end_of_consumption = 0;
580  fs->in_counter = fs->out_counter = 0;
581  fs->total_min_fill = fs->interval_min_fill = 0;
582  fs->put_counter = fs->get_counter = 0;
583  fs->empty_counter = fs->full_counter = 0;
584 
585  src = burn_source_new();
586  if (src == NULL) {
587  free((char *) fs);
588  return NULL;
589  }
590  src->read = NULL;
591  src->read_sub = NULL;
592  src->get_size = fifo_get_size;
593  src->set_size = fifo_set_size;
594  src->free_data = fifo_free;
595  src->data = fs;
596  src->version= 1;
597  src->read_xt = fifo_read;
598  src->cancel= burn_fifo_cancel;
599  fs->inp = inp;
600  inp->refcount++; /* make sure inp lives longer than src */
601 
602  return src;
603 }
604 
605 
606 /* ts A71003 : API */
608  int *size, int *free_bytes, char **status_text)
609 {
610  struct burn_source_fifo *fs = source->data;
611  int ret = 0, diff, wpos, rpos;
612  static char *(states[8]) = {
613  "standby", "active", "ending", "failing",
614  "unused", "abandoned", "ended", "aborted"};
615 
616  *status_text = NULL;
617  *size = 0;
618 
619  if (source->free_data != fifo_free) {
620  libdax_msgs_submit(libdax_messenger, -1, 0x00020157,
622  "burn_source is not a fifo object", 0, 0);
623  return -1;
624  }
625  *size = fs->chunksize * fs->chunks;
626  rpos = fs->buf_readpos;
627  wpos = fs->buf_writepos;
628  diff = rpos - wpos;
629  if (diff == 0)
630  *free_bytes = *size - 1;
631  else if (diff > 0)
632  *free_bytes = diff - 1;
633  else
634  *free_bytes = (*size - wpos) + rpos - 1;
635  ret = 0;
636  if (fs->end_of_consumption > 0)
637  ret |= 4;
638  if (fs->input_error)
639  ret |= 3;
640  else if (fs->end_of_input)
641  ret |= 2;
642  else if(fs->buf != NULL)
643  ret |= 1;
644  *status_text = states[ret];
645  return ret;
646 }
647 
648 
649 /* ts A91125 : API */
652  int *put_counter, int *get_counter,
653  int *empty_counter, int *full_counter)
654 {
655  struct burn_source_fifo *fs = source->data;
656 
659  *put_counter = fs->put_counter;
660  *get_counter = fs->get_counter;
662  *full_counter = fs->full_counter;
663 }
664 
665 
666 /* ts A91125 : API */
668  int *interval_min_fill)
669 {
670  struct burn_source_fifo *fs = source->data;
671  int size, free_bytes, ret;
672  char *status_text;
673 
675  ret = burn_fifo_inquire_status(source,
676  &size, &free_bytes, &status_text);
677  if (ret < 0)
678  return;
679  fs->interval_min_fill = size - free_bytes - 1;
680 }
681 
682 
683 /* @param flag bit0= do not copy to buf but only wait until the fifo has read
684  bufsize or input ended.
685  The same happens if buf is NULL.
686  bit1= fill to max fifo size
687 */
688 int burn_fifo_fill_data(struct burn_source *source, char *buf, int bufsize,
689  int flag)
690 {
691  int size, free_bytes, ret, wait_count= 0;
692  char *status_text;
693  struct burn_source_fifo *fs = source->data;
694 
695  if (buf == NULL)
696  flag |= 1;
697 
698  /* Eventually start fifo thread by reading 0 bytes */
699  ret = fifo_read(source, (unsigned char *) NULL, 0);
700  if (ret<0)
701  {ret = 0; goto ex;}
702 
703  /* wait for at least bufsize bytes being ready */
704  while (1) {
705  ret= burn_fifo_inquire_status(source,
706  &size, &free_bytes, &status_text);
707  if (flag & 2) {
708  bufsize = size - (size % fs->inp_read_size) -
709  fs->inp_read_size;
710  if (bufsize <= 0)
711  {ret = 0; goto ex;}
712  }
713  if (size - fs->inp_read_size < bufsize) {
714  if (flag & 1) {
715  bufsize = size - (size % fs->inp_read_size) -
716  fs->inp_read_size;
717  if (bufsize <= 0)
718  {ret = 0; goto ex;}
719  } else {
721  0x0002015c, LIBDAX_MSGS_SEV_FAILURE,
723  "Fifo size too small for desired peek buffer",
724  0, 0);
725  {ret = -1; goto ex;}
726  }
727  }
728  if (fs->out_counter > 0 || (ret & 4) || fs->buf == NULL) {
729  libdax_msgs_submit(libdax_messenger, -1, 0x0002015e,
731  "Fifo is already under consumption when peeking is desired",
732  0, 0);
733  {ret = -1; goto ex;}
734  }
735  if(size - free_bytes >= bufsize) {
736 
737  /* <<<
738  fprintf(stderr,
739  "libburn_DEBUG: after waiting cycle %d : fifo %s , %d bytes\n",
740  wait_count, status_text, size - free_bytes);
741  */
742  if(!(flag & 1))
743  memcpy(buf, fs->buf, bufsize);
744  {ret = 1; goto ex;}
745  }
746 
747  if (ret & 2) {
748  /* input has ended, not enough data arrived */
749  if (flag & 1)
750  {ret = 0; goto ex;}
751  libdax_msgs_submit(libdax_messenger, -1, 0x0002015d,
753  "Fifo input ended short of desired peek buffer size",
754  0, 0);
755  {ret = 0; goto ex;}
756  }
757 
758  if (free_bytes < fs->inp_read_size) {
759  /* Usable fifo size filled, not enough data arrived */
760  if (flag & 1)
761  {ret = 0; goto ex;}
762  libdax_msgs_submit(libdax_messenger, -1, 0x00020174,
764  "Fifo alignment does not allow desired read size",
765  0, 0);
766  {ret = 0; goto ex;}
767  }
768 
769  usleep(100000);
770  wait_count++;
771 
772  /* <<<
773  if(wait_count%10==0)
774  fprintf(stderr,
775  "libburn_DEBUG: waiting cycle %d : fifo %s , %d bytes\n",
776  wait_count, status_text, size - free_bytes);
777  */
778 
779  }
780  ret = 0;
781 ex:;
783  return(ret);
784 }
785 
786 
787 /* ts A80713 : API */
788 int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
789  int flag)
790 {
791  return burn_fifo_fill_data(source, buf, bufsize, 0);
792 }
793 
794 
795 /* ts A91125 : API */
796 int burn_fifo_fill(struct burn_source *source, int bufsize, int flag)
797 {
798  return burn_fifo_fill_data(source, NULL, bufsize,
799  1 | ((flag & 1) << 1));
800 }
801 
802 
803 /* ----------------------------- Offset source ----------------------------- */
804 /* ts B00922 */
805 
806 static void offst_free(struct burn_source *source);
807 
808 /* @param flag bit0 = do not check for burn_source_offst, do not return NULL
809 */
810 static struct burn_source_offst *offst_auth(struct burn_source *source,
811  int flag)
812 {
813  if (source->free_data != offst_free && !(flag & 1)) {
814  libdax_msgs_submit(libdax_messenger, -1, 0x0002017a,
816  "Expected offset source object as parameter",
817  0, 0);
818  return NULL;
819  }
820  return (struct burn_source_offst *) source->data;
821 }
822 
823 static off_t offst_get_size(struct burn_source *source)
824 {
825  struct burn_source_offst *fs;
826 
827  if ((fs = offst_auth(source, 0)) == NULL)
828  return (off_t) 0;
829  return fs->nominal_size;
830 }
831 
832 static int offst_set_size(struct burn_source *source, off_t size)
833 {
834  struct burn_source_offst *fs;
835 
836  if ((fs = offst_auth(source, 0)) == NULL)
837  return 0;
838 
839  fs->nominal_size = size;
840  if (fs->size <= 0 || fs->size_adjustable)
841  fs->size = size;
842  return 1;
843 }
844 
845 static void offst_free(struct burn_source *source)
846 {
847  struct burn_source_offst *fs;
848 
849  if ((fs = offst_auth(source, 0)) == NULL)
850  return;
851  if (fs->prev != NULL)
852  offst_auth(fs->prev, 1)->next = fs->next;
853  if (fs->next != NULL)
854  offst_auth(fs->next, 1)->prev = fs->prev;
855  if (fs->inp != NULL)
856  burn_source_free(fs->inp); /* i.e. decrement refcount */
857  free(source->data);
858 }
859 
860 static int offst_read(struct burn_source *source, unsigned char *buffer,
861  int size)
862 {
863  int ret, to_read, todo;
864  struct burn_source_offst *fs;
865 
866  if ((fs = offst_auth(source, 0)) == NULL)
867  return -1;
868 
869  /* Eventually skip bytes up to start position */;
870  if (!fs->running) {
871  if (fs->prev != NULL)
872  fs->pos = offst_auth(fs->prev, 1)->pos;
873  fs->running= 1;
874  }
875  if(fs->pos < fs->start) {
876  todo = fs->start - fs->pos;
877  while (todo > 0) {
878  to_read = todo;
879  if (to_read > size)
880  to_read = size;
881  ret = burn_source_read(fs->inp, buffer, to_read);
882  if (ret <= 0)
883  return ret;
884  todo -= ret;
885  fs->pos += ret;
886  }
887  }
888 
889  /* Produce EOF if source size is exhausted.
890  burn_source delivers no incomplete sector buffers.
891  */
892  if (fs->pos + size > fs->start + fs->size)
893  return 0;
894 
895  /* Read payload */
896  ret = burn_source_read(fs->inp, buffer, size);
897  if (ret > 0)
898  fs->pos += ret;
899  return ret;
900 }
901 
902 static int offst_cancel(struct burn_source *source)
903 {
904  int ret;
905  struct burn_source_offst *fs;
906 
907  if ((fs = offst_auth(source, 0)) == NULL)
908  return -1;
909  ret = burn_source_cancel(fs->inp);
910  return ret;
911 }
912 
914  struct burn_source *inp, struct burn_source *prev,
915  off_t start, off_t size, int flag)
916 {
917  struct burn_source *src;
918  struct burn_source_offst *fs, *prev_fs = NULL;
919 
920  if (prev != NULL)
921  if ((prev_fs = offst_auth(prev, 0)) == NULL)
922  return NULL; /* Not type burn_source_offst */
923 
924  fs = calloc(1, sizeof(struct burn_source_offst));
925  if (fs == NULL)
926  return NULL;
927  src = burn_source_new();
928  if (src == NULL) {
929  free((char *) fs);
930  return NULL;
931  }
932  src->read = NULL;
933  src->read_sub = NULL;
934  src->get_size = offst_get_size;
935  src->set_size = offst_set_size;
936  src->free_data = offst_free;
937  src->data = fs;
938  src->version= 1;
939  src->read_xt = offst_read;
940  src->cancel= offst_cancel;
941  fs->inp = inp;
942  fs->prev = prev;
943  fs->next = NULL;
944  if (prev != NULL) {
945  if (prev_fs->next != NULL) {
946  offst_auth(prev_fs->next, 1)->prev = src;
947  fs->next = prev_fs->next;
948  }
949  prev_fs->next = src;
950  if (prev_fs->start + prev_fs->size > start) {
951  libdax_msgs_submit(libdax_messenger, -1, 0x00020179,
953  "Offset source start address is before end of previous source",
954  0, 0);
955  return NULL;
956  }
957  }
958  fs->start = start;
959  fs->size = size;
960  fs->size_adjustable = !(flag & 1);
961  fs->nominal_size = size;
962  fs->running = 0;
963  fs->pos = 0;
964  inp->refcount++; /* make sure inp lives longer than src */
965 
966  return src;
967 }
968 
969 
970 /* -------------------- WAVE file extractor ------------------- */
971 
972 
973 /* ts B30522 */
974 /* API
975  @param flag Bitfield for control purposes:
976  bit0= Report about progress by UPDATE message
977  bit3= Enable DAP : "flaw obscuring mechanisms like
978  audio data mute and interpolate"
979 
980 */
982  int start_sector, int sector_count,
983  char *target_path, int flag)
984 {
985  int fd = -1, ret, todo, sector_no, val, min, sec, fr;
986  int sectors_done= 0;
987  off_t data_size, data_count = 0;
988  time_t last_pacified = 0, now;
989  char *msg = NULL, *buf = NULL;
990 
991  BURN_ALLOC_MEM(msg, char, 4096);
992  BURN_ALLOC_MEM(buf, char, 24 * 2352);
993 
994  fd = open(target_path, O_WRONLY | O_CREAT | O_BINARY,
995  S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
996  if (fd == -1) {
997  sprintf(msg, "Cannot open disk file for writing: %.4000s",
998  target_path);
999  libdax_msgs_submit(libdax_messenger, -1, 0x000201a1,
1001  msg, errno, 0);
1002  ret = 0; goto ex;
1003  }
1004 
1005  /* WAV header */
1006  strcpy(buf, "RIFF");
1007  val = 4 + 8 + 16 + 8 + sector_count * 2352; /* ChunkSize */
1008  burn_int_to_lsb(val, buf + 4);
1009  strcpy(buf + 8, "WAVE");
1010  strcpy(buf + 12, "fmt ");
1011  burn_int_to_lsb(16, buf + 16); /* Subchunk1Size */
1012  buf[20] = 1; /* AudioFormat */
1013  buf[21] = 0;
1014  buf[22] = 2; /* NumChannels */
1015  buf[23] = 0;
1016  burn_int_to_lsb(44100, buf + 24); /* SampleRate */
1017  burn_int_to_lsb(176400, buf + 28); /* ByteRate */
1018  buf[32] = 4; /* BlockAlign */
1019  buf[33] = 0;
1020  buf[34] = 16; /* BitsPerSample */
1021  buf[35] = 0;
1022  strcpy(buf + 36, "data");
1023  burn_int_to_lsb(sector_count * 2352, buf + 40); /* Subchunk2Size */
1024 
1025  ret = write(fd, buf, 44);
1026  if (ret == -1)
1027  goto write_error;
1028 
1029  /* Audio data */
1030  todo = sector_count;
1031  sector_no = start_sector;
1032  while (todo > 0) {
1033  if (todo > 24)
1034  data_size = 24 * 2352;
1035  else
1036  data_size = todo * 2352;
1037  ret = burn_read_audio(drive, sector_no, buf, data_size,
1038  &data_count, flag & 8);
1039  if (ret <= 0) {
1040  sprintf(msg, "Failure to read audio sectors");
1041  libdax_msgs_submit(libdax_messenger, -1, 0x000201a4,
1043  msg, 0, 0);
1044  goto ex;
1045  }
1046  ret = write(fd, buf, data_count);
1047  if (ret == -1) {
1048 write_error:;
1049  sprintf(msg,
1050  "Error while writing to disk file: %.4000s",
1051  target_path);
1052  libdax_msgs_submit(libdax_messenger, -1, 0x000201a2,
1055  msg, errno, 0);
1056  ret = 0; goto ex;
1057  }
1058  todo -= data_count / 2352;
1059  sectors_done += data_count / 2352;
1060  sector_no += data_count / 2352;
1061  if ((flag & 1) && (now = time(NULL)) - last_pacified >= 1) {
1062  last_pacified = now;
1063  burn_lba_to_msf(sectors_done, &min, &sec, &fr);
1064  sprintf(msg,
1065  "Minutes:seconds of audio data read: %2d:%2.2d (%6.2f MB)",
1066  min, sec,
1067  ((double) sectors_done) * 2352.0 / 1048576.0);
1068  libdax_msgs_submit(libdax_messenger, -1, 0x000201a3,
1071  msg, 0, 1);
1072  }
1073  }
1074  if ((flag & 1)) {
1075  burn_lba_to_msf(sectors_done, &min, &sec, &fr);
1076  sprintf(msg,
1077  "Minutes:seconds of audio data read: %2d:%2.2d (%6.2f MB)",
1078  min, sec, ((double) sectors_done) * 2352.0 / 1048576.0);
1079  libdax_msgs_submit(libdax_messenger, -1, 0x000201a3,
1082  msg, 0, 0);
1083  }
1084  ret = 1;
1085 ex:;
1086  BURN_FREE_MEM(buf);
1087  BURN_FREE_MEM(msg);
1088  if (fd != -1)
1089  close(fd);
1090  return ret;
1091 }
1092 
1093 
1094 /* ts B30522 */
1095 /* API
1096  @param flag Bitfield for control purposes:
1097  bit0= Report about progress by UPDATE message
1098  bit3= Enable DAP : "flaw obscuring mechanisms like
1099  audio data mute and interpolate"
1100 */
1102  struct burn_track *track,
1103  char *target_path, int flag)
1104 {
1105  int ret;
1106  struct burn_toc_entry toc_entry;
1107 
1108  burn_track_get_entry(track, &toc_entry);
1109  if (!(toc_entry.extensions_valid & 1)) {
1110  /* Can only happen if burn_disc_cd_toc_extensions() is skipped
1111  in mmc_read_toc_al().
1112  */
1113  libdax_msgs_submit(libdax_messenger, -1, 0x00000004,
1115  "Internal libburn error: Outdated burn_toc_entry format encountered",
1116  errno, 0);
1117  return -1;
1118  }
1119  ret = burn_drive_extract_audio(drive, toc_entry.start_lba,
1120  toc_entry.track_blocks,
1121  target_path, flag & (1 | 8));
1122  return ret;
1123 }
1124 
int burn_fifo_abort(struct burn_source_fifo *fs, int flag)
Definition: async.c:795
int burn_fifo_start(struct burn_source *source, int flag)
Definition: async.c:770
int burn_async_manage_lock(int mode)
Definition: async.c:128
#define BURN_ASYNC_LOCK_OBTAIN
Definition: async.h:24
#define BURN_ASYNC_LOCK_RELEASE
Definition: async.h:23
static struct burn_source_offst * offst_auth(struct burn_source *source, int flag)
Definition: file.c:810
static void file_free(struct burn_source *source)
Definition: file.c:86
static int read_full_buffer(int fd, unsigned char *buffer, int size)
Definition: file.c:49
void burn_fifo_next_interval(struct burn_source *source, int *interval_min_fill)
Definition: file.c:667
static void fifo_free(struct burn_source *source)
Definition: file.c:331
static int offst_set_size(struct burn_source *source, off_t size)
Definition: file.c:832
int burn_fifo_inquire_status(struct burn_source *source, int *size, int *free_bytes, char **status_text)
Definition: file.c:607
struct burn_source * burn_offst_source_new(struct burn_source *inp, struct burn_source *prev, off_t start, off_t size, int flag)
Definition: file.c:913
struct burn_source * burn_fifo_source_new(struct burn_source *inp, int chunksize, int chunks, int flag)
Definition: file.c:542
struct burn_source * burn_fd_source_new(int datafd, int subfd, off_t size)
Definition: file.c:178
static int file_read_sub(struct burn_source *source, unsigned char *buffer, int size)
Definition: file.c:77
#define O_BINARY
Definition: file.c:27
int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize, int flag)
Definition: file.c:788
static int offst_read(struct burn_source *source, unsigned char *buffer, int size)
Definition: file.c:860
struct libdax_msgs * libdax_messenger
Definition: init.c:42
int burn_drive_extract_audio(struct burn_drive *drive, int start_sector, int sector_count, char *target_path, int flag)
Definition: file.c:981
void burn_fifo_get_statistics(struct burn_source *source, int *total_min_fill, int *interval_min_fill, int *put_counter, int *get_counter, int *empty_counter, int *full_counter)
Definition: file.c:650
int burn_fifo_fill_data(struct burn_source *source, char *buf, int bufsize, int flag)
Definition: file.c:688
static int offst_cancel(struct burn_source *source)
Definition: file.c:902
static int file_read(struct burn_source *source, unsigned char *buffer, int size)
Definition: file.c:68
static off_t offst_get_size(struct burn_source *source)
Definition: file.c:823
int burn_fifo_cancel(struct burn_source *source)
Definition: file.c:530
int burn_fifo_fill(struct burn_source *source, int bufsize, int flag)
Definition: file.c:796
int burn_fifo_source_shoveller(struct burn_source *source, int flag)
Definition: file.c:369
static int fifo_read(struct burn_source *source, unsigned char *buffer, int size)
Definition: file.c:228
static off_t file_size(struct burn_source *source)
Definition: file.c:96
struct burn_source * burn_file_source_new(const char *path, const char *subpath)
Definition: file.c:121
static int file_set_size(struct burn_source *source, off_t size)
Definition: file.c:112
static int fifo_set_size(struct burn_source *source, off_t size)
Definition: file.c:323
static int fifo_sleep(int flag)
Definition: file.c:219
static void offst_free(struct burn_source *source)
Definition: file.c:845
static off_t fifo_get_size(struct burn_source *source)
Definition: file.c:315
int burn_drive_extract_audio_track(struct burn_drive *drive, struct burn_track *track, char *target_path, int flag)
Definition: file.c:1101
void * burn_alloc_mem(size_t size, size_t count, int flag)
Definition: init.c:653
#define BURN_FREE_MEM(pt)
Definition: init.h:52
#define BURN_ALLOC_MEM(pt, typ, count)
Definition: init.h:40
void burn_int_to_lsb(int val, char *target)
Definition: util.c:341
void * burn_os_alloc_buffer(size_t amount, int flag)
Definition: sg-dummy.c:343
void burn_source_free(struct burn_source *s)
Definition: source.c:20
void burn_track_get_entry(struct burn_track *t, struct burn_toc_entry *entry)
Definition: structure.c:685
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
Definition: sg-dummy.c:352
void burn_lba_to_msf(int lba, int *m, int *s, int *f)
Definition: sector.c:767
int burn_read_audio(struct burn_drive *d, int sector_no, char data[], off_t data_size, off_t *data_count, int flag)
Definition: read.c:637
int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code, int severity, int priority, char *msg_text, int os_errno, int flag)
Definition: libdax_msgs.c:334
#define LIBDAX_MSGS_SEV_FATAL
Definition: libdax_msgs.h:217
#define LIBDAX_MSGS_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_SEV_UPDATE
Definition: libdax_msgs.h:142
#define LIBDAX_MSGS_SEV_FAILURE
Definition: libdax_msgs.h:205
int burn_source_cancel(struct burn_source *src)
Definition: source.c:56
struct burn_source * burn_source_new(void)
Definition: source.c:41
int burn_source_read(struct burn_source *src, unsigned char *buffer, int size)
Definition: source.c:67
int put_counter
Definition: file.h:66
off_t in_counter
Definition: file.h:61
int get_counter
Definition: file.h:67
int chunks
Definition: file.h:53
volatile int end_of_input
Definition: file.h:57
int chunksize
Definition: file.h:52
volatile int input_error
Definition: file.h:58
struct burn_source * inp
Definition: file.h:45
volatile int do_abort
Definition: file.h:42
int thread_is_valid
Definition: file.h:39
void * thread_handle
Definition: file.h:37
volatile int end_of_consumption
Definition: file.h:59
volatile int buf_readpos
Definition: file.h:56
int inp_read_size
Definition: file.h:46
volatile int buf_writepos
Definition: file.h:55
int is_started
Definition: file.h:35
int total_min_fill
Definition: file.h:64
int interval_min_fill
Definition: file.h:65
int empty_counter
Definition: file.h:68
char * buf
Definition: file.h:54
int thread_pid
Definition: file.h:38
int full_counter
Definition: file.h:69
off_t out_counter
Definition: file.h:62
off_t fixed_size
Definition: file.h:17
int datafd
Definition: file.h:15
struct burn_source * inp
Definition: file.h:84
int size_adjustable
Definition: file.h:88
int nominal_size
Definition: file.h:91
off_t start
Definition: file.h:86
struct burn_source * next
Definition: file.h:94
off_t pos
Definition: file.h:98
off_t size
Definition: file.h:87
struct burn_source * prev
Definition: file.h:85
int(* set_size)(struct burn_source *source, off_t size)
Definition: libburn.h:526
void(* free_data)(struct burn_source *)
Definition: libburn.h:533
off_t(* get_size)(struct burn_source *)
Definition: libburn.h:509
int(* read_sub)(struct burn_source *, unsigned char *buffer, int size)
Definition: libburn.h:502
int(* read)(struct burn_source *, unsigned char *buffer, int size)
Definition: libburn.h:493
int(* cancel)(struct burn_source *source)
Definition: libburn.h:581
int refcount
Definition: libburn.h:469
void * data
Definition: libburn.h:557
int(* read_xt)(struct burn_source *, unsigned char *buffer, int size)
Definition: libburn.h:575
int version
Definition: libburn.h:572
Definition: libburn.h:351
unsigned char extensions_valid
Definition: libburn.h:380
int start_lba
Definition: libburn.h:389
int track_blocks
Definition: libburn.h:391