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