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
9 #ifdef HAVE_CONFIG_H
10 #include "../config.h"
11 #endif
12
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <signal.h>
18 #include <dirent.h>
19
20 /* ts A61007 */
21 /* #include <a ssert.h> */
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <pthread.h>
27 #include <errno.h>
28 #include <fcntl.h>
29
30 /* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
31 #ifndef O_BINARY
32 #define O_BINARY 0
33 #endif
34
35 #include "libburn.h"
36 #include "init.h"
37 #include "drive.h"
38 #include "transport.h"
39 #include "debug.h"
40 #include "init.h"
41 #include "toc.h"
42 #include "util.h"
43 #include "sg.h"
44 #include "structure.h"
45
46 /* ts A70107 : to get BE_CANCELLED */
47 #include "error.h"
48
49 /* ts A70219 : for burn_disc_get_write_mode_demands() */
50 #include "options.h"
51
52 /* A70225 : to learn about eventual Libburn_dvd_r_dl_multi_no_close_sessioN */
53 #include "write.h"
54
55 /* A70903 : for burn_scsi_setup_drive() */
56 #include "spc.h"
57
58 /* A90815 : for mmc_obtain_profile_name() */
59 #include "mmc.h"
60
61 /* B60730 : for Libburn_do_no_immed_defaulT */
62 #include "os.h"
63
64 #include "libdax_msgs.h"
65 extern struct libdax_msgs *libdax_messenger;
66
67 static struct burn_drive drive_array[255];
68 static int drivetop = -1;
69
70 /* ts A80410 : in init.c */
71 extern int burn_support_untested_profiles;
72
73 /* ts B10312 : in init.c */
74 extern int burn_drive_role_4_allowed;
75
76
77 /* ts A61021 : the unspecific part of sg.c:enumerate_common()
78 */
burn_setup_drive(struct burn_drive * d,char * fname)79 int burn_setup_drive(struct burn_drive *d, char *fname)
80 {
81 d->devname = strdup(fname);
82 memset(&d->params, 0, sizeof(struct params));
83 d->idata = NULL;
84 d->mdata = NULL;
85 d->toc_entry = NULL;
86 d->released = 1;
87 d->stdio_fd = -1;
88 d->status = BURN_DISC_UNREADY;
89 d->erasable = 0;
90 d->current_profile = -1;
91 d->do_stream_recording = 0;
92 d->stream_recording_start= 0;
93 d->role_5_nwa = 0;
94
95 #ifdef Libburn_do_no_immed_defaulT
96 d->do_no_immed = Libburn_do_no_immed_defaulT;
97 #else
98 d->do_no_immed = 0;
99 #endif
100
101 d->features = NULL;
102 d->drive_serial_number = NULL;
103 d->drive_serial_number_len = -1;
104 d->media_serial_number = NULL;
105 d->media_serial_number_len = -1;
106 return 1;
107 }
108
109
110 /* ts A70903 */
burn_drive_free_subs(struct burn_drive * d)111 void burn_drive_free_subs(struct burn_drive *d)
112 {
113 if (d->idata != NULL)
114 free((void *) d->idata);
115 d->idata = NULL;
116 if (d->mdata != NULL) {
117 burn_mdata_free_subs(d->mdata);
118 free((void *) d->mdata);
119 }
120 d->mdata = NULL;
121 if(d->toc_entry != NULL)
122 free((void *) d->toc_entry);
123 d->toc_entry = NULL;
124 if (d->devname != NULL)
125 free(d->devname);
126 d->devname = NULL;
127 if (d->stdio_fd >= 0)
128 close (d->stdio_fd);
129 d->stdio_fd = -1;
130 burn_feature_descr_free(&(d->features), 0);
131 BURN_FREE_MEM(d->drive_serial_number);
132 BURN_FREE_MEM(d->media_serial_number);
133 d->drive_serial_number = d->media_serial_number = NULL;
134 d->drive_serial_number_len = d->media_serial_number_len = 0;
135 sg_dispose_drive(d, 0);
136 }
137
138
139 /* ts A60904 : ticket 62, contribution by elmom */
140 /* splitting former burn_drive_free() (which freed all, into two calls) */
burn_drive_free(struct burn_drive * d)141 void burn_drive_free(struct burn_drive *d)
142 {
143 if (d->global_index == -1)
144 return;
145 /* ts A60822 : close open fds before forgetting them */
146 if (d->drive_role == 1)
147 if (burn_drive_is_open(d)) {
148 d->unlock(d);
149 d->release(d);
150 }
151 burn_drive_free_subs(d);
152 d->global_index = -1;
153 }
154
burn_drive_free_all(void)155 void burn_drive_free_all(void)
156 {
157 int i;
158
159 for (i = 0; i < drivetop + 1; i++)
160 burn_drive_free(&(drive_array[i]));
161 drivetop = -1;
162 memset(drive_array, 0, sizeof(drive_array));
163 }
164
165
166 /* ts A60822 */
burn_drive_is_open(struct burn_drive * d)167 int burn_drive_is_open(struct burn_drive *d)
168 {
169 if (d->drive_role != 1)
170 return (d->stdio_fd >= 0);
171 /* ts A61021 : moved decision to sg.c */
172 return d->drive_is_open(d);
173 }
174
175
176 /* ts A60906 */
burn_drive_force_idle(struct burn_drive * d)177 int burn_drive_force_idle(struct burn_drive *d)
178 {
179 d->busy = BURN_DRIVE_IDLE;
180 return 1;
181 }
182
183
184 /* ts A60906 */
burn_drive_is_released(struct burn_drive * d)185 int burn_drive_is_released(struct burn_drive *d)
186 {
187 return !!d->released;
188 }
189
190
191 /* ts A60906 */
192 /** Inquires drive status in respect to degree of app usage.
193 @param return -2 = drive is forgotten
194 -1 = drive is closed (i.e. released explicitly)
195 0 = drive is open, not grabbed (after scan, before 1st grab)
196 1 = drive is grabbed but BURN_DRIVE_IDLE
197 2 = drive is grabbed, synchronous read/write interrupted
198 10 = drive is grabbing (BURN_DRIVE_GRABBING)
199 100 = drive is busy in cancelable state
200 1000 = drive is in non-cancelable state
201 Expect a monotonous sequence of usage severity to emerge in future.
202 */
burn_drive_is_occupied(struct burn_drive * d)203 int burn_drive_is_occupied(struct burn_drive *d)
204 {
205 if(d->global_index < 0)
206 return -2;
207 if(!burn_drive_is_open(d))
208 return -1;
209 if(d->busy == BURN_DRIVE_GRABBING)
210 return 10;
211 if(d->released)
212 return 0;
213 if(d->busy == BURN_DRIVE_IDLE)
214 return 1;
215 if(d->busy == BURN_DRIVE_READING_SYNC ||
216 d->busy == BURN_DRIVE_WRITING_SYNC)
217 return 2;
218 if(d->busy == BURN_DRIVE_WRITING ||
219 d->busy == BURN_DRIVE_WRITING_LEADIN ||
220 d->busy == BURN_DRIVE_WRITING_LEADOUT ||
221 d->busy == BURN_DRIVE_WRITING_PREGAP) {
222
223 /* ts A70928 */
224 /* >>> how do i learn whether the writer thread is still
225 alive ? */;
226 /* >>> what to do if writer is dead ?
227 At least sync disc ?*/;
228 return 50;
229 }
230 if(d->busy == BURN_DRIVE_READING) {
231 return 50;
232 }
233 return 1000;
234 }
235
236
237 /*
238 void drive_read_lead_in(int dnum)
239 {
240 mmc_read_lead_in(&drive_array[dnum], get_4k());
241 }
242 */
burn_drive_count(void)243 unsigned int burn_drive_count(void)
244 {
245 return drivetop + 1;
246 }
247
248
249 /* ts A80801 */
burn_drive_is_listed(char * path,struct burn_drive ** found,int flag)250 int burn_drive_is_listed(char *path, struct burn_drive **found, int flag)
251 {
252 int i, ret;
253 char *drive_adr = NULL, *off_adr = NULL;
254
255 BURN_ALLOC_MEM(drive_adr, char, BURN_DRIVE_ADR_LEN);
256 BURN_ALLOC_MEM(off_adr, char, BURN_DRIVE_ADR_LEN);
257
258 ret = burn_drive_convert_fs_adr(path, off_adr);
259 if (ret <= 0)
260 strcpy(off_adr, path);
261 for (i = 0; i <= drivetop; i++) {
262 if (drive_array[i].global_index < 0)
263 continue;
264 ret = burn_drive_d_get_adr(&(drive_array[i]), drive_adr);
265 if (ret <= 0)
266 continue;
267 if(strcmp(off_adr, drive_adr) == 0) {
268 if (found != NULL)
269 *found= &(drive_array[i]);
270 {ret= 1; goto ex;}
271 }
272 }
273 ret= 0;
274 ex:;
275 BURN_FREE_MEM(drive_adr);
276 BURN_FREE_MEM(off_adr);
277 return ret;
278 }
279
280
281 /* ts A61125 : media status aspects of burn_drive_grab() */
burn_drive_inquire_media(struct burn_drive * d)282 int burn_drive_inquire_media(struct burn_drive *d)
283 {
284
285 /* ts A61225 : after loading the tray, mode page 2Ah can change */
286 d->getcaps(d);
287
288 /* ts A61020 : d->status was set to BURN_DISC_BLANK as pure guess */
289
290 /* ts A71128 : run read_disc_info() for any recognizable profile */
291 if (d->current_profile > 0 || d->current_is_guessed_profile ||
292 (d->mdata->p2a_valid > 0 &&
293 (d->mdata->cdr_write || d->mdata->cdrw_write ||
294 d->mdata->dvdr_write || d->mdata->dvdram_write)) ) {
295 d->read_disc_info(d);
296 } else {
297 if (d->current_profile == -1 || d->current_is_cd_profile)
298 d->read_toc(d);
299
300 /* ts A70314 , B10712 */
301 if (d->status != BURN_DISC_EMPTY)
302 d->status = BURN_DISC_UNSUITABLE;
303 }
304 return 1;
305 }
306
307 /* ts B10730 */
308 /* Send a default mode page 05 to CD and DVD-R-oids */
burn_drive_send_default_page_05(struct burn_drive * d,int flag)309 int burn_drive_send_default_page_05(struct burn_drive *d, int flag)
310 {
311 struct burn_write_opts *opts;
312
313 if (d->sent_default_page_05)
314 return 0;
315 if (!((d->status == BURN_DISC_APPENDABLE ||
316 d->status == BURN_DISC_BLANK) &&
317 (d->current_is_cd_profile || d->current_profile == 0x11 ||
318 d->current_profile == 0x14 || d->current_profile == 0x15)))
319 return 0;
320 opts = burn_write_opts_new(d);
321 if (opts == NULL)
322 return -1;
323 if (d->status == BURN_DISC_APPENDABLE)
324 burn_write_opts_set_write_type(opts,
325 BURN_WRITE_TAO, BURN_BLOCK_MODE1);
326 else
327 burn_write_opts_set_write_type(opts,
328 BURN_WRITE_SAO, BURN_BLOCK_SAO);
329 d->send_write_parameters(d, NULL, -1, opts);
330 burn_write_opts_free(opts);
331 d->sent_default_page_05 = 1;
332 return 1;
333 }
334
335
336 /* ts A70924 */
burn_drive__fd_from_special_adr(char * adr)337 int burn_drive__fd_from_special_adr(char *adr)
338 {
339 int fd = -1, i;
340
341 if (strcmp(adr, "-") == 0)
342 fd = 1;
343 if(strncmp(adr, "/dev/fd/", 8) == 0) {
344 for (i = 8; adr[i]; i++)
345 if (!isdigit(adr[i]))
346 break;
347 if (i> 8 && adr[i] == 0)
348 fd = atoi(adr + 8);
349 }
350 return fd;
351 }
352
353 /* @param flag bit0= accept read-only files and return 2 in this case
354 bit1= accept write-only files and return 3 in this case
355 */
burn_drive__is_rdwr(char * fname,int * stat_ret,struct stat * stbuf_ret,off_t * read_size_ret,int flag)356 static int burn_drive__is_rdwr(char *fname, int *stat_ret,
357 struct stat *stbuf_ret,
358 off_t *read_size_ret, int flag)
359 {
360 int fd, is_rdwr = 1, ret, getfl_ret, st_ret, mask;
361 struct stat stbuf;
362 off_t read_size = 0;
363
364 memset(&stbuf, 0, sizeof(struct stat));
365 fd = burn_drive__fd_from_special_adr(fname);
366 if (fd >= 0)
367 st_ret = fstat(fd, &stbuf);
368 else
369 st_ret = stat(fname, &stbuf);
370 if (st_ret != -1) {
371 is_rdwr = burn_os_is_2k_seekrw(fname, 0);
372 ret = 1;
373 if (S_ISREG(stbuf.st_mode))
374 read_size = stbuf.st_size;
375 else if (is_rdwr)
376 ret = burn_os_stdio_capacity(fname, 0, &read_size);
377 if (ret <= 0 ||
378 read_size / (off_t) 2048 >= (off_t) 0x7ffffff0)
379 read_size = (off_t) 0x7ffffff0 * (off_t) 2048;
380 }
381
382 if (is_rdwr && fd >= 0) {
383 getfl_ret = fcntl(fd, F_GETFL);
384
385 /*
386 fprintf(stderr, "LIBBURN_DEBUG: burn_drive__is_rdwr: getfl_ret = %lX , O_RDWR = %lX , & = %lX , O_RDONLY = %lX\n", (unsigned long) getfl_ret, (unsigned long) O_RDWR, (unsigned long) (getfl_ret & O_RDWR), (unsigned long) O_RDONLY);
387 */
388
389 mask = O_RDWR | O_WRONLY | O_RDONLY;
390
391 if (getfl_ret == -1 || (getfl_ret & mask) != O_RDWR)
392 is_rdwr = 0;
393 if ((flag & 1) && getfl_ret != -1 &&
394 (getfl_ret & mask) == O_RDONLY)
395 is_rdwr = 2;
396 if ((flag & 2) && getfl_ret != -1 &&
397 (getfl_ret & mask) == O_WRONLY)
398 is_rdwr = 3;
399 }
400 if (stat_ret != NULL)
401 *stat_ret = st_ret;
402 if (stbuf_ret != NULL)
403 memcpy(stbuf_ret, &stbuf, sizeof(struct stat));
404 if (read_size_ret != NULL)
405 *read_size_ret = read_size;
406 return is_rdwr;
407 }
408
409
410 /* flag bit0= ( not needed yet: grab even if it is already grabbed )
411 */
burn_drive_grab_stdio(struct burn_drive * d,int flag)412 int burn_drive_grab_stdio(struct burn_drive *d, int flag)
413 {
414 int stat_ret = -1, is_rdwr, ret;
415 struct stat stbuf;
416 off_t read_size= 0, size= 0;
417 char fd_name[40], *name_pt = NULL;
418
419 if(d->stdio_fd >= 0) {
420 sprintf(fd_name, "/dev/fd/%d", d->stdio_fd);
421 name_pt = fd_name;
422 } else if (d->devname[0]) {
423 name_pt = d->devname;
424 }
425 if (name_pt != NULL) {
426 /* re-assess d->media_read_capacity and free space */
427 is_rdwr = burn_drive__is_rdwr(name_pt, &stat_ret, &stbuf,
428 &read_size, 1 | 2);
429 /* despite its name : last valid address, not size */
430 d->media_read_capacity =
431 read_size / 2048 - !(read_size % 2048);
432 d->mr_capacity_trusted = 1;
433 if ((stat_ret == -1 || is_rdwr) && d->devname[0]) {
434 ret = burn_os_stdio_capacity(d->devname, 0, &size);
435 if (ret > 0)
436 burn_drive_set_media_capacity_remaining(d,
437 size);
438 }
439 }
440
441 d->released = 0;
442 d->current_profile = 0xffff;
443 if(d->drive_role == 2 || d->drive_role == 3) {
444 d->status = BURN_DISC_BLANK;
445 } else if(d->drive_role == 4) {
446 if (d->media_read_capacity > 0)
447 d->status = BURN_DISC_FULL;
448 else
449 d->status = BURN_DISC_EMPTY;
450 } else if(d->drive_role == 5) {
451 if (stat_ret != -1 && S_ISREG(stbuf.st_mode) &&
452 stbuf.st_size > 0) {
453 d->status = BURN_DISC_APPENDABLE;
454 if (stbuf.st_size / (off_t) 2048
455 >= 0x7ffffff0) {
456 d->status = BURN_DISC_FULL;
457 d->role_5_nwa = 0x7ffffff0;
458 } else
459 d->role_5_nwa = stbuf.st_size / 2048 +
460 !!(stbuf.st_size % 2048);
461 } else
462 d->status = BURN_DISC_BLANK;
463 } else {
464 d->status = BURN_DISC_EMPTY;
465 d->current_profile = 0;
466 }
467 d->busy = BURN_DRIVE_IDLE;
468 return 1;
469 }
470
471
burn_drive_grab(struct burn_drive * d,int le)472 int burn_drive_grab(struct burn_drive *d, int le)
473 {
474 int errcode;
475 /* ts A61125 - B20122 */
476 int ret, sose, signal_action_mem = -1;
477
478 sose = d->silent_on_scsi_error;
479 if (!d->released) {
480 libdax_msgs_submit(libdax_messenger, d->global_index,
481 0x00020189, LIBDAX_MSGS_SEV_FATAL,
482 LIBDAX_MSGS_PRIO_LOW,
483 "Drive is already grabbed by libburn", 0, 0);
484 return 0;
485 }
486 if(d->drive_role != 1) {
487 ret = burn_drive_grab_stdio(d, 0);
488 return ret;
489 }
490
491 d->status = BURN_DISC_UNREADY;
492 errcode = d->grab(d);
493 if (errcode == 0)
494 return 0;
495
496 burn_grab_prepare_sig_action(&signal_action_mem, 0);
497 d->busy = BURN_DRIVE_GRABBING;
498
499 if (le)
500 d->load(d);
501 if (d->cancel || burn_is_aborting(0))
502 {ret = 0; goto ex;}
503
504 d->lock(d);
505 if (d->cancel || burn_is_aborting(0))
506 {ret = 0; goto ex;}
507
508 /* ts A61118 */
509 d->start_unit(d);
510 if (d->cancel || burn_is_aborting(0))
511 {ret = 0; goto ex;}
512
513 /* ts A61202 : gave bit1 of le a meaning */
514 if (!le)
515 d->silent_on_scsi_error = 1;
516 /* ts A61125 : outsourced media state inquiry aspects */
517 ret = burn_drive_inquire_media(d);
518 if (d->cancel || burn_is_aborting(0))
519 {ret = 0; goto ex;}
520
521 burn_drive_send_default_page_05(d, 0);
522 if (d->cancel || burn_is_aborting(0))
523 {ret = 0; goto ex;}
524
525 ex:;
526 if (d->cancel || burn_is_aborting(0)) {
527 d->unlock(d);
528 d->release(d);
529 }
530 d->silent_on_scsi_error = sose;
531 d->busy = BURN_DRIVE_IDLE;
532 burn_grab_restore_sig_action(signal_action_mem, 0);
533 return ret;
534 }
535
536
537 /* ts A71015 */
538 #define Libburn_ticket_62_re_register_is_possiblE 1
539
burn_drive_register(struct burn_drive * d)540 struct burn_drive *burn_drive_register(struct burn_drive *d)
541 {
542 #ifdef Libburn_ticket_62_re_register_is_possiblE
543 int i;
544 #endif
545
546 d->block_types[0] = 0;
547 d->block_types[1] = 0;
548 d->block_types[2] = 0;
549 d->block_types[3] = 0;
550 d->toc_temp = 0;
551 d->nwa = 0;
552 d->alba = 0;
553 d->rlba = 0;
554 d->cancel = 0;
555 d->busy = BURN_DRIVE_IDLE;
556 d->thread_pid = 0;
557 d->thread_pid_valid = 0;
558 memset(&(d->thread_tid), 0, sizeof(d->thread_tid));
559 d->medium_state_changed = 0;
560 d->set_streaming_exact_bit = 0;
561 d->set_streaming_err = 0;
562 d->toc_entries = 0;
563 d->toc_entry = NULL;
564 d->disc = NULL;
565 d->erasable = 0;
566 d->write_opts = NULL;
567
568 #ifdef Libburn_ticket_62_re_register_is_possiblE
569 /* ts A60904 : ticket 62, contribution by elmom */
570 /* Not yet accepted because no use case seen yet */
571 /* ts A71015 : xorriso dialog imposes a use case now */
572
573 /* This is supposed to find an already freed drive struct among
574 all the the ones that have been used before */
575 for (i = 0; i < drivetop + 1; i++)
576 if (drive_array[i].global_index == -1)
577 break;
578 d->global_index = i;
579 memcpy(&drive_array[i], d, sizeof(struct burn_drive));
580 pthread_mutex_init(&drive_array[i].access_lock, NULL);
581 if (drivetop < i)
582 drivetop = i;
583 return &(drive_array[i]);
584
585 #else /* Libburn_ticket_62_re_register_is_possiblE */
586 /* old A60904 : */
587 /* Still active by default */
588
589 d->global_index = drivetop + 1;
590 memcpy(&drive_array[drivetop + 1], d, sizeof(struct burn_drive));
591 pthread_mutex_init(&drive_array[drivetop + 1].access_lock, NULL);
592 return &drive_array[++drivetop];
593
594 #endif /* ! Libburn_ticket_62_re_register_is_possiblE */
595
596 }
597
598
599 /* unregister most recently registered drive */
burn_drive_unregister(struct burn_drive * d)600 int burn_drive_unregister(struct burn_drive *d)
601 {
602 if(d->global_index != drivetop)
603 return 0;
604 burn_drive_free(d);
605 drivetop--;
606 return 1;
607 }
608
609
610 /* ts A61021 : after-setup activities from sg.c:enumerate_common()
611 */
burn_drive_finish_enum(struct burn_drive * d)612 struct burn_drive *burn_drive_finish_enum(struct burn_drive *d)
613 {
614 struct burn_drive *t = NULL;
615 char *msg = NULL;
616 int ret;
617
618 BURN_ALLOC_MEM(msg, char, BURN_DRIVE_ADR_LEN + 160);
619
620 d->drive_role = 1; /* MMC drive */
621
622 t = burn_drive_register(d);
623
624 /* ts A60821 */
625 mmc_function_spy(NULL, "enumerate_common : -------- doing grab");
626
627 /* try to get the drive info */
628 ret = t->grab(t);
629 if (ret) {
630 t->getcaps(t);
631 t->unlock(t);
632 t->released = 1;
633 } else {
634 /* ts A90602 */
635 d->mdata->p2a_valid = -1;
636 sprintf(msg, "Unable to grab scanned drive %s", d->devname);
637 libdax_msgs_submit(libdax_messenger, d->global_index,
638 0x0002016f, LIBDAX_MSGS_SEV_DEBUG,
639 LIBDAX_MSGS_PRIO_LOW, msg, 0, 0);
640 burn_drive_unregister(t);
641 t = NULL;
642 }
643
644 /* ts A60821 */
645 mmc_function_spy(NULL, "enumerate_common : ----- would release ");
646
647 ex:
648 BURN_FREE_MEM(msg);
649 return t;
650 }
651
652
653 /* ts A61125 : model aspects of burn_drive_release */
654 /* @param flag bit3= do not close d->stdio_fd
655 */
burn_drive_mark_unready(struct burn_drive * d,int flag)656 int burn_drive_mark_unready(struct burn_drive *d, int flag)
657 {
658 /* ts A61020 : mark media info as invalid */
659 d->start_lba= -2000000000;
660 d->end_lba= -2000000000;
661
662 /* ts A61202 */
663 d->current_profile = -1;
664 d->current_has_feat21h = 0;
665 d->current_feat2fh_byte4 = -1;
666
667 d->status = BURN_DISC_UNREADY;
668 if (d->toc_entry != NULL)
669 free(d->toc_entry);
670 d->toc_entry = NULL;
671 d->toc_entries = 0;
672 if (d->write_opts != NULL) {
673 burn_write_opts_free(d->write_opts);
674 d->write_opts = NULL;
675 }
676 if (d->disc != NULL) {
677 burn_disc_free(d->disc);
678 d->disc = NULL;
679 }
680 if (!(flag & 8)) {
681 if (d->stdio_fd >= 0)
682 close (d->stdio_fd);
683 d->stdio_fd = -1;
684 }
685 return 1;
686 }
687
688
689 /* ts A70918 : outsourced from burn_drive_release() and enhanced */
690 /** @param flag bit0-2 = mode : 0=unlock , 1=unlock+eject , 2=leave locked
691 bit3= do not call d->release()
692 */
burn_drive_release_fl(struct burn_drive * d,int flag)693 int burn_drive_release_fl(struct burn_drive *d, int flag)
694 {
695 if (d->released) {
696 /* ts A61007 */
697 libdax_msgs_submit(libdax_messenger,
698 d->global_index, 0x00020105,
699 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
700 "Drive is already released", 0, 0);
701 return 0;
702 }
703
704 /* ts A61007 */
705 /* ts A60906: one should not assume BURN_DRIVE_IDLE == 0 */
706 /* a ssert(d->busy == BURN_DRIVE_IDLE); */
707 if (d->busy != BURN_DRIVE_IDLE) {
708 libdax_msgs_submit(libdax_messenger,
709 d->global_index, 0x00020106,
710 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
711 "Drive is busy on attempt to close", 0, 0);
712 return 0;
713 }
714
715 if (d->drive_role == 1) {
716 if (d->needs_sync_cache)
717 d->sync_cache(d);
718 if ((flag & 7) != 2)
719 d->unlock(d);
720 if ((flag & 7) == 1)
721 d->eject(d);
722 if (!(flag & 8)) {
723 burn_drive_snooze(d, 0);
724 d->release(d);
725 }
726 }
727
728 d->needs_sync_cache = 0; /* just to be sure */
729
730 if (d->drive_serial_number != NULL)
731 BURN_FREE_MEM(d->drive_serial_number);
732 if (d->media_serial_number != NULL)
733 BURN_FREE_MEM(d->media_serial_number);
734 d->drive_serial_number = d->media_serial_number = NULL;
735 d->drive_serial_number_len = d->media_serial_number_len = 0;
736
737 d->released = 1;
738
739 /* ts A61125 : outsourced model aspects */
740 burn_drive_mark_unready(d, flag & 8);
741 return 1;
742 }
743
744
745 /* API */
746 /* ts A90824
747 @param flag bit0= wake up (else start snoozing)
748 */
burn_drive_snooze(struct burn_drive * d,int flag)749 int burn_drive_snooze(struct burn_drive *d, int flag)
750 {
751 if (d->drive_role != 1)
752 return 0;
753 if (flag & 1)
754 d->start_unit(d);
755 else
756 d->stop_unit(d);
757 return 1;
758 }
759
760
761 /* API */
burn_drive_release(struct burn_drive * d,int le)762 void burn_drive_release(struct burn_drive *d, int le)
763 {
764 burn_drive_release_fl(d, !!le);
765 }
766
767
768 /* ts B11002 */
769 /* API */
burn_drive_re_assess(struct burn_drive * d,int flag)770 int burn_drive_re_assess(struct burn_drive *d, int flag)
771 {
772 int ret, signal_action_mem;
773
774 if (d->released) {
775 libdax_msgs_submit(libdax_messenger, d->global_index,
776 0x00020108,
777 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
778 "Drive is not grabbed on burn_drive_re_assess()",
779 0, 0);
780 return 0;
781 }
782 burn_drive_release_fl(d, 2 | 8);
783
784 if(d->drive_role != 1) {
785 ret = burn_drive_grab_stdio(d, 0);
786 return ret;
787 }
788
789 burn_grab_prepare_sig_action(&signal_action_mem, 0);
790 d->busy = BURN_DRIVE_GRABBING;
791 ret = burn_drive_inquire_media(d);
792 burn_drive_send_default_page_05(d, 0);
793 d->busy = BURN_DRIVE_IDLE;
794 burn_grab_restore_sig_action(signal_action_mem, 0);
795 d->released = 0;
796 return ret;
797 }
798
799
800 /* ts A70918 */
801 /* API */
burn_drive_leave_locked(struct burn_drive * d,int flag)802 int burn_drive_leave_locked(struct burn_drive *d, int flag)
803 {
804 return burn_drive_release_fl(d, 2);
805 }
806
807
808 /* ts A61007 : former void burn_wait_all() */
809 /* @param flag bit0= demand freed drives (else released drives) */
burn_drives_are_clear(int flag)810 int burn_drives_are_clear(int flag)
811 {
812 int i;
813
814 for (i = burn_drive_count() - 1; i >= 0; --i) {
815 /* ts A60904 : ticket 62, contribution by elmom */
816 if (drive_array[i].global_index == -1)
817 continue;
818 if (drive_array[i].released && !(flag & 1))
819 continue;
820 return 0;
821 }
822 return 1;
823 }
824
825
826 #if 0
827 void burn_wait_all(void)
828 {
829 unsigned int i;
830 int finished = 0;
831 struct burn_drive *d;
832
833 while (!finished) {
834 finished = 1;
835 d = drive_array;
836 for (i = burn_drive_count(); i > 0; --i, ++d) {
837
838 /* ts A60904 : ticket 62, contribution by elmom */
839 if (d->global_index==-1)
840 continue;
841
842 a ssert(d->released);
843 }
844 if (!finished)
845 sleep(1);
846 }
847 }
848 #endif
849
850
burn_disc_erase_sync(struct burn_drive * d,int fast)851 void burn_disc_erase_sync(struct burn_drive *d, int fast)
852 {
853 int ret, was_error = 0;
854
855 if (d->drive_role == 5) { /* Random access write-only drive */
856 ret = truncate(d->devname, (off_t) 0);
857 if (ret == -1) {
858 libdax_msgs_submit(libdax_messenger, -1,
859 0x00020182,
860 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
861 "Cannot truncate disk file for pseudo blanking",
862 0, 0);
863 return;
864 }
865 d->role_5_nwa = 0;
866 d->cancel = 0;
867 d->status = BURN_DISC_BLANK;
868 d->busy = BURN_DRIVE_IDLE;
869 d->progress.sector = 0x10000;
870 return;
871 }
872
873 d->cancel = 0;
874
875 #ifdef Libburn_reset_progress_asynC
876 /* <<< This is now done in async.c */
877 /* reset the progress */
878 d->progress.session = 0;
879 d->progress.sessions = 1;
880 d->progress.track = 0;
881 d->progress.tracks = 1;
882 d->progress.index = 0;
883 d->progress.indices = 1;
884 d->progress.start_sector = 0;
885 d->progress.sectors = 0x10000;
886 d->progress.sector = 0;
887 #endif /* Libburn_reset_progress_asynC */
888
889 d->medium_state_changed = 1;
890 d->erase(d, fast);
891 d->busy = BURN_DRIVE_ERASING;
892
893 #ifdef Libburn_old_progress_looP
894
895 /* read the initial 0 stage */
896 while (!d->test_unit_ready(d) && d->get_erase_progress(d) == 0)
897 sleep(1);
898 while ((d->progress.sector = d->get_erase_progress(d)) > 0 ||
899 !d->test_unit_ready(d))
900 sleep(1);
901
902 #else /* Libburn_old_progress_looP */
903
904 while (1) {
905
906 /* >>> ??? ts B60730 : abort if user interrupts ?
907 if (d->cancel)
908 break;
909 */
910
911 ret = d->get_erase_progress(d);
912 if (ret == -2 || ret > 0)
913 break;
914 if (ret == -3)
915 was_error = 1;
916 sleep(1);
917 }
918 while (1) {
919
920 /* >>> ??? ts B60730 : abort if user interrupts ?
921 if (d->cancel)
922 break;
923 */
924
925 ret = d->get_erase_progress(d);
926 if(ret == -2)
927 break;
928 if (ret == -3)
929 was_error = 1;
930 if (ret >= 0)
931 d->progress.sector = ret;
932 sleep(1);
933 }
934
935 #endif /* ! Libburn_old_progress_looP */
936
937 d->progress.sector = 0x10000;
938
939 /* ts A61125 : update media state records */
940 burn_drive_mark_unready(d, 0);
941 if (d->drive_role == 1 && !d->cancel)
942 burn_drive_inquire_media(d);
943 d->busy = BURN_DRIVE_IDLE;
944 if (was_error)
945 d->cancel = 1;
946 }
947
948 /*
949 @param flag: bit0 = fill formatted size with zeros
950 bit1, bit2 , bit4, bit5, bit7 - bit15 are for d->format_unit()
951 */
burn_disc_format_sync(struct burn_drive * d,off_t size,int flag)952 void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
953 {
954 int ret, buf_secs, err, i, stages = 1, pbase, pfill, pseudo_sector;
955 int was_error = 0;
956 off_t num_bufs;
957 char msg[80];
958 struct buffer *buf = NULL, *buf_mem = d->buffer;
959
960 BURN_ALLOC_MEM(buf, struct buffer, 1);
961
962 #ifdef Libburn_reset_progress_asynC
963 /* <<< This is now done in async.c */
964 /* reset the progress */
965 d->progress.session = 0;
966 d->progress.sessions = 1;
967 d->progress.track = 0;
968 d->progress.tracks = 1;
969 d->progress.index = 0;
970 d->progress.indices = 1;
971 d->progress.start_sector = 0;
972 d->progress.sectors = 0x10000;
973 d->progress.sector = 0;
974 #endif /* Libburn_reset_progress_asynC */
975
976 stages = 1 + ((flag & 1) && size > 1024 * 1024);
977 d->cancel = 0;
978 d->busy = BURN_DRIVE_FORMATTING;
979 d->medium_state_changed = 1;
980
981 ret = d->format_unit(d, size, flag & 0xfff6); /* forward bits */
982 if (ret <= 0)
983 d->cancel = 1;
984
985 #ifdef Libburn_old_progress_looP
986
987 while (!d->test_unit_ready(d) && d->get_erase_progress(d) == 0)
988 sleep(1);
989 while ((pseudo_sector = d->get_erase_progress(d)) > 0 ||
990 !d->test_unit_ready(d)) {
991 d->progress.sector = pseudo_sector / stages;
992 sleep(1);
993 }
994
995 #else /* Libburn_old_progress_looP */
996
997 while (1) {
998 ret = d->get_erase_progress(d);
999 if (ret == -2 || ret > 0)
1000 break;
1001 if (ret == -3)
1002 was_error = 1;
1003 sleep(1);
1004 }
1005 while (1) {
1006 pseudo_sector = d->get_erase_progress(d);
1007 if(pseudo_sector == -2)
1008 break;
1009 if (pseudo_sector == -3)
1010 was_error = 1;
1011 if (pseudo_sector >= 0)
1012 d->progress.sector = pseudo_sector / stages;
1013 sleep(1);
1014 }
1015
1016 #endif /* ! Libburn_old_progress_looP */
1017
1018 d->sync_cache(d);
1019
1020 if (size <= 0)
1021 goto ex;
1022
1023 /* update media state records */
1024 burn_drive_mark_unready(d, 0);
1025 burn_drive_inquire_media(d);
1026 if (flag & 1) {
1027 /* write size in zeros */;
1028 pbase = 0x8000 + 0x7fff * (stages == 1);
1029 pfill = 0xffff - pbase;
1030 buf_secs = 16; /* Must not be more than 16 */
1031 num_bufs = size / buf_secs / 2048;
1032 if (num_bufs > 0x7fffffff) {
1033 d->cancel = 1;
1034 goto ex;
1035 }
1036
1037 /* <<< */
1038 sprintf(msg,
1039 "Writing %.f sectors of zeros to formatted media",
1040 (double) num_bufs * (double) buf_secs);
1041 libdax_msgs_submit(libdax_messenger, d->global_index,
1042 0x00000002,
1043 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
1044 msg, 0, 0);
1045
1046 d->buffer = buf;
1047 memset(d->buffer, 0, sizeof(struct buffer));
1048 d->buffer->bytes = buf_secs * 2048;
1049 d->buffer->sectors = buf_secs;
1050 d->busy = BURN_DRIVE_WRITING;
1051 for (i = 0; i < num_bufs; i++) {
1052 d->nwa = i * buf_secs;
1053 err = d->write(d, d->nwa, d->buffer);
1054 if (err == BE_CANCELLED || d->cancel) {
1055 d->cancel = 1;
1056 break;
1057 }
1058 d->progress.sector = pbase
1059 + pfill * ((double) i / (double) num_bufs);
1060 }
1061 d->sync_cache(d);
1062 if (d->current_profile == 0x13 || d->current_profile == 0x1a) {
1063 /* DVD-RW or DVD+RW */
1064 d->busy = BURN_DRIVE_CLOSING_SESSION;
1065 /* CLOSE SESSION, 010b */
1066 d->close_track_session(d, 1, 0);
1067 d->busy = BURN_DRIVE_WRITING;
1068 }
1069 }
1070 ex:;
1071 d->progress.sector = 0x10000;
1072 d->busy = BURN_DRIVE_IDLE;
1073 d->buffer = buf_mem;
1074 if (was_error)
1075 d->cancel = 1;
1076 BURN_FREE_MEM(buf);
1077 }
1078
1079
1080 /* ts A70112 API */
burn_disc_get_formats(struct burn_drive * d,int * status,off_t * size,unsigned * bl_sas,int * num_formats)1081 int burn_disc_get_formats(struct burn_drive *d, int *status, off_t *size,
1082 unsigned *bl_sas, int *num_formats)
1083 {
1084 int ret;
1085
1086 *status = 0;
1087 *size = 0;
1088 *bl_sas = 0;
1089 *num_formats = 0;
1090 if (d->drive_role != 1)
1091 return 0;
1092 ret = d->read_format_capacities(d, 0x00);
1093 if (ret <= 0)
1094 return 0;
1095 *status = d->format_descr_type;
1096 *size = d->format_curr_max_size;
1097 *bl_sas = d->format_curr_blsas;
1098 *num_formats = d->num_format_descr;
1099 return 1;
1100 }
1101
1102
1103 /* ts A70112 API */
burn_disc_get_format_descr(struct burn_drive * d,int index,int * type,off_t * size,unsigned * tdp)1104 int burn_disc_get_format_descr(struct burn_drive *d, int index,
1105 int *type, off_t *size, unsigned *tdp)
1106 {
1107 *type = 0;
1108 *size = 0;
1109 *tdp = 0;
1110 if (index < 0 || index >= d->num_format_descr)
1111 return 0;
1112 *type = d->format_descriptors[index].type;
1113 *size = d->format_descriptors[index].size;
1114 *tdp = d->format_descriptors[index].tdp;
1115 return 1;
1116 }
1117
1118
burn_disc_get_status(struct burn_drive * d)1119 enum burn_disc_status burn_disc_get_status(struct burn_drive *d)
1120 {
1121 /* ts A61007 */
1122 /* a ssert(!d->released); */
1123 if (d->released) {
1124 libdax_msgs_submit(libdax_messenger,
1125 d->global_index, 0x00020108,
1126 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
1127 "Drive is not grabbed on disc status inquiry",
1128 0, 0);
1129 return BURN_DISC_UNGRABBED;
1130 }
1131
1132 return d->status;
1133 }
1134
burn_disc_erasable(struct burn_drive * d)1135 int burn_disc_erasable(struct burn_drive *d)
1136 {
1137 return d->erasable;
1138 }
burn_drive_get_status(struct burn_drive * d,struct burn_progress * p)1139 enum burn_drive_status burn_drive_get_status(struct burn_drive *d,
1140 struct burn_progress *p)
1141 {
1142 /* --- Part of asynchronous signal handling --- */
1143 /* This frequently used call may be used to react on messages from
1144 the libburn built-in signal handler.
1145 */
1146
1147 /* ts B00225 :
1148 If aborting with action 2:
1149 catch control thread after it returned from signal handler.
1150 Let it run burn_abort(4440,...)
1151 */
1152 burn_init_catch_on_abort(0);
1153
1154 /* ts A70928 : inform control thread of signal in sub-threads */
1155 if (burn_builtin_triggered_action < 2 && burn_global_abort_level > 0)
1156 burn_global_abort_level++;
1157 if (burn_builtin_triggered_action < 2 && burn_global_abort_level > 5) {
1158 if (burn_global_signal_handler == NULL)
1159 kill(getpid(), burn_global_abort_signum);
1160 else
1161 (*burn_global_signal_handler)
1162 (burn_global_signal_handle,
1163 burn_global_abort_signum, 0);
1164 burn_global_abort_level = -1;
1165 }
1166
1167 /* --- End of asynchronous signal handling --- */
1168
1169
1170 if (p != NULL) {
1171 memcpy(p, &(d->progress), sizeof(struct burn_progress));
1172 /* TODO: add mutex */
1173 }
1174 return d->busy;
1175 }
1176
1177
burn_drive_set_stream_recording(struct burn_drive * d,int recmode,int start,int flag)1178 int burn_drive_set_stream_recording(struct burn_drive *d, int recmode,
1179 int start, int flag)
1180 {
1181 #ifndef Libburn_force_stream_recordinG
1182 struct burn_feature_descr *descr;
1183 #endif
1184
1185 if (recmode == 1) {
1186
1187 #ifdef Libburn_force_stream_recordinG
1188
1189 d->do_stream_recording = 1;
1190
1191 #else /* Libburn_force_stream_recordinG */
1192
1193 d->do_stream_recording = 0;
1194 if (burn_drive_has_feature(d, 0x107, &descr, 0)) {
1195 if ((descr->data[0] & 1) && (descr->flags & 1))
1196 d->do_stream_recording = 1;
1197 }
1198 if (!d->do_stream_recording) {
1199 libdax_msgs_submit(libdax_messenger, d->global_index,
1200 0x000201ac,
1201 LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
1202 "Drive currently does not offer Stream Recording",
1203 0, 0);
1204 } else if (d->current_profile != 0x12 &&
1205 d->current_profile != 0x41 &&
1206 d->current_profile != 0x43) {
1207 d->do_stream_recording = 0;
1208 libdax_msgs_submit(libdax_messenger, d->global_index,
1209 0x000201ad,
1210 LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
1211 "Stream Recording suppressed due to medium type",
1212 0, 0);
1213 }
1214
1215 #endif /* ! Libburn_force_stream_recordinG */
1216
1217 } else if (recmode == -1) {
1218 d->do_stream_recording = 0;
1219 }
1220 if (d->do_stream_recording)
1221 d->stream_recording_start = start;
1222 else
1223 d->stream_recording_start = 0;
1224 return(1);
1225 }
1226
burn_drive_cancel(struct burn_drive * d)1227 void burn_drive_cancel(struct burn_drive *d)
1228 {
1229 /* ts B00225 : these mutexes are unnecessary because "= 1" is atomar.
1230 pthread_mutex_lock(&d->access_lock);
1231 */
1232 if (!d->cancel) {
1233 libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
1234 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
1235 "burn_drive_cancel() was called", 0, 0);
1236 }
1237 d->cancel = 1;
1238 /*
1239 pthread_mutex_unlock(&d->access_lock);
1240 */
1241 }
1242
1243
strip_spaces(char * str,size_t len)1244 static void strip_spaces(char *str, size_t len)
1245 {
1246 char *tmp, *tmp2;
1247
1248 /* Remove trailing blanks */
1249 for (tmp = str + len - 1; tmp >= str && (isspace(*tmp) || !*tmp); tmp--)
1250 *tmp = 0;
1251 /* Condense remaining blank intervals to single blanks */
1252 for (tmp = str; tmp < str + len - 1 && *tmp; tmp++) {
1253 if (isspace(*tmp) && isspace(*(tmp + 1))) {
1254 for (tmp2 = tmp + 1; tmp2 < str + len && *tmp2; tmp2++)
1255 *(tmp2 - 1) = *tmp2;
1256 *(tmp2 - 1) = '\0';
1257 tmp--; /* try same first blank again */
1258 }
1259 }
1260 }
1261
drive_getcaps(struct burn_drive * d,struct burn_drive_info * out)1262 static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
1263 {
1264 struct burn_scsi_inquiry_data *id;
1265 int i, profile;
1266 struct burn_feature_descr *feat;
1267
1268 /* ts A61007 : now prevented in enumerate_common() */
1269 #if 0
1270 a ssert(d->idata);
1271 a ssert(d->mdata);
1272 #endif
1273
1274 if(d->idata->valid <= 0)
1275 return 0;
1276
1277 id = (struct burn_scsi_inquiry_data *)d->idata;
1278
1279 memcpy(out->vendor, id->vendor, sizeof(id->vendor));
1280 strip_spaces(out->vendor, sizeof(id->vendor));
1281 memcpy(out->product, id->product, sizeof(id->product));
1282 strip_spaces(out->product, sizeof(id->product));
1283 memcpy(out->revision, id->revision, sizeof(id->revision));
1284 strip_spaces(out->revision, sizeof(id->revision));
1285 strncpy(out->location, d->devname, 16);
1286 out->location[16] = '\0';
1287
1288 if (d->mdata->p2a_valid > 0) {
1289 out->buffer_size = d->mdata->buffer_size;
1290 out->read_dvdram = !!d->mdata->dvdram_read;
1291 out->read_dvdr = !!d->mdata->dvdr_read;
1292 out->read_dvdrom = !!d->mdata->dvdrom_read;
1293 out->read_cdr = !!d->mdata->cdr_read;
1294 out->read_cdrw = !!d->mdata->cdrw_read;
1295 out->write_dvdram = !!d->mdata->dvdram_write;
1296 out->write_dvdr = !!d->mdata->dvdr_write;
1297 out->write_cdr = !!d->mdata->cdr_write;
1298 out->write_cdrw = !!d->mdata->cdrw_write;
1299 out->write_simulate = !!d->mdata->simulate;
1300 out->c2_errors = !!d->mdata->c2_pointers;
1301 } else {
1302 out->buffer_size = out->read_dvdram = out->read_dvdr = 0;
1303 out->read_dvdrom = out->read_cdr = out->read_cdrw = 0;
1304 out->write_dvdram = out->write_dvdr = out->write_cdr = 0;
1305 out->write_cdrw = out->write_simulate = out->c2_errors = 0;
1306 for (i = 0; i < d->num_profiles; i++) {
1307 profile = (d->all_profiles[i * 4] << 8) |
1308 d->all_profiles[i * 4 + 1];
1309 if (profile == 0x09)
1310 out->write_cdr = out->read_cdr = 1;
1311 else if (profile == 0x0a)
1312 out->write_cdrw = out->read_cdrw = 1;
1313 else if (profile == 0x10)
1314 out->read_dvdrom = 1;
1315 else if (profile == 0x11)
1316 out->write_dvdr = out->read_dvdr = 1;
1317 else if (profile == 0x12)
1318 out->write_dvdram = out->read_dvdram = 1;
1319 }
1320
1321 /* Test Write bit of CD TAO, CD Mastering, DVD-R/-RW Write */
1322 for (i = 0x002D; i <= 0x002F; i++)
1323 if (burn_drive_has_feature(d, i, &feat, 0))
1324 if (feat->data_lenght > 0)
1325 out->write_simulate |=
1326 !!(feat->data[0] & 4);
1327 }
1328
1329 out->drive = d;
1330
1331 #ifdef Libburn_dummy_probe_write_modeS
1332
1333 /* ts A91112 */
1334 /* Set default block types. The call d->probe_write_modes() is quite
1335 obtrusive. It may be performed explicitly by new API call
1336 burn_drive_probe_cd_write_modes().
1337 */
1338 if (out->write_dvdram || out->write_dvdr ||
1339 out->write_cdrw || out->write_cdr) {
1340 out->tao_block_types = d->block_types[BURN_WRITE_TAO] =
1341 BURN_BLOCK_MODE1 | BURN_BLOCK_RAW0;
1342 out->sao_block_types = d->block_types[BURN_WRITE_SAO] =
1343 BURN_BLOCK_SAO;
1344 } else {
1345 out->tao_block_types = d->block_types[BURN_WRITE_TAO] = 0;
1346 out->sao_block_types = d->block_types[BURN_WRITE_SAO] = 0;
1347 }
1348 out->raw_block_types = d->block_types[BURN_WRITE_RAW] = 0;
1349 out->packet_block_types = 0;
1350
1351 #else /* Libburn_dummy_probe_write_modeS */
1352
1353 /* update available block types for burners */
1354 if (out->write_dvdram || out->write_dvdr ||
1355 out->write_cdrw || out->write_cdr)
1356 d->probe_write_modes(d);
1357 out->tao_block_types = d->block_types[BURN_WRITE_TAO];
1358 out->sao_block_types = d->block_types[BURN_WRITE_SAO];
1359 out->raw_block_types = d->block_types[BURN_WRITE_RAW];
1360 out->packet_block_types = d->block_types[BURN_WRITE_PACKET];
1361
1362 #endif /* ! Libburn_dummy_probe_write_modeS */
1363
1364 return 1;
1365 }
1366
1367
1368
1369 /* ts A91112 - B00114 API */
1370 /* Probe available CD write modes and block types.
1371 */
burn_drive_probe_cd_write_modes(struct burn_drive_info * dinfo)1372 int burn_drive_probe_cd_write_modes(struct burn_drive_info *dinfo)
1373 {
1374 struct burn_drive *d = dinfo->drive;
1375
1376 if (d == NULL)
1377 return 0;
1378 if (dinfo->write_dvdram || dinfo->write_dvdr ||
1379 dinfo->write_cdrw || dinfo->write_cdr)
1380 d->probe_write_modes(d);
1381 dinfo->tao_block_types = d->block_types[BURN_WRITE_TAO];
1382 dinfo->sao_block_types = d->block_types[BURN_WRITE_SAO];
1383 dinfo->raw_block_types = d->block_types[BURN_WRITE_RAW];
1384 dinfo->packet_block_types = d->block_types[BURN_WRITE_PACKET];
1385 return 1;
1386 }
1387
1388
1389 /* ts A70907 : added parameter flag */
1390 /* @param flag bit0= reset global drive list */
burn_drive_scan_sync(struct burn_drive_info * drives[],unsigned int * n_drives,int flag)1391 int burn_drive_scan_sync(struct burn_drive_info *drives[],
1392 unsigned int *n_drives, int flag)
1393 {
1394 /* ts A70907 :
1395 There seems to have been a misunderstanding about the role of
1396 burn_drive_scan_sync(). It needs no static state because it
1397 is only started once during an asynchronous scan operation.
1398 Its starter, burn_drive_scan(), is the one which ends immediately
1399 and gets called repeatedly. It acts on start of scanning by
1400 calling burn_drive_scan_sync(), returns idle while scanning is
1401 not done and finally removes the worker object which represented
1402 burn_drive_scan_sync().
1403 The scanning itself is not parallel but enumerates sequentially
1404 drive by drive (within scsi_enumerate_drives()).
1405
1406 I will use "scanned" for marking drives found by previous runs.
1407 It will not be static any more.
1408 */
1409 /* ts A71015 : this makes only trouble : static int scanning = 0; */
1410 /* ts A70907 :
1411 These variables are too small anyway. We got up to 255 drives.
1412 static int scanned = 0, found = 0;
1413 Variable "found" was only set but never read.
1414 */
1415 unsigned char scanned[32];
1416 unsigned count = 0;
1417 int i, ret;
1418
1419 /* ts A61007 : moved up to burn_drive_scan() */
1420 /* a ssert(burn_running); */
1421
1422
1423 /* ts A61007 : test moved up to burn_drive_scan()
1424 burn_wait_all() is obsoleted */
1425 #if 0
1426 /* make sure the drives aren't in use */
1427 burn_wait_all(); /* make sure the queue cleans up
1428 before checking for the released
1429 state */
1430 #endif /* 0 */
1431
1432 *n_drives = 0;
1433
1434 /* ts A70907 : whether to scan from scratch or to extend */
1435 for (i = 0; i < (int) sizeof(scanned); i++)
1436 scanned[i] = 0;
1437 if (flag & 1) {
1438 burn_drive_free_all();
1439 } else {
1440 for (i = 0; i <= drivetop; i++)
1441 if (drive_array[i].global_index >= 0)
1442 scanned[i / 8] |= (1 << (i % 8));
1443 }
1444
1445 /* refresh the lib's drives */
1446
1447 /* ts A61115 : formerly sg_enumerate(); ata_enumerate(); */
1448 scsi_enumerate_drives();
1449
1450 count = burn_drive_count();
1451 if (count) {
1452 /* ts A70907 :
1453 Extra array element marks end of array. */
1454 *drives = calloc(count + 1,
1455 sizeof(struct burn_drive_info));
1456 if (*drives == NULL) {
1457 libdax_msgs_submit(libdax_messenger, -1, 0x00000003,
1458 LIBDAX_MSGS_SEV_FATAL,
1459 LIBDAX_MSGS_PRIO_HIGH,
1460 "Out of virtual memory", 0, 0);
1461 return -1;
1462 } else
1463 for (i = 0; i <= (int) count; i++) /* invalidate */
1464 (*drives)[i].drive = NULL;
1465 } else
1466 *drives = NULL;
1467
1468 for (i = 0; i < (int) count; ++i) {
1469 if (scanned[i / 8] & (1 << (i % 8)))
1470 continue; /* device already scanned by previous run */
1471 if (drive_array[i].global_index < 0)
1472 continue; /* invalid device */
1473
1474 /* ts A90602 : This old loop is not plausible. See A70907.
1475 while (!drive_getcaps(&drive_array[i],
1476 &(*drives)[*n_drives])) {
1477 sleep(1);
1478 }
1479 */
1480 /* ts A90602 : A single call shall do (rather than a loop) */
1481 ret = drive_getcaps(&drive_array[i], &(*drives)[*n_drives]);
1482 if (ret > 0)
1483 (*n_drives)++;
1484 scanned[i / 8] |= 1 << (i % 8);
1485 }
1486 if (*drives != NULL && *n_drives == 0) {
1487 free ((char *) *drives);
1488 *drives = NULL;
1489 }
1490
1491 return(1);
1492 }
1493
1494 /* ts A61001 : internal call */
burn_drive_forget(struct burn_drive * d,int force)1495 int burn_drive_forget(struct burn_drive *d, int force)
1496 {
1497 int occup;
1498
1499 occup = burn_drive_is_occupied(d);
1500 /*
1501 fprintf(stderr, "libburn: experimental: occup == %d\n",occup);
1502 */
1503 if(occup <= -2)
1504 return 2;
1505 if(occup > 0)
1506 if(force < 1)
1507 return 0;
1508 if(occup >= 10)
1509 return 0;
1510
1511 /* >>> do any drive calming here */;
1512
1513
1514 burn_drive_force_idle(d);
1515 if(occup > 0 && !burn_drive_is_released(d))
1516 burn_drive_release(d,0);
1517 burn_drive_free(d);
1518 return 1;
1519 }
1520
1521 /* API call */
burn_drive_info_forget(struct burn_drive_info * info,int force)1522 int burn_drive_info_forget(struct burn_drive_info *info, int force)
1523 {
1524 return burn_drive_forget(info->drive, force);
1525 }
1526
1527
burn_drive_info_free(struct burn_drive_info drive_infos[])1528 void burn_drive_info_free(struct burn_drive_info drive_infos[])
1529 {
1530 #ifndef Libburn_free_all_drives_on_infO
1531 int i;
1532 #endif
1533
1534 /* ts A60904 : ticket 62, contribution by elmom */
1535 /* clarifying the meaning and the identity of the victim */
1536
1537 if(drive_infos == NULL)
1538 return;
1539
1540 #ifndef Libburn_free_all_drives_on_infO
1541
1542 #ifdef Not_yeT
1543 int new_drivetop;
1544
1545 /* ts A71015: compute reduced drivetop counter */
1546 new_drivetop = drivetop;
1547 for (i = 0; drive_infos[i].drive != NULL; i++)
1548 if (drive_infos[i].global_index == new_drivetop
1549 && new_drivetop >= 0) {
1550 new_drivetop--;
1551 i = 0;
1552 }
1553 #endif /* Not_yeT */
1554
1555 /* ts A70907 : Solution for wrong behavior below */
1556 for (i = 0; drive_infos[i].drive != NULL; i++)
1557 burn_drive_free(drive_infos[i].drive);
1558
1559 #ifdef Not_yeT
1560 drivetop = new_drivetop;
1561 #endif /* Not_yeT */
1562
1563 #endif /* ! Libburn_free_all_drives_on_infO */
1564
1565 /* ts A60904 : This looks a bit weird. [ts A70907 : not any more]
1566 burn_drive_info is not the manager of burn_drive but only its
1567 spokesperson. To my knowledge drive_infos from burn_drive_scan()
1568 are not memorized globally. */
1569 free((void *) drive_infos);
1570
1571 #ifdef Libburn_free_all_drives_on_infO
1572 /* ts A70903 : THIS IS WRONG ! (disabled now)
1573 It endangers multi drive usage.
1574 This call is not entitled to delete all drives, only the
1575 ones of the array which it receives a parameter.
1576
1577 Problem: It was unclear how many items are listed in drive_infos
1578 Solution: Added a end marker element to any burn_drive_info array
1579 The mark can be recognized by having drive == NULL
1580 */
1581 burn_drive_free_all();
1582 #endif
1583 }
1584
1585
burn_drive_get_disc(struct burn_drive * d)1586 struct burn_disc *burn_drive_get_disc(struct burn_drive *d)
1587 {
1588 /* ts A61022: SIGSEGV on calling this function with blank media */
1589 if(d->disc == NULL)
1590 return NULL;
1591
1592 d->disc->refcnt++;
1593 return d->disc;
1594 }
1595
burn_drive_set_speed(struct burn_drive * d,int r,int w)1596 void burn_drive_set_speed(struct burn_drive *d, int r, int w)
1597 {
1598 d->nominal_write_speed = w;
1599 if(d->drive_role != 1)
1600 return;
1601 d->set_speed(d, r, w);
1602 }
1603
burn_drive_set_speed_exact(struct burn_drive * d,int r,int w)1604 int burn_drive_set_speed_exact(struct burn_drive *d, int r, int w)
1605 {
1606 int sose;
1607
1608 d->nominal_write_speed = w;
1609 if(d->drive_role != 1)
1610 return 0;
1611 sose = d->silent_on_scsi_error;
1612 d->silent_on_scsi_error = 3;
1613 d->set_streaming_err = 0;
1614 d->set_streaming_exact_bit = 1;
1615 d->set_speed(d, r, w);
1616 d->silent_on_scsi_error = sose;
1617 d->set_streaming_exact_bit = 0;
1618 return !d->set_streaming_err;
1619 }
1620
1621 /* ts A70711 API function */
burn_drive_set_buffer_waiting(struct burn_drive * d,int enable,int min_usec,int max_usec,int timeout_sec,int min_percent,int max_percent)1622 int burn_drive_set_buffer_waiting(struct burn_drive *d, int enable,
1623 int min_usec, int max_usec, int timeout_sec,
1624 int min_percent, int max_percent)
1625 {
1626
1627 if (enable >= 0)
1628 d->wait_for_buffer_free = !!enable;
1629 if (min_usec >= 0)
1630 d->wfb_min_usec = min_usec;
1631 if (max_usec >= 0)
1632 d->wfb_max_usec = max_usec;
1633 if (timeout_sec >= 0)
1634 d->wfb_timeout_sec = timeout_sec;
1635 if (min_percent >= 0) {
1636 if (min_percent < 25 || min_percent > 100)
1637 return 0;
1638 d->wfb_min_percent = min_percent;
1639 }
1640 if (max_percent >= 0) {
1641 if (max_percent < 25 || max_percent > 100)
1642 return 0;
1643 d->wfb_max_percent = max_percent;
1644 }
1645 return 1;
1646 }
1647
1648
burn_drive_reset_simulate(struct burn_drive * d,int simulate)1649 int burn_drive_reset_simulate(struct burn_drive *d, int simulate)
1650 {
1651 if (d->busy != BURN_DRIVE_IDLE) {
1652 libdax_msgs_submit(libdax_messenger,
1653 d->global_index, 0x00020140,
1654 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
1655 "Drive is busy on attempt to write random access",0,0);
1656 return 0;
1657 }
1658 d->do_simulate = !!simulate;
1659 return 1;
1660 }
1661
1662
burn_msf_to_sectors(int m,int s,int f)1663 int burn_msf_to_sectors(int m, int s, int f)
1664 {
1665 return (m * 60 + s) * 75 + f;
1666 }
1667
burn_sectors_to_msf(int sectors,int * m,int * s,int * f)1668 void burn_sectors_to_msf(int sectors, int *m, int *s, int *f)
1669 {
1670 *m = sectors / (60 * 75);
1671 *s = (sectors - *m * 60 * 75) / 75;
1672 *f = sectors - *m * 60 * 75 - *s * 75;
1673 }
1674
burn_drive_get_read_speed(struct burn_drive * d)1675 int burn_drive_get_read_speed(struct burn_drive *d)
1676 {
1677 return d->mdata->max_read_speed;
1678 }
1679
burn_drive_get_write_speed(struct burn_drive * d)1680 int burn_drive_get_write_speed(struct burn_drive *d)
1681 {
1682 return d->mdata->max_write_speed;
1683 }
1684
1685 /* ts A61021 : New API function */
burn_drive_get_min_write_speed(struct burn_drive * d)1686 int burn_drive_get_min_write_speed(struct burn_drive *d)
1687 {
1688 return d->mdata->min_write_speed;
1689 }
1690
1691
1692 /* ts A51221 */
1693 static char *enumeration_whitelist[BURN_DRIVE_WHITELIST_LEN];
1694 static int enumeration_whitelist_top = -1;
1695
1696 /** Add a device to the list of permissible drives. As soon as some entry is in
1697 the whitelist all non-listed drives are banned from enumeration.
1698 @return 1 success, <=0 failure
1699 */
burn_drive_add_whitelist(char * device_address)1700 int burn_drive_add_whitelist(char *device_address)
1701 {
1702 char *new_item;
1703 if(enumeration_whitelist_top+1 >= BURN_DRIVE_WHITELIST_LEN)
1704 return 0;
1705 enumeration_whitelist_top++;
1706 new_item = calloc(1, strlen(device_address) + 1);
1707 if (new_item == NULL)
1708 return -1;
1709 strcpy(new_item, device_address);
1710 enumeration_whitelist[enumeration_whitelist_top] = new_item;
1711 return 1;
1712 }
1713
1714 /** Remove all drives from whitelist. This enables all possible drives. */
burn_drive_clear_whitelist(void)1715 void burn_drive_clear_whitelist(void)
1716 {
1717 int i;
1718 for (i = 0; i <= enumeration_whitelist_top; i++)
1719 free(enumeration_whitelist[i]);
1720 enumeration_whitelist_top = -1;
1721 }
1722
burn_drive_is_banned(char * device_address)1723 int burn_drive_is_banned(char *device_address)
1724 {
1725 int i;
1726 if(enumeration_whitelist_top<0)
1727 return 0;
1728 for (i = 0; i <= enumeration_whitelist_top; i++)
1729 if (strcmp(enumeration_whitelist[i], device_address) == 0)
1730 return 0;
1731 return 1;
1732 }
1733
1734
1735 /* ts A80731 */
burn_drive_whitelist_count(void)1736 int burn_drive_whitelist_count(void)
1737 {
1738 return enumeration_whitelist_top + 1;
1739 }
1740
burn_drive_whitelist_item(int idx,int flag)1741 char *burn_drive_whitelist_item(int idx, int flag)
1742 {
1743 if (idx < 0 || idx > enumeration_whitelist_top)
1744 return NULL;
1745 return enumeration_whitelist[idx];
1746 }
1747
1748
burn_role_by_access(char * fname,int flag)1749 static int burn_role_by_access(char *fname, int flag)
1750 {
1751 /* We normally need _LARGEFILE64_SOURCE defined by the build system.
1752 Nevertheless the system might use large address integers by default.
1753 */
1754 #ifndef O_LARGEFILE
1755 #define O_LARGEFILE 0
1756 #endif
1757 int fd;
1758
1759 fd = open(fname, O_RDWR | O_LARGEFILE | O_BINARY);
1760 if (fd != -1) {
1761 close(fd);
1762 return 2;
1763 }
1764 fd = open(fname, O_RDONLY | O_LARGEFILE | O_BINARY);
1765 if (fd != -1) {
1766 close(fd);
1767 return 4;
1768 }
1769 fd = open(fname, O_WRONLY | O_LARGEFILE | O_BINARY);
1770 if (fd != -1) {
1771 close(fd);
1772 return 5;
1773 }
1774 if (flag & 1)
1775 return 0;
1776 return 2;
1777 }
1778
1779
1780 /* ts A70903 : Implements adquiration of pseudo drives */
burn_drive_grab_dummy(struct burn_drive_info * drive_infos[],char * fname)1781 int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
1782 {
1783 int ret = -1, role = 0, fd;
1784 int is_rdwr = 0, stat_ret = -1;
1785 /* divided by 512 it needs to fit into a signed long integer */
1786 off_t size = ((off_t) (512 * 1024 * 1024 - 1) * (off_t) 2048);
1787 off_t read_size = -1;
1788 struct burn_drive *d= NULL, *regd_d;
1789 struct stat stbuf;
1790
1791 if (fname[0] != 0) {
1792 fd = burn_drive__fd_from_special_adr(fname);
1793 is_rdwr = burn_drive__is_rdwr(fname, &stat_ret, &stbuf,
1794 &read_size, 1 | 2);
1795 if (stat_ret == -1 || is_rdwr) {
1796 ret = burn_os_stdio_capacity(fname, 0, &size);
1797 if (ret == -1) {
1798 libdax_msgs_submit(libdax_messenger, -1,
1799 0x00020009,
1800 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
1801 "Neither stdio-path nor its directory exist",
1802 0, 0);
1803 return 0;
1804 } else if (ret == -2) {
1805 libdax_msgs_submit(libdax_messenger, -1,
1806 0x00020005,
1807 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
1808 "Failed to open device (a pseudo-drive)",
1809 errno, 0);
1810 return 0;
1811 }
1812 if (fname[0] != 0) {
1813 if (is_rdwr == 2 &&
1814 (burn_drive_role_4_allowed & 1))
1815 role = 4;
1816 else if (is_rdwr == 3 &&
1817 (burn_drive_role_4_allowed & 1))
1818 role = 5;
1819 else
1820 role = 2;
1821 if (stat_ret != -1 && role == 2 && fd == -1 &&
1822 (burn_drive_role_4_allowed & 3) == 3)
1823 role = burn_role_by_access(fname,
1824 !!(burn_drive_role_4_allowed & 4));
1825 } else
1826 role = 0;
1827 } else {
1828 role = 3;
1829 }
1830 }
1831 d= (struct burn_drive *) calloc(1, sizeof(struct burn_drive));
1832 if (d == NULL)
1833 return 0;
1834 burn_setup_drive(d, fname);
1835 d->status = BURN_DISC_EMPTY;
1836
1837 d->drive_role = role;
1838 ret = burn_scsi_setup_drive(d, -1, -1, -1, -1, -1, 0);
1839 if (ret <= 0)
1840 goto ex;
1841 regd_d = burn_drive_register(d);
1842 if (regd_d == NULL) {
1843 ret = -1;
1844 goto ex;
1845 }
1846 free((char *) d); /* all sub pointers have been copied to *regd_d */
1847 d = regd_d;
1848 if (d->drive_role >= 2 && d->drive_role <= 5) {
1849 if (d->drive_role == 4) {
1850 if (read_size > 0)
1851 d->status = BURN_DISC_FULL;
1852 else
1853 d->status = BURN_DISC_EMPTY;
1854 d->block_types[BURN_WRITE_TAO] = 0;
1855 d->block_types[BURN_WRITE_SAO] = 0;
1856 } else {
1857 if (d->drive_role == 5 && stat_ret != -1 &&
1858 S_ISREG(stbuf.st_mode) && stbuf.st_size > 0 &&
1859 (burn_drive_role_4_allowed & 8)) {
1860 d->status = BURN_DISC_APPENDABLE;
1861 d->block_types[BURN_WRITE_SAO] = 0;
1862 if (stbuf.st_size / (off_t) 2048
1863 >= 0x7ffffff0) {
1864 d->status = BURN_DISC_FULL;
1865 d->role_5_nwa = 0x7ffffff0;
1866 } else
1867 d->role_5_nwa = stbuf.st_size / 2048 +
1868 !!(stbuf.st_size % 2048);
1869 } else {
1870 d->status = BURN_DISC_BLANK;
1871 d->block_types[BURN_WRITE_SAO] =
1872 BURN_BLOCK_SAO;
1873 d->role_5_nwa = 0;
1874 }
1875 d->block_types[BURN_WRITE_TAO] = BURN_BLOCK_MODE1;
1876 }
1877 d->current_profile = 0xffff; /* MMC for non-compliant drive */
1878 strcpy(d->current_profile_text,"stdio file");
1879 d->current_is_cd_profile = 0;
1880 d->current_is_supported_profile = 1;
1881 if (read_size >= 0) {
1882 /* despite its name : last valid address, not size */
1883 d->media_read_capacity =
1884 read_size / 2048 - !(read_size % 2048);
1885 d->mr_capacity_trusted = 1;
1886 }
1887 burn_drive_set_media_capacity_remaining(d, size);
1888 } else
1889 d->current_profile = 0; /* Drives return this if empty */
1890
1891 *drive_infos = calloc(2, sizeof(struct burn_drive_info));
1892 if (*drive_infos == NULL)
1893 goto ex;
1894 (*drive_infos)[0].drive = d;
1895 (*drive_infos)[1].drive = NULL; /* End-Of-List mark */
1896 (*drive_infos)[0].tao_block_types = d->block_types[BURN_WRITE_TAO];
1897 (*drive_infos)[0].sao_block_types = d->block_types[BURN_WRITE_SAO];
1898 if (d->drive_role == 2) {
1899 strcpy((*drive_infos)[0].vendor,"YOYODYNE");
1900 strcpy((*drive_infos)[0].product,"WARP DRIVE");
1901 strcpy((*drive_infos)[0].revision,"FX01");
1902 } else if (d->drive_role == 3) {
1903 strcpy((*drive_infos)[0].vendor,"YOYODYNE");
1904 strcpy((*drive_infos)[0].product,"BLACKHOLE");
1905 strcpy((*drive_infos)[0].revision,"FX02");
1906 } else if (d->drive_role == 4) {
1907 strcpy((*drive_infos)[0].vendor,"YOYODYNE");
1908 strcpy((*drive_infos)[0].product,"WARP DRIVE");
1909 strcpy((*drive_infos)[0].revision,"FX03");
1910 } else if (d->drive_role == 5) {
1911 strcpy((*drive_infos)[0].vendor,"YOYODYNE");
1912 strcpy((*drive_infos)[0].product,"WARP DRIVE");
1913 strcpy((*drive_infos)[0].revision,"FX04");
1914 } else {
1915 strcpy((*drive_infos)[0].vendor,"FERENGI");
1916 strcpy((*drive_infos)[0].product,"VAPORWARE");
1917 strcpy((*drive_infos)[0].revision,"0000");
1918 }
1919 d->released = 0;
1920 ret = 1;
1921 ex:;
1922 if (ret <= 0 && d != NULL) {
1923 burn_drive_free_subs(d);
1924 free((char *) d);
1925 }
1926 return ret;
1927 }
1928
1929
1930 /* ts A60823 */
1931 /** Acquire a drive with known persistent address.
1932 */
burn_drive_scan_and_grab(struct burn_drive_info * drive_infos[],char * adr,int load)1933 int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], char* adr,
1934 int load)
1935 {
1936 unsigned int n_drives;
1937 int ret, i;
1938
1939 /* check whether drive address is already registered */
1940 for (i = 0; i <= drivetop; i++)
1941 if (drive_array[i].global_index >= 0)
1942 if (strcmp(drive_array[i].devname, adr) == 0)
1943 break;
1944 if (i <= drivetop) {
1945 libdax_msgs_submit(libdax_messenger, i,
1946 0x0002014b,
1947 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
1948 "Drive is already registered resp. scanned",
1949 0, 0);
1950 return -1;
1951 }
1952
1953 if (strncmp(adr, "stdio:", 6) == 0) {
1954 ret = burn_drive_grab_dummy(drive_infos, adr + 6);
1955 return ret;
1956 }
1957
1958 burn_drive_clear_whitelist();
1959 burn_drive_add_whitelist(adr);
1960 /*
1961 fprintf(stderr,"libburn: experimental: burn_drive_scan_and_grab(%s)\n",
1962 adr);
1963 */
1964
1965 /* ts A70907 : now calling synchronously rather than looping */
1966 ret = burn_drive_scan_sync(drive_infos, &n_drives, 0);
1967 if (ret < 0)
1968 return -1;
1969
1970 if (n_drives == 0)
1971 return 0;
1972 /*
1973 fprintf(stderr, "libburn: experimental: n_drives %d , drivetop %d\n",
1974 n_drives, drivetop);
1975 if (n_drives > 0)
1976 fprintf(stderr, "libburn: experimental: global_index %d\n",
1977 drive_infos[0]->drive->global_index);
1978 */
1979
1980 ret = burn_drive_grab(drive_infos[0]->drive, load);
1981 if (ret != 1) {
1982 burn_drive_forget(drive_infos[0]->drive, 0);
1983 return -1;
1984 }
1985 return 1;
1986 }
1987
1988 /* ts A60925 */
1989 /** Simple debug message frontend to libdax_msgs_submit().
1990 If arg is not NULL, then fmt MUST contain exactly one %s and no
1991 other sprintf() %-formatters.
1992 */
burn_drive_adr_debug_msg(char * fmt,char * arg)1993 int burn_drive_adr_debug_msg(char *fmt, char *arg)
1994 {
1995 int ret;
1996 char *msg = NULL, *msgpt;
1997
1998 if(libdax_messenger == NULL)
1999 return 0;
2000 if(arg != NULL) {
2001 BURN_ALLOC_MEM(msg, char, 4096);
2002 msgpt = msg;
2003 sprintf(msg, fmt, arg);
2004 } else {
2005 msgpt = fmt;
2006 }
2007 ret = libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
2008 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
2009 msgpt, 0, 0);
2010 ex:;
2011 BURN_FREE_MEM(msg);
2012 return ret;
2013 }
2014
2015 /* ts A60923 */ /* ts A70906 : promoted to API */
2016 /** Inquire the persistent address of the given drive. */
burn_drive_d_get_adr(struct burn_drive * d,char adr[])2017 int burn_drive_d_get_adr(struct burn_drive *d, char adr[])
2018 {
2019 if (strlen(d->devname) >= BURN_DRIVE_ADR_LEN) {
2020 libdax_msgs_submit(libdax_messenger, d->global_index,
2021 0x00020110,
2022 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
2023 "Persistent drive address too long", 0, 0);
2024 return -1;
2025 }
2026 strcpy(adr,d->devname);
2027 return 1;
2028 }
2029
2030 /* ts A60823 - A60923 */ /* A70906 : Now legacy API call */
2031 /** Inquire the persistent address of the given drive. */
burn_drive_get_adr(struct burn_drive_info * drive_info,char adr[])2032 int burn_drive_get_adr(struct burn_drive_info *drive_info, char adr[])
2033 {
2034 int ret;
2035
2036 ret = burn_drive_d_get_adr(drive_info->drive, adr);
2037 return ret;
2038 }
2039
2040
2041
2042
2043 /* ts A60922 ticket 33 */
2044 /** Evaluate whether the given address would be enumerated by libburn */
burn_drive_is_enumerable_adr(char * adr)2045 int burn_drive_is_enumerable_adr(char *adr)
2046 {
2047 return sg_is_enumerable_adr(adr);
2048 }
2049
2050 #define BURN_DRIVE_MAX_LINK_DEPTH 20
2051
2052 /* ts A60922 ticket 33 */
2053 /* @param flag bit0= no debug messages
2054 bit1= resolve only links,
2055 do not rely on drive list for resolving via st_rdev
2056 */
burn_drive_resolve_link(char * path,char adr[],int * recursion_count,int flag)2057 int burn_drive_resolve_link(char *path, char adr[], int *recursion_count,
2058 int flag)
2059 {
2060 int ret, link_target_size = 4096;
2061 char *link_target = NULL, *msg = NULL, *link_adr = NULL, *adrpt;
2062 struct stat stbuf;
2063
2064 BURN_ALLOC_MEM(link_target, char, link_target_size);
2065 BURN_ALLOC_MEM(msg, char, link_target_size + 100);
2066 BURN_ALLOC_MEM(link_adr, char, link_target_size);
2067
2068 if (flag & 1)
2069 burn_drive_adr_debug_msg("burn_drive_resolve_link( %s )",
2070 path);
2071 if (*recursion_count >= BURN_DRIVE_MAX_LINK_DEPTH) {
2072 if (flag & 1)
2073 burn_drive_adr_debug_msg(
2074 "burn_drive_resolve_link aborts because link too deep",
2075 NULL);
2076 {ret = 0; goto ex;}
2077 }
2078 (*recursion_count)++;
2079 ret = readlink(path, link_target, link_target_size);
2080 if (ret == -1) {
2081 if (flag & 1)
2082 burn_drive_adr_debug_msg("readlink( %s ) returns -1",
2083 path);
2084 {ret = 0; goto ex;}
2085 }
2086 if (ret >= link_target_size - 1) {
2087 sprintf(msg,"readlink( %s ) returns %d (too much)", path, ret);
2088 if (flag & 1)
2089 burn_drive_adr_debug_msg(msg, NULL);
2090 {ret = -1; goto ex;}
2091 }
2092 link_target[ret] = 0;
2093 adrpt = link_target;
2094 if (link_target[0] != '/') {
2095 strcpy(link_adr, path);
2096 if ((adrpt = strrchr(link_adr, '/')) != NULL) {
2097 strcpy(adrpt + 1, link_target);
2098 adrpt = link_adr;
2099 } else
2100 adrpt = link_target;
2101 }
2102 if (flag & 2) {
2103 /* Link-only recursion */
2104 if (lstat(adrpt, &stbuf) == -1) {
2105 ;
2106 } else if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
2107 ret = burn_drive_resolve_link(adrpt, adr,
2108 recursion_count, flag);
2109 } else {
2110 strcpy(adr, adrpt);
2111 }
2112 } else {
2113 /* Link and device number recursion */
2114 ret = burn_drive_convert_fs_adr_sub(adrpt, adr,
2115 recursion_count);
2116 sprintf(msg,"burn_drive_convert_fs_adr( %s ) returns %d",
2117 link_target, ret);
2118 }
2119 if (flag & 1)
2120 burn_drive_adr_debug_msg(msg, NULL);
2121 ex:;
2122 BURN_FREE_MEM(link_target);
2123 BURN_FREE_MEM(msg);
2124 BURN_FREE_MEM(link_adr);
2125 return ret;
2126 }
2127
2128 /* ts A60922 - A61014 ticket 33 */
2129 /* Try to find an enumerated address with the given stat.st_rdev number */
burn_drive_find_devno(dev_t devno,char adr[])2130 int burn_drive_find_devno(dev_t devno, char adr[])
2131 {
2132 char *fname = NULL, *msg = NULL;
2133 int ret = 0, first = 1, fname_size = 4096;
2134 struct stat stbuf;
2135 burn_drive_enumerator_t enm;
2136
2137 BURN_ALLOC_MEM(fname, char, fname_size);
2138 BURN_ALLOC_MEM(msg, char, fname_size + 100);
2139
2140 while (1) {
2141 ret = sg_give_next_adr(&enm, fname, fname_size, first);
2142 if(ret <= 0)
2143 break;
2144 first = 0;
2145 ret = stat(fname, &stbuf);
2146 if(ret == -1)
2147 continue;
2148 if(devno != stbuf.st_rdev)
2149 continue;
2150 if(strlen(fname) >= BURN_DRIVE_ADR_LEN)
2151 {ret= -1; goto ex;}
2152
2153 sprintf(msg, "burn_drive_find_devno( 0x%lX ) found %s",
2154 (long) devno, fname);
2155 burn_drive_adr_debug_msg(msg, NULL);
2156 strcpy(adr, fname);
2157 { ret = 1; goto ex;}
2158 }
2159 ret = 0;
2160 ex:;
2161 if (first == 0)
2162 sg_give_next_adr(&enm, fname, fname_size, -1);
2163 BURN_FREE_MEM(fname);
2164 BURN_FREE_MEM(msg);
2165 return ret;
2166 }
2167
2168 /* ts A60923 */
2169 /** Try to obtain host,channel,target,lun from path.
2170 @return 1 = success , 0 = failure , -1 = severe error
2171 */
burn_drive_obtain_scsi_adr(char * path,int * bus_no,int * host_no,int * channel_no,int * target_no,int * lun_no)2172 int burn_drive_obtain_scsi_adr(char *path,
2173 int *bus_no, int *host_no, int *channel_no,
2174 int *target_no, int *lun_no)
2175 {
2176 int ret, i;
2177 char *adr = NULL;
2178
2179 BURN_ALLOC_MEM(adr, char, BURN_DRIVE_ADR_LEN);
2180
2181 /* open drives cannot be inquired by sg_obtain_scsi_adr() */
2182 for (i = 0; i < drivetop + 1; i++) {
2183 if (drive_array[i].global_index < 0)
2184 continue;
2185 ret = burn_drive_d_get_adr(&(drive_array[i]),adr);
2186 if (ret < 0)
2187 {ret = 1; goto ex;}
2188 if (ret == 0)
2189 continue;
2190 if (strcmp(adr, path) == 0) {
2191 *host_no = drive_array[i].host;
2192 *channel_no = drive_array[i].channel;
2193 *target_no = drive_array[i].id;
2194 *lun_no = drive_array[i].lun;
2195 *bus_no = drive_array[i].bus_no;
2196 if (*host_no < 0 || *channel_no < 0 ||
2197 *target_no < 0 || *lun_no < 0)
2198 {ret = 0; goto ex;}
2199 {ret = 1; goto ex;}
2200 }
2201 }
2202
2203 ret = sg_obtain_scsi_adr(path, bus_no, host_no, channel_no,
2204 target_no, lun_no);
2205 ex:;
2206 BURN_FREE_MEM(adr);
2207 return ret;
2208 }
2209
2210 /* ts A60923 */
burn_drive_convert_scsi_adr(int bus_no,int host_no,int channel_no,int target_no,int lun_no,char adr[])2211 int burn_drive_convert_scsi_adr(int bus_no, int host_no, int channel_no,
2212 int target_no, int lun_no, char adr[])
2213 {
2214 char *fname = NULL, *msg = NULL;
2215 int ret = 0, first = 1, i_bus_no = -1, fname_size = 4096;
2216 int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
2217 burn_drive_enumerator_t enm;
2218
2219 BURN_ALLOC_MEM(fname, char, fname_size);
2220 BURN_ALLOC_MEM(msg, char, fname_size + 100);
2221
2222 sprintf(msg,"burn_drive_convert_scsi_adr( %d,%d,%d,%d,%d )",
2223 bus_no, host_no, channel_no, target_no, lun_no);
2224 burn_drive_adr_debug_msg(msg, NULL);
2225
2226 while (1) {
2227 ret= sg_give_next_adr(&enm, fname, fname_size, first);
2228 if(ret <= 0)
2229 break;
2230 first = 0;
2231 ret = burn_drive_obtain_scsi_adr(fname, &i_bus_no, &i_host_no,
2232 &i_channel_no, &i_target_no, &i_lun_no);
2233 if(ret <= 0)
2234 continue;
2235 if(bus_no >=0 && i_bus_no != bus_no)
2236 continue;
2237 if(host_no >=0 && i_host_no != host_no)
2238 continue;
2239 if(channel_no >= 0 && i_channel_no != channel_no)
2240 continue;
2241 if(target_no >= 0 && i_target_no != target_no)
2242 continue;
2243 if(lun_no >= 0 && i_lun_no != lun_no)
2244 continue;
2245 if(strlen(fname) >= BURN_DRIVE_ADR_LEN)
2246 { ret = -1; goto ex;}
2247 burn_drive_adr_debug_msg(
2248 "burn_drive_convert_scsi_adr() found %s", fname);
2249 strcpy(adr, fname);
2250 { ret = 1; goto ex;}
2251 }
2252 ret = 0;
2253 ex:;
2254 if (first == 0)
2255 sg_give_next_adr(&enm, fname, fname_size, -1);
2256 BURN_FREE_MEM(fname);
2257 BURN_FREE_MEM(msg);
2258 return ret;
2259 }
2260
2261 /* ts A60922 ticket 33 */
2262 /* Try to find an enumerated address with the same host,channel,target,lun
2263 as path */
burn_drive_find_scsi_equiv(char * path,char adr[])2264 int burn_drive_find_scsi_equiv(char *path, char adr[])
2265 {
2266 int ret = 0;
2267 int bus_no, host_no, channel_no, target_no, lun_no;
2268 char msg[4096];
2269
2270 ret = burn_drive_obtain_scsi_adr(path, &bus_no, &host_no, &channel_no,
2271 &target_no, &lun_no);
2272 if(ret <= 0) {
2273 sprintf(msg,"burn_drive_obtain_scsi_adr( %s ) returns %d",
2274 path, ret);
2275 burn_drive_adr_debug_msg(msg, NULL);
2276 return 0;
2277 }
2278 sprintf(msg, "burn_drive_find_scsi_equiv( %s ) : (%d),%d,%d,%d,%d",
2279 path, bus_no, host_no, channel_no, target_no, lun_no);
2280 burn_drive_adr_debug_msg(msg, NULL);
2281
2282 ret= burn_drive_convert_scsi_adr(-1, host_no, channel_no, target_no,
2283 lun_no, adr);
2284 return ret;
2285 }
2286
2287
2288 /* ts A60922 ticket 33 */
2289 /** Try to convert a given existing filesystem address into a persistent drive
2290 address. */
burn_drive_convert_fs_adr_sub(char * path,char adr[],int * rec_count)2291 int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count)
2292 {
2293 int ret;
2294 struct stat stbuf;
2295
2296 burn_drive_adr_debug_msg("burn_drive_convert_fs_adr( %s )", path);
2297 if (strncmp(path, "stdio:", 6) == 0 ||
2298 burn_drive_is_enumerable_adr(path)) {
2299 if(strlen(path) >= BURN_DRIVE_ADR_LEN)
2300 return -1;
2301 if (strncmp(path, "stdio:", 6) != 0)
2302 burn_drive_adr_debug_msg(
2303 "burn_drive_is_enumerable_adr( %s ) is true", path);
2304 strcpy(adr, path);
2305 return 1;
2306 }
2307
2308 if(lstat(path, &stbuf) == -1) {
2309 burn_drive_adr_debug_msg("lstat( %s ) returns -1", path);
2310 return 0;
2311 }
2312 if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
2313 ret = burn_drive_resolve_link(path, adr, rec_count, 0);
2314 if(ret > 0)
2315 return 1;
2316 burn_drive_adr_debug_msg("link fallback via stat( %s )", path);
2317 if(stat(path, &stbuf) == -1) {
2318 burn_drive_adr_debug_msg("stat( %s ) returns -1",path);
2319 return 0;
2320 }
2321 }
2322 if((stbuf.st_mode&S_IFMT) == S_IFBLK ||
2323 (stbuf.st_mode&S_IFMT) == S_IFCHR) {
2324 ret = burn_drive_find_devno(stbuf.st_rdev, adr);
2325 if(ret > 0)
2326 return 1;
2327 ret = burn_drive_find_scsi_equiv(path, adr);
2328 if(ret > 0)
2329 return 1;
2330 }
2331 burn_drive_adr_debug_msg("Nothing found for %s", path);
2332 return 0;
2333 }
2334
2335 /* API */
2336 /** Try to convert a given existing filesystem address into a persistent drive
2337 address. */
burn_drive_convert_fs_adr(char * path,char adr[])2338 int burn_drive_convert_fs_adr(char *path, char adr[])
2339 {
2340 int ret, rec_count = 0;
2341
2342 ret = burn_drive_convert_fs_adr_sub(path, adr, &rec_count);
2343 return ret;
2344 }
2345
2346
2347 /* API */
burn_lookup_device_link(char * dev_adr,char link_adr[],char * dir_adr,char ** ranks,int rank_count,int flag)2348 int burn_lookup_device_link(char *dev_adr, char link_adr[],
2349 char *dir_adr, char **ranks, int rank_count, int flag)
2350 {
2351 DIR *dirpt= NULL;
2352 struct dirent *entry;
2353 struct stat link_stbuf;
2354 char *adr= NULL, *namept, *sys_adr= NULL;
2355 int ret, name_rank, found_rank= 0x7fffffff, dirlen, i, rec_count = 0;
2356 static char default_ranks_data[][8] =
2357 {"dvdrw", "cdrw", "dvd", "cdrom", "cd"};
2358 char *default_ranks[5];
2359
2360 link_adr[0] = 0;
2361 if (ranks == NULL) {
2362 for (i = 0; i < 5; i++)
2363 default_ranks[i] = default_ranks_data[i];
2364 ranks = default_ranks;
2365 rank_count= 5;
2366 }
2367 dirlen= strlen(dir_adr) + 1;
2368 if (strlen(dir_adr) + 1 >= BURN_DRIVE_ADR_LEN) {
2369
2370 /* >>> Issue warning about oversized directory address */;
2371
2372 {ret = 0; goto ex;}
2373 }
2374 BURN_ALLOC_MEM(adr, char, BURN_DRIVE_ADR_LEN);
2375 BURN_ALLOC_MEM(sys_adr, char, BURN_DRIVE_ADR_LEN);
2376
2377 dirpt = opendir(dir_adr);
2378 if (dirpt == NULL)
2379 {ret = 0; goto ex;}
2380 strcpy(adr, dir_adr);
2381 strcat(adr, "/");
2382 namept = adr + strlen(dir_adr) + 1;
2383 while(1) {
2384 entry = readdir(dirpt);
2385 if(entry == NULL)
2386 break;
2387 if (strlen(entry->d_name) + dirlen >= BURN_DRIVE_ADR_LEN)
2388 continue;
2389 strcpy(namept, entry->d_name);
2390 if(lstat(adr, &link_stbuf) == -1)
2391 continue;
2392 if((link_stbuf.st_mode & S_IFMT) != S_IFLNK)
2393 continue;
2394 /* Determine rank and omit uninteresting ones */
2395 for(name_rank= 0; name_rank < rank_count; name_rank++)
2396 if(strncmp(namept, ranks[name_rank],
2397 strlen(ranks[name_rank])) == 0)
2398 break;
2399 /* we look for lowest rank */
2400 if(name_rank >= rank_count ||
2401 name_rank > found_rank ||
2402 (name_rank == found_rank &&
2403 strcmp(namept, link_adr + dirlen) >= 0))
2404 continue;
2405
2406 /* Does name point to the same device as dev_adr ? */
2407 ret= burn_drive_resolve_link(adr, sys_adr, &rec_count, 2);
2408 if(ret < 0)
2409 goto ex;
2410 if(ret == 0)
2411 continue;
2412 if(strcmp(dev_adr, sys_adr) == 0) {
2413 strcpy(link_adr, adr);
2414 found_rank= name_rank;
2415 }
2416 }
2417 ret= 2;
2418 if(found_rank < 0x7fffffff)
2419 ret= 1;
2420 ex:;
2421 if(dirpt != NULL)
2422 closedir(dirpt);
2423 BURN_FREE_MEM(adr);
2424 BURN_FREE_MEM(sys_adr);
2425 return(ret);
2426 }
2427
2428
2429 /** A pacifier function suitable for burn_abort.
2430 @param handle If not NULL, a pointer to a text suitable for printf("%s")
2431 */
burn_abort_pacifier(void * handle,int patience,int elapsed)2432 int burn_abort_pacifier(void *handle, int patience, int elapsed)
2433 {
2434 char *prefix= "libburn : ";
2435
2436 if(handle!=NULL)
2437 prefix= handle;
2438 fprintf(stderr,
2439 "\r%sABORT : Waiting for drive to finish ( %d s, %d max)",
2440 (char *) prefix, elapsed, patience);
2441 return(1);
2442 }
2443
2444
2445 /* ts B00226 : Outsourced backend of burn_abort()
2446 @param flag bit0= do not call burn_finish()
2447 */
burn_abort_5(int patience,int (* pacifier_func)(void * handle,int patience,int elapsed),void * handle,int elapsed,int flag)2448 int burn_abort_5(int patience,
2449 int (*pacifier_func)(void *handle, int patience, int elapsed),
2450 void *handle, int elapsed, int flag)
2451 {
2452 int ret, i, occup, still_not_done= 1, pacifier_off= 0, first_round= 1;
2453 unsigned long wait_grain= 100000;
2454 time_t start_time, current_time, pacifier_time, end_time;
2455
2456 #ifndef NIX
2457 time_t stdio_patience = 3;
2458 #endif
2459
2460
2461 /*
2462 fprintf(stderr,
2463 "libburn_EXPERIMENTAL: burn_abort_5(%d,%d)\n", patience, flag);
2464 */
2465
2466 current_time = start_time = pacifier_time = time(0);
2467 start_time -= elapsed;
2468 end_time = start_time + patience;
2469
2470 /* >>> ts A71002 : are there any threads at work ?
2471 If not, then one can force abort because the drives will not
2472 change status on their own.
2473 */
2474
2475 while(current_time < end_time || (patience <= 0 && first_round)) {
2476 still_not_done = 0;
2477
2478 for(i = 0; i < drivetop + 1; i++) {
2479 occup = burn_drive_is_occupied(&(drive_array[i]));
2480 if(occup == -2)
2481 continue;
2482
2483 if(drive_array[i].drive_role != 1) {
2484
2485 #ifdef NIX
2486
2487 /* ts A90302
2488 <<< this causes a race condition with drive
2489 usage and drive disposal.
2490 */
2491 drive_array[i].busy = BURN_DRIVE_IDLE;
2492 burn_drive_forget(&(drive_array[i]), 1);
2493 continue;
2494
2495 #else /* NIX */
2496
2497 /* ts A90318
2498 >>> but if a pipe breaks then the drive
2499 never gets idle.
2500 So for now with a short patience timespan
2501 and eventually a deliberate memory leak.
2502 */
2503 if (current_time - start_time >
2504 stdio_patience) {
2505 drive_array[i].global_index = -1;
2506 continue;
2507 }
2508
2509 #endif /* ! NIX */
2510
2511 }
2512
2513 if(occup < 10) {
2514 if (!drive_array[i].cancel)
2515 burn_drive_cancel(&(drive_array[i]));
2516 if (drive_array[i].drive_role != 1)
2517 /* occup == -1 comes early */
2518 usleep(1000000);
2519 burn_drive_forget(&(drive_array[i]), 1);
2520 } else if(occup <= 100) {
2521 if (!drive_array[i].cancel)
2522 burn_drive_cancel(&(drive_array[i]));
2523 still_not_done++;
2524 } else if(occup <= 1000) {
2525 still_not_done++;
2526 }
2527 }
2528 first_round = 0;
2529
2530 if(still_not_done == 0 || patience <= 0)
2531 break;
2532 usleep(wait_grain);
2533 current_time = time(0);
2534 if(current_time>pacifier_time) {
2535 if(pacifier_func != NULL && !pacifier_off) {
2536 ret = (*pacifier_func)(handle, patience,
2537 current_time-start_time);
2538 pacifier_off = (ret <= 0);
2539 }
2540 pacifier_time = current_time;
2541 }
2542 }
2543 if (!(flag & 1))
2544 burn_finish();
2545 return(still_not_done == 0);
2546 }
2547
2548
2549 /** Abort any running drive operation and finish libburn.
2550 @param patience Maximum number of seconds to wait for drives to finish
2551 @param pacifier_func Function to produce appeasing messages. See
2552 burn_abort_pacifier() for an example.
2553 @return 1 ok, all went well
2554 0 had to leave a drive in unclean state
2555 <0 severe error, do no use libburn again
2556 */
burn_abort(int patience,int (* pacifier_func)(void * handle,int patience,int elapsed),void * handle)2557 int burn_abort(int patience,
2558 int (*pacifier_func)(void *handle, int patience, int elapsed),
2559 void *handle)
2560 {
2561 int ret, flg = 0;
2562
2563 if (patience < 0) {
2564 patience = 0;
2565 flg |= 1;
2566 }
2567 ret = burn_abort_5(patience, pacifier_func, handle, 0, flg);
2568 return ret;
2569 }
2570
2571
2572 /* ts A61020 API function */
burn_drive_get_start_end_lba(struct burn_drive * d,int * start_lba,int * end_lba,int flag)2573 int burn_drive_get_start_end_lba(struct burn_drive *d,
2574 int *start_lba, int *end_lba, int flag)
2575 {
2576 if (d->start_lba == -2000000000 || d->end_lba == -2000000000)
2577 return 0;
2578 *start_lba = d->start_lba;
2579 *end_lba= d->end_lba;
2580 return 1;
2581 }
2582
2583
2584 /* ts A61020 API function */
burn_disc_pretend_blank(struct burn_drive * d)2585 int burn_disc_pretend_blank(struct burn_drive *d)
2586 {
2587 if (d->drive_role == 0)
2588 return 0;
2589 if (d->status != BURN_DISC_UNREADY &&
2590 d->status != BURN_DISC_UNSUITABLE)
2591 return 0;
2592 d->status = BURN_DISC_BLANK;
2593 return 1;
2594 }
2595
2596 /* ts A61106 API function */
burn_disc_pretend_full(struct burn_drive * d)2597 int burn_disc_pretend_full(struct burn_drive *d)
2598 {
2599 if (d->drive_role == 0)
2600 return 0;
2601 if (d->status != BURN_DISC_UNREADY &&
2602 d->status != BURN_DISC_UNSUITABLE)
2603 return 0;
2604 d->status = BURN_DISC_FULL;
2605 return 1;
2606 }
2607
2608 /* ts B31110 API function */
burn_disc_pretend_full_uncond(struct burn_drive * d)2609 int burn_disc_pretend_full_uncond(struct burn_drive *d)
2610 {
2611 d->status = BURN_DISC_FULL;
2612 return 1;
2613 }
2614
2615 /* ts A61021: new API function */
burn_disc_read_atip(struct burn_drive * d)2616 int burn_disc_read_atip(struct burn_drive *d)
2617 {
2618 if (burn_drive_is_released(d)) {
2619 libdax_msgs_submit(libdax_messenger,
2620 d->global_index, 0x0002010e,
2621 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
2622 "Attempt to read ATIP from ungrabbed drive",
2623 0, 0);
2624 return -1;
2625 }
2626 if(d->drive_role != 1)
2627 return 0;
2628 if ((d->current_profile == -1 || d->current_is_cd_profile)
2629 && ((d->mdata->p2a_valid > 0 && d->mdata->cdrw_write) ||
2630 d->current_profile != 0x08)) {
2631 d->read_atip(d);
2632 /* >>> some control of success would be nice :) */
2633 } else {
2634 /* mmc5r03c.pdf 6.26.3.6.3 : ATIP is undefined for non-CD
2635 (and it seems meaningless for non-burners).
2636 ts A90823: Pseudo-CD U3 memory stick stalls with ATIP.
2637 It is !cdrw_write and profile is 0x08.
2638 */
2639 return 0;
2640 }
2641 return 1;
2642 }
2643
2644 /* ts A61110 : new API function */
burn_disc_track_lba_nwa(struct burn_drive * d,struct burn_write_opts * o,int trackno,int * lba,int * nwa)2645 int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o,
2646 int trackno, int *lba, int *nwa)
2647 {
2648 int ret;
2649
2650 if (burn_drive_is_released(d)) {
2651 libdax_msgs_submit(libdax_messenger,
2652 d->global_index, 0x0002011b,
2653 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
2654 "Attempt to read track info from ungrabbed drive",
2655 0, 0);
2656 return -1;
2657 }
2658 if (d->busy != BURN_DRIVE_IDLE) {
2659 libdax_msgs_submit(libdax_messenger,
2660 d->global_index, 0x0002011c,
2661 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
2662 "Attempt to read track info from busy drive",
2663 0, 0);
2664 return -1;
2665 }
2666 *lba = *nwa = 0;
2667 if (d->drive_role == 5 && trackno == 0 &&
2668 d->status == BURN_DISC_APPENDABLE) {
2669 *lba = *nwa = d->role_5_nwa;
2670 return 1;
2671 }
2672 if (d->drive_role != 1)
2673 return 0;
2674 if (o != NULL)
2675 d->send_write_parameters(d, NULL, -1, o);
2676 ret = d->get_nwa(d, trackno, lba, nwa);
2677 return ret;
2678 }
2679
2680
2681 /* ts A70131 : new API function */
burn_disc_get_msc1(struct burn_drive * d,int * start)2682 int burn_disc_get_msc1(struct burn_drive *d, int *start)
2683 {
2684 int ret, trackno;
2685
2686 if (burn_drive_is_released(d)) {
2687 libdax_msgs_submit(libdax_messenger,
2688 d->global_index, 0x0002011b,
2689 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
2690 "Attempt to read track info from ungrabbed drive",
2691 0, 0);
2692 return -1;
2693 }
2694 if (d->busy != BURN_DRIVE_IDLE) {
2695 libdax_msgs_submit(libdax_messenger,
2696 d->global_index, 0x0002011c,
2697 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
2698 "Attempt to read track info from busy drive",
2699 0, 0);
2700 return -1;
2701 }
2702 *start = 0;
2703 if (d->drive_role != 1)
2704 return 0;
2705 ret = d->read_multi_session_c1(d, &trackno, start);
2706 return ret;
2707 }
2708
2709
2710 /* ts A70213 : new API function */
burn_disc_available_space(struct burn_drive * d,struct burn_write_opts * o)2711 off_t burn_disc_available_space(struct burn_drive *d,
2712 struct burn_write_opts *o)
2713 {
2714 int lba, nwa, ret;
2715 off_t bytes, start_byte = 0;
2716
2717 if (burn_drive_is_released(d))
2718 return 0;
2719 if (d->busy != BURN_DRIVE_IDLE)
2720 return 0;
2721 if (d->drive_role == 0)
2722 return 0;
2723 if (d->drive_role != 1) {
2724 if (o != NULL)
2725 start_byte = o->start_byte;
2726 ret = burn_os_stdio_capacity(d->devname, start_byte, &bytes);
2727 if (ret != 1)
2728 bytes = d->media_capacity_remaining;
2729 if (bytes <= 0)
2730 bytes = (off_t) (512 * 1024 * 1024 - 1) * (off_t) 2048;
2731 if (bytes != d->media_capacity_remaining)
2732 burn_drive_set_media_capacity_remaining(d, bytes);
2733 } else {
2734 if (o != NULL)
2735 d->send_write_parameters(d, NULL, -1, o);
2736 d->get_nwa(d, -1, &lba, &nwa);
2737 }
2738 if (o != NULL) {
2739 if (o->start_byte > 0) {
2740 if (o->start_byte > d->media_capacity_remaining)
2741 return 0;
2742 return d->media_capacity_remaining - o->start_byte;
2743 }
2744 }
2745 return d->media_capacity_remaining;
2746 }
2747
2748
2749 /* ts A61202 : New API function */
burn_disc_get_profile(struct burn_drive * d,int * pno,char name[80])2750 int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80])
2751 {
2752 *pno = d->current_profile;
2753 strcpy(name,d->current_profile_text);
2754 return *pno >= 0;
2755 }
2756
2757
2758 /* ts A90815 : New API function */
burn_drive_get_all_profiles(struct burn_drive * d,int * num_profiles,int profiles[64],char is_current[64])2759 int burn_drive_get_all_profiles(struct burn_drive *d, int *num_profiles,
2760 int profiles[64], char is_current[64])
2761 {
2762 int i;
2763
2764 *num_profiles = d->num_profiles;
2765 for (i = 0; i < d->num_profiles; i++) {
2766 profiles[i] = (d->all_profiles[i * 4] << 8) |
2767 d->all_profiles[i * 4 + 1];
2768 is_current[i] = d->all_profiles[i * 4 + 2] & 1;
2769 }
2770 return 1;
2771 }
2772
2773
2774 /* ts A90815 : New API function */
burn_obtain_profile_name(int profile_number,char name[80])2775 int burn_obtain_profile_name(int profile_number, char name[80])
2776 {
2777 strcpy(name, mmc_obtain_profile_name(profile_number));
2778 return(name[0] != 0);
2779 }
2780
2781
2782 /* ts A61223 : New API function */
burn_drive_wrote_well(struct burn_drive * d)2783 int burn_drive_wrote_well(struct burn_drive *d)
2784 {
2785 return !d->cancel;
2786 }
2787
2788
2789 /* ts A61226 */
burn_speed_descriptor_new(struct burn_speed_descriptor ** s,struct burn_speed_descriptor * prev,struct burn_speed_descriptor * next,int flag)2790 int burn_speed_descriptor_new(struct burn_speed_descriptor **s,
2791 struct burn_speed_descriptor *prev,
2792 struct burn_speed_descriptor *next, int flag)
2793 {
2794 struct burn_speed_descriptor *o;
2795
2796 (*s) = o = calloc(1, sizeof(struct burn_speed_descriptor));
2797 if (o == NULL)
2798 return -1;
2799 o->source = 0;
2800 o->profile_loaded = -2;
2801 o->profile_name[0] = 0;
2802 o->wrc = 0;
2803 o->exact = 0;
2804 o->mrw = 0;
2805 o->end_lba = -1;
2806 o->write_speed = 0;
2807 o->read_speed = 0;
2808
2809 o->prev = prev;
2810 if (prev != NULL) {
2811 next = prev->next;
2812 prev->next = o;
2813 }
2814 o->next = next;
2815 if (next != NULL)
2816 next->prev = o;
2817 return 1;
2818 }
2819
2820
2821 /* ts A61226 */
2822 /* @param flag bit0= destroy whole next-chain of descriptors */
burn_speed_descriptor_destroy(struct burn_speed_descriptor ** s,int flag)2823 int burn_speed_descriptor_destroy(struct burn_speed_descriptor **s, int flag)
2824 {
2825 struct burn_speed_descriptor *next, *o;
2826
2827 if ((*s) == NULL)
2828 return 0;
2829 if (flag&1)
2830 for (o = (*s); o->prev != NULL; o = o->prev);
2831 else
2832 o = (*s);
2833 next = o->next;
2834 if (next != NULL)
2835 next->prev = o->prev;
2836 if (o->prev != NULL)
2837 o->prev->next = next;
2838 free((char *) (*s));
2839 (*s) = NULL;
2840 if (flag&1)
2841 return burn_speed_descriptor_destroy(&next, flag&1);
2842 return 1;
2843 }
2844
2845
2846 /* ts A61226 */
burn_speed_descriptor_copy(struct burn_speed_descriptor * from,struct burn_speed_descriptor * to,int flag)2847 int burn_speed_descriptor_copy(struct burn_speed_descriptor *from,
2848 struct burn_speed_descriptor *to, int flag)
2849 {
2850 to->source = from->source;
2851 to->profile_loaded = from->profile_loaded;
2852 strcpy(to->profile_name, from->profile_name);
2853 to->wrc = from->wrc;
2854 to->exact = from->exact;
2855 to->mrw = from->mrw;
2856 to->end_lba = from->end_lba;
2857 to->write_speed = from->write_speed;
2858 to->read_speed = from->read_speed;
2859 return 1;
2860 }
2861
2862
2863 /* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */
burn_mdata_free_subs(struct scsi_mode_data * m)2864 int burn_mdata_free_subs(struct scsi_mode_data *m)
2865 {
2866 burn_speed_descriptor_destroy(&(m->speed_descriptors), 1);
2867 return 1;
2868 }
2869
2870
2871 /* ts A61226 : API function */
burn_drive_get_speedlist(struct burn_drive * d,struct burn_speed_descriptor ** speed_list)2872 int burn_drive_get_speedlist(struct burn_drive *d,
2873 struct burn_speed_descriptor **speed_list)
2874 {
2875 int ret;
2876 struct burn_speed_descriptor *sd, *csd = NULL;
2877
2878 (*speed_list) = NULL;
2879 for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
2880 ret = burn_speed_descriptor_new(&csd, NULL, csd, 0);
2881 if (ret <= 0)
2882 return -1;
2883 burn_speed_descriptor_copy(sd, csd, 0);
2884 }
2885 (*speed_list) = csd;
2886 return (csd != NULL);
2887 }
2888
2889
2890 /* ts A70713 : API function */
burn_drive_get_best_speed(struct burn_drive * d,int speed_goal,struct burn_speed_descriptor ** best_descr,int flag)2891 int burn_drive_get_best_speed(struct burn_drive *d, int speed_goal,
2892 struct burn_speed_descriptor **best_descr, int flag)
2893 {
2894 struct burn_speed_descriptor *sd;
2895 int best_speed = 0, best_lba = 0, source= 2, speed;
2896
2897 if (flag & 2)
2898 source = -1;
2899 if (speed_goal < 0)
2900 best_speed = 2000000000;
2901 *best_descr = NULL;
2902 for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
2903 if (flag & 1)
2904 speed = sd->read_speed;
2905 else
2906 speed = sd->write_speed;
2907 if ((source >= 0 && sd->source != source) ||
2908 speed <= 0)
2909 continue;
2910 if (speed_goal < 0) {
2911 if (speed < best_speed) {
2912 best_speed = speed;
2913 *best_descr = sd;
2914 }
2915 } else if (speed_goal == 0) {
2916 if ((source == 2 && sd->end_lba > best_lba) ||
2917 ((source !=2 || sd->end_lba == best_lba) &&
2918 speed > best_speed)) {
2919 best_lba = sd->end_lba;
2920 best_speed = speed;
2921 *best_descr = sd;
2922 }
2923 } else if (speed <= speed_goal) {
2924 if (speed > best_speed) {
2925 best_speed = speed;
2926 *best_descr = sd;
2927 }
2928 }
2929 }
2930 if (d->current_is_cd_profile && *best_descr == NULL && ! (flag & 2))
2931 /* Mode page 2Ah is deprecated in MMC-5 although all known
2932 burners still support it with CD media. */
2933 return burn_drive_get_best_speed(d, speed_goal, best_descr,
2934 flag | 2);
2935 return (*best_descr != NULL);
2936 }
2937
2938
2939 /* ts A61226 : API function */
burn_drive_free_speedlist(struct burn_speed_descriptor ** speed_list)2940 int burn_drive_free_speedlist(struct burn_speed_descriptor **speed_list)
2941 {
2942 return burn_speed_descriptor_destroy(speed_list, 1);
2943 }
2944
2945
2946 /* ts A70203 : API function */
burn_disc_get_multi_caps(struct burn_drive * d,enum burn_write_types wt,struct burn_multi_caps ** caps,int flag)2947 int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt,
2948 struct burn_multi_caps **caps, int flag)
2949 {
2950 enum burn_disc_status s;
2951 struct burn_multi_caps *o;
2952 int status, num_formats, ret, type, i;
2953 off_t size;
2954 unsigned dummy;
2955
2956 *caps = NULL;
2957 s = burn_disc_get_status(d);
2958 if(s == BURN_DISC_UNGRABBED)
2959 return -1;
2960 *caps = o = (struct burn_multi_caps *)
2961 calloc(1, sizeof(struct burn_multi_caps));
2962 if(*caps == NULL)
2963 return -1;
2964 /* Default says nothing is available */
2965 o->multi_session = o->multi_track = 0;
2966 o-> start_adr = 0;
2967 o->start_alignment = o->start_range_low = o->start_range_high = 0;
2968 o->might_do_tao = o->might_do_sao = o->might_do_raw = 0;
2969 o->advised_write_mode = BURN_WRITE_NONE;
2970 o->selected_write_mode = wt;
2971 o->current_profile = d->current_profile;
2972 o->current_is_cd_profile = d->current_is_cd_profile;
2973 o->might_simulate = 0;
2974
2975 if (d->drive_role == 0 || d->drive_role == 4)
2976 return 0;
2977 if (d->drive_role == 2) {
2978 /* stdio file drive : random access read-write */
2979 o->start_adr = 1;
2980 size = d->media_capacity_remaining;
2981 burn_os_stdio_capacity(d->devname, 0, &size);
2982 burn_drive_set_media_capacity_remaining(d, size);
2983 o->start_range_high = d->media_capacity_remaining - 2048;
2984 o->start_alignment = 2048; /* imposting a drive, not a file */
2985 o->might_do_sao = 4;
2986 o->might_do_tao = 2;
2987 o->advised_write_mode = BURN_WRITE_TAO;
2988 o->might_simulate = 1;
2989 } else if (d->drive_role == 5) {
2990 /* stdio file drive : random access write-only */
2991 o->start_adr = 1;
2992 size = d->media_capacity_remaining;
2993 burn_os_stdio_capacity(d->devname, 0, &size);
2994 burn_drive_set_media_capacity_remaining(d, size);
2995
2996 /* >>> start_range_low = file size rounded to 2048 */;
2997
2998 o->start_range_high = d->media_capacity_remaining - 2048;
2999 o->start_alignment = 2048; /* imposting a drive, not a file */
3000 if (s == BURN_DISC_APPENDABLE) {
3001 if (wt == BURN_WRITE_SAO || wt == BURN_WRITE_RAW)
3002 return 0;
3003 o->might_do_sao = 0;
3004 } else
3005 o->might_do_sao = 4;
3006 o->might_do_tao = 2;
3007 o->advised_write_mode = BURN_WRITE_TAO;
3008 o->might_simulate = 1;
3009 } else if (d->drive_role != 1) {
3010 /* stdio file drive : sequential access write-only */
3011 o->might_do_sao = 4;
3012 o->might_do_tao = 2;
3013 o->advised_write_mode = BURN_WRITE_TAO;
3014 o->might_simulate = 1;
3015 } else if (s != BURN_DISC_BLANK && s != BURN_DISC_APPENDABLE) {
3016 return 0;
3017 } else if (s == BURN_DISC_APPENDABLE &&
3018 (wt == BURN_WRITE_SAO || wt == BURN_WRITE_RAW)) {
3019 return 0;
3020 } else if (wt == BURN_WRITE_RAW && !d->current_is_cd_profile) {
3021 return 0;
3022 } else if (d->current_profile == 0x09 || d->current_profile == 0x0a) {
3023 /* CD-R , CD-RW */
3024 if (d->block_types[BURN_WRITE_TAO]) {
3025 o->multi_session = o->multi_track = 1;
3026 o->might_do_tao = 2;
3027 if (o->advised_write_mode == BURN_WRITE_NONE)
3028 o->advised_write_mode = BURN_WRITE_TAO;
3029 }
3030 if (d->block_types[BURN_WRITE_SAO]) {
3031 o->multi_session = o->multi_track = 1;
3032 o->might_do_sao = 1;
3033 if (o->advised_write_mode == BURN_WRITE_NONE)
3034 o->advised_write_mode = BURN_WRITE_SAO;
3035 }
3036 if (d->block_types[BURN_WRITE_RAW]) {
3037 o->might_do_raw = 1;
3038 if (o->advised_write_mode == BURN_WRITE_NONE)
3039 o->advised_write_mode = BURN_WRITE_RAW;
3040 }
3041 if (wt == BURN_WRITE_RAW)
3042 o->multi_session = o->multi_track = 0;
3043 else if(wt == BURN_WRITE_NONE || wt == BURN_WRITE_SAO ||
3044 wt == BURN_WRITE_TAO)
3045 o->might_simulate = !!(d->mdata->p2a_valid > 0 &&
3046 d->mdata->simulate);
3047 } else if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
3048 d->current_profile == 0x15) {
3049 /* DVD-R , sequential DVD-RW , DVD-R/DL Sequential */
3050 if (s == BURN_DISC_BLANK) {
3051 o->might_do_sao = 1;
3052 o->advised_write_mode = BURN_WRITE_SAO;
3053 }
3054 if (d->current_has_feat21h) {
3055 #ifndef Libburn_dvd_r_dl_multi_no_close_sessioN
3056 if (d->current_profile != 0x15)
3057 #endif
3058 o->multi_session = 1;
3059 o->multi_track = 1;
3060 o->might_do_tao = 2;
3061 o->advised_write_mode = BURN_WRITE_TAO;
3062 }
3063 if (wt == BURN_WRITE_SAO)
3064 o->multi_session = o->multi_track = 0;
3065 if (wt == BURN_WRITE_NONE || wt == BURN_WRITE_SAO ||
3066 wt == BURN_WRITE_TAO)
3067 o->might_simulate = 1;
3068 } else if (d->current_profile == 0x12 ||
3069 d->current_profile == 0x13 ||
3070 d->current_profile == 0x1a ||
3071 d->current_profile == 0x43
3072 ) {
3073 /* DVD-RAM, overwritable DVD-RW, DVD+RW, BD-RE */
3074 o->start_adr = 1;
3075 ret = burn_disc_get_formats(d, &status, &size, &dummy,
3076 &num_formats);
3077 if (ret == 1) {
3078 if (status == BURN_FORMAT_IS_FORMATTED)
3079 o->start_range_high = size - 2048;
3080 if (d->current_profile == 0x13) {
3081 o->start_alignment = 32 * 1024;
3082 for (i = 0; i < num_formats; i++) {
3083 ret = burn_disc_get_format_descr(d, i,
3084 &type, &size, &dummy);
3085 if (ret <= 0)
3086 continue;
3087 if (type == 0x13) /* expandable */
3088 break;
3089 }
3090 if (i >= num_formats) /* not expandable */
3091 o->start_range_high -= 32 * 1024;
3092 if (o->start_range_high < 0)
3093 o->start_range_high = 0;
3094 } else {
3095 o->start_alignment = 2 * 1024;
3096 if (d->best_format_size - 2048 >
3097 o->start_range_high)
3098 o->start_range_high =
3099 d->best_format_size - 2048;
3100 }
3101 }
3102 o->might_do_sao = 4;
3103 o->might_do_tao = 2;
3104 o->advised_write_mode = BURN_WRITE_TAO;
3105 } else if (d->current_profile == 0x1b || d->current_profile == 0x2b ||
3106 d->current_profile == 0x41) {
3107 /* DVD+R , DVD+R/DL , BD-R SRM */
3108 o->multi_session = o->multi_track = 1;
3109 o->might_do_tao = 2;
3110 o->might_do_sao = 1;
3111 o->advised_write_mode = BURN_WRITE_TAO;
3112 } else /* unknown media */
3113 return 0;
3114
3115 if (s == BURN_DISC_APPENDABLE)
3116 o->might_do_sao = o->might_do_raw = 0;
3117
3118 if (wt == BURN_WRITE_TAO && !o->might_do_tao)
3119 return 0;
3120 else if (wt == BURN_WRITE_SAO && !o->might_do_sao)
3121 return 0;
3122 else if (wt == BURN_WRITE_RAW && !o->might_do_raw)
3123 return 0;
3124 return 1;
3125 }
3126
3127
3128 /* ts A70203 : API function */
burn_disc_free_multi_caps(struct burn_multi_caps ** caps)3129 int burn_disc_free_multi_caps(struct burn_multi_caps **caps)
3130 {
3131 if (*caps == NULL)
3132 return 0;
3133 free((char *) *caps);
3134 *caps = NULL;
3135 return 1;
3136 }
3137
3138
3139 /* ts A70207 : evaluate write mode related peculiarities of a disc
3140 @param flag bit0= fill_up_media is active
3141 */
burn_disc_get_write_mode_demands(struct burn_disc * disc,struct burn_write_opts * opts,struct burn_disc_mode_demands * result,int flag)3142 int burn_disc_get_write_mode_demands(struct burn_disc *disc,
3143 struct burn_write_opts *opts,
3144 struct burn_disc_mode_demands *result, int flag)
3145 {
3146 struct burn_session *session;
3147 struct burn_track *track;
3148 int i, j, mode, unknown_track_sizes = 0, last_track_is_unknown = 0;
3149 enum burn_disc_status s;
3150
3151
3152 memset((char *) result, 0, sizeof(struct burn_disc_mode_demands));
3153 if (disc == NULL)
3154 return 2;
3155 s = burn_disc_get_status(opts->drive);
3156 if (s == BURN_DISC_APPENDABLE || disc->sessions > 1)
3157 result->will_append = 1;
3158 if (disc->sessions > 1)
3159 result->multi_session = 1;
3160 for (i = 0; i < disc->sessions; i++) {
3161 session = disc->session[i];
3162 if (session->tracks <= 0)
3163 continue;
3164 mode = session->track[0]->mode;
3165 if (session->tracks > 1)
3166 result->multi_track = 1;
3167 for (j = 0; j < session->tracks; j++) {
3168 track = session->track[j];
3169 if (burn_track_is_open_ended(track)) {
3170 if (burn_track_get_default_size(track) > 0) {
3171 if (result->unknown_track_size == 0)
3172 result->unknown_track_size = 2;
3173 } else
3174 result->unknown_track_size = 1;
3175 unknown_track_sizes++;
3176 last_track_is_unknown = 1;
3177 } else
3178 last_track_is_unknown = 0;
3179 if ((mode & BURN_MODE_BITS) !=
3180 (track->mode & BURN_MODE_BITS))
3181 result->mixed_mode = 1;
3182 if (track->mode & BURN_MODE1) {
3183 result->block_types |= BURN_BLOCK_MODE1;
3184 } else if (track->mode & BURN_AUDIO) {
3185 result->audio = 1;
3186 result->block_types |= BURN_BLOCK_RAW0;
3187 result->exotic_track = 1;
3188 } else {
3189 result->block_types |= opts->block_type;
3190 result->exotic_track = 1;
3191 }
3192 }
3193 }
3194 if (flag&1) {/* fill_up_media will define the size of the last track */
3195 if (unknown_track_sizes == 1 && last_track_is_unknown)
3196 result->unknown_track_size = 0;
3197 }
3198 return (disc->sessions > 0);
3199 }
3200
3201
3202 /* ts A70903 : API */
burn_drive_get_drive_role(struct burn_drive * d)3203 int burn_drive_get_drive_role(struct burn_drive *d)
3204 {
3205 return d->drive_role;
3206 }
3207
3208
3209 /* ts A70923
3210 Hands out pointers *dpt to directory path and *npt to basename.
3211 Caution: the last '/' in adr gets replaced by a 0.
3212 */
burn__split_path(char * adr,char ** dpt,char ** npt)3213 static int burn__split_path(char *adr, char **dpt, char **npt)
3214 {
3215 *dpt = adr;
3216 *npt = strrchr(*dpt, '/');
3217 if (*npt == NULL) {
3218 *npt = *dpt;
3219 *dpt = ".";
3220 return 1;
3221 }
3222 **npt = 0;
3223 if(*npt == *dpt)
3224 *dpt = "/";
3225 (*npt)++;
3226 return 2;
3227 }
3228
3229
3230 /* ts A70923 : API */
burn_drive_equals_adr(struct burn_drive * d1,char * adr2_in,int role2)3231 int burn_drive_equals_adr(struct burn_drive *d1, char *adr2_in, int role2)
3232 {
3233 struct stat stbuf1, stbuf2;
3234 char *adr1 = NULL, *adr2 = adr2_in;
3235 char *conv_adr1 = NULL, *conv_adr2 = NULL;
3236 char *npt1, *dpt1, *npt2, *dpt2;
3237 int role1, stat_ret1, stat_ret2, conv_ret2, exact_role_matters = 0, fd;
3238 int ret;
3239
3240 BURN_ALLOC_MEM(adr1, char, BURN_DRIVE_ADR_LEN);
3241 BURN_ALLOC_MEM(conv_adr1, char, BURN_DRIVE_ADR_LEN);
3242 BURN_ALLOC_MEM(conv_adr2, char, BURN_DRIVE_ADR_LEN);
3243
3244 role1 = burn_drive_get_drive_role(d1);
3245 burn_drive_d_get_adr(d1, adr1);
3246 stat_ret1 = stat(adr1, &stbuf1);
3247
3248 /* If one of the candidate paths depicts an open file descriptor then
3249 its read-write capability decides about its role and the difference
3250 between roles 2 and 3 does matter.
3251 */
3252 fd = burn_drive__fd_from_special_adr(d1->devname);
3253 if (fd != -1)
3254 exact_role_matters = 1;
3255 if (strncmp(adr2, "stdio:", 6) == 0) {
3256 adr2+= 6;
3257 if (adr2[0] == 0) {
3258 role2 = 0;
3259 } else {
3260 fd = burn_drive__fd_from_special_adr(adr2);
3261 if (fd != -1)
3262 exact_role_matters = 1;
3263 ret = burn_drive__is_rdwr(adr2, NULL, NULL, NULL,
3264 1 | 2);
3265 if (ret == 2 && (burn_drive_role_4_allowed & 1))
3266 role2 = 4;
3267 else if (ret == 3 && (burn_drive_role_4_allowed & 1))
3268 role2 = 5;
3269 else if (ret > 0)
3270 role2 = 2;
3271 else
3272 role2 = 3;
3273 if (fd == -1 &&
3274 role2 == 2 && (burn_drive_role_4_allowed & 3) == 3)
3275 role2 = burn_role_by_access(adr2,
3276 !!(burn_drive_role_4_allowed & 4));
3277 }
3278 }
3279
3280 if (strlen(adr2) >= BURN_DRIVE_ADR_LEN)
3281 {ret = -1; goto ex;}
3282 stat_ret2 = stat(adr2, &stbuf2);
3283 conv_ret2 = burn_drive_convert_fs_adr(adr2, conv_adr2);
3284
3285 if (!exact_role_matters) {
3286 /* roles >= 2 have the same name space and object
3287 interpretation */
3288 if (role1 >= 2)
3289 role1 = 2;
3290 if (role2 >= 2)
3291 role2 = 2;
3292 }
3293
3294 if (strcmp(adr1, adr2) == 0 && role1 == role2)
3295 {ret = 1; goto ex;} /* equal role and address */
3296 if (role1 == 1 && role2 == 1) {
3297 /* MMC drive meets wannabe MMC drive */
3298 if (conv_ret2 <= 0)
3299 {ret = 0; goto ex;} /* no MMC drive at adr2 */
3300 if (strcmp(adr1, conv_adr2) == 0)
3301 {ret = 1; goto ex;} /* equal real MMC drives */
3302 {ret = 0; goto ex;}
3303
3304 } else if (role1 == 0 || role2 == 0)
3305 {ret = 0; goto ex;} /* one null-drive, one not */
3306
3307 else if (role1 != 1 && role2 != 1) {
3308 /* pseudo-drive meets file object */
3309
3310 if (role1 != role2)
3311 {ret = 0; goto ex;}
3312 if (stat_ret1 == -1 || stat_ret2 == -1) {
3313 if (stat_ret1 != -1 || stat_ret2 != -1)
3314 {ret = 0; goto ex;}
3315 /* one address existing, one not */
3316
3317 /* Two non-existing file objects */
3318
3319 strcpy(conv_adr1, adr1);
3320 burn__split_path(conv_adr1, &dpt1, &npt1);
3321 strcpy(conv_adr2, adr2);
3322 burn__split_path(conv_adr2, &dpt2, &npt2);
3323 if (strcmp(npt1, npt2))
3324 {ret = 0; goto ex;} /* basenames differ */
3325 stat_ret1= stat(adr1, &stbuf1);
3326 stat_ret2= stat(adr2, &stbuf2);
3327 if (stat_ret1 != stat_ret2)
3328 {ret = 0; goto ex;}
3329 /* one dir existing, one not */
3330
3331 /* Both directories exist. The basenames are equal.
3332 So the addresses are equal if the directories are
3333 equal.*/
3334 }
3335 if (stbuf1.st_ino == stbuf2.st_ino &&
3336 stbuf1.st_dev == stbuf2.st_dev)
3337 {ret = 1; goto ex;} /* same filesystem object */
3338
3339 if (S_ISBLK(stbuf1.st_mode) && S_ISBLK(stbuf2.st_mode) &&
3340 stbuf1.st_rdev == stbuf2.st_rdev)
3341 {ret = 1; goto ex;}/* same major,minor device number */
3342 if (S_ISCHR(stbuf1.st_mode) && S_ISCHR(stbuf2.st_mode) &&
3343 stbuf1.st_rdev == stbuf2.st_rdev)
3344 {ret = 1; goto ex;}/* same major,minor device number */
3345
3346 /* Are both filesystem objects related to the same MMC drive */
3347 if (conv_ret2 <= 0)
3348 {ret = 0; goto ex;} /* no MMC drive at adr2 */
3349 if (burn_drive_convert_fs_adr(adr1, conv_adr1) <= 0)
3350 {ret = 0; goto ex;} /* no MMC drive at adr1 */
3351 if (strcmp(conv_adr1, conv_adr2) == 0)
3352 {ret = 1; goto ex;} /* same MMC drive */
3353
3354 {ret = 0; goto ex;} /* all filesystem disguises are checked */
3355
3356 } else if (role1 == 1 && role2 != 1) {
3357 /* MMC drive meets file object */
3358
3359 if (conv_ret2 <= 0)
3360 {ret = 0; goto ex;} /* no MMC drive at adr2 */
3361 if (strcmp(adr1, conv_adr2) == 0)
3362 {ret = 1; goto ex;} /* same MMC drive */
3363 {ret = 0; goto ex;}
3364
3365 } else if (role1 != 1 && role2 == 1) {
3366 /* stdio-drive meets wannabe MMC drive */
3367
3368 if (conv_ret2 <= 0)
3369 {ret = 0; goto ex;} /* no MMC drive at adr2 */
3370 if (burn_drive_convert_fs_adr(adr1, conv_adr1) <= 0)
3371 {ret = 0; goto ex;} /* no MMC drive at adr1 */
3372 if (strcmp(conv_adr1, conv_adr2) == 0)
3373 {ret = 1; goto ex;} /* same MMC drive */
3374 {ret = 0; goto ex;}
3375
3376 }
3377 ret = 0;
3378 ex:;
3379 BURN_FREE_MEM(adr1);
3380 BURN_FREE_MEM(conv_adr1);
3381 BURN_FREE_MEM(conv_adr2);
3382 return ret;
3383 }
3384
3385
burn_drive_find_by_thread_pid(struct burn_drive ** d,pid_t pid,pthread_t tid)3386 int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid,
3387 pthread_t tid)
3388 {
3389 int i;
3390
3391 for (i = 0; i < drivetop + 1; i++) {
3392
3393 /*
3394 if (drive_array[i].thread_pid_valid)
3395 fprintf(stderr, "libburn_EXPERIMENTAL : drive %d , thread_pid %d\n", i, drive_array[i].thread_pid);
3396 */
3397
3398 if (drive_array[i].thread_pid_valid &&
3399 drive_array[i].thread_pid == pid &&
3400 pthread_equal(drive_array[i].thread_tid, tid)) {
3401 *d = &(drive_array[i]);
3402 return 1;
3403 }
3404 }
3405 return 0;
3406 }
3407
3408
3409 /* ts A80422 : centralizing this setting for debugging purposes
3410 */
burn_drive_set_media_capacity_remaining(struct burn_drive * d,off_t value)3411 int burn_drive_set_media_capacity_remaining(struct burn_drive *d, off_t value)
3412 {
3413 if (value / (off_t) 2048 > (off_t) 0x7ffffff0)
3414 value = ((off_t) 0x7ffffff0) * (off_t) 2048;
3415 d->media_capacity_remaining = value;
3416 return 1;
3417 }
3418
3419
3420 /* ts A81215 : API */
burn_get_read_capacity(struct burn_drive * d,int * capacity,int flag)3421 int burn_get_read_capacity(struct burn_drive *d, int *capacity, int flag)
3422 {
3423 *capacity = d->media_read_capacity +
3424 (d->media_read_capacity != 0x7fffffff);
3425 return (d->media_read_capacity != 0x7fffffff);
3426 }
3427
3428
3429 /* ts A90903 : API */
burn_disc_get_media_id(struct burn_drive * d,char ** product_id,char ** media_code1,char ** media_code2,char ** book_type,int flag)3430 int burn_disc_get_media_id(struct burn_drive *d,
3431 char **product_id, char **media_code1, char **media_code2,
3432 char **book_type, int flag)
3433 {
3434 int ret;
3435
3436 *product_id = *media_code1 = *media_code2 = *book_type = NULL;
3437 if (burn_drive_get_drive_role(d) != 1)
3438 return 0;
3439 ret = mmc_get_media_product_id(d,
3440 product_id, media_code1, media_code2, book_type,
3441 flag & 1);
3442 return ret;
3443 }
3444
3445
3446 /* ts A90909 : API */
3447 /**
3448 @param valid Replies bits which indicate the validity of other reply
3449 parameters or the state of certain CD info bits:
3450 bit0= disc_type valid
3451 bit1= disc_id valid
3452 bit2= bar_code valid
3453 bit3= disc_app_code valid
3454 bit4= Disc is unrestricted (URU bit)
3455 bit5= Disc is nominally erasable (Erasable bit)
3456 This will be set with overwritable media which
3457 libburn normally considers to be unerasable blank.
3458 */
burn_disc_get_cd_info(struct burn_drive * d,char disc_type[80],unsigned int * disc_id,char bar_code[9],int * app_code,int * valid)3459 int burn_disc_get_cd_info(struct burn_drive *d, char disc_type[80],
3460 unsigned int *disc_id, char bar_code[9], int *app_code,
3461 int *valid)
3462 {
3463 if (d->disc_type == 0x00) {
3464 strcpy(disc_type, "CD-DA or CD-ROM");
3465 } else if (d->disc_type == 0x10) {
3466 strcpy(disc_type, "CD-I");
3467 } else if (d->disc_type == 0x20) {
3468 strcpy(disc_type, "CD-ROM XA");
3469 } else {
3470 strcpy(disc_type, "undefined");
3471 }
3472 *disc_id = d->disc_id;
3473 memcpy(bar_code, d->disc_bar_code, 8);
3474 bar_code[8]= 0;
3475 *app_code = d->disc_app_code;
3476 *valid = d->disc_info_valid;
3477 return 1;
3478 }
3479
3480
3481 /* ts B00924 : API */
burn_disc_get_bd_spare_info(struct burn_drive * d,int * alloc_blocks,int * free_blocks,int flag)3482 int burn_disc_get_bd_spare_info(struct burn_drive *d,
3483 int *alloc_blocks, int *free_blocks, int flag)
3484 {
3485 int ret;
3486
3487 if (burn_drive_get_drive_role(d) != 1)
3488 return 0;
3489 *alloc_blocks = *free_blocks = 0;
3490 ret = mmc_get_bd_spare_info(d, alloc_blocks, free_blocks, 0);
3491 return ret;
3492 }
3493
3494
3495 /* ts B10801 : API */
burn_disc_get_phys_format_info(struct burn_drive * d,int * disk_category,char ** book_name,int * part_version,int * num_layers,int * num_blocks,int flag)3496 int burn_disc_get_phys_format_info(struct burn_drive *d, int *disk_category,
3497 char **book_name, int *part_version, int *num_layers,
3498 int *num_blocks, int flag)
3499 {
3500 int ret;
3501
3502 if (burn_drive_get_drive_role(d) != 1)
3503 return 0;
3504 *disk_category = *part_version = *num_layers = *num_blocks = 0;
3505 ret = mmc_get_phys_format_info(d, disk_category, book_name,
3506 part_version, num_layers, num_blocks, 0);
3507 return ret;
3508 }
3509
3510
3511
3512 /* ts B10525 : API */
burn_disc_next_track_is_damaged(struct burn_drive * d,int flag)3513 int burn_disc_next_track_is_damaged(struct burn_drive *d, int flag)
3514 {
3515 return d->next_track_damaged;
3516 }
3517
3518
3519 /* ts B11201 : API */
3520 /* Read the CD-TEXT data from the Lead-in of an Audio CD
3521 */
burn_disc_get_leadin_text(struct burn_drive * d,unsigned char ** text_packs,int * num_packs,int flag)3522 int burn_disc_get_leadin_text(struct burn_drive *d,
3523 unsigned char **text_packs, int *num_packs,
3524 int flag)
3525 {
3526 int ret;
3527
3528 ret = mmc_get_leadin_text(d, text_packs, num_packs, 0);
3529 return ret;
3530 }
3531
3532
3533 /* ts B31023 API */
3534 /* Inquire for DVD-RW failure of TAO
3535 */
burn_drive_was_feat21_failure(struct burn_drive * d)3536 int burn_drive_was_feat21_failure(struct burn_drive *d)
3537 {
3538 return !!d->was_feat21h_failure;
3539 }
3540
3541
3542 /* ts B40106 */
burn_feature_descr_new(struct burn_feature_descr ** new,unsigned char * descr,int descr_len,int flag)3543 int burn_feature_descr_new(struct burn_feature_descr **new,
3544 unsigned char *descr, int descr_len, int flag)
3545 {
3546 struct burn_feature_descr *o;
3547
3548 *new = NULL;
3549 if (descr_len < 4)
3550 return 0;
3551 (*new) = o = calloc(1, sizeof(struct burn_feature_descr));
3552 if (o == NULL)
3553 return -1;
3554 o->feature_code = (descr[0] << 8) | descr[1];
3555 o->flags = descr[2];
3556 if (descr[3] > descr_len - 4)
3557 o->data_lenght = 0;
3558 else
3559 o->data_lenght = descr[3];
3560 o->data = NULL;
3561 o->next = NULL;
3562 if (o->data_lenght > 0) {
3563 o->data = calloc(1, o->data_lenght);
3564 if (o->data == NULL) {
3565 burn_feature_descr_free(new, 0);
3566 return -1;
3567 }
3568 memcpy(o->data, descr + 4, o->data_lenght);
3569 }
3570 return 1;
3571 }
3572
3573
3574 /* ts B40106 */
burn_feature_descr_free(struct burn_feature_descr ** descr,int flag)3575 int burn_feature_descr_free(struct burn_feature_descr **descr, int flag)
3576 {
3577 struct burn_feature_descr *o, *next;
3578
3579 if (*descr == NULL)
3580 return 0;
3581 for (o = *descr; o != NULL; o = next) {
3582 next = o->next;
3583 if (o->data != NULL)
3584 free(o->data);
3585 free((char *) o);
3586 }
3587 *descr = NULL;
3588 return 1;
3589 }
3590
3591
3592 /* ts B40107 */
burn_drive_has_feature(struct burn_drive * d,int feature_code,struct burn_feature_descr ** descr,int flag)3593 int burn_drive_has_feature(struct burn_drive *d, int feature_code,
3594 struct burn_feature_descr **descr, int flag)
3595 {
3596 struct burn_feature_descr *o;
3597
3598 for (o = d->features; o != NULL; o = o->next) {
3599 if (o->feature_code == feature_code) {
3600 if (descr != NULL)
3601 *descr = o;
3602 return 1;
3603 }
3604 }
3605 return 0;
3606 }
3607
3608
3609 /* ts B51016 API */
burn_drive_get_serial_no(struct burn_drive * d,char ** sno,int * sno_len)3610 int burn_drive_get_serial_no(struct burn_drive *d, char **sno, int *sno_len)
3611 {
3612 int ret;
3613
3614 if (*sno != NULL)
3615 BURN_FREE_MEM(*sno);
3616 if (d->drive_serial_number_len > 0)
3617 *sno_len = d->drive_serial_number_len;
3618 else
3619 *sno_len = 0;
3620 BURN_ALLOC_MEM(*sno, char, *sno_len + 1);
3621 if (d->drive_serial_number_len > 0)
3622 memcpy(*sno, d->drive_serial_number, *sno_len);
3623 (*sno)[*sno_len] = 0;
3624 ret = 1;
3625 ex:
3626 return ret;
3627 }
3628
3629
3630 /* ts B51016 API */
burn_drive_get_media_sno(struct burn_drive * d,char ** sno,int * sno_len)3631 int burn_drive_get_media_sno(struct burn_drive *d, char **sno, int *sno_len)
3632 {
3633 int ret;
3634
3635 #ifdef Libburn_enable_scsi_cmd_ABh
3636 struct burn_feature_descr *feat;
3637 #endif
3638
3639 if (*sno != NULL)
3640 BURN_FREE_MEM(*sno);
3641 *sno = NULL;
3642
3643 if (d->media_serial_number_len == -1) {
3644
3645 #ifdef Libburn_enable_scsi_cmd_ABh
3646
3647 if (burn_drive_has_feature(d, 0x109, &feat, 0))
3648
3649 #ifndef Libburn_enable_scsi_cmd_ABh_pretend_currenT
3650 if (feat->flags & 1) /* current */
3651 #endif
3652
3653 spc_read_media_serial_number(d);
3654
3655 #else
3656 ;
3657
3658 #endif /* ! Libburn_enable_scsi_cmd_ABh */
3659
3660 }
3661
3662 if (d->media_serial_number_len > 0)
3663 *sno_len = d->media_serial_number_len;
3664 else
3665 *sno_len = 0;
3666 BURN_ALLOC_MEM(*sno, char, *sno_len + 1);
3667 if (*sno_len > 0)
3668 memcpy(*sno, d->media_serial_number, *sno_len);
3669 (*sno)[*sno_len] = 0;
3670 ret = 1;
3671 ex:
3672 return ret;
3673 }
3674
3675
burn_drive_get_bd_r_pow(struct burn_drive * d)3676 int burn_drive_get_bd_r_pow(struct burn_drive *d)
3677 {
3678 struct burn_feature_descr *feature;
3679
3680 if (d->current_profile == 0x41)
3681 if (burn_drive_has_feature(d, 0x38, &feature, 0) == 1)
3682 if (feature->flags & 1)
3683 return 1;
3684 return 0;
3685 }
3686
3687
burn_drive_set_immed(struct burn_drive * drive,int enable)3688 int burn_drive_set_immed(struct burn_drive *drive, int enable)
3689 {
3690 drive->do_no_immed = !enable;
3691 return 1;
3692 }
3693
3694
burn_drive_get_immed(struct burn_drive * drive)3695 int burn_drive_get_immed(struct burn_drive *drive)
3696 {
3697 return !drive->do_no_immed;
3698 }
3699
3700
3701 /* ts B90412 , API */
burn_drive_get_feature(struct burn_drive * d,unsigned int feature_code,unsigned char * flags,unsigned char * additional_length,unsigned char ** feature_data,char ** feature_text)3702 int burn_drive_get_feature(struct burn_drive *d, unsigned int feature_code,
3703 unsigned char *flags,
3704 unsigned char *additional_length,
3705 unsigned char **feature_data,
3706 char **feature_text)
3707 {
3708 int ret, i;
3709 struct burn_feature_descr *descr;
3710
3711 *flags = 0;
3712 *additional_length = 0;
3713 *feature_data = NULL;
3714 if (feature_text != NULL)
3715 *feature_text = NULL;
3716 if (!burn_drive_has_feature(d, feature_code, &descr, 0))
3717 return 0;
3718 *flags = descr->flags;
3719 *additional_length = descr->data_lenght;
3720 if (*additional_length > 0)
3721 BURN_ALLOC_MEM(*feature_data, unsigned char,
3722 *additional_length);
3723 for (i = 0; i < *additional_length; i++)
3724 (*feature_data)[i] = descr->data[i];
3725
3726 if (feature_text != NULL) {
3727 ret = burn_make_feature_text(d, feature_code, *flags,
3728 *additional_length, *feature_data,
3729 feature_text, 0);
3730 } else {
3731 ret = 1;
3732 }
3733 ex:
3734 return ret;
3735 }
3736
3737
3738 /* ts B90412 , API */
burn_drive_get_feature_codes(struct burn_drive * d,int * count,unsigned int ** feature_codes)3739 void burn_drive_get_feature_codes(struct burn_drive *d,
3740 int *count, unsigned int **feature_codes)
3741 {
3742 struct burn_feature_descr *o;
3743 int to_alloc;
3744
3745 *count = 0;
3746 *feature_codes = NULL;
3747 for (o = d->features; o != NULL; o = o->next)
3748 (*count)++;
3749 if (*count == 0)
3750 return;
3751 to_alloc = *count;
3752 *count = 0;
3753 BURN_ALLOC_MEM_VOID(*feature_codes, unsigned int, to_alloc);
3754 for (o = d->features; o != NULL; o = o->next) {
3755 (*feature_codes)[*count] = o->feature_code;
3756 (*count)++;
3757 }
3758 ex:;
3759 }
3760
3761