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