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