"Fossies" - the Fresh Open Source Software Archive 
Member "xorriso-1.5.4/libburn/async.c" (30 Jan 2021, 20352 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "async.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
1.5.2_vs_1.5.4.
1 /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
2
3 /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
4 Copyright (c) 2006 - 2020 Thomas Schmitt <scdbackup@gmx.net>
5 Provided under GPL version 2 or later.
6 */
7
8 /* ts A71019 */
9
10 /* Standard measure should be: Threads are created detached.
11 According to the man pages they should then care for disposing themselves.
12
13 >>> ??? It is yet unclear why the threads vanish from the process list
14 even if joinable and even if never joined.
15
16 To be activated after release of libburn-0.4.0
17 */
18 #define Libburn_create_detached_threadS 1
19
20 /* Alternative : Threads are created joinable.
21 Threads get detached in remove_worker() and thus should dispose themselves.
22
23 #define Libburn_detach_done_workeR 1
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include "../config.h"
28 #endif
29
30 #include "libburn.h"
31 #include "transport.h"
32 #include "drive.h"
33 #include "write.h"
34 #include "options.h"
35 #include "file.h"
36 #include "async.h"
37 #include "init.h"
38 #include "back_hacks.h"
39
40 #include <pthread.h>
41 #include <sys/types.h>
42 #include <unistd.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <signal.h>
47
48 /*
49 #include <a ssert.h>
50 */
51 #include "libdax_msgs.h"
52 extern struct libdax_msgs *libdax_messenger;
53
54 /* ts A80714 : introduced type codes for the worker list */
55 #define Burnworker_type_scaN 0
56 #define Burnworker_type_erasE 1
57 #define Burnworker_type_formaT 2
58 #define Burnworker_type_writE 3
59 #define Burnworker_type_fifO 4
60
61 #define SCAN_GOING() (workers != NULL && \
62 workers->w_type == Burnworker_type_scaN)
63
64 typedef void *(*WorkerFunc) (void *);
65
66 struct scan_opts
67 {
68 struct burn_drive_info **drives;
69 unsigned int *n_drives;
70
71 int done;
72 };
73
74 struct erase_opts
75 {
76 struct burn_drive *drive;
77 int fast;
78 };
79
80 /* ts A61230 */
81 struct format_opts
82 {
83 struct burn_drive *drive;
84 off_t size;
85 int flag;
86 };
87
88 struct write_opts
89 {
90 struct burn_drive *drive;
91 struct burn_write_opts *opts;
92 struct burn_disc *disc;
93 };
94
95 struct fifo_opts
96 {
97 struct burn_source *source;
98 int flag;
99 };
100
101 union w_list_data
102 {
103 struct scan_opts scan;
104 struct erase_opts erase;
105 struct format_opts format;
106 struct write_opts write;
107 struct fifo_opts fifo;
108 };
109
110 struct w_list
111 {
112 /* ts A80714 */
113 int w_type; /* see above define Burnworker_type_* */
114
115 struct burn_drive *drive;
116 pthread_t thread;
117
118 struct w_list *next;
119
120 union w_list_data u;
121 };
122
123 static struct w_list *workers = NULL;
124
125 static void *fifo_worker_func(struct w_list *w);
126
127
128 int burn_async_manage_lock(int mode)
129 {
130 int ret;
131
132 static pthread_mutex_t access_lock;
133 static int mutex_initialized = 0;
134 static int mutex_locked = 0;
135
136 if (mode == BURN_ASYNC_LOCK_INIT) {
137 if (mutex_initialized)
138 return 2;
139 ret = pthread_mutex_init(&access_lock, NULL);
140 if (ret != 0)
141 return 0;
142 mutex_initialized = 1;
143 return 1;
144 }
145 if (!mutex_initialized)
146 return 0;
147 if (mode == BURN_ASYNC_LOCK_OBTAIN) {
148 ret = pthread_mutex_lock(&access_lock);
149 if (ret != 0)
150 return 0;
151 mutex_locked = 1;
152 } else if (mode == BURN_ASYNC_LOCK_RELEASE) {
153 if (!mutex_locked)
154 return 2;
155 ret = pthread_mutex_unlock(&access_lock);
156 if (ret != 0)
157 return 0;
158 mutex_locked = 0;
159 }
160 return 1;
161 }
162
163
164 static struct w_list *find_worker(struct burn_drive *d)
165 {
166 struct w_list *a;
167
168 for (a = workers; a; a = a->next)
169 if (a->drive == d)
170 return a;
171 return NULL;
172 }
173
174 static void add_worker(int w_type, struct burn_drive *d,
175 WorkerFunc f, union w_list_data *data)
176 {
177 struct w_list *a;
178 struct w_list *tmp;
179 pthread_attr_t *attr_pt = NULL;
180
181 #ifdef Libburn_create_detached_threadS
182 pthread_attr_t attr;
183 #endif
184
185 a = calloc(1, sizeof(struct w_list));
186 a->w_type = w_type;
187 a->drive = d;
188
189 a->u = *data;
190
191 burn_async_manage_lock(BURN_ASYNC_LOCK_INIT);
192
193 /* insert at front of the list */
194 a->next = workers;
195 tmp = workers;
196 workers = a;
197
198 if (d != NULL)
199 d->busy = BURN_DRIVE_SPAWNING;
200
201 #ifdef Libburn_create_detached_threadS
202
203 /* ts A71019 :
204 Trying to start the threads detached to get rid of the zombies
205 which do neither react on pthread_join() nor on pthread_detach().
206 */
207 pthread_attr_init(&attr);
208 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
209 attr_pt= &attr;
210
211 #endif /* Libburn_create_detached_threadS */
212
213 /* Worker specific locks are to be released early by the worker */
214 if (f == (WorkerFunc) fifo_worker_func)
215 burn_async_manage_lock(BURN_ASYNC_LOCK_OBTAIN);
216
217 if (pthread_create(&a->thread, attr_pt, f, a)) {
218 free(a);
219 workers = tmp;
220 return;
221 }
222 }
223
224
225 static void remove_worker(pthread_t th)
226 {
227 struct w_list *a, *l = NULL;
228
229 for (a = workers; a; l = a, a = a->next)
230 if (a->thread == th) {
231 if (l)
232 l->next = a->next;
233 else
234 workers = a->next;
235
236 #ifdef Libburn_detach_done_workeR
237 /* ts A71019 : burry dead puppy before forgetting it */
238 /* Alternative : threads get detached and thus should
239 dispose themselves.
240 */
241 pthread_detach(th);
242 /*
243 int ret;
244 char msg[80];
245
246 ret = pthread_detach(th);
247 sprintf(msg,
248 "remove_workers(): pid= %lu pthread_detach(%lu)= %d",
249 (unsigned long) getpid(), (unsigned long) th, ret);
250 libdax_msgs_submit(libdax_messenger, -1, 0x00020158,
251 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW,
252 msg, 0, 0);
253 */
254
255 #endif /* Libburn_detach_done_workeR */
256
257 free(a);
258 break;
259 }
260
261 /* ts A61006 */
262 /* a ssert(a != NULL);/ * wasn't found.. this should not be possible */
263 if (a == NULL)
264 libdax_msgs_submit(libdax_messenger, -1, 0x00020101,
265 LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
266 "remove_worker() cannot find given worker item", 0, 0);
267 }
268
269 static void *scan_worker_func(struct w_list *w)
270 {
271 int ret;
272
273 ret = burn_drive_scan_sync(w->u.scan.drives, w->u.scan.n_drives, 1);
274 if (ret <= 0)
275 w->u.scan.done = -1;
276 else
277 w->u.scan.done = 1;
278 return NULL;
279 }
280
281 static void reset_progress(struct burn_drive *d, int sessions, int tracks,
282 int indices, int sectors, int flag)
283 {
284 /* reset the progress indicator */
285 d->progress.session = 0;
286 d->progress.sessions = sessions;
287 d->progress.track = 0;
288 d->progress.tracks = tracks;
289 d->progress.index = 0;
290 d->progress.indices = indices;
291 d->progress.start_sector = 0;
292 d->progress.sectors = sectors;
293 d->progress.sector = 0;
294 }
295
296
297 int burn_drive_scan(struct burn_drive_info *drives[], unsigned int *n_drives)
298 {
299 union w_list_data o;
300 int ret = 0;
301
302 /* ts A61006 : moved up from burn_drive_scan_sync , former Assert */
303 if (!burn_running) {
304 libdax_msgs_submit(libdax_messenger, -1, 0x00020109,
305 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
306 "Library not running (on attempt to scan)", 0, 0);
307 *drives = NULL;
308 *n_drives = 0;
309 return -1;
310 }
311
312 /* cannot be anything working! */
313
314 /* ts A61006 */
315 /* a ssert(!(workers && workers->drive)); */
316 if (workers != NULL && workers->drive != NULL) {
317 drive_is_active:;
318 libdax_msgs_submit(libdax_messenger, -1, 0x00020102,
319 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
320 "A drive operation is still going on (want to scan)",
321 0, 0);
322 *drives = NULL;
323 *n_drives = 0;
324 return -1;
325 }
326
327 if (workers == NULL) {
328 /* start it */
329
330 /* ts A61007 : test moved up from burn_drive_scan_sync()
331 was burn_wait_all() */
332 /* ts A70907 : now demanding freed drives, not only released */
333 if (!burn_drives_are_clear(1))
334 goto drive_is_active;
335 *drives = NULL;
336 *n_drives = 0;
337
338 o.scan.drives = drives;
339 o.scan.n_drives = n_drives;
340 o.scan.done = 0;
341 add_worker(Burnworker_type_scaN, NULL,
342 (WorkerFunc) scan_worker_func, &o);
343 } else if (workers->u.scan.done) {
344 /* its done */
345 ret = workers->u.scan.done;
346 remove_worker(workers->thread);
347
348 /* ts A61006 */
349 /* a ssert(workers == NULL); */
350 if (workers != NULL) {
351 libdax_msgs_submit(libdax_messenger, -1, 0x00020101,
352 LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
353 "After scan a drive operation is still going on",
354 0, 0);
355 return -1;
356 }
357
358 } else {
359 /* still going */
360 }
361 return ret;
362 }
363
364 static void *erase_worker_func(struct w_list *w)
365 {
366
367 #define Libburn_protect_erase_threaD 1
368
369 #ifdef Libburn_protect_erase_threaD
370 sigset_t sigset, oldset;
371
372 /* Protect blank thread from being interrupted by external signals */
373 sigfillset(&sigset);
374 sigdelset(&sigset, SIGSEGV);
375 sigdelset(&sigset, SIGILL);
376 pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
377 #endif /* Libburn_protect_erase_threaD */
378
379 burn_disc_erase_sync(w->u.erase.drive, w->u.erase.fast);
380 remove_worker(pthread_self());
381
382 #ifdef Libburn_protect_erase_threaD
383 /* (just in case it would not end with all signals blocked) */
384 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
385 #endif /* Libburn_protect_erase_threaD */
386
387 return NULL;
388 }
389
390 void burn_disc_erase(struct burn_drive *drive, int fast)
391 {
392 union w_list_data o;
393
394 /* ts A61006 */
395 /* a ssert(drive); */
396 /* a ssert(!SCAN_GOING()); */
397 /* a ssert(!find_worker(drive)); */
398
399 if(drive == NULL) {
400 libdax_msgs_submit(libdax_messenger, -1,
401 0x00020104,
402 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
403 "NULL pointer caught in burn_disc_erase", 0, 0);
404 return;
405 }
406 if ((SCAN_GOING()) || find_worker(drive) != NULL) {
407 libdax_msgs_submit(libdax_messenger, drive->global_index,
408 0x00020102,
409 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
410 "A drive operation is still going on (want to erase)",
411 0, 0);
412 return;
413 }
414
415 reset_progress(drive, 1, 1, 1, 0x10000, 0);
416
417 /* A70103 : will be set to 0 by burn_disc_erase_sync() */
418 drive->cancel = 1;
419
420 /* ts A70103 moved up from burn_disc_erase_sync() */
421 /* ts A60825 : allow on parole to blank appendable CDs */
422 /* ts A70131 : allow blanking of overwritable DVD-RW (profile 0x13) */
423 /* ts A70216 : allow blanking of CD-RW or DVD-RW in any regular state
424 and of any kind of full media */
425 /* ts A70909 : the willingness to burn any BURN_DISC_FULL media is
426 inappropriate. One would rather need a -force option
427 Note: keep this in sync with mmc_read_disc_info() */
428 /* ts B10321 : Allowed role 5 to be blanked */
429 if ((drive->drive_role == 1 &&
430 drive->current_profile != 0x0a &&
431 drive->current_profile != 0x13 &&
432 drive->current_profile != 0x14 &&
433 drive->status != BURN_DISC_FULL)
434 ||
435 (drive->status != BURN_DISC_FULL &&
436 drive->status != BURN_DISC_APPENDABLE &&
437 drive->status != BURN_DISC_BLANK)
438 ||
439 (drive->drive_role != 1 && drive->drive_role != 5)
440 ) {
441 char msg[160];
442
443 sprintf(msg, "Drive and media state unsuitable for blanking. (role= %d , profile= 0x%x , status= %d)",
444 drive->drive_role,
445 (unsigned int) drive->current_profile,
446 drive->status);
447 libdax_msgs_submit(libdax_messenger, drive->global_index,
448 0x00020130,
449 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
450 msg, 0, 0);
451 return;
452 }
453
454 o.erase.drive = drive;
455 o.erase.fast = fast;
456 add_worker(Burnworker_type_erasE, drive,
457 (WorkerFunc) erase_worker_func, &o);
458 }
459
460
461 /* ts A61230 */
462 static void *format_worker_func(struct w_list *w)
463 {
464
465 #define Libburn_protect_format_threaD 1
466
467 #ifdef Libburn_protect_format_threaD
468 sigset_t sigset, oldset;
469
470 /* Protect format thread from being interrupted by external signals */
471 sigfillset(&sigset);
472 sigdelset(&sigset, SIGSEGV);
473 sigdelset(&sigset, SIGILL);
474 pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
475 #endif /* Libburn_protect_format_threaD */
476
477 burn_disc_format_sync(w->u.format.drive, w->u.format.size,
478 w->u.format.flag);
479 remove_worker(pthread_self());
480
481 #ifdef Libburn_protect_format_threaD
482 /* (just in case it would not end with all signals blocked) */
483 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
484 #endif /* Libburn_protect_format_threaD */
485
486 return NULL;
487 }
488
489
490 /* ts A61230 */
491 void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
492 {
493 union w_list_data o;
494 int ok = 0, ret;
495 char msg[40];
496
497 reset_progress(drive, 1, 1, 1, 0x10000, 0);
498
499 if ((SCAN_GOING()) || find_worker(drive) != NULL) {
500 libdax_msgs_submit(libdax_messenger, drive->global_index,
501 0x00020102,
502 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
503 "A drive operation is still going on (want to format)",
504 0, 0);
505 return;
506 }
507 if (drive->drive_role != 1) {
508 libdax_msgs_submit(libdax_messenger, drive->global_index,
509 0x00020146,
510 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
511 "Drive is a virtual placeholder", 0, 0);
512 drive->cancel = 1;
513 return;
514 }
515 if (flag & 128) /* application prescribed format type */
516 flag |= 16; /* enforce re-format */
517
518 if (drive->current_profile == 0x14)
519 ok = 1; /* DVD-RW sequential */
520 else if (drive->current_profile == 0x13 && (flag & 16))
521 ok = 1; /* DVD-RW Restricted Overwrite with force bit */
522 else if (drive->current_profile == 0x1a) {
523 ok = 1; /* DVD+RW */
524 size = 0;
525 flag &= ~(2|8); /* no insisting in size 0, no expansion */
526 flag |= 4; /* format up to maximum size */
527 } else if (drive->current_profile == 0x12) {
528 ok = 1; /* DVD-RAM */
529
530 } else if (drive->current_profile == 0x41) {
531 /* BD-R SRM */
532 ok= 1;
533 ret = drive->read_format_capacities(drive, 0x00);
534 if (ret > 0 &&
535 drive->format_descr_type == BURN_FORMAT_IS_FORMATTED)
536 ok = 0;
537 if (drive->status != BURN_DISC_BLANK)
538 ok = 0;
539 if (!ok) {
540 libdax_msgs_submit(libdax_messenger,
541 drive->global_index, 0x00020162,
542 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
543 "BD-R not unformatted blank any more. Cannot format.",
544 0, 0);
545 drive->cancel = 1;
546 return;
547 }
548 if (flag & 32) {
549 libdax_msgs_submit(libdax_messenger,
550 drive->global_index, 0x00020163,
551 LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
552 "Blank BD-R left unformatted for zero spare capacity.",
553 0, 0);
554 return;
555 }
556 } else if (drive->current_profile == 0x43) {
557 ok = 1; /* BD-RE */
558
559 if ((flag & 32) && !(drive->current_feat23h_byte4 & 8)) {
560 libdax_msgs_submit(libdax_messenger,
561 drive->global_index, 0x00020164,
562 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
563 "Drive does not format BD-RE without spares.",
564 0, 0);
565 drive->cancel = 1;
566 return;
567
568 }
569 }
570
571 if (!ok) {
572 sprintf(msg,"Will not format media type %4.4Xh",
573 drive->current_profile);
574 libdax_msgs_submit(libdax_messenger, drive->global_index,
575 0x00020129,
576 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
577 msg, 0, 0);
578 drive->cancel = 1;
579 return;
580 }
581 o.format.drive = drive;
582 o.format.size = size;
583 o.format.flag = flag;
584 add_worker(Burnworker_type_formaT, drive,
585 (WorkerFunc) format_worker_func, &o);
586 }
587
588
589 static void *write_disc_worker_func(struct w_list *w)
590 {
591 struct burn_drive *d = w->u.write.drive;
592 char msg[80];
593
594 #define Libburn_protect_write_threaD 1
595
596 #ifdef Libburn_protect_write_threaD
597 sigset_t sigset, oldset;
598
599 /* Protect write thread from being interrupted by external signals */
600 sigfillset(&sigset);
601 sigdelset(&sigset, SIGSEGV);
602 sigdelset(&sigset, SIGILL);
603 pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
604 #endif /* Libburn_protect_write_threaD */
605
606 d->thread_pid = getpid();
607 d->thread_tid = pthread_self();
608 d->thread_pid_valid= 1;
609 burn_disc_write_sync(w->u.write.opts, w->u.write.disc);
610 d->thread_pid_valid= 0;
611 d->thread_pid = 0;
612
613 /* the options are refcounted, free out ref count which we added below
614 */
615 burn_write_opts_free(w->u.write.opts);
616
617 sprintf(msg, "Write thread on drive %d ended", d->global_index);
618 libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020178,
619 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
620 msg, 0, 0);
621
622 remove_worker(pthread_self());
623 d->busy = BURN_DRIVE_IDLE;
624
625 #ifdef Libburn_protect_write_threaD
626 /* (just in case it would not end with all signals blocked) */
627 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
628 #endif /* Libburn_protect_write_threaD */
629
630 return NULL;
631 }
632
633 void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
634 {
635 union w_list_data o;
636 char *reasons= NULL;
637 struct burn_drive *d;
638 int mvalid;
639
640 d = opts->drive;
641
642 /* ts A61006 */
643 /* a ssert(!SCAN_GOING()); */
644 /* a ssert(!find_worker(opts->drive)); */
645 if ((SCAN_GOING()) || find_worker(opts->drive) != NULL) {
646 libdax_msgs_submit(libdax_messenger, d->global_index,
647 0x00020102,
648 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
649 "A drive operation is still going on (want to write)",
650 0, 0);
651 return;
652 }
653
654 reset_progress(d, disc->sessions, disc->session[0]->tracks,
655 disc->session[0]->track[0]->indices, 0, 0);
656
657 /* For the next lines any return indicates failure */
658 d->cancel = 1;
659
660 /* ts A70203 : people have been warned in API specs */
661 if (opts->write_type == BURN_WRITE_NONE) {
662 libdax_msgs_submit(libdax_messenger, d->global_index,
663 0x0002017c,
664 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
665 "No valid write type selected", 0, 0);
666 return;
667 }
668
669 if (d->drive_role == 0) {
670 libdax_msgs_submit(libdax_messenger, d->global_index,
671 0x00020146,
672 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
673 "Drive is a virtual placeholder (null-drive)", 0, 0);
674 return;
675 }
676 if (d->drive_role == 4) {
677 libdax_msgs_submit(libdax_messenger, d->global_index,
678 0x00020181,
679 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
680 "Pseudo-drive is a read-only file. Cannot write.",
681 0, 0);
682 return;
683 }
684
685 /* ts A61007 : obsolete Assert in spc_select_write_params() */
686 if (d->drive_role == 1) {
687 mvalid = 0;
688 if (d->mdata != NULL)
689 mvalid = 1;
690 if (!mvalid) {
691 libdax_msgs_submit(libdax_messenger,
692 d->global_index, 0x00020113,
693 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
694 "Drive capabilities not inquired yet", 0, 0);
695 return;
696 }
697 }
698
699 /* ts A70219 : intended to replace all further tests here and many
700 tests in burn_*_write_sync()
701 */
702
703 BURN_ALLOC_MEM_VOID(reasons, char, BURN_REASONS_LEN + 80);
704 strcpy(reasons, "Write job parameters are unsuitable:\n");
705 if (burn_precheck_write(opts, disc, reasons + strlen(reasons), 1)
706 <= 0) {
707 libdax_msgs_submit(libdax_messenger,
708 d->global_index, 0x00020139,
709 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
710 reasons, 0, 0);
711 goto ex;
712 }
713 BURN_FREE_MEM(reasons); reasons= NULL;
714
715 /* ts A90106 : early catching of unformatted BD-RE */
716 if (d->current_profile == 0x43)
717 if (d->read_format_capacities(d, 0x00) > 0 &&
718 d->format_descr_type != BURN_FORMAT_IS_FORMATTED) {
719 libdax_msgs_submit(libdax_messenger,
720 d->global_index, 0x00020168,
721 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
722 "Media not properly formatted. Cannot write.",
723 0, 0);
724 return;
725 }
726
727 d->cancel = 0; /* End of the return = failure area */
728
729 o.write.drive = d;
730 o.write.opts = opts;
731 o.write.disc = disc;
732
733 opts->refcount++;
734
735 add_worker(Burnworker_type_writE, d,
736 (WorkerFunc) write_disc_worker_func, &o);
737
738 ex:;
739 BURN_FREE_MEM(reasons);
740 }
741
742
743 static void *fifo_worker_func(struct w_list *w)
744 {
745
746 #define Libburn_protect_fifo_threaD 1
747
748 #ifdef Libburn_protect_fifo_threaD
749 sigset_t sigset, oldset;
750
751 /* Protect fifo thread from being interrupted by external signals */
752 sigfillset(&sigset);
753 sigdelset(&sigset, SIGSEGV);
754 sigdelset(&sigset, SIGILL);
755 pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
756 #endif /* Libburn_protect_fifo_threaD */
757
758 burn_fifo_source_shoveller(w->u.fifo.source, w->u.fifo.flag);
759 remove_worker(pthread_self());
760
761 #ifdef Libburn_protect_fifo_threaD
762 /* (just in case it would not end with all signals blocked) */
763 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
764 #endif /* Libburn_protect_fifo_threaD */
765
766 return NULL;
767 }
768
769
770 int burn_fifo_start(struct burn_source *source, int flag)
771 {
772 union w_list_data o;
773 struct burn_source_fifo *fs = source->data;
774
775 fs->is_started = -1;
776
777 /* create and set up ring buffer */;
778 fs->buf = burn_os_alloc_buffer(
779 ((size_t) fs->chunksize) * (size_t) fs->chunks, 0);
780 if (fs->buf == NULL) {
781 /* >>> could not start ring buffer */;
782 return -1;
783 }
784
785 o.fifo.source = source;
786 o.fifo.flag = flag;
787 add_worker(Burnworker_type_fifO, NULL,
788 (WorkerFunc) fifo_worker_func, &o);
789 fs->is_started = 1;
790
791 return 1;
792 }
793
794
795 int burn_fifo_abort(struct burn_source_fifo *fs, int flag)
796 {
797 int ret;
798 pthread_t pt;
799
800 burn_async_manage_lock(BURN_ASYNC_LOCK_OBTAIN);
801
802 if (fs->thread_is_valid <= 0 || fs->thread_handle == NULL) {
803 burn_async_manage_lock(BURN_ASYNC_LOCK_RELEASE);
804 return 2;
805 }
806 pt = *((pthread_t *) fs->thread_handle);
807
808 burn_async_manage_lock(BURN_ASYNC_LOCK_RELEASE);
809
810 fs->do_abort = 1;
811 ret = pthread_join(pt, NULL);
812
813 return (ret == 0);
814 }
815
816
817 #ifdef Libburn_has_burn_async_join_alL
818
819 /* ts A71019 : never used */
820 void burn_async_join_all(void)
821 {
822 void *ret;
823
824 while (workers)
825 pthread_join(workers->thread, &ret);
826 }
827
828 #endif /* Libburn_has_burn_async_join_alL */
829
830