|
libisoburn 0.5.6
|
00001 00002 /* 00003 cc -g -c isofs_wrap.c 00004 */ 00005 00006 /* 00007 libisofs related functions of libisoburn. 00008 00009 Copyright 2007 - 2010 Vreixo Formoso Lopes <metalpain2002@yahoo.es> 00010 Thomas Schmitt <scdbackup@gmx.net> 00011 Provided under GPL version 2 or later. 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 /* ! Xorriso_standalonE */ 00025 00026 #include "../libisofs/libisofs.h" 00027 #include "../libburn/libburn.h" 00028 00029 #endif /* Xorriso_standalonE */ 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 /* API function. See libisoburn.h 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 /* API function. See libisoburn.h 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 * Blank disc, we create a new image without files. 00141 */ 00142 00143 if (d == NULL) { 00144 /* New empty image without relation to a drive */ 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 /* create a new image */ 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 /* Blank new image for the drive */ 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); /*protects object from premature free*/ 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 /* create the data source */ 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 /* Important: do not return until iso_read_opts_free() */ 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 /* Important: do not return until free(features) */ 00239 if (image!=NULL) { 00240 *image = o->image; 00241 iso_image_ref(*image); /*protects object from premature free*/ 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 /* API function. See libisoburn.h 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 /* API function. See libisoburn.h 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; /* don't need to activate session */ 00289 if (o->fabricated_msc2 >= 0) 00290 return 1; /* blind growing: do not alter anything outside the session */ 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 /** Initialize the emulation of multi-session on random access media. 00305 The need for emulation is confirmed already. 00306 @param o A freshly created isoburn object. isoburn_create_data_source() was 00307 already called, nevertheless. 00308 @return <=0 error , 1 = success 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 /* We can assume 0 as start block for image. 00327 The data there point to the most recent session. 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 /* Might be a block device on a system where libburn cannot determine its 00335 size. Try to read anyway. */ 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 /* an error means a disc with no ISO image */ 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 /* No read capacity means blank media */ 00352 o->fabricated_disc_status= BURN_DISC_BLANK; 00353 return 1; 00354 } 00355 00356 /* check first 64K. If 0's, the disc is treated as a blank disc, and thus 00357 overwritten without extra check. */ 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 /* sanity check */ 00373 if (pvm->vol_desc_type[0] != 1 || pvm->vol_desc_version[0] != 1 00374 || pvm->file_structure_version[0] != 1 ) { 00375 /* TODO for now I treat this as a full disc */ 00376 o->fabricated_disc_status= BURN_DISC_FULL; 00377 return 1; 00378 } 00379 00380 /* ok, PVM found, set size */ 00381 size = (off_t) iso_read_lsb(pvm->vol_space_size, 4); 00382 size *= (off_t) 2048; /* block size in bytes */ 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 /* empty image */ 00388 isoburn_set_start_byte(o, o->zero_nwa * 2048, 0); 00389 o->fabricated_disc_status= BURN_DISC_BLANK; 00390 } else { 00391 /* treat any disc in an unknown format as full */ 00392 o->fabricated_disc_status= BURN_DISC_FULL; 00393 } 00394 return 1; 00395 } 00396 00397 00398 /** Alters and writes the first 64 kB of a "media" to invalidate 00399 an ISO image. (It shall stay restorable by skilled humans, though). 00400 The result shall especially keep libisoburn from accepting the media 00401 image as ISO filesystem. 00402 @param o A fully activated isoburn object. isoburn_start_emulation() 00403 was already called. 00404 @return <=0 error , 1 = success 00405 */ 00406 int isoburn_invalidate_iso(struct isoburn *o, int flag) 00407 { 00408 /* 00409 * replace CD001 with CDXX1 in PVM. 00410 * I think this is enought for invalidating an iso image 00411 */ 00412 strncpy((char*)o->target_iso_head + 16 * 2048 + 1, "CDXX1", 5); 00413 return isoburn_activate_session(o->drive); 00414 } 00415 00416 00417 /* API @since 0.1.0 */ 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
1.7.3