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