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.

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