00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <ctype.h>
00020 #include <sys/types.h>
00021 #include <unistd.h>
00022 #include <string.h>
00023 #include <stdlib.h>
00024 #include <sys/stat.h>
00025 #include <fcntl.h>
00026 #include <time.h>
00027 #include <regex.h>
00028
00029
00030 #ifndef Xorriso_standalonE
00031
00032 #include <libburn/libburn.h>
00033
00034 #include <libisofs/libisofs.h>
00035
00036 #else
00037
00038 #include "../libisofs/libisofs.h"
00039 #include "../libburn/libburn.h"
00040
00041 #endif
00042
00043
00044 #include "libisoburn.h"
00045 #include "isoburn.h"
00046
00047
00048
00049 extern struct isoburn *isoburn_list_start;
00050
00051
00052
00053
00054
00055 extern int (*libisoburn_default_msgs_submit)
00056 (void *handle, int error_code, char msg_text[],
00057 int os_errno, char severity[], int flag);
00058 extern void *libisoburn_default_msgs_submit_handle;
00059 extern int libisoburn_default_msgs_submit_flag;
00060
00061
00062 static int isoburn_emulate_toc(struct burn_drive *d, int flag);
00063
00064
00065 int isoburn_initialize(char msg[1024], int flag)
00066 {
00067 int major, minor, micro, bad_match= 0;
00068
00069
00070
00071
00072
00073
00074
00075 #ifdef iso_lib_header_version_major
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 #if isoburn_libisofs_req_major > iso_lib_header_version_major
00095 #define Isoburn_libisofs_dot_h_too_olD 1
00096 #endif
00097 #if isoburn_libisofs_req_major == iso_lib_header_version_major && isoburn_libisofs_req_minor > iso_lib_header_version_minor
00098 #define Isoburn_libisofs_dot_h_too_olD 1
00099 #endif
00100 #if isoburn_libisofs_req_minor == iso_lib_header_version_minor && isoburn_libisofs_req_micro > iso_lib_header_version_micro
00101 #define Isoburn_libisofs_dot_h_too_olD 1
00102 #endif
00103
00104 #ifdef Isoburn_libisofs_dot_h_too_olD
00105 LIBISOFS_MISCONFIGURATION = 0;
00106 INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libisofs_dot_h_TOO_OLD__SEE_libisoburn_dot_h_AND_burn_wrap_dot_h = 0;
00107 LIBISOFS_MISCONFIGURATION_ = 0;
00108 #endif
00109
00110 #endif
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 #if isoburn_libburn_req_major > burn_header_version_major
00132 #define Isoburn_libburn_dot_h_too_olD 1
00133 #endif
00134 #if isoburn_libburn_req_major == burn_header_version_major && isoburn_libburn_req_minor > burn_header_version_minor
00135 #define Isoburn_libburn_dot_h_too_olD 1
00136 #endif
00137 #if isoburn_libburn_req_minor == burn_header_version_minor && isoburn_libburn_req_micro > burn_header_version_micro
00138 #define Isoburn_libburn_dot_h_too_olD 1
00139 #endif
00140
00141 #ifdef Isoburn_libburn_dot_h_too_olD
00142 LIBBURN_MISCONFIGURATION = 0;
00143 INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libburn_dot_h_TOO_OLD__SEE_libisoburn_dot_h_and_burn_wrap_dot_h = 0;
00144 LIBBURN_MISCONFIGURATION_ = 0;
00145 #endif
00146
00147
00148
00149
00150
00151 msg[0]= 0;
00152 if(iso_init()<0) {
00153 sprintf(msg+strlen(msg), "Cannot initialize libisofs\n");
00154 return(0);
00155 }
00156 iso_lib_version(&major, &minor, µ);
00157 sprintf(msg+strlen(msg), "libisofs-%d.%d.%d ", major, minor, micro);
00158 #ifdef iso_lib_header_version_major
00159 if(iso_lib_is_compatible(iso_lib_header_version_major,
00160 iso_lib_header_version_minor,
00161 iso_lib_header_version_micro)) {
00162 sprintf(msg+strlen(msg), "ok, ");
00163 } else {
00164 sprintf(msg+strlen(msg),"- TOO OLD -, need at least libisofs-%d.%d.%d ,\n",
00165 iso_lib_header_version_major, iso_lib_header_version_minor,
00166 iso_lib_header_version_micro);
00167 bad_match= 1;
00168 }
00169 #else
00170 if(iso_lib_is_compatible(isoburn_libisofs_req_major,
00171 isoburn_libisofs_req_minor,
00172 isoburn_libisofs_req_micro)) {
00173 sprintf(msg+strlen(msg), "suspicious, ");
00174 } else {
00175 sprintf(msg+strlen(msg),"- TOO OLD -, need at least libisofs-%d.%d.%d ,\n",
00176 isoburn_libisofs_req_major, isoburn_libisofs_req_minor,
00177 isoburn_libisofs_req_micro);
00178 bad_match= 1;
00179 }
00180 #endif
00181
00182 if(!burn_initialize()) {
00183 sprintf(msg+strlen(msg), "Cannot initialize libburn\n");
00184 return(0);
00185 }
00186 burn_version(&major, &minor, µ);
00187 sprintf(msg+strlen(msg), "libburn-%d.%d.%d ", major, minor, micro);
00188 if(major > burn_header_version_major
00189 || (major == burn_header_version_major
00190 && (minor > burn_header_version_minor
00191 || (minor == burn_header_version_minor
00192 && micro >= burn_header_version_micro)))) {
00193 sprintf(msg+strlen(msg), "ok, ");
00194 } else {
00195 sprintf(msg+strlen(msg), "- TOO OLD -, need at least libburn-%d.%d.%d ,\n",
00196 burn_header_version_major, burn_header_version_minor,
00197 burn_header_version_micro);
00198 bad_match= 1;
00199 }
00200
00201 isoburn_version(&major, &minor, µ);
00202 sprintf(msg+strlen(msg), "for libisoburn-%d.%d.%d", major, minor, micro);
00203 if(bad_match)
00204 return(0);
00205
00206 isoburn_destroy_all(&isoburn_list_start, 0);
00207 return(1);
00208 }
00209
00210
00211
00212 int isoburn_libisofs_req(int *major, int *minor, int *micro)
00213 {
00214 *major= iso_lib_header_version_major;
00215 *minor= iso_lib_header_version_minor;
00216 *micro= iso_lib_header_version_micro;
00217 return(1);
00218 }
00219
00220
00221
00222 int isoburn_libburn_req(int *major, int *minor, int *micro)
00223 {
00224 *major= burn_header_version_major;
00225 *minor= burn_header_version_minor;
00226 *micro= burn_header_version_micro;
00227 return(1);
00228 }
00229
00230
00231 int isoburn_set_msgs_submit(int (*msgs_submit)(void *handle, int error_code,
00232 char msg_text[], int os_errno,
00233 char severity[], int flag),
00234 void *submit_handle, int submit_flag, int flag)
00235 {
00236 libisoburn_default_msgs_submit= msgs_submit;
00237 libisoburn_default_msgs_submit_handle= submit_handle;
00238 libisoburn_default_msgs_submit_flag= submit_flag;
00239 return(1);
00240 }
00241
00242
00243 int isoburn_is_intermediate_dvd_rw(struct burn_drive *d, int flag)
00244 {
00245 int profile, ret= 0, format_status, num_formats;
00246 char profile_name[80];
00247 enum burn_disc_status s;
00248 off_t format_size= -1;
00249 unsigned bl_sas;
00250
00251 s= isoburn_disc_get_status(d);
00252 ret= burn_disc_get_profile(d, &profile, profile_name);
00253 if(ret>0 && profile==0x13)
00254 ret= burn_disc_get_formats(d, &format_status, &format_size,
00255 &bl_sas, &num_formats);
00256 if(ret>0 && profile==0x13 && s==BURN_DISC_BLANK &&
00257 format_status==BURN_FORMAT_IS_UNKNOWN)
00258 return(1);
00259 return(0);
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 static int isoburn_welcome_media(struct isoburn **o, struct burn_drive *d,
00272 int flag)
00273 {
00274 int ret, lba, nwa, profile, readonly= 0;
00275 struct burn_multi_caps *caps= NULL;
00276 struct isoburn_toc_entry *t;
00277 char profile_name[80];
00278
00279 profile_name[0]= 0;
00280 ret= burn_disc_get_profile(d, &profile, profile_name);
00281 if(ret<=0)
00282 profile= 0x00;
00283 ret= burn_disc_get_multi_caps(d, BURN_WRITE_NONE, &caps, 0);
00284 if(ret<0)
00285 goto ex;
00286 if(ret==0)
00287 readonly= 1;
00288 ret= isoburn_new(o, 0);
00289 if(ret<=0)
00290 goto ex;
00291 (*o)->drive= d;
00292 (*o)->msgs_submit= libisoburn_default_msgs_submit;
00293 (*o)->msgs_submit_handle= libisoburn_default_msgs_submit_handle;
00294 (*o)->msgs_submit_flag= libisoburn_default_msgs_submit_flag;
00295 iso_image_set_ignore_aclea((*o)->image, (flag >> 5 ) & 3);
00296
00297 #ifdef Hardcoded_cd_rW
00298
00299 caps->start_adr= 0;
00300 (*o)->fabricated_disc_status= BURN_DISC_APPENDABLE;
00301 #endif
00302
00303 if(caps->start_adr) {
00304 (*o)->emulation_mode= 1;
00305 ret= isoburn_is_intermediate_dvd_rw(d, 0);
00306 if(ret>0) {
00307 (*o)->min_start_byte= 0;
00308 (*o)->nwa= 0;
00309 (*o)->zero_nwa= 0;
00310 }
00311 if(flag&1) {
00312 (*o)->nwa= (*o)->zero_nwa;
00313 (*o)->fabricated_disc_status= BURN_DISC_BLANK;
00314 } else {
00315 ret= isoburn_start_emulation(*o, 0);
00316 if(ret<=0) {
00317 (*o)->emulation_mode= -1;
00318 goto ex;
00319 }
00320 if(!(flag & 16)) {
00321
00322 ret= isoburn_emulate_toc(d, 0);
00323 if(ret<0) {
00324 (*o)->emulation_mode= -1;
00325 goto ex;
00326 }
00327 }
00328 }
00329
00330 } else {
00331
00332 ;
00333
00334 if(readonly) {
00335
00336 if((flag & 16)) {
00337 ret= 0;
00338 } else {
00339 ret= isoburn_emulate_toc(d, 1);
00340 if(ret<0)
00341 goto ex;
00342 }
00343 if(ret==0 && profile !=0x08 && (flag&8)) {
00344
00345
00346
00347
00348
00349 ret= isoburn_emulate_toc(d, 1|2);
00350 if(ret<0)
00351 goto ex;
00352 if(ret>0) {
00353 if((*o)->toc!=NULL) {
00354 for(t= (*o)->toc; t->next!=NULL; t= t->next);
00355 (*o)->fabricated_msc1= t->start_lba;
00356 }
00357 }
00358 }
00359 }
00360 #ifdef Hardcoded_cd_rW
00361 (*o)->nwa= Hardcoded_cd_rw_nwA;
00362 #else
00363 ret= burn_disc_track_lba_nwa(d, NULL, 0, &lba, &nwa);
00364 if(ret>0)
00365 (*o)->nwa= nwa;
00366 #endif
00367
00368 }
00369
00370 ret= 1;
00371 ex:
00372 if(caps!=NULL)
00373 burn_disc_free_multi_caps(&caps);
00374 return(ret);
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 int isoburn_drive_aquire(struct burn_drive_info *drive_infos[],
00392 char *adr, int flag)
00393 {
00394 int ret, drive_grabbed= 0;
00395 struct isoburn *o= NULL;
00396
00397 #ifndef NIX
00398
00399
00400
00401
00402 int conv_ret;
00403 char libburn_drive_adr[BURN_DRIVE_ADR_LEN];
00404
00405 conv_ret= burn_drive_convert_fs_adr(adr, libburn_drive_adr);
00406 if(conv_ret<=0)
00407 strcpy(libburn_drive_adr, adr);
00408 ret= burn_drive_scan_and_grab(drive_infos, libburn_drive_adr, flag&1);
00409
00410 #else
00411
00412 ret= burn_drive_scan_and_grab(drive_infos, adr, flag & 1);
00413
00414 #endif
00415
00416 if(ret<=0)
00417 goto ex;
00418 drive_grabbed= 1;
00419 ret= isoburn_welcome_media(&o, (*drive_infos)[0].drive,
00420 (flag & (8 | 16 | 32 | 64)) | !!(flag&2));
00421 if(ret<=0)
00422 goto ex;
00423
00424 if(flag&4) {
00425 ret= isoburn_find_emulator(&o, (*drive_infos)[0].drive, 0);
00426 if(ret>0 && o!=NULL)
00427 o->truncate= 1;
00428 }
00429
00430 ret= 1;
00431 ex:
00432 if(ret<=0) {
00433 if(drive_grabbed)
00434 burn_drive_release((*drive_infos)[0].drive, 0);
00435 isoburn_destroy(&o, 0);
00436 }
00437 return(ret);
00438 }
00439
00440
00441 int isoburn_drive_scan_and_grab(struct burn_drive_info *drive_infos[],
00442 char *adr, int load)
00443 {
00444 int ret;
00445
00446 ret= isoburn_drive_aquire(drive_infos, adr, !!load);
00447 return(ret);
00448 }
00449
00450
00451 int isoburn_drive_grab(struct burn_drive *drive, int load)
00452 {
00453 int ret;
00454 struct isoburn *o= NULL;
00455
00456 ret= burn_drive_grab(drive, load);
00457 if(ret<=0)
00458 goto ex;
00459 ret= isoburn_welcome_media(&o, drive, 0);
00460 if(ret<=0)
00461 goto ex;
00462
00463 ret= 1;
00464 ex:
00465 if(ret<=0)
00466 isoburn_destroy(&o,0);
00467 return(ret);
00468 }
00469
00470
00471
00472
00473
00474 int isoburn_find_emulator(struct isoburn **pt,
00475 struct burn_drive *drive, int flag)
00476 {
00477 int ret;
00478
00479 ret= isoburn_find_by_drive(pt, drive, 0);
00480 if(ret<=0)
00481 return(0);
00482 if((*pt)->emulation_mode==-1) {
00483 isoburn_msgs_submit(*pt, 0x00060000,
00484 "Unsuitable drive and media state", 0, "FAILURE", 0);
00485 return(-1);
00486 }
00487 if((*pt)->emulation_mode==0)
00488 return(0);
00489 return(1);
00490 }
00491
00492
00493 enum burn_disc_status isoburn_disc_get_status(struct burn_drive *drive)
00494 {
00495 int ret;
00496 struct isoburn *o;
00497
00498 ret= isoburn_find_emulator(&o, drive, 0);
00499 if(ret<0)
00500 return(BURN_DISC_UNSUITABLE);
00501 if(o!=NULL)
00502 if(o->fabricated_disc_status!=BURN_DISC_UNREADY)
00503 return(o->fabricated_disc_status);
00504 if(ret==0)
00505 return(burn_disc_get_status(drive));
00506
00507
00508 if(o->emulation_mode==-1)
00509 return(BURN_DISC_UNSUITABLE);
00510 if(o->nwa>o->zero_nwa)
00511 return(BURN_DISC_APPENDABLE);
00512 return(BURN_DISC_BLANK);
00513 }
00514
00515
00516 int isoburn_disc_erasable(struct burn_drive *d)
00517 {
00518 int ret;
00519 struct isoburn *o;
00520
00521 ret= isoburn_find_emulator(&o, d, 0);
00522 if(ret>0)
00523 if(o->emulation_mode==1)
00524 return(1);
00525 return burn_disc_erasable(d);
00526 }
00527
00528
00529 void isoburn_disc_erase(struct burn_drive *drive, int fast)
00530 {
00531 int ret;
00532 struct isoburn *o;
00533 enum burn_disc_status s;
00534 char zero_buffer[Libisoburn_target_head_sizE];
00535
00536 ret= isoburn_find_emulator(&o, drive, 0);
00537 if(ret>0) {
00538 if(o->emulation_mode==-1) {
00539
00540 burn_drive_cancel(drive);
00541 return;
00542 }
00543 if(o->emulation_mode>0) {
00544 s= isoburn_disc_get_status(drive);
00545 if(s==BURN_DISC_FULL) {
00546 memset(zero_buffer, 0, Libisoburn_target_head_sizE);
00547 ret= burn_random_access_write(drive, (off_t) 0, zero_buffer,
00548 (off_t) Libisoburn_target_head_sizE, 1);
00549 } else {
00550 ret= isoburn_invalidate_iso(o, 0);
00551 }
00552 if(ret<=0)
00553 burn_drive_cancel(drive);
00554 return;
00555 }
00556 }
00557 burn_disc_erase(drive, fast);
00558 }
00559
00560
00561 off_t isoburn_disc_available_space(struct burn_drive *d,
00562 struct burn_write_opts *opts)
00563 {
00564 int ret;
00565 struct isoburn *o;
00566 struct burn_write_opts *eff_opts= NULL, *local_opts= NULL;
00567 enum burn_disc_status s;
00568 off_t avail;
00569
00570 eff_opts= opts;
00571 ret= isoburn_find_emulator(&o, d, 0);
00572 if(ret>0 && o!=NULL)
00573 if(o->emulation_mode!=0) {
00574 s= isoburn_disc_get_status(d);
00575 if(s==BURN_DISC_FULL)
00576 return((off_t) 0);
00577 local_opts= burn_write_opts_new(d);
00578 eff_opts= local_opts;
00579 burn_write_opts_set_start_byte(eff_opts, ((off_t) o->nwa) * (off_t) 2048);
00580 }
00581 avail= burn_disc_available_space(d, eff_opts);
00582 if(local_opts!=NULL)
00583 burn_write_opts_free(local_opts);
00584 local_opts= NULL;
00585 return(avail);
00586 }
00587
00588
00589 int isoburn_disc_get_msc1(struct burn_drive *d, int *start_lba)
00590 {
00591 int ret;
00592 struct isoburn *o;
00593
00594 #ifdef Hardcoded_cd_rW
00595
00596 *start_lba= Hardcoded_cd_rw_c1;
00597 return(1);
00598 #endif
00599
00600 if(isoburn_disc_get_status(d)!=BURN_DISC_APPENDABLE &&
00601 isoburn_disc_get_status(d)!=BURN_DISC_FULL) {
00602 isoburn_msgs_submit(NULL, 0x00060000,
00603 "Media contains no recognizable data", 0, "SORRY", 0);
00604 return(0);
00605 }
00606 ret= isoburn_find_emulator(&o, d, 0);
00607 if(ret<0)
00608 return(0);
00609 if(o->fabricated_msc1>=0) {
00610 *start_lba= o->fabricated_msc1;
00611 return(1);
00612 }
00613 if(ret>0) if(o->emulation_mode>0) {
00614 *start_lba= 0;
00615 return(1);
00616 }
00617 return(burn_disc_get_msc1(d, start_lba));
00618 }
00619
00620
00621 int isoburn_disc_track_lba_nwa(struct burn_drive *d,
00622 struct burn_write_opts *opts,
00623 int trackno, int *lba, int *nwa)
00624 {
00625 int ret;
00626 struct isoburn *o;
00627
00628 #ifdef Hardcoded_cd_rW
00629
00630 *lba= Hardcoded_cd_rw_c1;
00631 *nwa= Hardcoded_cd_rw_nwA;
00632 return(1);
00633 #endif
00634
00635 *nwa= *lba= 0;
00636 ret= isoburn_find_emulator(&o, d, 0);
00637 if(ret<0)
00638 return(0);
00639 if(ret>0) if(o->emulation_mode>0) {
00640 *lba= 0;
00641 *nwa= o->nwa;
00642 return(1);
00643 }
00644 if(burn_drive_get_drive_role(d) != 1)
00645 return(1);
00646 return(burn_disc_track_lba_nwa(d, opts, trackno, lba, nwa));
00647 }
00648
00649
00650 int isoburn_get_msc2(struct isoburn *o,
00651 struct burn_write_opts *opts, int *msc2, int flag)
00652 {
00653 int ret, lba, nwa;
00654
00655 if(o->fabricated_msc2>=0)
00656 *msc2= o->fabricated_msc2;
00657 else {
00658 ret= isoburn_disc_track_lba_nwa(o->drive, opts, 0, &lba, &nwa);
00659 if(ret<=0)
00660 return(ret);
00661 *msc2= nwa;
00662 }
00663 return(1);
00664 }
00665
00666
00667 void isoburn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
00668 {
00669 int ret;
00670 off_t nwa= 0;
00671 struct isoburn *o;
00672 struct burn_drive *drive;
00673 char reasons[BURN_REASONS_LEN],msg[160+BURN_REASONS_LEN];
00674 char adr[BURN_DRIVE_ADR_LEN];
00675 enum burn_write_types write_type;
00676 struct stat stbuf;
00677
00678 drive= burn_write_opts_get_drive(opts);
00679 ret= isoburn_find_emulator(&o, drive, 0);
00680 if(ret<0)
00681 return;
00682 if(o!=NULL) {
00683 o->wrote_well= -1;
00684 if(o->emulation_mode!=0) {
00685 burn_write_opts_set_multi(opts, 0);
00686 if(o->emulation_mode>0 && o->nwa >= 0) {
00687 nwa= o->nwa;
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 ret= isoburn_is_intermediate_dvd_rw(drive, 0);
00700 if(ret>0 && nwa>0 && nwa <= o->zero_nwa) {
00701
00702
00703
00704 sprintf(msg,
00705 "DVD-RW insufficiently formatted. (Intermediate State, size unknown)");
00706 isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0);
00707 sprintf(msg,
00708 "It might help to first deformat it and then format it again");
00709 isoburn_msgs_submit(o, 0x00060000, msg, 0, "HINT", 0);
00710 burn_drive_cancel(drive);
00711 return;
00712 }
00713
00714
00715 burn_write_opts_set_start_byte(opts, nwa * (off_t) 2048);
00716 }
00717 }
00718 }
00719
00720 write_type= burn_write_opts_auto_write_type(opts, disc, reasons, 0);
00721 if (write_type == BURN_WRITE_NONE) {
00722 sprintf(msg, "Failed to find a suitable write mode:\n%s", reasons);
00723 isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0);
00724 if(o!=NULL)
00725 o->wrote_well= 0;
00726
00727 burn_drive_cancel(drive);
00728 return;
00729 }
00730
00731 sprintf(reasons, "%d", (int) write_type);
00732 sprintf(msg, "Write_type = %s\n",
00733 (write_type == BURN_WRITE_SAO ? "SAO" :
00734 (write_type == BURN_WRITE_TAO ? "TAO" : reasons)));
00735 isoburn_msgs_submit(o, 0x00060000, msg, 0, "DEBUG", 0);
00736
00737 #ifdef Hardcoded_cd_rW
00738
00739 fprintf(stderr, "Setting write address to LBA %d\n", Hardcoded_cd_rw_nwA);
00740 burn_write_opts_set_start_byte(opts,
00741 ((off_t) Hardcoded_cd_rw_nwA) * (off_t) 2048);
00742 #endif
00743
00744 if(o->truncate) {
00745 ret= burn_drive_get_drive_role(drive);
00746 if(ret==2) {
00747 ret= burn_drive_d_get_adr(drive, adr);
00748 if(ret>0) {
00749 ret= lstat(adr, &stbuf);
00750 if(ret!=-1)
00751 if(S_ISREG(stbuf.st_mode))
00752 truncate(adr, nwa * (off_t) 2048);
00753 }
00754 }
00755 }
00756
00757 burn_disc_write(opts, disc);
00758 }
00759
00760
00761 void isoburn_drive_release(struct burn_drive *drive, int eject)
00762 {
00763 int ret;
00764 struct isoburn *o;
00765
00766 ret= isoburn_find_emulator(&o, drive, 0);
00767 if(ret<0)
00768 return;
00769 if(o!=NULL) {
00770 isoburn_destroy(&o, 0);
00771 }
00772 burn_drive_release(drive, eject);
00773 }
00774
00775
00776 void isoburn_finish(void)
00777 {
00778 isoburn_destroy_all(&isoburn_list_start, 0);
00779 burn_finish();
00780 iso_finish();
00781 }
00782
00783
00784 int isoburn_needs_emulation(struct burn_drive *drive)
00785 {
00786 int ret;
00787 struct isoburn *o;
00788 enum burn_disc_status s;
00789
00790 s= isoburn_disc_get_status(drive);
00791 if(s!=BURN_DISC_BLANK && s!=BURN_DISC_APPENDABLE)
00792 return(-1);
00793 ret= isoburn_find_emulator(&o, drive, 0);
00794 if(ret<0)
00795 return(-1);
00796 if(ret>0)
00797 if(o->emulation_mode>0)
00798 return(1);
00799 return(0);
00800 }
00801
00802
00803 int isoburn_set_start_byte(struct isoburn *o, off_t value, int flag)
00804 {
00805 int ret;
00806 struct burn_drive *drive = o->drive;
00807 struct burn_multi_caps *caps= NULL;
00808
00809 ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0);
00810 if(ret<=0)
00811 goto ex;
00812 if(!caps->start_adr) {
00813 isoburn_msgs_submit(o, 0x00060000,
00814 "Cannot set start byte address with this type of media",
00815 0, "FAILURE", 0);
00816 {ret= 0; goto ex;}
00817 }
00818 o->min_start_byte= value;
00819 if(value % caps->start_alignment)
00820 value+= caps->start_alignment - (value % caps->start_alignment);
00821 o->nwa= value/2048;
00822
00823 if((o->nwa % Libisoburn_nwa_alignemenT) &&
00824 ((Libisoburn_nwa_alignemenT*2048) % caps->start_alignment)==0 )
00825 o->nwa+= Libisoburn_nwa_alignemenT - (o->nwa % Libisoburn_nwa_alignemenT);
00826 ret= 1;
00827 ex:
00828 if(caps!=NULL)
00829 burn_disc_free_multi_caps(&caps);
00830 return(ret);
00831 }
00832
00833
00834 int isoburn_get_min_start_byte(struct burn_drive *d, off_t *start_byte,
00835 int flag)
00836 {
00837 int ret;
00838 struct isoburn *o;
00839
00840 ret= isoburn_find_emulator(&o, d, 0);
00841 if(ret<0)
00842 return(-1);
00843 if(ret==0)
00844 return(0);
00845 *start_byte= o->min_start_byte;
00846 if(o->min_start_byte<=0)
00847 return(0);
00848 return(1);
00849 }
00850
00851
00852 int isoburn_drive_wrote_well(struct burn_drive *d)
00853 {
00854 int ret;
00855 struct isoburn *o;
00856
00857 ret= isoburn_find_emulator(&o, d, 0);
00858 if(ret<0)
00859 return(-1);
00860 if(o!=NULL)
00861 if(o->wrote_well>=0)
00862 return(o->wrote_well);
00863 ret= burn_drive_wrote_well(d);
00864 return ret;
00865 }
00866
00867
00868 int isoburn_get_fifo_status(struct burn_drive *d, int *size, int *free_bytes,
00869 char **status_text)
00870 {
00871 int ret;
00872 struct isoburn *o;
00873 size_t hsize= 0, hfree_bytes= 0;
00874
00875 ret= isoburn_find_emulator(&o, d, 0);
00876 if(ret<0)
00877 return(-1);
00878
00879 if(o==NULL)
00880 return(-1);
00881 if(o->iso_source==NULL)
00882 return(-1);
00883 ret= iso_ring_buffer_get_status(o->iso_source, &hsize, &hfree_bytes);
00884 if(hsize > 1024*1024*1024)
00885 *size= 1024*1024*1024;
00886 else
00887 *size= hsize;
00888 if(hfree_bytes > 1024*1024*1024)
00889 *free_bytes= 1024*1024*1024;
00890 else
00891 *free_bytes= hfree_bytes;
00892 *status_text= "";
00893 if(ret==0)
00894 *status_text= "standby";
00895 else if(ret==1)
00896 *status_text= "active";
00897 else if(ret==2)
00898 *status_text= "ending";
00899 else if(ret==3)
00900 *status_text= "failing";
00901 else if(ret==4)
00902 *status_text= "unused";
00903 else if(ret==5)
00904 *status_text= "abandoned";
00905 else if(ret==6)
00906 *status_text= "ended";
00907 else if(ret==7)
00908 *status_text= "aborted";
00909 return(ret);
00910 }
00911
00912
00913
00914
00915
00916 int isoburn__sev_to_text(int severity, char **severity_name,
00917 int flag)
00918 {
00919 int ret;
00920
00921 ret= iso_sev_to_text(severity, severity_name);
00922 if(ret>0)
00923 return(ret);
00924 ret= burn_sev_to_text(severity, severity_name, 0);
00925 return(ret);
00926 }
00927
00928
00929 int isoburn__text_to_sev(char *severity_name, int *severity_number, int flag)
00930 {
00931 int ret= 1;
00932
00933 ret= iso_text_to_sev(severity_name, severity_number);
00934 if(ret>0)
00935 return(ret);
00936 ret= burn_text_to_sev(severity_name, severity_number, 0);
00937 return(ret);
00938 }
00939
00940
00941 int isoburn_report_iso_error(int iso_error_code, char msg_text[], int os_errno,
00942 char min_severity[], int flag)
00943 {
00944 int error_code, iso_sev, min_sev, ret;
00945 char *sev_text_pt, *msg_text_pt= NULL;
00946
00947 error_code= iso_error_get_code(iso_error_code);
00948 if(error_code < 0x00030000 || error_code >= 0x00040000)
00949 error_code= (error_code & 0xffff) | 0x00050000;
00950
00951 if(iso_error_code<0)
00952 msg_text_pt= (char *) iso_error_to_msg(iso_error_code);
00953 if(msg_text_pt==NULL)
00954 msg_text_pt= msg_text;
00955 iso_sev= iso_error_get_severity(iso_error_code);
00956 sev_text_pt= min_severity;
00957 isoburn__text_to_sev(min_severity, &min_sev, 0);
00958 if(min_sev < iso_sev)
00959 isoburn__sev_to_text(iso_sev, &sev_text_pt, 0);
00960 ret= iso_msgs_submit(error_code, msg_text_pt, os_errno, sev_text_pt, 0);
00961 return(ret);
00962 }
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973 int isoburn_read_iso_head_parse(struct burn_drive *d, unsigned char *data,
00974 int *image_blocks, char *info, int flag)
00975 {
00976 int i, info_mode;
00977
00978
00979 if(data[0]!=1)
00980 return(0);
00981 if(strncmp((char *) (data+1),"CD001",5)!=0)
00982 return(0);
00983
00984
00985 *image_blocks= data[80] | (data[81]<<8) | (data[82]<<16) | (data[83]<<24);
00986 info_mode= flag&255;
00987 if(info_mode==0) {
00988 ;
00989 } else if(info_mode==1) {
00990 strncpy(info, (char *) (data+40), 32);
00991 info[32]= 0;
00992 for(i= strlen(info)-1; i>=0; i--)
00993 if(info[i]!=' ')
00994 break;
00995 else
00996 info[i]= 0;
00997 } else if(info_mode==2) {
00998 ;
00999 } else {
01000 isoburn_msgs_submit(NULL, 0x00060000,
01001 "Program error: Unknown info mode with isoburn_read_iso_head()",
01002 0, "FATAL", 0);
01003 return(-1);
01004 }
01005 return(1);
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021 int isoburn_read_iso_head(struct burn_drive *d, int lba,
01022 int *image_blocks, char *info, int flag)
01023 {
01024 unsigned char buffer[64*1024];
01025 int ret, info_mode;
01026 off_t data_count;
01027
01028 info_mode= flag&255;
01029 *image_blocks= 0;
01030 if(flag&(1<<13)) {
01031 memcpy(buffer, info, 64*1024);
01032 } else {
01033 ret = burn_read_data(d, ((off_t) lba) * (off_t) 2048, (char *) buffer,
01034 (off_t) 64*1024, &data_count, 2);
01035 if(ret<=0)
01036 return(-1*!!(flag&(1<<15)));
01037 if(info_mode==2)
01038 memcpy(info, buffer, 64*1024);
01039 }
01040
01041 if(flag&(1<<14)) {
01042 ret= isoburn_read_iso_head_parse(d, buffer, image_blocks, info, info_mode);
01043 if(ret<0)
01044 return(ret);
01045 if(ret>0)
01046 return(2);
01047 }
01048 ret= isoburn_read_iso_head_parse(d, buffer+32*1024, image_blocks, info,
01049 info_mode);
01050 if(ret<=0)
01051 return(ret);
01052 return(1);
01053 }
01054
01055
01056 int isoburn_make_toc_entry(struct isoburn *o, int *session_count, int lba,
01057 int track_blocks, int flag)
01058 {
01059 int ret;
01060 struct isoburn_toc_entry *item;
01061
01062 ret= isoburn_toc_entry_new(&item, o->toc, 0);
01063 if(ret<=0) {
01064 isoburn_msgs_submit(o, 0x00060000,
01065 "Not enough memory for emulated TOC entry object",
01066 0, "FATAL", 0);
01067 return(-1);
01068 }
01069 if(o->toc==NULL)
01070 o->toc= item;
01071 (*session_count)++;
01072 item->session= *session_count;
01073 item->track_no= *session_count;
01074 item->start_lba= lba;
01075 item->track_blocks= track_blocks;
01076 return(1);
01077 }
01078
01079
01080
01081
01082
01083
01084 int isoburn_emulate_toc(struct burn_drive *d, int flag)
01085 {
01086 int ret, image_size= 0, lba, track_blocks, session_count= 0, read_flag= 0;
01087 int scan_start= 0, scan_count= 0, probe_minus_16= 0, growisofs_nwa;
01088 int with_enclosure= 0;
01089 struct isoburn *o;
01090 char msg[160], size_text[80], *sev;
01091 time_t start_time, last_pacifier, now;
01092
01093
01094 ret= isoburn_find_emulator(&o, d, 0);
01095 if(ret<0)
01096 return(-1);
01097 if(o==NULL)
01098 return(-1);
01099 if(o->emulation_mode<=0 && !(flag&1))
01100 return(0);
01101
01102 start_time= last_pacifier= time(NULL);
01103 lba= 0;
01104 if(!(flag&2)) {
01105 ret= isoburn_read_iso_head(d, lba, &image_size, NULL, 0);
01106 if(ret<=0)
01107 {ret= 0; goto failure;}
01108 lba= Libisoburn_overwriteable_starT;
01109 with_enclosure= 1;
01110 }
01111 while(lba<image_size || (flag&2)) {
01112 now= time(NULL);
01113 if(now - last_pacifier >= 5) {
01114 last_pacifier= now;
01115 if(scan_count>=10*512)
01116 sprintf(size_text, "%.f MB", ((double) scan_count) / 512.0);
01117 else
01118 sprintf(size_text, "%.f kB", 2 * (double) scan_count);
01119 sprintf(msg, "Found %d ISO sessions by scanning %s in %.f seconds",
01120 session_count, size_text, (double) (now - start_time));
01121 isoburn_msgs_submit(o, 0x00060000, msg, 0, "UPDATE", 0);
01122 }
01123 read_flag= 0;
01124 if(flag&2)
01125 read_flag|= (1<<15)|((session_count>0)<<14);
01126 else {
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136 if(probe_minus_16)
01137 read_flag|= (1<<14);
01138 probe_minus_16= 0;
01139 }
01140
01141 ret= isoburn_read_iso_head(d, lba, &track_blocks, NULL, read_flag);
01142 if(ret<=0) {
01143 if(session_count>0) {
01144 if(flag&2) {
01145 if(ret==0) {
01146
01147 lba+= 32;
01148 scan_count+= 32;
01149 if(lba-scan_start <= Libisoburn_toc_scan_max_gaP)
01150 continue;
01151 }
01152 break;
01153 }
01154 sprintf(msg,
01155 "Chain of ISO session headers broken at #%d, LBA %ds",
01156 session_count+1, lba);
01157 isoburn_msgs_submit(o, 0x00060000, msg, 0, "WARNING", 0);
01158
01159 if(with_enclosure) {
01160 ret= isoburn_make_toc_entry(o, &session_count, 0, image_size, 0);
01161 if(ret<=0)
01162 goto failure;
01163 }
01164 break;
01165
01166 }
01167 {ret= 0; goto failure;}
01168 }
01169 if(ret==2)
01170 lba-= 16;
01171
01172 ret= isoburn_make_toc_entry(o, &session_count, lba, track_blocks, 0);
01173 if(ret<=0)
01174 goto failure;
01175 lba+= track_blocks;
01176 scan_count+= 32;
01177
01178
01179 growisofs_nwa= lba;
01180 if(growisofs_nwa % 16)
01181 growisofs_nwa+= 16 - (growisofs_nwa % 16);
01182 if(lba % Libisoburn_nwa_alignemenT)
01183 lba+= Libisoburn_nwa_alignemenT - (lba % Libisoburn_nwa_alignemenT);
01184 scan_start= lba;
01185 if(lba - growisofs_nwa == 16)
01186 probe_minus_16= 1;
01187 }
01188 if(last_pacifier != start_time)
01189 sev= "UPDATE";
01190 else
01191 sev= "DEBUG";
01192 now= time(NULL);
01193 if(scan_count>=10*512)
01194 sprintf(size_text, "%.f MB", ((double) scan_count) / 512.0);
01195 else
01196 sprintf(size_text, "%.f kB", 2 * (double) scan_count);
01197 sprintf(msg, "Found %d ISO sessions by scanning %s in %.f seconds",
01198 session_count, size_text, (double) (now - start_time));
01199 isoburn_msgs_submit(o, 0x00060000, msg, 0, sev, 0);
01200 return(1);
01201 failure:;
01202 isoburn_toc_entry_destroy(&(o->toc), 1);
01203 if(with_enclosure && o->emulation_mode == 1) {
01204 session_count= 0;
01205 ret= isoburn_make_toc_entry(o, &session_count, 0, image_size, 0);
01206 }
01207 return(ret);
01208 }
01209
01210
01211 int isoburn_toc_new_arrays(struct isoburn_toc_disc *o,
01212 int session_count, int track_count, int flag)
01213 {
01214 int i;
01215 int isoburn_toc_destroy_arrays(struct isoburn_toc_disc *o, int flag);
01216
01217 o->sessions= calloc(session_count, sizeof(struct isoburn_toc_session));
01218 o->session_pointers=
01219 calloc(session_count, sizeof(struct isoburn_toc_session *));
01220 o->tracks= calloc(track_count, sizeof(struct isoburn_toc_track));
01221 o->track_pointers= calloc(track_count, sizeof(struct isoburn_toc_track *));
01222 if(o->sessions!=NULL && o->session_pointers!=NULL &&
01223 o->tracks!=NULL && o->track_pointers!=NULL) {
01224 for(i= 0; i<session_count; i++) {
01225 o->sessions[i].session= NULL;
01226 o->sessions[i].track_pointers= NULL;
01227 o->sessions[i].track_count= 0;
01228 o->sessions[i].toc_entry= NULL;
01229 o->session_pointers[i]= NULL;
01230 }
01231 for(i= 0; i<track_count; i++) {
01232 o->tracks[i].track= NULL;
01233 o->tracks[i].toc_entry= NULL;
01234 o->track_pointers[i]= NULL;
01235 }
01236 return(1);
01237 }
01238
01239 isoburn_toc_destroy_arrays(o, 0);
01240 return(-1);
01241 }
01242
01243
01244 int isoburn_toc_destroy_arrays(struct isoburn_toc_disc *o, int flag)
01245 {
01246 if(o->sessions!=NULL)
01247 free((char *) o->sessions);
01248 o->sessions= NULL;
01249 if(o->session_pointers!=NULL)
01250 free((char *) o->session_pointers);
01251 o->session_pointers= NULL;
01252 if(o->tracks!=NULL)
01253 free((char *) o->tracks);
01254 o->tracks= NULL;
01255 if(o->track_pointers!=NULL)
01256 free((char *) o->track_pointers);
01257 o->track_pointers= NULL;
01258 return(1);
01259 }
01260
01261
01262 struct isoburn_toc_disc *isoburn_toc_drive_get_disc(struct burn_drive *d)
01263 {
01264 int ret, session_count= 0, track_count= 0, num_tracks= 0, i, j;
01265 struct isoburn *o;
01266 struct isoburn_toc_entry *t;
01267 struct isoburn_toc_disc *toc_disc= NULL;
01268 struct burn_session **s;
01269 struct burn_track **tracks;
01270
01271 toc_disc= calloc(1, sizeof(struct isoburn_toc_disc));
01272 if(toc_disc==NULL)
01273 return(NULL);
01274 toc_disc->disc= NULL;
01275 toc_disc->sessions= NULL;
01276 toc_disc->session_pointers= NULL;
01277 toc_disc->tracks= NULL;
01278 toc_disc->track_pointers= NULL;
01279 toc_disc->session_count= 0;
01280 toc_disc->track_count= 0;
01281 toc_disc->toc= NULL;
01282
01283
01284 ret= isoburn_find_emulator(&o, d, 0);
01285 if(ret<0)
01286 goto libburn;
01287 if(o->toc==NULL)
01288 goto libburn;
01289
01290
01291 toc_disc->toc= o->toc;
01292 for(t= toc_disc->toc; t!=NULL; t= t->next)
01293 session_count++;
01294 ret= isoburn_toc_new_arrays(toc_disc, session_count, session_count, 0);
01295 if(ret<=0)
01296 goto failure;
01297 t= toc_disc->toc;
01298 for(i= 0; i<session_count; i++) {
01299 toc_disc->sessions[i].track_pointers= toc_disc->track_pointers+i;
01300 toc_disc->sessions[i].track_count= 1;
01301 toc_disc->sessions[i].toc_entry= t;
01302 toc_disc->session_pointers[i]= toc_disc->sessions+i;
01303 toc_disc->tracks[i].toc_entry= t;
01304 toc_disc->track_pointers[i]= toc_disc->tracks+i;
01305 t= t->next;
01306 }
01307 toc_disc->session_count= session_count;
01308 toc_disc->track_count= session_count;
01309 return(toc_disc);
01310
01311 libburn:;
01312
01313 toc_disc->disc= burn_drive_get_disc(d);
01314 if(toc_disc->disc == NULL) {
01315 failure:;
01316 free((char *) toc_disc);
01317 return(NULL);
01318 }
01319 s= burn_disc_get_sessions(toc_disc->disc, &session_count);
01320 for(i= 0; i<session_count; i++) {
01321 tracks = burn_session_get_tracks(s[i], &num_tracks);
01322 track_count+= num_tracks;
01323 }
01324 if(session_count<=0 || track_count<=0)
01325 goto failure;
01326 ret= isoburn_toc_new_arrays(toc_disc, session_count, track_count, 0);
01327 if(ret<=0)
01328 goto failure;
01329 track_count= 0;
01330 for(i= 0; i<session_count; i++) {
01331 tracks = burn_session_get_tracks(s[i], &num_tracks);
01332 toc_disc->sessions[i].session= s[i];
01333 toc_disc->sessions[i].track_pointers= toc_disc->track_pointers+track_count;
01334 toc_disc->sessions[i].track_count= num_tracks;
01335 toc_disc->session_pointers[i]= toc_disc->sessions+i;
01336 for(j= 0; j<num_tracks; j++) {
01337 toc_disc->tracks[track_count+j].track= tracks[j];
01338 toc_disc->track_pointers[track_count+j]= toc_disc->tracks+(track_count+j);
01339 }
01340 track_count+= num_tracks;
01341 }
01342 toc_disc->session_count= session_count;
01343 toc_disc->track_count= track_count;
01344 return(toc_disc);
01345 }
01346
01347
01348 int isoburn_toc_disc_get_sectors(struct isoburn_toc_disc *disc)
01349 {
01350 struct isoburn_toc_entry *t;
01351 int ret= 0, num_sessions, num_tracks;
01352 struct burn_session **sessions;
01353 struct burn_track **tracks;
01354 struct burn_toc_entry entry;
01355
01356 if(disc==NULL)
01357 return(0);
01358 if(disc->toc!=NULL) {
01359 for(t= disc->toc; t!=NULL; t= t->next)
01360 ret= t->start_lba + t->track_blocks;
01361 } else if(disc->disc!=NULL) {
01362 sessions= burn_disc_get_sessions(disc->disc, &num_sessions);
01363 if(num_sessions > 0) {
01364 tracks = burn_session_get_tracks(sessions[num_sessions - 1],
01365 &num_tracks);
01366 if(num_tracks > 0) {
01367 burn_track_get_entry(tracks[num_tracks - 1], &entry);
01368 if(entry.extensions_valid & 1)
01369 ret= entry.start_lba + entry.track_blocks;
01370 }
01371 }
01372
01373
01374
01375 }
01376 return(ret);
01377 }
01378
01379
01380 struct isoburn_toc_session **isoburn_toc_disc_get_sessions(
01381 struct isoburn_toc_disc *disc, int *num)
01382 {
01383 *num= disc->session_count;
01384 return(disc->session_pointers);
01385 }
01386
01387
01388 int isoburn_toc_session_get_sectors(struct isoburn_toc_session *s)
01389 {
01390 struct isoburn_toc_entry *t;
01391 int count= 0, i;
01392
01393 if(s==NULL)
01394 return(0);
01395 if(s->toc_entry!=NULL) {
01396 t= s->toc_entry;
01397 for(i= 0; i<s->track_count; i++) {
01398 count+= t->track_blocks;
01399 t= t->next;
01400 }
01401 } else if(s->session!=NULL)
01402 count= burn_session_get_sectors(s->session);
01403 return(count);
01404 }
01405
01406
01407 int isoburn_toc_entry_finish(struct burn_toc_entry *entry,
01408 int session_no, int track_no, int flag)
01409 {
01410 int pmin, psec, pframe;
01411
01412 entry->extensions_valid= 1;
01413 entry->adr= 1;
01414 entry->control= 4;
01415 entry->session= session_no & 255;
01416 entry->session_msb= (session_no >> 8) & 255;
01417 entry->point= track_no & 255;
01418 entry->point_msb= (track_no >> 8) & 255;
01419
01420 burn_lba_to_msf(entry->start_lba, &pmin, &psec, &pframe);
01421 if(pmin<=255)
01422 entry->pmin= pmin;
01423 else
01424 entry->pmin= 255;
01425 entry->psec= psec;
01426 entry->pframe= pframe;
01427 return(1);
01428 }
01429
01430
01431 void isoburn_toc_session_get_leadout_entry(struct isoburn_toc_session *s,
01432 struct burn_toc_entry *entry)
01433 {
01434 struct isoburn_toc_track *t;
01435
01436 if(s==NULL)
01437 return;
01438 if(s->session!=NULL && s->toc_entry==NULL) {
01439 burn_session_get_leadout_entry(s->session, entry);
01440 return;
01441 }
01442 if(s->track_count<=0 || s->track_pointers==NULL || s->toc_entry==NULL)
01443 return;
01444 t= s->track_pointers[s->track_count-1];
01445 entry->start_lba= t->toc_entry->start_lba + t->toc_entry->track_blocks;
01446 entry->track_blocks= 0;
01447 isoburn_toc_entry_finish(entry, s->toc_entry->session, t->toc_entry->track_no,
01448 0);
01449 }
01450
01451
01452 struct isoburn_toc_track **isoburn_toc_session_get_tracks(
01453 struct isoburn_toc_session *s, int *num)
01454 {
01455 *num= s->track_count;
01456 return(s->track_pointers);
01457 }
01458
01459
01460 void isoburn_toc_track_get_entry(struct isoburn_toc_track *t,
01461 struct burn_toc_entry *entry)
01462 {
01463 if(t==0)
01464 return;
01465 if(t->track!=NULL && t->toc_entry==NULL) {
01466 burn_track_get_entry(t->track, entry);
01467 return;
01468 }
01469 if(t->toc_entry==NULL)
01470 return;
01471 entry->start_lba= t->toc_entry->start_lba;
01472 entry->track_blocks= t->toc_entry->track_blocks;
01473 isoburn_toc_entry_finish(entry, t->toc_entry->session, t->toc_entry->track_no,
01474 0);
01475 }
01476
01477
01478 void isoburn_toc_disc_free(struct isoburn_toc_disc *d)
01479 {
01480 if(d->disc!=NULL)
01481 burn_disc_free(d->disc);
01482 isoburn_toc_destroy_arrays(d, 0);
01483 free((char *) d);
01484 }
01485
01486
01487 int isoburn_get_track_lba(struct isoburn_toc_track *track, int *lba, int flag)
01488 {
01489 struct burn_toc_entry entry;
01490
01491 isoburn_toc_track_get_entry(track, &entry);
01492 if (entry.extensions_valid & 1)
01493 *lba= entry.start_lba;
01494 else
01495 *lba= burn_msf_to_lba(entry.pmin, entry.psec, entry.pframe);
01496 return(1);
01497 }
01498
01499
01500 int isoburn_drive_set_msgs_submit(struct burn_drive *d,
01501 int (*msgs_submit)(void *handle, int error_code,
01502 char msg_text[], int os_errno,
01503 char severity[], int flag),
01504 void *submit_handle, int submit_flag, int flag)
01505 {
01506 struct isoburn *o;
01507 int ret;
01508
01509 ret= isoburn_find_emulator(&o, d, 0);
01510 if(ret<0 || o==NULL)
01511 return(-1);
01512 o->msgs_submit= msgs_submit;
01513 o->msgs_submit_handle= submit_handle;
01514 o->msgs_submit_flag= submit_flag;
01515 return(1);
01516 }
01517
01518
01519
01520
01521
01522
01523 int isoburn_set_msc1(struct burn_drive *d, int adr_mode, char *adr_value,
01524 int flag)
01525 {
01526 int ret, num_sessions, num_tracks, adr_num, i, j, total_tracks;
01527 int lba, best_lba, size, re_valid= 0;
01528 char volid[33], msg[160];
01529 struct isoburn *o;
01530 struct isoburn_toc_disc *disc= NULL;
01531 struct isoburn_toc_session **sessions= NULL;
01532 struct isoburn_toc_track **tracks= NULL;
01533 static char mode_names[][20]= {"auto", "session", "track", "lba", "volid"};
01534 static int max_mode_names= 4;
01535 regex_t re;
01536 regmatch_t match[1];
01537
01538 ret= isoburn_find_emulator(&o, d, 0);
01539 if(ret<0)
01540 return(-1);
01541 if(o==NULL)
01542 return(-1);
01543
01544 adr_num= atoi(adr_value);
01545 if(adr_mode!=3 || (flag & 2)) {
01546 disc= isoburn_toc_drive_get_disc(d);
01547 if(disc==NULL) {
01548 not_found:;
01549 if(adr_mode<0 || adr_mode>max_mode_names)
01550 goto unknown_mode;
01551 sprintf(msg, "Failed to find %s %s", mode_names[adr_mode],
01552 strlen(adr_value)<=80 ? adr_value : "-oversized-string-");
01553 isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0);
01554 ret= 0; goto ex;
01555 }
01556 sessions= isoburn_toc_disc_get_sessions(disc, &num_sessions);
01557 if(sessions==NULL || num_sessions<=0)
01558 goto not_found;
01559 }
01560 if(adr_mode==0) {
01561
01562 tracks= isoburn_toc_session_get_tracks(sessions[num_sessions-1],
01563 &num_tracks);
01564 if(tracks==NULL || num_tracks<=0)
01565 goto not_found;
01566 isoburn_get_track_lba(tracks[0], &(o->fabricated_msc1), 0);
01567
01568 } else if(adr_mode==1) {
01569
01570 if(adr_num<1 || adr_num>num_sessions)
01571 goto not_found;
01572 tracks= isoburn_toc_session_get_tracks(sessions[adr_num-1], &num_tracks);
01573 if(tracks==NULL || num_tracks<=0)
01574 goto not_found;
01575 isoburn_get_track_lba(tracks[0], &(o->fabricated_msc1), 0);
01576
01577 } else if(adr_mode==2) {
01578
01579 total_tracks= 0;
01580 for(i=0; i<num_sessions; i++) {
01581 tracks= isoburn_toc_session_get_tracks(sessions[i], &num_tracks);
01582 if(tracks==NULL)
01583 continue;
01584 for(j= 0; j<num_tracks; j++) {
01585 total_tracks++;
01586 if(total_tracks==adr_num) {
01587 isoburn_get_track_lba(tracks[j], &(o->fabricated_msc1), 0);
01588 ret= 1; goto ex;
01589 }
01590 }
01591 }
01592 goto not_found;
01593
01594 } else if(adr_mode==3) {
01595 o->fabricated_msc1= adr_num;
01596 if((flag & 1) && o->fabricated_msc1 >= 16) {
01597
01598 ret= isoburn_read_iso_head(d, o->fabricated_msc1, &size,volid, 1|(1<<14));
01599 if(ret==2)
01600 o->fabricated_msc1-= 16;
01601 }
01602 } else if(adr_mode==4) {
01603
01604 if(flag & 4) {
01605 ret= regcomp(&re, adr_value, 0);
01606 if(ret != 0)
01607 flag&= ~4;
01608 else
01609 re_valid= 1;
01610 }
01611 best_lba= -1;
01612 for(i=0; i<num_sessions; i++) {
01613 tracks= isoburn_toc_session_get_tracks(sessions[i], &num_tracks);
01614 if(tracks==NULL)
01615 continue;
01616 for(j= 0; j<num_tracks; j++) {
01617 isoburn_get_track_lba(tracks[0], &lba, 0);
01618 ret= isoburn_read_iso_head(d, lba, &size, volid, 1);
01619 if(ret<=0)
01620 continue;
01621 if(flag & 4) {
01622 ret= regexec(&re, volid, 1, match, 0);
01623 if(ret != 0)
01624 continue;
01625 } else {
01626 if(strcmp(volid, adr_value)!=0)
01627 continue;
01628 }
01629 best_lba= lba;
01630 }
01631 }
01632 if(best_lba<0)
01633 goto not_found;
01634 o->fabricated_msc1= best_lba;
01635
01636 } else {
01637 unknown_mode:;
01638 sprintf(msg, "Program error: Unknown msc1 address mode %d", adr_mode);
01639 isoburn_msgs_submit(o, 0x00060000, msg, 0, "FATAL", 0);
01640 ret= 0; goto ex;
01641 }
01642 ret= 1;
01643 ex:;
01644 if(disc!=NULL)
01645 isoburn_toc_disc_free(disc);
01646 if((flag & 4) && re_valid)
01647 regfree(&re);
01648 return(ret);
01649 }
01650
01651
01652 int isoburn_get_mount_params(struct burn_drive *d,
01653 int adr_mode, char *adr_value,
01654 int *lba, int *track, int *session,
01655 char volid[33], int flag)
01656 {
01657 int msc1_mem, ret, total_tracks, num_sessions, num_tracks, i, j, track_lba;
01658 int size, is_iso= 0;
01659 struct isoburn *o;
01660 struct isoburn_toc_disc *disc= NULL;
01661 struct isoburn_toc_session **sessions= NULL;
01662 struct isoburn_toc_track **tracks= NULL;
01663
01664 *lba= *track= *session= -1;
01665 volid[0]= 0;
01666 ret= isoburn_find_emulator(&o, d, 0);
01667 if(ret < 0 || o == NULL)
01668 return(-1);
01669 msc1_mem= o->fabricated_msc1;
01670 ret= isoburn_set_msc1(d, adr_mode, adr_value, 2 | (flag & 4));
01671 if(ret <= 0)
01672 return(ret);
01673 *lba= o->fabricated_msc1;
01674
01675 disc= isoburn_toc_drive_get_disc(d);
01676 if(disc==NULL)
01677 {ret= -1; goto ex;}
01678 sessions= isoburn_toc_disc_get_sessions(disc, &num_sessions);
01679 if(sessions==NULL || num_sessions<=0)
01680 {ret= -1; goto ex;}
01681 total_tracks= 0;
01682 for(i=0; i<num_sessions && *session < 0; i++) {
01683 tracks= isoburn_toc_session_get_tracks(sessions[i], &num_tracks);
01684 if(tracks==NULL)
01685 continue;
01686 for(j= 0; j<num_tracks && *track < 0; j++) {
01687 total_tracks++;
01688 isoburn_get_track_lba(tracks[j], &track_lba, 0);
01689 if(track_lba == *lba) {
01690 *track= total_tracks;
01691 *session= i + 1;
01692 }
01693 }
01694 }
01695 ret= isoburn_read_iso_head(d, *lba, &size, volid, 1);
01696 if(ret <= 0)
01697 volid[0]= 0;
01698 else
01699 is_iso= 1;
01700
01701 ex:;
01702 o->fabricated_msc1= msc1_mem;
01703 return(2 - is_iso);
01704 }
01705
01706