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