"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