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