1
2 /*
3 cc -g -c \
4 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \
5 burn_wrap.c
6 */
7 /* libburn wrappers for libisoburn
8
9 Copyright 2007 - 2017 Thomas Schmitt, <scdbackup@gmx.net>
10 Provided under GPL version 2 or later.
11 */
12
13 #ifdef HAVE_CONFIG_H
14 #include "../config.h"
15 #endif
16
17 /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo
18 #define Hardcoded_cd_rW 1
19 #define Hardcoded_cd_rw_c1 12999
20 #define Hardcoded_cd_rw_nwA 152660
21 */
22
23 #include <stdio.h>
24 #include <ctype.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <time.h>
32 #include <regex.h>
33
34 #ifndef Xorriso_standalonE
35
36 #include <libburn/libburn.h>
37 #include <libisofs/libisofs.h>
38 #ifdef Xorriso_with_libjtE
39 #include <libjte/libjte.h>
40 #endif
41
42 #else /* ! Xorriso_standalonE */
43
44 #include "../libisofs/libisofs.h"
45 #include "../libburn/libburn.h"
46 #ifdef Xorriso_with_libjtE
47 #include "../libjte/libjte.h"
48 #endif
49
50 #endif /* Xorriso_standalonE */
51
52
53 #include "libisoburn.h"
54 #include "isoburn.h"
55
56
57 /* The global list of isoburn objects. Usually there is only one. */
58 extern struct isoburn *isoburn_list_start; /* in isoburn.c */
59
60 /* Default values for application provided msgs_submit methods.
61 To be attached to newly acquired drives.
62 Storage location is isoburn.c
63 */
64 extern int (*libisoburn_default_msgs_submit)
65 (void *handle, int error_code, char msg_text[],
66 int os_errno, char severity[], int flag);
67 extern void *libisoburn_default_msgs_submit_handle;
68 extern int libisoburn_default_msgs_submit_flag;
69
70
71 static int isoburn_emulate_toc(struct burn_drive *d, int flag);
72
73
isoburn_initialize(char msg[1024],int flag)74 int isoburn_initialize(char msg[1024], int flag)
75 {
76 int major, minor, micro, bad_match= 0, no_iso_init= 0;
77
78
79 /* First the ugly compile time checks for header version compatibility.
80 If everything matches, then they produce no C code. In case of mismatch,
81 intentionally faulty C code will be inserted.
82 */
83
84 #ifdef iso_lib_header_version_major
85 /* The minimum requirement of libisoburn towards the libisofs header
86 at compile time is defined in libisoburn/libisoburn.h :
87 isoburn_libisofs_req_major
88 isoburn_libisofs_req_minor
89 isoburn_libisofs_req_micro
90 It gets compared against the version macros in libisofs/libisofs.h :
91 iso_lib_header_version_major
92 iso_lib_header_version_minor
93 iso_lib_header_version_micro
94 If the header is too old then the following code shall cause failure of
95 libisoburn compilation rather than to allow production of a program with
96 unpredictable bugs or memory corruption.
97 The compiler messages supposed to appear in this case are:
98 error: 'LIBISOFS_MISCONFIGURATION' undeclared (first use in this function)
99 error: 'INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libisofs_dot_h_TOO_OLD__SEE_libisoburn_dot_h_AND_burn_wrap_dot_h' undeclared (first use in this function)
100 error: 'LIBISOFS_MISCONFIGURATION_' undeclared (first use in this function)
101 */
102 /* The indendation is an advise of man gcc to help old compilers ignoring */
103 #if isoburn_libisofs_req_major > iso_lib_header_version_major
104 #define Isoburn_libisofs_dot_h_too_olD 1
105 #endif
106 #if isoburn_libisofs_req_major == iso_lib_header_version_major && isoburn_libisofs_req_minor > iso_lib_header_version_minor
107 #define Isoburn_libisofs_dot_h_too_olD 1
108 #endif
109 #if isoburn_libisofs_req_minor == iso_lib_header_version_minor && isoburn_libisofs_req_micro > iso_lib_header_version_micro
110 #define Isoburn_libisofs_dot_h_too_olD 1
111 #endif
112
113 #ifdef Isoburn_libisofs_dot_h_too_olD
114 LIBISOFS_MISCONFIGURATION = 0;
115 INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libisofs_dot_h_TOO_OLD__SEE_libisoburn_dot_h_AND_burn_wrap_dot_c = 0;
116 LIBISOFS_MISCONFIGURATION_ = 0;
117 #endif
118
119 #endif /* iso_lib_header_version_major */
120
121 /* The minimum requirement of libisoburn towards the libburn header
122 at compile time is defined in libisoburn/libisoburn.h :
123 isoburn_libburn_req_major
124 isoburn_libburn_req_minor
125 isoburn_libburn_req_micro
126 It gets compared against the version macros in libburn/libburn.h :
127 burn_header_version_major
128 burn_header_version_minor
129 burn_header_version_micro
130 If the header is too old then the following code shall cause failure of
131 cdrskin compilation rather than to allow production of a program with
132 unpredictable bugs or memory corruption.
133 The compiler messages supposed to appear in this case are:
134 error: 'LIBBURN_MISCONFIGURATION' undeclared (first use in this function)
135 error: 'INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libburn_dot_h_TOO_OLD__SEE_libisoburn_dot_h_and_burn_wrap_dot_h' undeclared (first use in this function)
136 error: 'LIBBURN_MISCONFIGURATION_' undeclared (first use in this function)
137 */
138
139 /* The indendation is an advise of man gcc to help old compilers ignoring */
140 #if isoburn_libburn_req_major > burn_header_version_major
141 #define Isoburn_libburn_dot_h_too_olD 1
142 #endif
143 #if isoburn_libburn_req_major == burn_header_version_major && isoburn_libburn_req_minor > burn_header_version_minor
144 #define Isoburn_libburn_dot_h_too_olD 1
145 #endif
146 #if isoburn_libburn_req_minor == burn_header_version_minor && isoburn_libburn_req_micro > burn_header_version_micro
147 #define Isoburn_libburn_dot_h_too_olD 1
148 #endif
149
150 #ifdef Isoburn_libburn_dot_h_too_olD
151 LIBBURN_MISCONFIGURATION = 0;
152 INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libburn_dot_h_TOO_OLD__SEE_libisoburn_dot_h_and_burn_wrap_dot_h = 0;
153 LIBBURN_MISCONFIGURATION_ = 0;
154 #endif
155
156
157 #ifdef Xorriso_with_libjtE
158
159 /* The minimum requirement of libisoburn towards the libjte header
160 at compile time is the same as the one of a usable libisofs towards libjte.
161 So the requirement is defined in libisofs/libisofs.h :
162 iso_libjte_req_major , iso_libjte_req_minor , iso_libjte_req_micro
163 */
164 /* The indendation is an advise of man gcc to help old compilers ignoring */
165 #if iso_libjte_req_major > LIBJTE_VERSION_MAJOR
166 #define Libisofs_libjte_dot_h_too_olD 1
167 #endif
168 #if iso_libjte_req_major == LIBJTE_VERSION_MAJOR && iso_libjte_req_minor > LIBJTE_VERSION_MINOR
169 #define Libisofs_libjte_dot_h_too_olD 1
170 #endif
171 #if iso_libjte_req_minor == LIBJTE_VERSION_MINOR && iso_libjte_req_micro > LIBJTE_VERSION_MICRO
172 #define Libisofs_libjte_dot_h_too_olD 1
173 #endif
174
175 #ifdef Libisofs_libjte_dot_h_too_olD
176 LIBJTE_MISCONFIGURATION = 0;
177 INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libjte_dot_h_TOO_OLD__SEE_libisofs_dot_h_AND_burn_wrap.c_c = 0;
178 LIBJTE_MISCONFIGURATION_ = 0;
179 #endif
180
181 #endif /* Xorriso_with_libjtE */
182
183
184 /* End of ugly compile time tests (scroll up for explanation) */
185
186
187 msg[0]= 0;
188
189 #ifdef Xorriso_with_libjtE
190
191 libjte__version(&major, &minor, µ);
192 sprintf(msg + strlen(msg), "libjte-%d.%d.%d ", major, minor, micro);
193 if (libjte__is_compatible(LIBJTE_VERSION_MAJOR, LIBJTE_VERSION_MINOR,
194 LIBJTE_VERSION_MICRO, 0)) {
195 sprintf(msg+strlen(msg), "ok, ");
196 } else {
197 sprintf(msg + strlen(msg),
198 "- TOO OLD -, need at least libjte-%d.%d.%d ,\n",
199 LIBJTE_VERSION_MAJOR, LIBJTE_VERSION_MINOR,
200 LIBJTE_VERSION_MICRO);
201 bad_match= 1;
202 no_iso_init= 1; /* iso_init() will fail anyway */
203 }
204
205 #endif /* Xorriso_with_libjtE */
206
207 if(!no_iso_init) {
208 if(iso_init()<0) {
209 sprintf(msg+strlen(msg), "Cannot initialize libisofs\n");
210 return(0);
211 }
212 }
213 iso_lib_version(&major, &minor, µ);
214 sprintf(msg+strlen(msg), "libisofs-%d.%d.%d ", major, minor, micro);
215 #ifdef iso_lib_header_version_major
216 if(iso_lib_is_compatible(iso_lib_header_version_major,
217 iso_lib_header_version_minor,
218 iso_lib_header_version_micro)) {
219 sprintf(msg+strlen(msg), "ok, ");
220 } else {
221 sprintf(msg+strlen(msg),"- TOO OLD -, need at least libisofs-%d.%d.%d ,\n",
222 iso_lib_header_version_major, iso_lib_header_version_minor,
223 iso_lib_header_version_micro);
224 bad_match= 1;
225 }
226 #else
227 if(iso_lib_is_compatible(isoburn_libisofs_req_major,
228 isoburn_libisofs_req_minor,
229 isoburn_libisofs_req_micro)) {
230 sprintf(msg+strlen(msg), "suspicious, ");
231 } else {
232 sprintf(msg+strlen(msg),"- TOO OLD -, need at least libisofs-%d.%d.%d ,\n",
233 isoburn_libisofs_req_major, isoburn_libisofs_req_minor,
234 isoburn_libisofs_req_micro);
235 bad_match= 1;
236 }
237 #endif /* ! iso_lib_header_version_major */
238
239 if(!burn_initialize()) {
240 sprintf(msg+strlen(msg), "Cannot initialize libburn\n");
241 return(0);
242 }
243
244 burn_version(&major, &minor, µ);
245 sprintf(msg+strlen(msg), "libburn-%d.%d.%d ", major, minor, micro);
246 if(major > burn_header_version_major
247 || (major == burn_header_version_major
248 && (minor > burn_header_version_minor
249 || (minor == burn_header_version_minor
250 && micro >= burn_header_version_micro)))) {
251 sprintf(msg+strlen(msg), "ok, ");
252 } else {
253 sprintf(msg+strlen(msg), "- TOO OLD -, need at least libburn-%d.%d.%d ,\n",
254 burn_header_version_major, burn_header_version_minor,
255 burn_header_version_micro);
256 bad_match= 1;
257 }
258
259 isoburn_version(&major, &minor, µ);
260 sprintf(msg+strlen(msg), "for libisoburn-%d.%d.%d", major, minor, micro);
261 if(bad_match)
262 return(0);
263
264 isoburn_destroy_all(&isoburn_list_start, 0); /* isoburn_list_start= NULL */
265 return(1);
266 }
267
268
269 /* API @since 0.1.0 */
isoburn_libisofs_req(int * major,int * minor,int * micro)270 int isoburn_libisofs_req(int *major, int *minor, int *micro)
271 {
272 *major= iso_lib_header_version_major;
273 *minor= iso_lib_header_version_minor;
274 *micro= iso_lib_header_version_micro;
275 return(1);
276 }
277
278
279 /* API @since 0.1.0 */
isoburn_libburn_req(int * major,int * minor,int * micro)280 int isoburn_libburn_req(int *major, int *minor, int *micro)
281 {
282 *major= burn_header_version_major;
283 *minor= burn_header_version_minor;
284 *micro= burn_header_version_micro;
285 return(1);
286 }
287
288
289 /* API @since 0.6.4 */
isoburn_libjte_req(int * major,int * minor,int * micro)290 int isoburn_libjte_req(int *major, int *minor, int *micro)
291 {
292 #ifdef Xorriso_with_libjtE
293 *major= LIBJTE_VERSION_MAJOR;
294 *minor= LIBJTE_VERSION_MINOR;
295 *micro= LIBJTE_VERSION_MICRO;
296 #else
297 *major= *minor= *micro= 0;
298 #endif /* ! Xorriso_with_libjtE */
299 return(1);
300 }
301
302
isoburn_set_msgs_submit(int (* msgs_submit)(void * handle,int error_code,char msg_text[],int os_errno,char severity[],int flag),void * submit_handle,int submit_flag,int flag)303 int isoburn_set_msgs_submit(int (*msgs_submit)(void *handle, int error_code,
304 char msg_text[], int os_errno,
305 char severity[], int flag),
306 void *submit_handle, int submit_flag, int flag)
307 {
308 libisoburn_default_msgs_submit= msgs_submit;
309 libisoburn_default_msgs_submit_handle= submit_handle;
310 libisoburn_default_msgs_submit_flag= submit_flag;
311 return(1);
312 }
313
314
isoburn_is_intermediate_dvd_rw(struct burn_drive * d,int flag)315 int isoburn_is_intermediate_dvd_rw(struct burn_drive *d, int flag)
316 {
317 int profile, ret= 0, format_status, num_formats;
318 char profile_name[80];
319 enum burn_disc_status s;
320 off_t format_size= -1;
321 unsigned bl_sas;
322
323 s= isoburn_disc_get_status(d);
324 ret= burn_disc_get_profile(d, &profile, profile_name);
325 if(ret>0 && profile==0x13)
326 ret= burn_disc_get_formats(d, &format_status, &format_size,
327 &bl_sas, &num_formats);
328 if(ret>0 && profile==0x13 && s==BURN_DISC_BLANK &&
329 format_status==BURN_FORMAT_IS_UNKNOWN)
330 return(1);
331 return(0);
332 }
333
334
335 /** Examines the medium and sets appropriate emulation if needed.
336 @param flag bit0= pretent blank on overwriteable media
337 bit3= if the drive reports a -ROM profile then try to read
338 table of content by scanning for ISO image headers.
339 bit4= do not emulate TOC on overwriteable media
340 bit5= ignore ACL from external filesystems
341 bit6= ignore POSIX Extended Attributes from external filesystems
342 bit7= pretend -ROM and scan for table of content
343 bit9= when scanning for ISO 9660 sessions on overwritable
344 media: Do not demand a valid superblock at LBA 0
345 and scan until end of medium.
346 bit10= if not bit6: accept all xattr namespaces from external
347 filesystems, not only "user.".
348 */
isoburn_welcome_media(struct isoburn ** o,struct burn_drive * d,int flag)349 static int isoburn_welcome_media(struct isoburn **o, struct burn_drive *d,
350 int flag)
351 {
352 int ret, profile, readonly= 0, role, random_access;
353 int emulation_started= 0;
354 struct burn_multi_caps *caps= NULL;
355 struct isoburn_toc_entry *t;
356 char profile_name[80];
357 struct isoburn_toc_disc *disc= NULL;
358 struct isoburn_toc_session **sessions;
359 struct isoburn_toc_track **tracks;
360 int num_sessions= 0, num_tracks= 0, track_count= 0, session_no= 0;
361 char msg[80];
362 enum burn_disc_status s;
363
364 #ifndef Hardcoded_cd_rW
365 int lba, nwa;
366 #endif
367
368 s= burn_disc_get_status(d);
369 profile_name[0]= 0;
370 ret= burn_disc_get_profile(d, &profile, profile_name);
371 if(ret<=0)
372 profile= 0x00;
373 ret= burn_disc_get_multi_caps(d, BURN_WRITE_NONE, &caps, 0);
374 if(ret<0) /*== 0 is read-only medium, but it is too early to reject it here */
375 goto ex;
376 if(ret==0 || (flag & 128))
377 readonly= 1;
378 if(flag & 128)
379 flag = (flag & ~ 16) | 8;
380
381 ret= isoburn_find_emulator(o, d, 0);
382 if(ret >= 0 && *o != NULL)
383 isoburn_destroy(o, 0);
384 ret= isoburn_new(o, 0);
385 if(ret<=0)
386 goto ex;
387 (*o)->drive= d;
388 (*o)->msgs_submit= libisoburn_default_msgs_submit;
389 (*o)->msgs_submit_handle= libisoburn_default_msgs_submit_handle;
390 (*o)->msgs_submit_flag= libisoburn_default_msgs_submit_flag;
391 iso_image_set_ignore_aclea((*o)->image,
392 ((flag >> 5 ) & 3) | ((!!(flag & 1024)) << 3));
393
394 #ifdef Hardcoded_cd_rW
395 /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
396 caps->start_adr= 0;
397 (*o)->fabricated_disc_status= BURN_DISC_APPENDABLE;
398 #endif
399
400 role= burn_drive_get_drive_role(d);
401 random_access= caps->start_adr || role == 4;
402 if(random_access)
403 (*o)->emulation_mode= 1;
404 if(random_access && !readonly) { /* set emulation to overwriteable */
405 ret= isoburn_is_intermediate_dvd_rw(d, 0);
406 if(ret>0) {
407 (*o)->min_start_byte= 0;
408 (*o)->nwa= 0;
409 (*o)->zero_nwa= 0;
410 }
411 if((flag & 1) && role != 4 && role != 5) {
412 (*o)->nwa= (*o)->zero_nwa;
413 (*o)->fabricated_disc_status= BURN_DISC_BLANK;
414 } else {
415 ret= isoburn_start_emulation(*o, 0);
416 if(ret<=0) {
417 (*o)->emulation_mode= -1;
418 goto ex;
419 }
420 emulation_started= 1;
421 /* try to read emulated toc */
422 ret= isoburn_emulate_toc(d, (flag & 16) | ((!!(flag & 512)) << 1));
423 if(ret<0) {
424 (*o)->emulation_mode= -1;
425 goto ex;
426 }
427 }
428 } else {
429
430 /* >>> recognize unsuitable media (but allow read-only media) */;
431
432 if(readonly && s != BURN_DISC_EMPTY) {
433
434 /* >>> ts B10712: This maps BURN_DISC_UNSUITABLE to BURN_DISC_FULL
435 which can hardly be correct in general.
436 ??? What reason does this have ?
437 */
438 (*o)->fabricated_disc_status= BURN_DISC_FULL;
439
440 /* This might be an overwriteable medium in a -ROM drive.
441 Pitfall:
442 Multi-session media which bear a xorriso image for overwriteables
443 in their first session would get a TOC of that first image rather
444 than of the medium.
445 It is not possible to distinguish a BD-RE from a single session
446 BD-R with an image for overwriteables. But as soon as the medium
447 bears 2 logical tracks it cannot be overwriteable.
448 So count the number of tracks first.
449 */
450 disc= isoburn_toc_drive_get_disc(d);
451 if(disc != NULL) {
452 sessions= isoburn_toc_disc_get_sessions(disc, &num_sessions);
453 for(session_no= 0; session_no < num_sessions; session_no++) {
454 tracks= isoburn_toc_session_get_tracks(sessions[session_no],
455 &num_tracks);
456 if(tracks != NULL)
457 track_count+= num_tracks;
458 }
459 isoburn_toc_disc_free(disc);
460 }
461
462 sprintf(msg, "ROM medium has libburn track count = %d", track_count);
463 isoburn_msgs_submit(*o, 0x00060000, msg, 0, "DEBUG", 0);
464
465 if((flag & 16) || track_count >= 2) {
466 ret= 0; /* toc emulation off, or not overwriteable */
467 } else {
468 ret= isoburn_start_emulation(*o, 1);
469 if(ret<=0) {
470 (*o)->emulation_mode= -1;
471 goto ex;
472 }
473 emulation_started= 1;
474 ret= isoburn_emulate_toc(d, 1 | ((!!(flag & 512)) << 1));
475 if(ret<0)
476 goto ex;
477 else if(ret > 0)
478 (*o)->emulation_mode= 1;
479 }
480 if(ret == 0 && (profile != 0x08 || (flag & 128)) && (flag & 8)) {
481 /* This might also be multi-session media which do not
482 get shown with a decent TOC.
483 CD-R TOC (profile 0x08) can be trusted. Others not.
484 Do a scan search of ISO headers.
485 */
486 if(!emulation_started) {
487 ret= isoburn_start_emulation(*o, 1);
488 if(ret<=0) {
489 (*o)->emulation_mode= -1;
490 goto ex;
491 }
492 }
493 ret= isoburn_emulate_toc(d, 1 | 2);
494 if(ret<0)
495 goto ex;
496 if(ret>0) { /* point msc1 to last session */
497 if((*o)->toc!=NULL) {
498 for(t= (*o)->toc; t->next!=NULL; t= t->next)
499 ; /* clang wants newline in empty loops */
500 (*o)->fabricated_msc1= t->start_lba;
501 }
502 }
503 }
504 }
505 #ifdef Hardcoded_cd_rW
506 (*o)->nwa= Hardcoded_cd_rw_nwA;
507 #else
508 ret= burn_disc_track_lba_nwa(d, NULL, 0, &lba, &nwa);
509 if(ret>0)
510 (*o)->nwa= nwa;
511 if((*o)->nwa < (*o)->zero_nwa)
512 (*o)->zero_nwa= 0;
513 #endif
514
515 }
516
517 ret= 1;
518 ex:
519 if(caps!=NULL)
520 burn_disc_free_multi_caps(&caps);
521 return(ret);
522 }
523
524
525 /**
526 @param flag bit0= load
527 bit1= regard overwriteable media as blank
528 bit2= if the drive is a regular disk file: truncate it to
529 the write start address
530 bit3= if the drive reports a -ROM profile then try to read
531 table of content by scanning for ISO image headers.
532 (depending on media type and drive state this might
533 help or it might make the resulting toc even worse)
534 bit4= do not emulate TOC on overwriteable media
535 bit5= ignore ACL from external filesystems
536 bit6= ignore POSIX Extended Attributes from external filesystems
537 bit7= pretend -ROM profile and scan for table of content
538 bit8= re-assess (*drive_infos)[0] rather than acquiring adr
539 bit9= when scanning for ISO 9660 sessions on overwritable
540 media: Do not demand a valid superblock at LBA 0
541 and scan until end of medium.
542 bit10= if not bit6: accept all xattr namespaces from external
543 filesystems, not only "user.".
544 */
isoburn_drive_aquire(struct burn_drive_info * drive_infos[],char * adr,int flag)545 int isoburn_drive_aquire(struct burn_drive_info *drive_infos[],
546 char *adr, int flag)
547 {
548 int ret, drive_grabbed= 0;
549 struct isoburn *o= NULL;
550 int conv_ret;
551 char *libburn_drive_adr= NULL;
552
553 /* Should be obsolete by new drive addressing of libburn-0.5.2 */
554 /* but helps with kernel 2.4 to use /dev/sr */
555 libburn_drive_adr= calloc(1, BURN_DRIVE_ADR_LEN);
556 if(libburn_drive_adr == NULL)
557 {ret= -1; goto ex;}
558 conv_ret= burn_drive_convert_fs_adr(adr, libburn_drive_adr);
559 if(conv_ret<=0)
560 strcpy(libburn_drive_adr, adr);
561
562 if(flag & 256)
563 ret= burn_drive_re_assess((*drive_infos)[0].drive, 0);
564 else
565 ret= burn_drive_scan_and_grab(drive_infos, libburn_drive_adr, flag&1);
566 if(ret<=0)
567 goto ex;
568 drive_grabbed= 1;
569 ret= isoburn_welcome_media(&o, (*drive_infos)[0].drive,
570 (flag & (8 | 16 | 32 | 64 | 128 | 512 | 1024)) |
571 !!(flag&2));
572 if(ret<=0)
573 goto ex;
574
575 if(flag&4) {
576 ret= isoburn_find_emulator(&o, (*drive_infos)[0].drive, 0);
577 if(ret>0 && o!=NULL)
578 o->truncate= 1;
579 }
580
581 ret= 1;
582 ex:
583 if(ret<=0) {
584 if(drive_grabbed)
585 burn_drive_release((*drive_infos)[0].drive, 0);
586 isoburn_destroy(&o, 0);
587 }
588 if(libburn_drive_adr != NULL)
589 free(libburn_drive_adr);
590 return(ret);
591 }
592
593
isoburn_drive_scan_and_grab(struct burn_drive_info * drive_infos[],char * adr,int load)594 int isoburn_drive_scan_and_grab(struct burn_drive_info *drive_infos[],
595 char *adr, int load)
596 {
597 int ret;
598
599 ret= isoburn_drive_aquire(drive_infos, adr, !!load);
600 return(ret);
601 }
602
603
isoburn_drive_grab(struct burn_drive * drive,int load)604 int isoburn_drive_grab(struct burn_drive *drive, int load)
605 {
606 int ret;
607 struct isoburn *o= NULL;
608
609 ret= burn_drive_grab(drive, load);
610 if(ret<=0)
611 goto ex;
612 ret= isoburn_welcome_media(&o, drive, 0);
613 if(ret<=0)
614 goto ex;
615
616 ret= 1;
617 ex:
618 if(ret<=0)
619 isoburn_destroy(&o,0);
620 return(ret);
621 }
622
623
624 /** Retrieve medium emulation and eventual isoburn emulator of drive.
625 @return -1 unsuitable medium, 0 generic medium, 1 emulated medium.
626 */
isoburn_find_emulator(struct isoburn ** pt,struct burn_drive * drive,int flag)627 int isoburn_find_emulator(struct isoburn **pt,
628 struct burn_drive *drive, int flag)
629 {
630 int ret;
631
632 ret= isoburn_find_by_drive(pt, drive, 0);
633 if(ret<=0)
634 return(0);
635 if((*pt)->emulation_mode==-1) {
636 isoburn_msgs_submit(*pt, 0x00060000,
637 "Unsuitable drive and medium state", 0, "FAILURE", 0);
638 return(-1);
639 }
640 if((*pt)->emulation_mode==0)
641 return(0);
642 return(1);
643 }
644
645
isoburn_disc_get_status(struct burn_drive * drive)646 enum burn_disc_status isoburn_disc_get_status(struct burn_drive *drive)
647 {
648 int ret;
649 struct isoburn *o;
650
651 ret= isoburn_find_emulator(&o, drive, 0);
652 if(ret<0)
653 return(BURN_DISC_UNSUITABLE);
654 if(o!=NULL)
655 if(o->fabricated_disc_status!=BURN_DISC_UNREADY)
656 return(o->fabricated_disc_status);
657 if(ret==0)
658 return(burn_disc_get_status(drive));
659
660 /* emulated status */
661 if(o->emulation_mode==-1)
662 return(BURN_DISC_UNSUITABLE);
663 if(o->nwa>o->zero_nwa)
664 return(BURN_DISC_APPENDABLE);
665 return(BURN_DISC_BLANK);
666 }
667
668
isoburn_disc_pretend_full_uncond(struct burn_drive * drive)669 int isoburn_disc_pretend_full_uncond(struct burn_drive *drive)
670 {
671 int ret;
672 struct isoburn *o;
673
674 ret= isoburn_find_emulator(&o, drive, 0);
675 if(ret > 0 && o != NULL)
676 o->fabricated_disc_status= BURN_DISC_FULL;
677 ret= burn_disc_pretend_full_uncond(drive);
678 return(ret);
679 }
680
681
isoburn_disc_erasable(struct burn_drive * d)682 int isoburn_disc_erasable(struct burn_drive *d)
683 {
684 int ret;
685 struct isoburn *o;
686
687 ret= isoburn_find_emulator(&o, d, 0);
688 if(ret>0)
689 if(o->emulation_mode==1)
690 return(1);
691 return burn_disc_erasable(d);
692 }
693
694
isoburn_is_overwritable(struct burn_drive * drive,int flag)695 static int isoburn_is_overwritable(struct burn_drive *drive, int flag)
696 {
697 char name[80];
698 int profile, ret;
699
700 ret= burn_disc_get_profile(drive, &profile, name);
701 if(ret <= 0)
702 return(0);
703 if(profile == 0x12 || profile == 0x13 || profile == 0x1a || profile == 0x43)
704 return(1);
705 return(0);
706
707 }
708
709
isoburn_disc_erase(struct burn_drive * drive,int fast)710 void isoburn_disc_erase(struct burn_drive *drive, int fast)
711 {
712 int ret, do_pseudo_blank= 0, role;
713 struct isoburn *o;
714 enum burn_disc_status s;
715 char *zero_buffer= NULL;
716 struct burn_multi_caps *caps= NULL;
717
718 zero_buffer= calloc(1, Libisoburn_target_head_sizE);
719 if(zero_buffer == NULL) {
720 /* To cause a negative reply with burn_drive_wrote_well() */
721 burn_drive_cancel(drive);
722 goto ex;
723 }
724
725 ret= isoburn_find_emulator(&o, drive, 0);
726 if(ret>0) {
727 if(o->emulation_mode==-1) {
728 /* To cause a negative reply with burn_drive_wrote_well() */
729 burn_drive_cancel(drive);
730 goto ex;
731 }
732 role = burn_drive_get_drive_role(drive);
733 if (role == 5) {
734 /* libburn will truncate the random-access write-only file
735 to zero size and change its state */
736 burn_disc_erase(drive, fast);
737 o->fabricated_disc_status= burn_disc_get_status(drive);
738 o->nwa= o->zero_nwa= 0;
739 goto ex;
740 }
741 if(o->emulation_mode > 0) { /* might be readonly with emulated sessions */
742 ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0);
743 if(ret <= 0) /* Maybe because of burn_disc_pretend_full() */
744 do_pseudo_blank= isoburn_is_overwritable(drive, 0); /* known profiles */
745 else if(caps->start_adr)
746 do_pseudo_blank= 1;
747 }
748 if(do_pseudo_blank) {
749 s= isoburn_disc_get_status(drive);
750 if(s==BURN_DISC_FULL) { /* unknown data format in first 64 kB */
751 memset(zero_buffer, 0, Libisoburn_target_head_sizE);
752 ret= burn_random_access_write(drive, (off_t) 0, zero_buffer,
753 (off_t) Libisoburn_target_head_sizE, 1);
754 } else {
755 ret= isoburn_invalidate_iso(o, 0);
756 }
757 if(ret<=0)
758 burn_drive_cancel(drive); /* mark run as failure */
759 goto ex;
760 }
761 }
762 burn_disc_erase(drive, fast);
763 ex:;
764 if(caps!=NULL)
765 burn_disc_free_multi_caps(&caps);
766 if(zero_buffer != NULL)
767 free(zero_buffer);
768 }
769
770
isoburn_disc_available_space(struct burn_drive * d,struct burn_write_opts * opts)771 off_t isoburn_disc_available_space(struct burn_drive *d,
772 struct burn_write_opts *opts)
773 {
774 int ret;
775 struct isoburn *o;
776 struct burn_write_opts *eff_opts= NULL, *local_opts= NULL;
777 enum burn_disc_status s;
778 off_t avail;
779
780 eff_opts= opts;
781 ret= isoburn_find_emulator(&o, d, 0);
782 if(ret>0 && o!=NULL)
783 if(o->emulation_mode!=0) {
784 s= isoburn_disc_get_status(d);
785 if(s==BURN_DISC_FULL) /* unknown data format in first 64 kB */
786 return((off_t) 0);
787 local_opts= burn_write_opts_new(d);
788 eff_opts= local_opts;
789 burn_write_opts_set_start_byte(eff_opts, ((off_t) o->nwa) * (off_t) 2048);
790 }
791 avail= burn_disc_available_space(d, eff_opts);
792 if(local_opts!=NULL)
793 burn_write_opts_free(local_opts);
794 local_opts= NULL;
795 return(avail);
796 }
797
798
isoburn_disc_get_msc1(struct burn_drive * d,int * start_lba)799 int isoburn_disc_get_msc1(struct burn_drive *d, int *start_lba)
800 {
801 int ret;
802 struct isoburn *o;
803
804 #ifdef Hardcoded_cd_rW
805 /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
806 *start_lba= Hardcoded_cd_rw_c1;
807 return(1);
808 #endif
809
810 if(isoburn_disc_get_status(d)!=BURN_DISC_APPENDABLE &&
811 isoburn_disc_get_status(d)!=BURN_DISC_FULL) {
812 isoburn_msgs_submit(NULL, 0x00060000,
813 "Medium contains no recognizable data", 0, "SORRY", 0);
814 return(0);
815 }
816 ret= isoburn_find_emulator(&o, d, 0);
817 if(ret<0)
818 return(0);
819 if(o->fabricated_msc1>=0) {
820 *start_lba= o->fabricated_msc1;
821 return(1);
822 }
823 if(ret>0) if(o->emulation_mode>0) {
824 *start_lba= 0;
825 return(1);
826 }
827 return(burn_disc_get_msc1(d, start_lba));
828 }
829
830
isoburn_disc_track_lba_nwa(struct burn_drive * d,struct burn_write_opts * opts,int trackno,int * lba,int * nwa)831 int isoburn_disc_track_lba_nwa(struct burn_drive *d,
832 struct burn_write_opts *opts,
833 int trackno, int *lba, int *nwa)
834 {
835 int ret;
836 struct isoburn *o;
837 enum burn_disc_status s;
838
839 #ifdef Hardcoded_cd_rW
840 /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
841 *lba= Hardcoded_cd_rw_c1;
842 *nwa= Hardcoded_cd_rw_nwA;
843 return(1);
844 #endif
845
846 *nwa= *lba= 0;
847 ret= isoburn_find_emulator(&o, d, 0);
848 if(ret<0)
849 return(0);
850 if(ret>0) if(o->emulation_mode>0) {
851 *lba= 0;
852 *nwa= o->nwa;
853 return(1);
854 }
855 if(burn_drive_get_drive_role(d) != 1)
856 return(1);
857
858 s= isoburn_disc_get_status(d);
859 if(s == BURN_DISC_BLANK) /* We do not believe in anything but nwa = lba = 0 */
860 return(1);
861 return(burn_disc_track_lba_nwa(d, opts, trackno, lba, nwa));
862 }
863
864
isoburn_get_msc2(struct isoburn * o,struct burn_write_opts * opts,int * msc2,int flag)865 int isoburn_get_msc2(struct isoburn *o,
866 struct burn_write_opts *opts, int *msc2, int flag)
867 {
868 int ret, lba, nwa;
869
870 if(o->fabricated_msc2>=0)
871 *msc2= o->fabricated_msc2;
872 else {
873 ret= isoburn_disc_track_lba_nwa(o->drive, opts, 0, &lba, &nwa);
874 if(ret<=0)
875 return(ret);
876 *msc2= nwa;
877 }
878 return(1);
879 }
880
881 /* @param flag bit0= truncate (else do not truncate)
882 bit1= do not warn if call is inappropriate to drive
883 bit2= only set if truncation is currently enabled
884 */
isoburn_set_truncate(struct burn_drive * drive,int flag)885 int isoburn_set_truncate(struct burn_drive *drive, int flag)
886 {
887 int ret;
888 struct isoburn *o;
889
890 ret= isoburn_find_emulator(&o, drive, 0);
891 if(ret < 0)
892 return ret;
893 if(o == NULL) {
894 if(!(flag & (2 | 4)))
895 isoburn_msgs_submit(o, 0x00060000,
896 "Drive type or role is inappropriate for truncation", 0, "WARNING", 0);
897 return(0);
898 }
899 if(o->truncate || !(flag & 4))
900 o->truncate= flag & 1;
901 return(1);
902 }
903
904
isoburn_disc_write(struct burn_write_opts * opts,struct burn_disc * disc)905 void isoburn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
906 {
907 int ret;
908 off_t nwa= 0;
909 struct isoburn *o;
910 struct burn_drive *drive;
911 char *reasons= NULL, *msg= NULL, *adr= NULL;
912 struct stat stbuf;
913 enum burn_write_types write_type;
914
915 drive= burn_write_opts_get_drive(opts);
916
917 reasons= calloc(1, BURN_REASONS_LEN);
918 msg= calloc(1, 160+BURN_REASONS_LEN);
919 adr= calloc(1, BURN_DRIVE_ADR_LEN);
920 if(reasons == NULL || msg == NULL || adr == NULL) {
921 /* To cause a negative reply with burn_drive_wrote_well() */
922 burn_drive_cancel(drive);
923 goto ex;
924 }
925
926 ret= isoburn_find_emulator(&o, drive, 0);
927 if(ret<0)
928 goto ex;
929 if(o == NULL) {
930 sprintf(msg,
931 "Program error: Cannot find isoburn object associated to the drive");
932 isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0);
933 burn_drive_cancel(drive);
934 goto ex;
935 }
936 o->wrote_well= -1;
937 if(o->emulation_mode!=0) {
938 burn_write_opts_set_multi(opts, 0);
939 if(o->emulation_mode>0 && o->nwa >= 0) {
940 nwa= o->nwa;
941
942 /* This caters for unwritten formatted DVD-RW. They need to be written
943 sequentially on the first use. Only written areas are random access.
944 If the first session is not written to LBA 0, then re-opening of
945 formatting and padding is needed.
946 This can be done. But when the track gets closed after padding,
947 this lasts a long time. There is a high risk that an app will not
948 poll the message queue while waiting for isoburn_disc_write() to
949 return. The pacifier loop usually happens only afterwards.
950 So automatic formatting might cause a nervous clueless user.
951 */
952 ret= isoburn_is_intermediate_dvd_rw(drive, 0);
953 if(ret>0 && nwa>0 && nwa <= o->zero_nwa) {
954 /* actually this should not happen since such media get recognized
955 by isoburn_welcome_media and o->zero_nwa gets set to 0
956 */
957 sprintf(msg,
958 "DVD-RW insufficiently formatted. (Intermediate State, size unknown)");
959 isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0);
960 sprintf(msg,
961 "It might help to first deformat it and then format it again");
962 isoburn_msgs_submit(o, 0x00060000, msg, 0, "HINT", 0);
963 burn_drive_cancel(drive); /* mark run as failure */
964 goto ex;
965 }
966 /* end of DVD-RW oriented check */
967 burn_write_opts_set_start_byte(opts, nwa * (off_t) 2048);
968 }
969 }
970
971 if(o->do_tao) {
972 if (o->do_tao > 0)
973 burn_write_opts_set_write_type(opts, BURN_WRITE_TAO, BURN_BLOCK_MODE1);
974 else
975 burn_write_opts_set_write_type(opts, BURN_WRITE_SAO, BURN_BLOCK_SAO);
976
977 ret = burn_precheck_write(opts, disc, reasons, 0);
978 if(ret <= 0) {
979 sprintf(msg, "Cannot set write type %s for this medium.",
980 o->do_tao > 0 ? "TAO" : "SAO");
981 sprintf(msg + strlen(msg), "Reasons given:\n %s", reasons);
982 goto no_write_type;
983 }
984 sprintf(msg, "Explicitly chosen write type: %s",
985 o->do_tao > 0 ? "TAO" : "SAO");
986 isoburn_msgs_submit(o, 0x00060000, msg, 0, "NOTE", 0);
987 } else {
988 write_type= burn_write_opts_auto_write_type(opts, disc, reasons, 0);
989 if (write_type == BURN_WRITE_NONE) {
990 sprintf(msg, "Failed to find a suitable write type:\n%s", reasons);
991 no_write_type:;
992 isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0);
993 if(o!=NULL)
994 o->wrote_well= 0;
995 /* To cause a negative reply with burn_drive_wrote_well() */
996 burn_drive_cancel(drive);
997 goto ex;
998 }
999
1000 sprintf(reasons, "%d", (int) write_type);
1001 sprintf(msg, "Write_type = %s\n",
1002 (write_type == BURN_WRITE_SAO ? "SAO" :
1003 (write_type == BURN_WRITE_TAO ? "TAO" : reasons)));
1004 isoburn_msgs_submit(o, 0x00060000, msg, 0, "DEBUG", 0);
1005 }
1006
1007 #ifdef Hardcoded_cd_rW
1008 /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
1009 fprintf(stderr, "Setting write address to LBA %d\n", Hardcoded_cd_rw_nwA);
1010 burn_write_opts_set_start_byte(opts,
1011 ((off_t) Hardcoded_cd_rw_nwA) * (off_t) 2048);
1012 #endif
1013
1014 if(o->truncate) {
1015 ret= burn_drive_get_drive_role(drive);
1016 if(ret == 2 || ret == 5) {
1017 ret= burn_drive_d_get_adr(drive, adr);
1018 if(ret>0) {
1019 ret= lstat(adr, &stbuf);
1020 if(ret!=-1)
1021 if(S_ISREG(stbuf.st_mode))
1022 ret= truncate(adr, nwa * (off_t) 2048);
1023 /* (result of truncate intentionally ignored) */
1024 }
1025 }
1026 }
1027
1028 burn_disc_write(opts, disc);
1029 ex:;
1030 if(reasons != NULL)
1031 free(reasons);
1032 if(msg != NULL)
1033 free(msg);
1034 if(adr != NULL)
1035 free(adr);
1036 }
1037
1038
isoburn_drive_release(struct burn_drive * drive,int eject)1039 void isoburn_drive_release(struct burn_drive *drive, int eject)
1040 {
1041 int ret;
1042 struct isoburn *o;
1043
1044 ret= isoburn_find_emulator(&o, drive, 0);
1045 if(ret<0)
1046 return;
1047 if(o!=NULL) {
1048 isoburn_destroy(&o, 0);
1049 }
1050 burn_drive_release(drive, eject);
1051 }
1052
1053
isoburn_finish(void)1054 void isoburn_finish(void)
1055 {
1056 isoburn_destroy_all(&isoburn_list_start, 0);
1057 burn_finish();
1058 iso_finish();
1059 }
1060
1061
isoburn_needs_emulation(struct burn_drive * drive)1062 int isoburn_needs_emulation(struct burn_drive *drive)
1063 {
1064 int ret;
1065 struct isoburn *o;
1066 enum burn_disc_status s;
1067
1068 s= isoburn_disc_get_status(drive);
1069 if(s!=BURN_DISC_BLANK && s!=BURN_DISC_APPENDABLE)
1070 return(-1);
1071 ret= isoburn_find_emulator(&o, drive, 0);
1072 if(ret<0)
1073 return(-1);
1074 if(ret>0)
1075 if(o->emulation_mode>0)
1076 return(1);
1077 return(0);
1078 }
1079
1080
isoburn_set_start_byte(struct isoburn * o,off_t value,int flag)1081 int isoburn_set_start_byte(struct isoburn *o, off_t value, int flag)
1082 {
1083 int ret;
1084 struct burn_drive *drive = o->drive;
1085 struct burn_multi_caps *caps= NULL;
1086
1087 ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0);
1088 if(ret<=0)
1089 goto ex;
1090 if(!caps->start_adr) {
1091 isoburn_msgs_submit(o, 0x00060000,
1092 "Cannot set start byte address with this type of media",
1093 0, "FAILURE", 0);
1094 {ret= 0; goto ex;}
1095 }
1096 o->min_start_byte= value;
1097 if(value % caps->start_alignment)
1098 value+= caps->start_alignment - (value % caps->start_alignment);
1099 o->nwa= value/2048;
1100 if(o->nwa < o->zero_nwa)
1101 o->zero_nwa= 0;
1102 /* If suitable for media alignment, round up to Libisoburn_nwa_alignemenT */
1103 if((o->nwa % Libisoburn_nwa_alignemenT) &&
1104 ((Libisoburn_nwa_alignemenT*2048) % caps->start_alignment)==0 )
1105 o->nwa+= Libisoburn_nwa_alignemenT - (o->nwa % Libisoburn_nwa_alignemenT);
1106 ret= 1;
1107 ex:
1108 if(caps!=NULL)
1109 burn_disc_free_multi_caps(&caps);
1110 return(ret);
1111 }
1112
1113
isoburn_get_min_start_byte(struct burn_drive * d,off_t * start_byte,int flag)1114 int isoburn_get_min_start_byte(struct burn_drive *d, off_t *start_byte,
1115 int flag)
1116 {
1117 int ret;
1118 struct isoburn *o;
1119
1120 ret= isoburn_find_emulator(&o, d, 0);
1121 if(ret<0)
1122 return(-1);
1123 if(ret==0)
1124 return(0);
1125 *start_byte= o->min_start_byte;
1126 if(o->min_start_byte<=0)
1127 return(0);
1128 return(1);
1129 }
1130
1131
isoburn_drive_wrote_well(struct burn_drive * d)1132 int isoburn_drive_wrote_well(struct burn_drive *d)
1133 {
1134 int ret;
1135 struct isoburn *o;
1136
1137 ret= isoburn_find_emulator(&o, d, 0);
1138 if(ret<0)
1139 return(-1);
1140 if(o!=NULL)
1141 if(o->wrote_well>=0)
1142 return(o->wrote_well);
1143 ret= burn_drive_wrote_well(d);
1144 return ret;
1145 }
1146
1147
isoburn_get_fifo_status(struct burn_drive * d,int * size,int * free_bytes,char ** status_text)1148 int isoburn_get_fifo_status(struct burn_drive *d, int *size, int *free_bytes,
1149 char **status_text)
1150 {
1151 int ret;
1152 struct isoburn *o;
1153 size_t hsize= 0, hfree_bytes= 0;
1154
1155 ret= isoburn_find_emulator(&o, d, 0);
1156 if(ret<0)
1157 return(-1);
1158
1159 if(o==NULL)
1160 return(-1);
1161 if(o->iso_source==NULL)
1162 return(-1);
1163 ret= iso_ring_buffer_get_status(o->iso_source, &hsize, &hfree_bytes);
1164 if(hsize > 1024*1024*1024)
1165 *size= 1024*1024*1024;
1166 else
1167 *size= hsize;
1168 if(hfree_bytes > 1024*1024*1024)
1169 *free_bytes= 1024*1024*1024;
1170 else
1171 *free_bytes= hfree_bytes;
1172 *status_text= "";
1173 if(ret==0)
1174 *status_text= "standby";
1175 else if(ret==1)
1176 *status_text= "active";
1177 else if(ret==2)
1178 *status_text= "ending";
1179 else if(ret==3)
1180 *status_text= "failing";
1181 else if(ret==4)
1182 *status_text= "unused";
1183 else if(ret==5)
1184 *status_text= "abandoned";
1185 else if(ret==6)
1186 *status_text= "ended";
1187 else if(ret==7)
1188 *status_text= "aborted";
1189 return(ret);
1190 }
1191
1192
1193 /* @param flag bit0= -reserved-
1194 bit1= this is a libburn severity
1195 */
isoburn__sev_to_text(int severity,char ** severity_name,int flag)1196 int isoburn__sev_to_text(int severity, char **severity_name,
1197 int flag)
1198 {
1199 int ret;
1200
1201 ret= iso_sev_to_text(severity, severity_name);
1202 if(ret>0)
1203 return(ret);
1204 ret= burn_sev_to_text(severity, severity_name, 0);
1205 return(ret);
1206 }
1207
1208
isoburn__text_to_sev(char * severity_name,int * severity_number,int flag)1209 int isoburn__text_to_sev(char *severity_name, int *severity_number, int flag)
1210 {
1211 int ret= 1;
1212
1213 ret= iso_text_to_sev(severity_name, severity_number);
1214 if(ret>0)
1215 return(ret);
1216 ret= burn_text_to_sev(severity_name, severity_number, 0);
1217 return(ret);
1218 }
1219
1220
isoburn_report_iso_error(int iso_error_code,char msg_text[],int os_errno,char min_severity[],int flag)1221 int isoburn_report_iso_error(int iso_error_code, char msg_text[], int os_errno,
1222 char min_severity[], int flag)
1223 {
1224 int error_code, iso_sev, min_sev, ret;
1225 char *sev_text_pt, *msg_text_pt= NULL;
1226
1227 error_code= iso_error_get_code(iso_error_code);
1228 if(error_code < 0x00030000 || error_code >= 0x00040000)
1229 error_code= (error_code & 0xffff) | 0x00050000;
1230
1231 if(iso_error_code<0)
1232 msg_text_pt= (char *) iso_error_to_msg(iso_error_code);
1233 if(msg_text_pt==NULL)
1234 msg_text_pt= msg_text;
1235 iso_sev= iso_error_get_severity(iso_error_code);
1236 sev_text_pt= min_severity;
1237 isoburn__text_to_sev(min_severity, &min_sev, 0);
1238 if(min_sev < iso_sev)
1239 isoburn__sev_to_text(iso_sev, &sev_text_pt, 0);
1240 ret= iso_msgs_submit(error_code, msg_text_pt, os_errno, sev_text_pt, 0);
1241 return(ret);
1242 }
1243
1244
1245 /* @param flag bit0-7: info return mode
1246 0= do not return anything in info (do not even touch it)
1247 1= copy volume id to info (info needs 33 bytes)
1248 2= do not touch info (caller will copy 64 kB header to it)
1249 bit14= -reserved -
1250 bit15= -reserved-
1251 @return 1 seems to be a valid ISO image , 0 format not recognized, <0 error
1252 */
isoburn_read_iso_head_parse(unsigned char * data,int * image_blocks,char * info,int flag)1253 int isoburn_read_iso_head_parse(unsigned char *data,
1254 int *image_blocks, char *info, int flag)
1255 {
1256 int i, info_mode;
1257
1258 /* is this an ISO image ? */
1259 if(data[0]!=1)
1260 return(0);
1261 if(strncmp((char *) (data+1),"CD001",5)!=0)
1262 return(0);
1263 /* believe so */
1264
1265 *image_blocks= data[80] | (data[81]<<8) | (data[82]<<16) | (data[83]<<24);
1266 info_mode= flag&255;
1267 if(info_mode==0) {
1268 ;
1269 } else if(info_mode==1) {
1270 strncpy(info, (char *) (data+40), 32);
1271 info[32]= 0;
1272 for(i= strlen(info)-1; i>=0; i--)
1273 if(info[i]!=' ')
1274 break;
1275 else
1276 info[i]= 0;
1277 } else if(info_mode==2) {
1278 ;
1279 } else {
1280 isoburn_msgs_submit(NULL, 0x00060000,
1281 "Program error: Unknown info mode with isoburn_read_iso_head()",
1282 0, "FATAL", 0);
1283 return(-1);
1284 }
1285 return(1);
1286 }
1287
1288
1289 /* API
1290 @param flag bit0-7: info return mode
1291 0= do not return anything in info (do not even touch it)
1292 1= copy volume id to info (info needs 33 bytes)
1293 2= copy 64 kB header to info (needs 65536 bytes)
1294 bit13= do not read head from media but use first 64 kB from info
1295 bit14= check both half buffers (not only second)
1296 return 2 if found in first block
1297 bit15= return-1 on read error
1298 @return 1 seems to be a valid ISO image , 2 found in first half buffer,
1299 0 format not recognized, <0 error
1300 */
isoburn_read_iso_head(struct burn_drive * d,int lba,int * image_blocks,char * info,int flag)1301 int isoburn_read_iso_head(struct burn_drive *d, int lba,
1302 int *image_blocks, char *info, int flag)
1303 {
1304 unsigned char *buffer= NULL;
1305 int ret, info_mode, capacity, role;
1306 off_t data_count, to_read;
1307 struct isoburn *o;
1308
1309 buffer= calloc(1, 64 * 1024);
1310 if(buffer == NULL)
1311 {ret= -1; goto ex;}
1312
1313 info_mode= flag&255;
1314 *image_blocks= 0;
1315 if(flag&(1<<13)) {
1316 memcpy(buffer, info, 64*1024);
1317 } else {
1318 memset(buffer, 0, 64 * 1024);
1319 role = burn_drive_get_drive_role(d);
1320 if (role == 3 || role == 5)
1321
1322 /* >>> ??? return always 0 ? */
1323 {ret= (-1*!!(flag&(1<<15))); goto ex;}
1324
1325 ret = burn_get_read_capacity(d, &capacity, 0);
1326 if (ret <= 0 && (role == 2 || role == 4)) {
1327 /* Might be a block device on a system where libburn cannot determine its
1328 size. Try to read anyway. */
1329 capacity = 0x7ffffff0;
1330 ret = 1;
1331 }
1332 to_read= (off_t) capacity * ((off_t) 2048);
1333 if(ret > 0 && to_read >= (off_t) (36 * 1024)) {
1334 ret= isoburn_find_emulator(&o, d, 0);
1335 if(ret > 0)
1336 if(o->media_read_error)
1337 {ret= (-1 * !!(flag & (1 << 15))); goto ex;}
1338 if(to_read >= (off_t) (64 * 1024))
1339 to_read= 64 * 1024;
1340 ret = burn_read_data(d, ((off_t) lba) * (off_t) 2048, (char *) buffer,
1341 to_read, &data_count, 32); /* error messages as DEBUG */
1342 } else
1343 ret= 0;
1344 if(ret<=0)
1345 {ret= (-1*!!(flag&(1<<15))); goto ex;}
1346 if(info_mode==2)
1347 memcpy(info, buffer, 64*1024);
1348 }
1349
1350 if(flag&(1<<14)) {
1351 ret= isoburn_read_iso_head_parse(buffer, image_blocks, info, info_mode);
1352 if(ret<0)
1353 goto ex;
1354 if(ret>0)
1355 {ret= 2; goto ex;}
1356 }
1357 ret= isoburn_read_iso_head_parse(buffer+32*1024, image_blocks, info,
1358 info_mode);
1359 if(ret<=0)
1360 goto ex;
1361 ret= 1;
1362 ex:;
1363 if(buffer != NULL)
1364 free(buffer);
1365 return(ret);
1366 }
1367
1368
isoburn_make_toc_entry(struct isoburn * o,int * session_count,int lba,int track_blocks,char * volid,int flag)1369 int isoburn_make_toc_entry(struct isoburn *o, int *session_count, int lba,
1370 int track_blocks, char *volid, int flag)
1371 {
1372 int ret;
1373 struct isoburn_toc_entry *item;
1374
1375 ret= isoburn_toc_entry_new(&item, o->toc, 0);
1376 if(ret<=0) {
1377 no_memory:;
1378 isoburn_msgs_submit(o, 0x00060000,
1379 "Not enough memory for emulated TOC entry object",
1380 0, "FATAL", 0);
1381 return(-1);
1382 }
1383 if(o->toc==NULL)
1384 o->toc= item;
1385 (*session_count)++;
1386 item->session= *session_count;
1387 item->track_no= *session_count;
1388 item->start_lba= lba;
1389 item->track_blocks= track_blocks;
1390 if(volid != NULL) {
1391 item->volid= strdup(volid);
1392 if(item->volid == NULL)
1393 goto no_memory;
1394 }
1395 return(1);
1396 }
1397
1398
1399 /* @param flag bit0= allow unemulated media
1400 bit1= free scanning without enclosing LBA-0-header
1401 bit4= represent emulated media as one single session
1402 (not with bit1)
1403 @return -1 severe error, 0= no neat header chain, 1= credible chain read
1404 */
isoburn_emulate_toc(struct burn_drive * d,int flag)1405 int isoburn_emulate_toc(struct burn_drive *d, int flag)
1406 {
1407 int ret, image_size= 0, lba, track_blocks, session_count= 0, read_flag= 0;
1408 int scan_start= 0, scan_count= 0, probe_minus_16= 0, growisofs_nwa, role;
1409 int with_enclosure= 0, readable_blocks= -1;
1410 struct isoburn *o;
1411 char *msg= NULL, *size_text= NULL, *sev, volid[33], *volid_pt= NULL;
1412 time_t start_time, last_pacifier, now;
1413
1414 msg= calloc(1, 160);
1415 size_text= calloc(1, 80);
1416 if(msg == NULL || size_text == NULL)
1417 {ret= -1; goto ex;}
1418
1419 /* is the medium emulated multi-session ? */
1420 ret= isoburn_find_emulator(&o, d, 0);
1421 if(ret<0)
1422 {ret= -1; goto ex;}
1423 if(o==NULL)
1424 {ret= -1; goto ex;}
1425 if(o->emulation_mode<=0 && !(flag&1))
1426 {ret= 0; goto ex;}
1427
1428 ret= burn_get_read_capacity(d, &readable_blocks, 0);
1429 if(ret <= 0) {
1430 role = burn_drive_get_drive_role(d);
1431 if (role == 2 || role == 4)
1432 /* Might be a block device on a system where libburn cannot determine its
1433 size. Try to read anyway. */
1434 readable_blocks= 0x7ffffff0; /* try to read anyway */
1435 else
1436 readable_blocks= -1;
1437 }
1438 if(o->fabricated_disc_status == BURN_DISC_BLANK)
1439 {ret= 0; goto failure;}
1440
1441 start_time= last_pacifier= time(NULL);
1442 lba= 0;
1443 if(flag & 2) {
1444 /* If there is a PVD at LBA 32 then this is an image with emulated TOC */
1445 ret= isoburn_read_iso_head(d, 32, &image_size, NULL, 0);
1446 if(ret > 0)
1447 lba= 32;
1448 } else {
1449 ret= isoburn_read_iso_head(d, lba, &image_size, NULL, 0);
1450 if(ret<=0)
1451 {ret= 0; goto failure;}
1452 lba= o->target_iso_head_size / 2048;
1453 with_enclosure= 1;
1454 if((flag & 16) && o->emulation_mode == 1) {
1455 ret= 1;
1456 goto failure; /* This will represent the medium as single session */
1457 }
1458 }
1459 while(lba<image_size || (flag&2)) {
1460 now= time(NULL);
1461 if(now - last_pacifier >= 5) {
1462 last_pacifier= now;
1463 if(scan_count>=10*512)
1464 sprintf(size_text, "%.f MB", ((double) scan_count) / 512.0);
1465 else
1466 sprintf(size_text, "%.f kB", 2 * (double) scan_count);
1467 sprintf(msg, "Found %d ISO sessions by scanning %s in %.f seconds",
1468 session_count, size_text, (double) (now - start_time));
1469 isoburn_msgs_submit(o, 0x00060000, msg, 0, "UPDATE", 0);
1470 }
1471 read_flag= 1;
1472 if(flag&2)
1473 read_flag|= (1<<15)|((session_count>0)<<14);
1474 else {
1475
1476 /* growisofs aligns to 16 rather than 32. Overwriteable TOC emulation
1477 relies on not accidentially seeing inter-session trash data.
1478 But one can safely access 16 blocks earlier because a xorriso header
1479 would have been overwritten with the unused 16 blocks at its start.
1480 If libisoburn alignment would increase, then this would not be
1481 possible any more.
1482 */
1483
1484 if(probe_minus_16)
1485 read_flag|= (1<<14);
1486 probe_minus_16= 0;
1487 }
1488
1489 ret= isoburn_read_iso_head(d, lba, &track_blocks, volid, read_flag);
1490 if(ret > 0) {
1491 volid_pt= volid;
1492 } else {
1493 volid_pt= NULL;
1494 if(session_count>0) {
1495 if(flag&2) {
1496 if(ret==0) {
1497 /* try at next 64 k block (check both 32 k halves) */
1498 lba+= 32;
1499 scan_count+= 32;
1500 if(lba-scan_start <= Libisoburn_toc_scan_max_gaP)
1501 continue;
1502 }
1503 break;
1504 }
1505 sprintf(msg,
1506 "Chain of ISO session headers broken at #%d, LBA %ds",
1507 session_count+1, lba);
1508 isoburn_msgs_submit(o, 0x00060000, msg, 0, "WARNING", 0);
1509
1510 if(with_enclosure) {
1511 ret= isoburn_make_toc_entry(o, &session_count, 0, image_size, NULL,0);
1512 if(ret<=0)
1513 goto failure;
1514 }
1515 break; /* do not return failure */
1516
1517 }
1518 {ret= 0; goto failure;}
1519 }
1520 if(ret==2) /* ISO header was found in first half block */
1521 lba-= 16;
1522
1523 if(readable_blocks >= 0 && lba + track_blocks > readable_blocks) {
1524 sprintf(msg, "ISO image size %ds larger than readable size %ds",
1525 lba + track_blocks, readable_blocks);
1526 isoburn_msgs_submit(o, 0x00060000, msg, 0, "WARNING", 0);
1527 track_blocks= readable_blocks - lba;
1528 }
1529 ret= isoburn_make_toc_entry(o, &session_count, lba, track_blocks, volid_pt,
1530 0);
1531 if(ret<=0)
1532 goto failure;
1533 lba+= track_blocks;
1534 scan_count+= 32;
1535
1536 /* growisofs aligns to 16 rather than 32 */
1537 growisofs_nwa= lba;
1538 if(growisofs_nwa % 16)
1539 growisofs_nwa+= 16 - (growisofs_nwa % 16);
1540 if(lba % Libisoburn_nwa_alignemenT)
1541 lba+= Libisoburn_nwa_alignemenT - (lba % Libisoburn_nwa_alignemenT);
1542 scan_start= lba;
1543 if(lba - growisofs_nwa == 16)
1544 probe_minus_16= 1;
1545 }
1546 if(last_pacifier != start_time)
1547 sev= "UPDATE";
1548 else
1549 sev= "DEBUG";
1550 now= time(NULL);
1551 if(scan_count>=10*512)
1552 sprintf(size_text, "%.f MB", ((double) scan_count) / 512.0);
1553 else
1554 sprintf(size_text, "%.f kB", 2 * (double) scan_count);
1555 sprintf(msg, "Found %d ISO sessions by scanning %s in %.f seconds",
1556 session_count, size_text, (double) (now - start_time));
1557 isoburn_msgs_submit(o, 0x00060000, msg, 0, sev, 0);
1558 {ret= 1; goto ex;}
1559 failure:;
1560 isoburn_toc_entry_destroy(&(o->toc), 1);
1561 if(with_enclosure && o->emulation_mode == 1) {
1562 if(readable_blocks >= 0 && image_size > readable_blocks) {
1563 sprintf(msg, "ISO image size %ds larger than readable size %ds",
1564 image_size, readable_blocks);
1565 isoburn_msgs_submit(o, 0x00060000, msg, 0, "WARNING", 0);
1566 image_size= readable_blocks;
1567 }
1568 session_count= 0;
1569 ret= isoburn_make_toc_entry(o, &session_count, 0, image_size, NULL, 0);
1570 }
1571 ex:;
1572 if(msg != NULL)
1573 free(msg);
1574 if(size_text != NULL)
1575 free(size_text);
1576 return(ret);
1577 }
1578
1579
isoburn_toc_new_arrays(struct isoburn_toc_disc * o,int session_count,int track_count,int flag)1580 int isoburn_toc_new_arrays(struct isoburn_toc_disc *o,
1581 int session_count, int track_count, int flag)
1582 {
1583 int i;
1584 int isoburn_toc_destroy_arrays(struct isoburn_toc_disc *o, int flag);
1585
1586 o->sessions= calloc(session_count, sizeof(struct isoburn_toc_session));
1587 o->session_pointers=
1588 calloc(session_count, sizeof(struct isoburn_toc_session *));
1589 o->tracks= calloc(track_count, sizeof(struct isoburn_toc_track));
1590 o->track_pointers= calloc(track_count, sizeof(struct isoburn_toc_track *));
1591 if(o->sessions!=NULL && o->session_pointers!=NULL &&
1592 o->tracks!=NULL && o->track_pointers!=NULL) {
1593 for(i= 0; i<session_count; i++) {
1594 o->sessions[i].session= NULL;
1595 o->sessions[i].track_pointers= NULL;
1596 o->sessions[i].track_count= 0;
1597 o->sessions[i].toc_entry= NULL;
1598 o->session_pointers[i]= NULL;
1599 }
1600 for(i= 0; i<track_count; i++) {
1601 o->tracks[i].track= NULL;
1602 o->tracks[i].toc_entry= NULL;
1603 o->track_pointers[i]= NULL;
1604 }
1605 return(1);
1606 }
1607 /* failed */
1608 isoburn_toc_destroy_arrays(o, 0);
1609 return(-1);
1610 }
1611
1612
isoburn_toc_destroy_arrays(struct isoburn_toc_disc * o,int flag)1613 int isoburn_toc_destroy_arrays(struct isoburn_toc_disc *o, int flag)
1614 {
1615 if(o->sessions!=NULL)
1616 free((char *) o->sessions);
1617 o->sessions= NULL;
1618 if(o->session_pointers!=NULL)
1619 free((char *) o->session_pointers);
1620 o->session_pointers= NULL;
1621 if(o->tracks!=NULL)
1622 free((char *) o->tracks);
1623 o->tracks= NULL;
1624 if(o->track_pointers!=NULL)
1625 free((char *) o->track_pointers);
1626 o->track_pointers= NULL;
1627 return(1);
1628 }
1629
1630
isoburn_toc_drive_get_disc(struct burn_drive * d)1631 struct isoburn_toc_disc *isoburn_toc_drive_get_disc(struct burn_drive *d)
1632 {
1633 int ret, session_count= 0, track_count= 0, num_tracks= 0, i, j;
1634 int open_sessions= 0;
1635 struct isoburn *o;
1636 struct isoburn_toc_entry *t;
1637 struct isoburn_toc_disc *toc_disc= NULL;
1638 struct burn_session **s;
1639 struct burn_track **tracks;
1640
1641 toc_disc= calloc(1, sizeof(struct isoburn_toc_disc));
1642 if(toc_disc==NULL)
1643 return(NULL);
1644 toc_disc->disc= NULL;
1645 toc_disc->sessions= NULL;
1646 toc_disc->session_pointers= NULL;
1647 toc_disc->tracks= NULL;
1648 toc_disc->track_pointers= NULL;
1649 toc_disc->session_count= 0;
1650 toc_disc->incomplete_session_count= 0;
1651 toc_disc->track_count= 0;
1652 toc_disc->toc= NULL;
1653
1654 /* is the medium emulated multi-session ? */
1655 ret= isoburn_find_emulator(&o, d, 0);
1656 if(ret<0)
1657 goto libburn;
1658 if(o->toc==NULL)
1659 goto libburn;
1660
1661 /* This is an emulated TOC */
1662 toc_disc->toc= o->toc;
1663 for(t= toc_disc->toc; t!=NULL; t= t->next)
1664 session_count++;
1665 ret= isoburn_toc_new_arrays(toc_disc, session_count, session_count, 0);
1666 if(ret<=0)
1667 goto failure;
1668 t= toc_disc->toc;
1669 for(i= 0; i<session_count; i++) {
1670 toc_disc->sessions[i].track_pointers= toc_disc->track_pointers+i;
1671 toc_disc->sessions[i].track_count= 1;
1672 toc_disc->sessions[i].toc_entry= t;
1673 toc_disc->session_pointers[i]= toc_disc->sessions+i;
1674 toc_disc->tracks[i].toc_entry= t;
1675 toc_disc->track_pointers[i]= toc_disc->tracks+i;
1676 t= t->next;
1677 }
1678 toc_disc->session_count= session_count;
1679 toc_disc->track_count= session_count;
1680 return(toc_disc);
1681
1682 libburn:;
1683 /* This is a libburn provided TOC */
1684 toc_disc->disc= burn_drive_get_disc(d);
1685 if(toc_disc->disc == NULL) {
1686 failure:;
1687 free((char *) toc_disc);
1688 return(NULL);
1689 }
1690 s= burn_disc_get_sessions(toc_disc->disc, &session_count);
1691 open_sessions= burn_disc_get_incomplete_sessions(toc_disc->disc);
1692 for(i= 0; i < session_count + open_sessions; i++) {
1693 tracks = burn_session_get_tracks(s[i], &num_tracks);
1694 if(i == session_count + open_sessions - 1 && open_sessions > 0) {
1695 /* Do not count the invisible track of the last incomplete session */
1696 num_tracks--;
1697 }
1698 track_count+= num_tracks;
1699 }
1700 if(session_count + open_sessions <= 0 || track_count <= 0)
1701 goto failure;
1702 ret= isoburn_toc_new_arrays(toc_disc, session_count + open_sessions,
1703 track_count, 0);
1704 if(ret<=0)
1705 goto failure;
1706 track_count= 0;
1707 for(i= 0; i < session_count + open_sessions; i++) {
1708 tracks = burn_session_get_tracks(s[i], &num_tracks);
1709 if(i == session_count + open_sessions - 1 && open_sessions > 0)
1710 num_tracks--;
1711 toc_disc->sessions[i].session= s[i];
1712 toc_disc->sessions[i].track_pointers= toc_disc->track_pointers+track_count;
1713 toc_disc->sessions[i].track_count= num_tracks;
1714 toc_disc->session_pointers[i]= toc_disc->sessions+i;
1715 for(j= 0; j<num_tracks; j++) {
1716 toc_disc->tracks[track_count+j].track= tracks[j];
1717 toc_disc->track_pointers[track_count+j]= toc_disc->tracks+(track_count+j);
1718 }
1719 track_count+= num_tracks;
1720 }
1721 toc_disc->session_count= session_count;
1722 toc_disc->incomplete_session_count= open_sessions;
1723 toc_disc->track_count= track_count;
1724 return(toc_disc);
1725 }
1726
1727
isoburn_toc_disc_get_sectors(struct isoburn_toc_disc * disc)1728 int isoburn_toc_disc_get_sectors(struct isoburn_toc_disc *disc)
1729 {
1730 struct isoburn_toc_entry *t;
1731 int ret= 0, num_sessions, num_tracks, open_sessions= 0, session_idx= -1;
1732 struct burn_session **sessions;
1733 struct burn_track **tracks;
1734 struct burn_toc_entry entry;
1735
1736 if(disc==NULL)
1737 return(0);
1738 if(disc->toc!=NULL) {
1739 for(t= disc->toc; t!=NULL; t= t->next)
1740 ret= t->start_lba + t->track_blocks;
1741 } else if(disc->disc!=NULL) {
1742 sessions= burn_disc_get_sessions(disc->disc, &num_sessions);
1743 open_sessions= burn_disc_get_incomplete_sessions(disc->disc);
1744 if(num_sessions + open_sessions > 0) {
1745 session_idx= num_sessions + open_sessions - 1;
1746 tracks = burn_session_get_tracks(sessions[session_idx], &num_tracks);
1747 if(open_sessions > 0) {
1748 /* Do not count the invisible track of the last incomplete session */
1749 num_tracks--;
1750 }
1751 if(num_tracks <= 0)
1752 session_idx--;
1753 }
1754 if(session_idx >= 0) {
1755 tracks = burn_session_get_tracks(sessions[session_idx], &num_tracks);
1756 if(session_idx == num_sessions + open_sessions - 1 && open_sessions > 0) {
1757 /* Do not count the invisible track of the last incomplete session */
1758 num_tracks--;
1759 }
1760 if(num_tracks > 0) {
1761 burn_track_get_entry(tracks[num_tracks - 1], &entry);
1762 if(entry.extensions_valid & 1)
1763 ret= entry.start_lba + entry.track_blocks;
1764 }
1765 }
1766 /*
1767 ret= burn_disc_get_sectors(disc->disc);
1768 */
1769 }
1770 return(ret);
1771 }
1772
1773
isoburn_toc_disc_get_sessions(struct isoburn_toc_disc * disc,int * num)1774 struct isoburn_toc_session **isoburn_toc_disc_get_sessions(
1775 struct isoburn_toc_disc *disc, int *num)
1776 {
1777 *num= disc->session_count;
1778 return(disc->session_pointers);
1779 }
1780
1781
isoburn_toc_disc_get_incmpl_sess(struct isoburn_toc_disc * disc)1782 int isoburn_toc_disc_get_incmpl_sess(struct isoburn_toc_disc *disc)
1783 {
1784 return(disc->incomplete_session_count);
1785 }
1786
1787
isoburn_toc_session_get_sectors(struct isoburn_toc_session * s)1788 int isoburn_toc_session_get_sectors(struct isoburn_toc_session *s)
1789 {
1790 struct isoburn_toc_entry *t;
1791 int count= 0, i;
1792
1793 if(s==NULL)
1794 return(0);
1795 if(s->toc_entry!=NULL) {
1796 t= s->toc_entry;
1797 for(i= 0; i<s->track_count; i++) {
1798 count+= t->track_blocks;
1799 t= t->next;
1800 }
1801 } else if(s->session!=NULL)
1802 count= burn_session_get_sectors(s->session);
1803 return(count);
1804 }
1805
1806
isoburn_toc_entry_finish(struct burn_toc_entry * entry,int session_no,int track_no,int flag)1807 int isoburn_toc_entry_finish(struct burn_toc_entry *entry,
1808 int session_no, int track_no, int flag)
1809 {
1810 int pmin, psec, pframe;
1811
1812 entry->extensions_valid= 1;
1813 entry->adr= 1;
1814 entry->control= 4;
1815 entry->session= session_no & 255;
1816 entry->session_msb= (session_no >> 8) & 255;
1817 entry->point= track_no & 255;
1818 entry->point_msb= (track_no >> 8) & 255;
1819
1820 burn_lba_to_msf(entry->start_lba, &pmin, &psec, &pframe);
1821 if(pmin<=255)
1822 entry->pmin= pmin;
1823 else
1824 entry->pmin= 255;
1825 entry->psec= psec;
1826 entry->pframe= pframe;
1827 return(1);
1828 }
1829
1830
isoburn_toc_session_get_leadout_entry(struct isoburn_toc_session * s,struct burn_toc_entry * entry)1831 void isoburn_toc_session_get_leadout_entry(struct isoburn_toc_session *s,
1832 struct burn_toc_entry *entry)
1833 {
1834 struct isoburn_toc_track *t;
1835
1836 if(s==NULL)
1837 return;
1838 if(s->session!=NULL && s->toc_entry==NULL) {
1839 burn_session_get_leadout_entry(s->session, entry);
1840 return;
1841 }
1842 if(s->track_count<=0 || s->track_pointers==NULL || s->toc_entry==NULL)
1843 return;
1844 t= s->track_pointers[s->track_count-1];
1845 entry->start_lba= t->toc_entry->start_lba + t->toc_entry->track_blocks;
1846 entry->track_blocks= 0;
1847 isoburn_toc_entry_finish(entry, s->toc_entry->session, t->toc_entry->track_no,
1848 0);
1849 }
1850
1851
isoburn_toc_session_get_tracks(struct isoburn_toc_session * s,int * num)1852 struct isoburn_toc_track **isoburn_toc_session_get_tracks(
1853 struct isoburn_toc_session *s, int *num)
1854 {
1855 *num= s->track_count;
1856 return(s->track_pointers);
1857 }
1858
1859
isoburn_toc_track_get_entry(struct isoburn_toc_track * t,struct burn_toc_entry * entry)1860 void isoburn_toc_track_get_entry(struct isoburn_toc_track *t,
1861 struct burn_toc_entry *entry)
1862 {
1863 if(t==0)
1864 return;
1865 if(t->track!=NULL && t->toc_entry==NULL) {
1866 burn_track_get_entry(t->track, entry);
1867 return;
1868 }
1869 if(t->toc_entry==NULL)
1870 return;
1871 entry->start_lba= t->toc_entry->start_lba;
1872 entry->track_blocks= t->toc_entry->track_blocks;
1873 isoburn_toc_entry_finish(entry, t->toc_entry->session, t->toc_entry->track_no,
1874 0);
1875 }
1876
1877
isoburn_toc_track_get_emul(struct isoburn_toc_track * t,int * start_lba,int * image_blocks,char volid[33],int flag)1878 int isoburn_toc_track_get_emul(struct isoburn_toc_track *t, int *start_lba,
1879 int *image_blocks, char volid[33], int flag)
1880 {
1881 if(t->toc_entry == NULL)
1882 return(0);
1883 if(t->toc_entry->volid == NULL)
1884 return(0);
1885 *start_lba= t->toc_entry->start_lba;
1886 *image_blocks= t->toc_entry->track_blocks;
1887 strncpy(volid, t->toc_entry->volid, 32);
1888 volid[32]= 0;
1889 return(1);
1890 }
1891
1892
isoburn_toc_disc_free(struct isoburn_toc_disc * d)1893 void isoburn_toc_disc_free(struct isoburn_toc_disc *d)
1894 {
1895 if(d->disc!=NULL)
1896 burn_disc_free(d->disc);
1897 isoburn_toc_destroy_arrays(d, 0);
1898 free((char *) d);
1899 }
1900
1901
isoburn_get_track_lba(struct isoburn_toc_track * track,int * lba,int flag)1902 int isoburn_get_track_lba(struct isoburn_toc_track *track, int *lba, int flag)
1903 {
1904 struct burn_toc_entry entry;
1905
1906 isoburn_toc_track_get_entry(track, &entry);
1907 if (entry.extensions_valid & 1)
1908 *lba= entry.start_lba;
1909 else
1910 *lba= burn_msf_to_lba(entry.pmin, entry.psec, entry.pframe);
1911 return(1);
1912 }
1913
1914
isoburn_drive_set_msgs_submit(struct burn_drive * d,int (* msgs_submit)(void * handle,int error_code,char msg_text[],int os_errno,char severity[],int flag),void * submit_handle,int submit_flag,int flag)1915 int isoburn_drive_set_msgs_submit(struct burn_drive *d,
1916 int (*msgs_submit)(void *handle, int error_code,
1917 char msg_text[], int os_errno,
1918 char severity[], int flag),
1919 void *submit_handle, int submit_flag, int flag)
1920 {
1921 struct isoburn *o;
1922 int ret;
1923
1924 ret= isoburn_find_emulator(&o, d, 0);
1925 if(ret<0 || o==NULL)
1926 return(-1);
1927 o->msgs_submit= msgs_submit;
1928 o->msgs_submit_handle= submit_handle;
1929 o->msgs_submit_flag= submit_flag;
1930 return(1);
1931 }
1932
1933
1934 /* @param flag bit0= with adr_mode 3: adr_value might be 16 blocks too high
1935 bit1= insist in seeing a disc object with at least one session
1936 bit2= with adr_mode 4: use adr_value as regular expression
1937 */
isoburn_set_msc1(struct burn_drive * d,int adr_mode,char * adr_value,int flag)1938 int isoburn_set_msc1(struct burn_drive *d, int adr_mode, char *adr_value,
1939 int flag)
1940 {
1941 int ret, num_sessions= 0, num_tracks, adr_num, i, j, total_tracks;
1942 int lba, best_lba, size, re_valid= 0, track_count= 0;
1943 time_t start_time= 0, last_pacifier= 0, now;
1944 char volid[33], *msg= NULL;
1945 struct isoburn *o;
1946 struct isoburn_toc_disc *disc= NULL;
1947 struct isoburn_toc_session **sessions= NULL;
1948 struct isoburn_toc_track **tracks= NULL;
1949 static char mode_names[][20]= {"auto", "session", "track", "lba", "volid"};
1950 static int max_mode_names= 4;
1951 regex_t re;
1952 regmatch_t match[1];
1953 enum burn_disc_status s;
1954
1955 ret= isoburn_find_emulator(&o, d, 0);
1956 if(ret<0)
1957 return(-1);
1958 if(o==NULL)
1959 return(-1);
1960
1961 msg= calloc(1, 160);
1962 if(msg == NULL)
1963 {ret= -1; goto ex;}
1964
1965 start_time= last_pacifier= time(NULL);
1966 adr_num= atoi(adr_value);
1967 if(adr_mode!=3 || (flag & 2)) {
1968 disc= isoburn_toc_drive_get_disc(d);
1969 if(disc==NULL) {
1970 not_found:;
1971 if(adr_mode<0 || adr_mode>max_mode_names)
1972 goto unknown_mode;
1973 sprintf(msg, "Failed to find %s %s", mode_names[adr_mode],
1974 strlen(adr_value)<=80 ? adr_value : "-oversized-string-");
1975 isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0);
1976 ret= 0; goto ex;
1977 }
1978 sessions= isoburn_toc_disc_get_sessions(disc, &num_sessions);
1979 if(sessions==NULL || num_sessions<=0)
1980 goto not_found;
1981 }
1982 if(adr_mode==0) {
1983 /* Set fabricated_msc1 to last session in TOC */
1984 tracks= isoburn_toc_session_get_tracks(sessions[num_sessions-1],
1985 &num_tracks);
1986 if(tracks==NULL || num_tracks<=0)
1987 goto not_found;
1988 isoburn_get_track_lba(tracks[0], &(o->fabricated_msc1), 0);
1989
1990 } else if(adr_mode==1) {
1991 /* Use adr_num as session index (first session is 1, not 0) */
1992 if(adr_num<1 || adr_num>num_sessions)
1993 goto not_found;
1994 tracks= isoburn_toc_session_get_tracks(sessions[adr_num-1], &num_tracks);
1995 if(tracks==NULL || num_tracks<=0)
1996 goto not_found;
1997 isoburn_get_track_lba(tracks[0], &(o->fabricated_msc1), 0);
1998
1999 } else if(adr_mode==2) {
2000 /* use adr_num as track index */
2001 total_tracks= 0;
2002 for(i=0; i<num_sessions; i++) {
2003 tracks= isoburn_toc_session_get_tracks(sessions[i], &num_tracks);
2004 if(tracks==NULL)
2005 continue;
2006 for(j= 0; j<num_tracks; j++) {
2007 total_tracks++;
2008 if(total_tracks==adr_num) {
2009 isoburn_get_track_lba(tracks[j], &(o->fabricated_msc1), 0);
2010 ret= 1; goto ex;
2011 }
2012 }
2013 }
2014 goto not_found;
2015
2016 } else if(adr_mode==3) {
2017 o->fabricated_msc1= adr_num;
2018 s= isoburn_disc_get_status(d);
2019 if(o->fabricated_msc1 > 0 && s != BURN_DISC_FULL
2020 && s != BURN_DISC_APPENDABLE) {
2021 isoburn_msgs_submit(o, 0x00060000,
2022 "Non-zero load offset given with blank input media",
2023 0, "FAILURE", 0);
2024 ret= 0; goto ex;
2025 }
2026 if((flag & 1) && o->fabricated_msc1 >= 16) {
2027 /* adr_num is possibly 16 blocks too high */
2028 ret= isoburn_read_iso_head(d, o->fabricated_msc1, &size,volid, 1|(1<<14));
2029 if(ret==2)
2030 o->fabricated_msc1-= 16;
2031 }
2032 } else if(adr_mode==4) {
2033 /* search for volume id that is equal to adr_value */
2034 if(flag & 4) {
2035 ret= regcomp(&re, adr_value, 0);
2036 if(ret != 0)
2037 flag&= ~4;
2038 else
2039 re_valid= 1;
2040 }
2041 best_lba= -1;
2042 for(i=0; i<num_sessions; i++) {
2043 tracks= isoburn_toc_session_get_tracks(sessions[i], &num_tracks);
2044 if(tracks==NULL)
2045 continue;
2046 for(j= 0; j<num_tracks; j++) {
2047 now= time(NULL);
2048 if(now - last_pacifier >= 5 && track_count > 0) {
2049 last_pacifier= now;
2050 sprintf(msg,
2051 "Scanned %d tracks for matching volid in %.f seconds",
2052 track_count, (double) (now - start_time));
2053 isoburn_msgs_submit(o, 0x00060000, msg, 0, "UPDATE", 0);
2054 }
2055 track_count++;
2056 ret= isoburn_toc_track_get_emul(tracks[0], &lba, &size, volid, 0);
2057 if(ret < 0)
2058 continue;
2059 if(ret == 0) {
2060 isoburn_get_track_lba(tracks[0], &lba, 0);
2061 ret= isoburn_read_iso_head(d, lba, &size, volid, 1);
2062 if(ret<=0)
2063 continue;
2064 }
2065 if(flag & 4) {
2066 ret= regexec(&re, volid, 1, match, 0);
2067 if(ret != 0)
2068 continue;
2069 } else {
2070 if(strcmp(volid, adr_value)!=0)
2071 continue;
2072 }
2073 best_lba= lba;
2074 }
2075 }
2076 if(best_lba<0)
2077 goto not_found;
2078 o->fabricated_msc1= best_lba;
2079
2080 } else {
2081 unknown_mode:;
2082 sprintf(msg, "Program error: Unknown msc1 address mode %d", adr_mode);
2083 isoburn_msgs_submit(o, 0x00060000, msg, 0, "FATAL", 0);
2084 ret= 0; goto ex;
2085 }
2086 ret= 1;
2087 ex:;
2088 if(start_time != last_pacifier && track_count > 0) {
2089 now= time(NULL);
2090 sprintf(msg,
2091 "Scanned %d tracks for matching volid in %.f seconds",
2092 track_count, (double) (now - start_time));
2093 isoburn_msgs_submit(o, 0x00060000, msg, 0, "UPDATE", 0);
2094 }
2095 if(disc!=NULL)
2096 isoburn_toc_disc_free(disc);
2097 if((flag & 4) && re_valid)
2098 regfree(&re);
2099 if(msg != NULL)
2100 free(msg);
2101 return(ret);
2102 }
2103
2104
isoburn_get_mount_params(struct burn_drive * d,int adr_mode,char * adr_value,int * lba,int * track,int * session,char volid[33],int flag)2105 int isoburn_get_mount_params(struct burn_drive *d,
2106 int adr_mode, char *adr_value,
2107 int *lba, int *track, int *session,
2108 char volid[33], int flag)
2109 {
2110 int msc1_mem, ret, total_tracks, num_sessions, num_tracks, i, j, track_lba;
2111 int size, is_iso= 0;
2112 struct isoburn *o;
2113 struct isoburn_toc_disc *disc= NULL;
2114 struct isoburn_toc_session **sessions= NULL;
2115 struct isoburn_toc_track **tracks= NULL;
2116
2117 *lba= *track= *session= -1;
2118 volid[0]= 0;
2119 ret= isoburn_find_emulator(&o, d, 0);
2120 if(ret < 0 || o == NULL)
2121 return(-1);
2122 msc1_mem= o->fabricated_msc1;
2123 ret= isoburn_set_msc1(d, adr_mode, adr_value, 2 | (flag & 4));
2124 if(ret <= 0)
2125 return(ret);
2126 *lba= o->fabricated_msc1;
2127
2128 disc= isoburn_toc_drive_get_disc(d);
2129 if(disc==NULL)
2130 {ret= -1; goto ex;} /* cannot happen because checked by isoburn_set_msc1 */
2131 sessions= isoburn_toc_disc_get_sessions(disc, &num_sessions);
2132 if(sessions==NULL || num_sessions<=0)
2133 {ret= -1; goto ex;} /* cannot happen because checked by isoburn_set_msc1 */
2134 total_tracks= 0;
2135 for(i=0; i<num_sessions && *session < 0; i++) {
2136 tracks= isoburn_toc_session_get_tracks(sessions[i], &num_tracks);
2137 if(tracks==NULL)
2138 continue;
2139 for(j= 0; j<num_tracks && *track < 0; j++) {
2140 total_tracks++;
2141 isoburn_get_track_lba(tracks[j], &track_lba, 0);
2142 if(track_lba == *lba) {
2143 *track= total_tracks;
2144 *session= i + 1;
2145 }
2146 }
2147 }
2148 ret= isoburn_read_iso_head(d, *lba, &size, volid, 1);
2149 if(ret <= 0)
2150 volid[0]= 0;
2151 else
2152 is_iso= 1;
2153
2154 ex:;
2155 o->fabricated_msc1= msc1_mem;
2156 if(disc != NULL)
2157 isoburn_toc_disc_free(disc);
2158 return(2 - is_iso);
2159 }
2160
2161
2162