You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

796 lines
19 KiB

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