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 return 1;
00170 }
00171
00172 if (status != BURN_DISC_APPENDABLE && status != BURN_DISC_FULL) {
00173 isoburn_msgs_submit(o, 0x00060000,
00174 "Program error: isoburn_read_image: incorrect disc status",
00175 0, "FATAL", 0);
00176 return -4;
00177 }
00178
00179 memset((char *) &ropts, 0, sizeof(ropts));
00180
00181 ret = isoburn_disc_get_msc1(d, &int_num);
00182 if (ret <= 0)
00183 return -2;
00184 ms_block= int_num;
00185 ret = isoburn_read_iso_head(d, int_num, &dummy, NULL, 0);
00186 if (ret <= 0) {
00187 sprintf(msg, "No ISO 9660 image at LBA %d. Creating blank image.", int_num);
00188 isoburn_msgs_submit(o, 0x00060000, msg, 0, "WARNING", 0);
00189 goto create_blank_image;
00190 }
00191
00192
00193 ret = iso_read_opts_new(&ropts, 0);
00194 if (ret < 0) {
00195 isoburn_report_iso_error(ret, "Cannot create write opts", 0, "FATAL", 0);
00196 return ret;
00197 }
00198
00199 iso_read_opts_set_start_block(ropts, ms_block);
00200 iso_read_opts_set_no_rockridge(ropts, read_opts->norock);
00201 iso_read_opts_set_no_joliet(ropts, read_opts->nojoliet);
00202 iso_read_opts_set_no_iso1999(ropts, read_opts->noiso1999);
00203 iso_read_opts_set_preferjoliet(ropts, read_opts->preferjoliet);
00204 iso_read_opts_set_default_permissions(ropts,
00205 read_opts->mode, read_opts->dirmode);
00206 iso_read_opts_set_default_uid(ropts, read_opts->uid);
00207 iso_read_opts_set_default_gid(ropts, read_opts->gid);
00208 iso_read_opts_set_input_charset(ropts, read_opts->input_charset);
00209
00210
00211
00212
00213
00214 ds = isoburn_data_source_new(d);
00215 if(o->iso_data_source!=NULL)
00216 iso_data_source_unref(o->iso_data_source);
00217 o->iso_data_source= ds;
00218 iso_image_attach_data(o->image, o->read_pacifier_handle,
00219 isoburn_idle_free_function);
00220 if(o->read_pacifier_handle==NULL)
00221 iso_tree_set_report_callback(o->image, NULL);
00222 else
00223 iso_tree_set_report_callback(o->image, o->read_pacifier);
00224 ret = iso_image_import(o->image, ds, ropts, &features);
00225 iso_tree_set_report_callback(o->image, NULL);
00226 iso_read_opts_free(ropts);
00227
00228 if (ret < 0) {
00229 isoburn_report_iso_error(ret, "Cannot import image", 0, "FAILURE", 0);
00230 return ret;
00231 }
00232
00233 if (image!=NULL) {
00234 *image = o->image;
00235 iso_image_ref(*image);
00236 }
00237 read_opts->hasRR = iso_read_image_features_has_rockridge(features);
00238 read_opts->hasJoliet = iso_read_image_features_has_joliet(features);
00239 read_opts->hasIso1999 = iso_read_image_features_has_iso1999(features);
00240 read_opts->hasElTorito = iso_read_image_features_has_eltorito(features);
00241 read_opts->size = iso_read_image_features_get_size(features);
00242 iso_read_image_features_destroy(features);
00243 return 1;
00244 }
00245
00246
00247
00248
00249 int isoburn_attach_image(struct burn_drive *d, IsoImage *image)
00250 {
00251 int ret;
00252 struct isoburn *o;
00253
00254 ret = isoburn_find_emulator(&o, d, 0);
00255 if (ret < 0 || o == NULL)
00256 return 0;
00257 if (image == NULL) {
00258 isoburn_msgs_submit(o, 0x00060000,
00259 "Program error: isoburn_attach_image: image==NULL",
00260 0, "FATAL", 0);
00261 return -1;
00262 }
00263 if(o->image != NULL)
00264 iso_image_unref(o->image);
00265 o->image = image;
00266 return(1);
00267 }
00268
00269
00270
00271
00272 int isoburn_activate_session(struct burn_drive *drive)
00273 {
00274 int ret;
00275 struct isoburn *o;
00276
00277 ret = isoburn_find_emulator(&o, drive, 0);
00278 if (ret < 0)
00279 return -1;
00280
00281 if (o->emulation_mode != 1)
00282 return 1;
00283 if (o->fabricated_msc2 >= 0)
00284 return 1;
00285
00286 if (!(o->fabricated_disc_status == BURN_DISC_APPENDABLE ||
00287 (o->fabricated_disc_status == BURN_DISC_BLANK &&
00288 o->zero_nwa > 0)))
00289 return 1;
00290
00291 ret = burn_random_access_write(drive, (off_t) 0, (char*)o->target_iso_head,
00292 Libisoburn_target_head_sizE, 1);
00293
00294 return ret;
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304 int isoburn_start_emulation(struct isoburn *o, int flag)
00305 {
00306 int ret, i;
00307 off_t data_count;
00308 struct burn_drive *drive;
00309 struct ecma119_pri_vol_desc *pvm;
00310
00311 if(o==NULL) {
00312 isoburn_msgs_submit(NULL, 0x00060000,
00313 "Program error: isoburn_start_emulation: o==NULL",
00314 0, "FATAL", 0);
00315 return -1;
00316 }
00317
00318 drive= o->drive;
00319
00320
00321
00322 ret = burn_read_data(drive, (off_t) 0, (char*)o->target_iso_head,
00323 (off_t) Libisoburn_target_head_sizE, &data_count, 2);
00324
00325
00326 if (ret <= 0) {
00327 o->fabricated_disc_status= BURN_DISC_BLANK;
00328 return 1;
00329 }
00330
00331
00332
00333 i = Libisoburn_target_head_sizE;
00334 while (i && !o->target_iso_head[i-1])
00335 --i;
00336
00337 if (!i) {
00338 o->fabricated_disc_status= BURN_DISC_BLANK;
00339 return 1;
00340 }
00341
00342 pvm = (struct ecma119_pri_vol_desc *)(o->target_iso_head + 16 * 2048);
00343
00344 if (!strncmp((char*)pvm->std_identifier, "CD001", 5)) {
00345 off_t size;
00346
00347
00348 if (pvm->vol_desc_type[0] != 1 || pvm->vol_desc_version[0] != 1
00349 || pvm->file_structure_version[0] != 1 ) {
00350
00351 o->fabricated_disc_status= BURN_DISC_FULL;
00352 return 1;
00353 }
00354
00355
00356 size = (off_t) iso_read_lsb(pvm->vol_space_size, 4);
00357 size *= (off_t) 2048;
00358 isoburn_set_start_byte(o, size, 0);
00359 o->fabricated_disc_status= BURN_DISC_APPENDABLE;
00360 } else if (!strncmp((char*)pvm->std_identifier, "CDXX1", 5)) {
00361
00362
00363 isoburn_set_start_byte(o, o->zero_nwa * 2048, 0);
00364 o->fabricated_disc_status= BURN_DISC_BLANK;
00365 } else {
00366
00367 o->fabricated_disc_status= BURN_DISC_FULL;
00368 }
00369 return 1;
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 int isoburn_invalidate_iso(struct isoburn *o, int flag)
00382 {
00383
00384
00385
00386
00387 strncpy((char*)o->target_iso_head + 16 * 2048 + 1, "CDXX1", 5);
00388 return isoburn_activate_session(o->drive);
00389 }
00390
00391
00392
00393 int isoburn_set_read_pacifier(struct burn_drive *drive,
00394 int (*read_pacifier)(IsoImage*, IsoFileSource*),
00395 void *read_handle)
00396 {
00397 int ret;
00398 struct isoburn *o;
00399
00400 ret = isoburn_find_emulator(&o, drive, 0);
00401 if(ret < 0 || o == NULL)
00402 return -1;
00403 o->read_pacifier_handle= read_handle;
00404 o->read_pacifier= read_pacifier;
00405 return(1);
00406 }
00407