00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <stdlib.h>
00014 #include <string.h>
00015 #include <stdio.h>
00016
00017 #ifndef Xorriso_standalonE
00018
00019 #include <libburn/libburn.h>
00020
00021 #include <libisofs/libisofs.h>
00022
00023 #else
00024
00025 #include "../libisofs/libisofs.h"
00026 #include "../libburn/libburn.h"
00027
00028 #endif
00029
00030 #include "isoburn.h"
00031 #include "libisoburn.h"
00032
00033 #define BP(a,b) [(b) - (a) + 1]
00034
00035 struct ecma119_pri_vol_desc
00036 {
00037 uint8_t vol_desc_type BP(1, 1);
00038 uint8_t std_identifier BP(2, 6);
00039 uint8_t vol_desc_version BP(7, 7);
00040 uint8_t unused1 BP(8, 8);
00041 uint8_t system_id BP(9, 40);
00042 uint8_t volume_id BP(41, 72);
00043 uint8_t unused2 BP(73, 80);
00044 uint8_t vol_space_size BP(81, 88);
00045 uint8_t unused3 BP(89, 120);
00046 uint8_t vol_set_size BP(121, 124);
00047 uint8_t vol_seq_number BP(125, 128);
00048 uint8_t block_size BP(129, 132);
00049 uint8_t path_table_size BP(133, 140);
00050 uint8_t l_path_table_pos BP(141, 144);
00051 uint8_t opt_l_path_table_pos BP(145, 148);
00052 uint8_t m_path_table_pos BP(149, 152);
00053 uint8_t opt_m_path_table_pos BP(153, 156);
00054 uint8_t root_dir_record BP(157, 190);
00055 uint8_t vol_set_id BP(191, 318);
00056 uint8_t publisher_id BP(319, 446);
00057 uint8_t data_prep_id BP(447, 574);
00058 uint8_t application_id BP(575, 702);
00059 uint8_t copyright_file_id BP(703, 739);
00060 uint8_t abstract_file_id BP(740, 776);
00061 uint8_t bibliographic_file_id BP(777, 813);
00062 uint8_t vol_creation_time BP(814, 830);
00063 uint8_t vol_modification_time BP(831, 847);
00064 uint8_t vol_expiration_time BP(848, 864);
00065 uint8_t vol_effective_time BP(865, 881);
00066 uint8_t file_structure_version BP(882, 882);
00067 uint8_t reserved1 BP(883, 883);
00068 uint8_t app_use BP(884, 1395);
00069 uint8_t reserved2 BP(1396, 2048);
00070 };
00071
00072 static
00073 uint32_t iso_read_lsb(const uint8_t *buf, int bytes)
00074 {
00075 int i;
00076 uint32_t ret = 0;
00077
00078 for (i=0; i<bytes; i++) {
00079 ret += ((uint32_t) buf[i]) << (i*8);
00080 }
00081 return ret;
00082 }
00083
00084
00085
00086
00087 IsoImage *isoburn_get_attached_image(struct burn_drive *d)
00088 {
00089 int ret;
00090 struct isoburn *o= NULL;
00091 ret = isoburn_find_emulator(&o, d, 0);
00092 if (ret < 0)
00093 return NULL;
00094
00095 if (o == NULL) {
00096 return NULL;
00097 }
00098 iso_image_ref(o->image);
00099 return o->image;
00100 }
00101
00102
00103 static void isoburn_idle_free_function(void *ignored)
00104 {
00105 return;
00106 }
00107
00108
00109
00110
00111 int isoburn_read_image(struct burn_drive *d,
00112 struct isoburn_read_opts *read_opts,
00113 IsoImage **image)
00114 {
00115 int ret, int_num, dummy;
00116 IsoReadOpts *ropts= NULL;
00117 IsoReadImageFeatures *features= NULL;
00118 uint32_t ms_block;
00119 char msg[160];
00120 enum burn_disc_status status= BURN_DISC_BLANK;
00121 IsoDataSource *ds= NULL;
00122 struct isoburn *o= NULL;
00123
00124 if(d != NULL) {
00125 ret = isoburn_find_emulator(&o, d, 0);
00126 if (ret < 0 || o == NULL)
00127 return 0;
00128 status = isoburn_disc_get_status(d);
00129 }
00130 if(read_opts==NULL) {
00131 isoburn_msgs_submit(o, 0x00060000,
00132 "Program error: isoburn_read_image: read_opts==NULL",
00133 0, "FATAL", 0);
00134 return(-1);
00135 }
00136 if (d == NULL || status == BURN_DISC_BLANK || read_opts->pretend_blank) {
00137 create_blank_image:;
00138
00139
00140
00141
00142 if (d == NULL) {
00143
00144 if (image==NULL) {
00145 isoburn_msgs_submit(o, 0x00060000,
00146 "Program error: isoburn_read_image: image==NULL",
00147 0, "FATAL", 0);
00148 return -1;
00149 }
00150
00151 ret = iso_image_new("ISOIMAGE", image);
00152 if (ret < 0) {
00153 isoburn_report_iso_error(ret, "Cannot create image", 0, "FATAL", 0);
00154 return ret;
00155 }
00156 } else {
00157
00158 iso_image_unref(o->image);
00159 ret = iso_image_new("ISOIMAGE", &o->image);
00160 if (ret < 0) {
00161 isoburn_report_iso_error(ret, "Cannot create image", 0, "FATAL", 0);
00162 return ret;
00163 }
00164 if (image) {
00165 *image = o->image;
00166 iso_image_ref(*image);
00167 }
00168 }
00169 iso_image_set_ignore_aclea(*image,
00170 (!!(read_opts->noacl)) | ((!!read_opts->noea) << 1) );
00171 return 1;
00172 }
00173
00174 if (status != BURN_DISC_APPENDABLE && status != BURN_DISC_FULL) {
00175 isoburn_msgs_submit(o, 0x00060000,
00176 "Program error: isoburn_read_image: incorrect disc status",
00177 0, "FATAL", 0);
00178 return -4;
00179 }
00180
00181 memset((char *) &ropts, 0, sizeof(ropts));
00182
00183 ret = isoburn_disc_get_msc1(d, &int_num);
00184 if (ret <= 0)
00185 return -2;
00186 ms_block= int_num;
00187 ret = isoburn_read_iso_head(d, int_num, &dummy, NULL, 0);
00188 if (ret <= 0) {
00189 sprintf(msg, "No ISO 9660 image at LBA %d. Creating blank image.", int_num);
00190 isoburn_msgs_submit(o, 0x00060000, msg, 0, "WARNING", 0);
00191 goto create_blank_image;
00192 }
00193
00194
00195 ret = iso_read_opts_new(&ropts, 0);
00196 if (ret < 0) {
00197 isoburn_report_iso_error(ret, "Cannot create write opts", 0, "FATAL", 0);
00198 return ret;
00199 }
00200
00201 iso_read_opts_set_start_block(ropts, ms_block);
00202 iso_read_opts_set_no_rockridge(ropts, read_opts->norock);
00203 iso_read_opts_set_no_aaip(ropts, read_opts->noaaip);
00204 iso_read_opts_set_no_md5(ropts, read_opts->nomd5);
00205
00206 iso_read_opts_set_new_inos(ropts, read_opts->noino);
00207
00208 iso_read_opts_set_no_joliet(ropts, read_opts->nojoliet);
00209 iso_read_opts_set_no_iso1999(ropts, read_opts->noiso1999);
00210 iso_read_opts_set_preferjoliet(ropts, read_opts->preferjoliet);
00211 iso_read_opts_set_default_permissions(ropts,
00212 read_opts->mode, read_opts->dirmode);
00213 iso_read_opts_set_default_uid(ropts, read_opts->uid);
00214 iso_read_opts_set_default_gid(ropts, read_opts->gid);
00215 iso_read_opts_set_input_charset(ropts, read_opts->input_charset);
00216 iso_read_opts_auto_input_charset(ropts, read_opts->auto_input_charset);
00217
00218 ds = isoburn_data_source_new(d);
00219 if(o->iso_data_source!=NULL)
00220 iso_data_source_unref(o->iso_data_source);
00221 o->iso_data_source= ds;
00222 iso_image_attach_data(o->image, o->read_pacifier_handle,
00223 isoburn_idle_free_function);
00224 if(o->read_pacifier_handle==NULL)
00225 iso_tree_set_report_callback(o->image, NULL);
00226 else
00227 iso_tree_set_report_callback(o->image, o->read_pacifier);
00228 ret = iso_image_import(o->image, ds, ropts, &features);
00229 iso_tree_set_report_callback(o->image, NULL);
00230 iso_read_opts_free(ropts);
00231
00232 if (ret < 0) {
00233 isoburn_report_iso_error(ret, "Cannot import image", 0, "FAILURE", 0);
00234 return ret;
00235 }
00236
00237 if (image!=NULL) {
00238 *image = o->image;
00239 iso_image_ref(*image);
00240 }
00241 read_opts->hasRR = iso_read_image_features_has_rockridge(features);
00242 read_opts->hasJoliet = iso_read_image_features_has_joliet(features);
00243 read_opts->hasIso1999 = iso_read_image_features_has_iso1999(features);
00244 read_opts->hasElTorito = iso_read_image_features_has_eltorito(features);
00245 read_opts->size = iso_read_image_features_get_size(features);
00246 iso_read_image_features_destroy(features);
00247 return 1;
00248 }
00249
00250
00251
00252
00253 int isoburn_attach_image(struct burn_drive *d, IsoImage *image)
00254 {
00255 int ret;
00256 struct isoburn *o;
00257
00258 ret = isoburn_find_emulator(&o, d, 0);
00259 if (ret < 0 || o == NULL)
00260 return 0;
00261 if (image == NULL) {
00262 isoburn_msgs_submit(o, 0x00060000,
00263 "Program error: isoburn_attach_image: image==NULL",
00264 0, "FATAL", 0);
00265 return -1;
00266 }
00267 if(o->image != NULL)
00268 iso_image_unref(o->image);
00269 o->image = image;
00270 return(1);
00271 }
00272
00273
00274
00275
00276 int isoburn_activate_session(struct burn_drive *drive)
00277 {
00278 int ret;
00279 struct isoburn *o;
00280
00281 ret = isoburn_find_emulator(&o, drive, 0);
00282 if (ret < 0)
00283 return -1;
00284
00285 if (o->emulation_mode != 1)
00286 return 1;
00287 if (o->fabricated_msc2 >= 0)
00288 return 1;
00289
00290 if (!(o->fabricated_disc_status == BURN_DISC_APPENDABLE ||
00291 (o->fabricated_disc_status == BURN_DISC_BLANK &&
00292 o->zero_nwa > 0)))
00293 return 1;
00294
00295 ret = burn_random_access_write(drive, (off_t) 0, (char*)o->target_iso_head,
00296 Libisoburn_target_head_sizE, 1);
00297
00298 return ret;
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308 int isoburn_start_emulation(struct isoburn *o, int flag)
00309 {
00310 int ret, i, capacity = -1, role;
00311 off_t data_count, to_read;
00312 struct burn_drive *drive;
00313 struct ecma119_pri_vol_desc *pvm;
00314
00315 if(o==NULL) {
00316 isoburn_msgs_submit(NULL, 0x00060000,
00317 "Program error: isoburn_start_emulation: o==NULL",
00318 0, "FATAL", 0);
00319 return -1;
00320 }
00321
00322 drive= o->drive;
00323
00324
00325
00326
00327 role = burn_drive_get_drive_role(drive);
00328 ret = burn_get_read_capacity(drive, &capacity, 0);
00329 if (ret <= 0)
00330 capacity = -1;
00331 if (capacity > 0 || role == 2) {
00332
00333
00334 memset(o->target_iso_head, 0, Libisoburn_target_head_sizE);
00335 to_read = Libisoburn_target_head_sizE;
00336 if(capacity > 0 && (off_t) capacity * (off_t) 2048 < to_read)
00337 to_read = (off_t) capacity * (off_t) 2048;
00338 ret = burn_read_data(drive, (off_t) 0, (char*)o->target_iso_head,
00339 to_read, &data_count, 2);
00340 if (ret <= 0) {
00341
00342 if (capacity > 0)
00343 o->fabricated_disc_status= BURN_DISC_FULL;
00344 else
00345 o->fabricated_disc_status= BURN_DISC_BLANK;
00346 return 1;
00347 }
00348 } else {
00349
00350 o->fabricated_disc_status= BURN_DISC_BLANK;
00351 return 1;
00352 }
00353
00354
00355
00356 i = Libisoburn_target_head_sizE;
00357 while (i && !o->target_iso_head[i-1])
00358 --i;
00359
00360 if (!i) {
00361 o->fabricated_disc_status= BURN_DISC_BLANK;
00362 return 1;
00363 }
00364
00365 pvm = (struct ecma119_pri_vol_desc *)(o->target_iso_head + 16 * 2048);
00366
00367 if (!strncmp((char*)pvm->std_identifier, "CD001", 5)) {
00368 off_t size;
00369
00370
00371 if (pvm->vol_desc_type[0] != 1 || pvm->vol_desc_version[0] != 1
00372 || pvm->file_structure_version[0] != 1 ) {
00373
00374 o->fabricated_disc_status= BURN_DISC_FULL;
00375 return 1;
00376 }
00377
00378
00379 size = (off_t) iso_read_lsb(pvm->vol_space_size, 4);
00380 size *= (off_t) 2048;
00381 isoburn_set_start_byte(o, size, 0);
00382 o->fabricated_disc_status= BURN_DISC_APPENDABLE;
00383 } else if (!strncmp((char*)pvm->std_identifier, "CDXX1", 5)) {
00384
00385
00386 isoburn_set_start_byte(o, o->zero_nwa * 2048, 0);
00387 o->fabricated_disc_status= BURN_DISC_BLANK;
00388 } else {
00389
00390 o->fabricated_disc_status= BURN_DISC_FULL;
00391 }
00392 return 1;
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 int isoburn_invalidate_iso(struct isoburn *o, int flag)
00405 {
00406
00407
00408
00409
00410 strncpy((char*)o->target_iso_head + 16 * 2048 + 1, "CDXX1", 5);
00411 return isoburn_activate_session(o->drive);
00412 }
00413
00414
00415
00416 int isoburn_set_read_pacifier(struct burn_drive *drive,
00417 int (*read_pacifier)(IsoImage*, IsoFileSource*),
00418 void *read_handle)
00419 {
00420 int ret;
00421 struct isoburn *o;
00422
00423 ret = isoburn_find_emulator(&o, drive, 0);
00424 if(ret < 0 || o == NULL)
00425 return -1;
00426 o->read_pacifier_handle= read_handle;
00427 o->read_pacifier= read_pacifier;
00428 return(1);
00429 }
00430