From d2fd48fcbcbf64581a3a7f3105afa40821bc30c8 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Tue, 20 Sep 2022 10:14:10 +0200 Subject: [PATCH] New API call isoburn_assess_written_features() --- libisoburn/isofs_wrap.c | 326 ++++++++++++++++++++++++++++++-------- libisoburn/libisoburn.h | 26 ++- libisoburn/libisoburn.ver | 1 + 3 files changed, 289 insertions(+), 64 deletions(-) diff --git a/libisoburn/isofs_wrap.c b/libisoburn/isofs_wrap.c index 0ad683d4..c48e8e66 100644 --- a/libisoburn/isofs_wrap.c +++ b/libisoburn/isofs_wrap.c @@ -137,16 +137,106 @@ int isoburn_root_defaults(IsoImage *image, int flag) } +/* @return <=0 = error , 1 = ok , 2 = no ISO filesystem found +*/ +int isoburn_make_iso_read_opts(struct burn_drive *d, + struct isoburn *o, + struct isoburn_read_opts *read_opts, + IsoReadOpts **ropts) +{ + int ret, int_num, dummy; + uint32_t ms_block; + char *msg= NULL; + + msg= calloc(1, 160); + *ropts= NULL; + + ret = isoburn_disc_get_msc1(d, &int_num); + if (ret <= 0) + {ret= -2; goto ex;} + ms_block= int_num; + if (o != NULL) + o->image_start_lba= ms_block; + ret = isoburn_read_iso_head(d, int_num, &dummy, NULL, 0); + if (ret <= 0) { + sprintf(msg, "No ISO 9660 image at LBA %d.", int_num); + isoburn_msgs_submit(o, 0x00060000, msg, 0, "WARNING", 0); + {ret= 2; goto ex;} + } + + if(read_opts->displacement != 0 && abs(read_opts->displacement_sign) == 1) { + /* Apply reverse displacement to session start */ + if(read_opts->displacement_sign == -1) { + if(ms_block+ read_opts->displacement < ms_block) { +displacement_rollover:; + sprintf(msg, "Displacement offset leads outside 32 bit range."); + isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + ms_block+= read_opts->displacement; + } else { + if(ms_block < read_opts->displacement) + goto displacement_rollover; + ms_block-= read_opts->displacement; + } + } + + ret = iso_read_opts_new(ropts, 0); + if (ret < 0) { + isoburn_report_iso_error(ret, "Cannot create write opts", 0, "FATAL", 0); + goto ex; + } + + iso_read_opts_set_start_block(*ropts, ms_block); + iso_read_opts_set_no_rockridge(*ropts, read_opts->norock); + iso_read_opts_set_no_aaip(*ropts, read_opts->noaaip); + if(read_opts->nomd5 == 2) + int_num= 2; + else if(read_opts->nomd5 == 1) + int_num= 1; + else + int_num= 0; + iso_read_opts_set_no_md5(*ropts, int_num); + if(read_opts->do_ecma119_map) + iso_read_opts_set_ecma119_map(*ropts, read_opts->map_mode); + if(read_opts->do_joliet_map) + iso_read_opts_set_joliet_map(*ropts, read_opts->joliet_map_mode); + iso_read_opts_set_new_inos(*ropts, read_opts->noino); + + iso_read_opts_set_no_joliet(*ropts, read_opts->nojoliet); + iso_read_opts_set_no_iso1999(*ropts, read_opts->noiso1999); + iso_read_opts_set_preferjoliet(*ropts, read_opts->preferjoliet); + iso_read_opts_set_default_permissions(*ropts, + read_opts->mode, read_opts->dirmode); + iso_read_opts_set_default_uid(*ropts, read_opts->uid); + iso_read_opts_set_default_gid(*ropts, read_opts->gid); + iso_read_opts_set_input_charset(*ropts, read_opts->input_charset); + iso_read_opts_auto_input_charset(*ropts, read_opts->auto_input_charset); + iso_read_opts_load_system_area(*ropts, 1); + iso_read_opts_keep_import_src(*ropts, 1); + + ret= 1; +ex:; + if(ret <= 0) { + if(*ropts != NULL) + iso_read_opts_free(*ropts); + *ropts= NULL; + } + if(msg != NULL) + free(msg); + return(ret); +} + + /* API function. See libisoburn.h */ int isoburn_read_image(struct burn_drive *d, struct isoburn_read_opts *read_opts, IsoImage **image) { - int ret, int_num, dummy, ignore_aclea= 0; + int ret, ignore_aclea= 0; IsoReadOpts *ropts= NULL; IsoReadImageFeatures *features= NULL; - uint32_t ms_block; char *msg= NULL; enum burn_disc_status status= BURN_DISC_BLANK; IsoDataSource *ds= NULL; @@ -223,73 +313,19 @@ create_blank_image:; {ret= -4; goto ex;} } - ret = isoburn_disc_get_msc1(d, &int_num); - if (ret <= 0) - {ret= -2; goto ex;} - ms_block= int_num; - if (o != NULL) - o->image_start_lba= ms_block; - ret = isoburn_read_iso_head(d, int_num, &dummy, NULL, 0); - if (ret <= 0) { - sprintf(msg, "No ISO 9660 image at LBA %d. Creating blank image.", int_num); + + /* create the data source */ + ret= isoburn_make_iso_read_opts(d, o, read_opts, &ropts); + if(ret <= 0) + goto ex; + if(ret == 2) { + sprintf(msg, "Creating blank image."); isoburn_msgs_submit(o, 0x00060000, msg, 0, "WARNING", 0); goto create_blank_image; } - if(read_opts->displacement != 0 && abs(read_opts->displacement_sign) == 1) { - /* Apply reverse displacement to session start */ - if(read_opts->displacement_sign == -1) { - if(ms_block+ read_opts->displacement < ms_block) { -displacement_rollover:; - sprintf(msg, "Displacement offset leads outside 32 bit range."); - isoburn_msgs_submit(o, 0x00060000, msg, 0, "FAILURE", 0); - {ret= 0; goto ex;} - } - ms_block+= read_opts->displacement; - } else { - if(ms_block < read_opts->displacement) - goto displacement_rollover; - ms_block-= read_opts->displacement; - } - } - - - /* create the data source */ - ret = iso_read_opts_new(&ropts, 0); - if (ret < 0) { - isoburn_report_iso_error(ret, "Cannot create write opts", 0, "FATAL", 0); - goto ex; - } - /* Important: do not return until iso_read_opts_free() */ - iso_read_opts_set_start_block(ropts, ms_block); - iso_read_opts_set_no_rockridge(ropts, read_opts->norock); - iso_read_opts_set_no_aaip(ropts, read_opts->noaaip); - if(read_opts->nomd5 == 2) - int_num= 2; - else if(read_opts->nomd5 == 1) - int_num= 1; - else - int_num= 0; - iso_read_opts_set_no_md5(ropts, int_num); - if(read_opts->do_ecma119_map) - iso_read_opts_set_ecma119_map(ropts, read_opts->map_mode); - if(read_opts->do_joliet_map) - iso_read_opts_set_joliet_map(ropts, read_opts->joliet_map_mode); - iso_read_opts_set_new_inos(ropts, read_opts->noino); - - iso_read_opts_set_no_joliet(ropts, read_opts->nojoliet); - iso_read_opts_set_no_iso1999(ropts, read_opts->noiso1999); - iso_read_opts_set_preferjoliet(ropts, read_opts->preferjoliet); - iso_read_opts_set_default_permissions(ropts, - read_opts->mode, read_opts->dirmode); - iso_read_opts_set_default_uid(ropts, read_opts->uid); - iso_read_opts_set_default_gid(ropts, read_opts->gid); - iso_read_opts_set_input_charset(ropts, read_opts->input_charset); - iso_read_opts_auto_input_charset(ropts, read_opts->auto_input_charset); - iso_read_opts_load_system_area(ropts, 1); - iso_read_opts_keep_import_src(ropts, 1); ret= iso_image_set_truncate_mode(o->image, read_opts->truncate_mode, read_opts->truncate_length); if(ret < 0) @@ -346,6 +382,170 @@ ex:; } +/* API function. See libisoburn.h +*/ +int isoburn_assess_written_features(struct burn_drive *d, + struct isoburn_read_opts *read_opts, + IsoReadImageFeatures **features, + struct isoburn_imgen_opts **imgen_opts, + int flag) +{ + int ret, type, ext; + int64_t num_value; + void *pt_value; + size_t pt_size; + IsoReadOpts *ropts= NULL; + char *msg= NULL; + enum burn_disc_status status= BURN_DISC_BLANK; + IsoDataSource *ds= NULL; + struct isoburn *o= NULL; + IsoWriteOpts *write_opts= NULL; + + msg= calloc(1, 160); + + if(d != NULL) { + ret = isoburn_find_emulator(&o, d, 0); + if (ret < 0 || o == NULL) + {ret= 0; goto ex;} + status = isoburn_disc_get_status(d); + o->image_start_lba= -1; + } + if(read_opts==NULL) { + isoburn_msgs_submit(o, 0x00060000, + "Program error: isoburn_read_image: read_opts==NULL", + 0, "FATAL", 0); + {ret= -1; goto ex;} + } + if (d == NULL || read_opts->pretend_blank || + (status != BURN_DISC_APPENDABLE && status != BURN_DISC_FULL)) { + isoburn_msgs_submit(o, 0x00060000, + "Empty drive, unsuitable medium state, or read option 'pretend_blank'", + 0, "FAILURE", 0); + {ret= 0; goto ex;} + } + + ret= isoburn_make_iso_read_opts(d, o, read_opts, &ropts); + if(ret <= 0) + goto ex; + if(ret == 2) + {ret= 0; goto ex;} + + /* ??? Only if o->iso_data_source == NULL ? */ + ds = isoburn_data_source_new(d, read_opts->displacement, + read_opts->displacement_sign, + read_opts->cache_tiles, read_opts->cache_tile_blocks); + if (ds == NULL) { + isoburn_report_iso_error(ret, "Cannot create IsoDataSource object", 0, + "FATAL", 0); + ret= -1; goto ex; + } + if(o->iso_data_source != NULL) + iso_data_source_unref(o->iso_data_source); + o->iso_data_source= ds; + + ret= iso_assess_written_features(ds, ropts, features, &write_opts); + if(ret < 0) { + isoburn_report_iso_error(ret, "Failed to assess ISO filesystem features", + 0, "FAILURE", 0); + ret= 0; goto ex; + } + + ret= isoburn_igopt_new(imgen_opts, 0); + if(ret <= 0) + goto ex; + + /* Convert features to imgen_opts */ + + if(iso_read_image_feature_named(*features, "iso_level", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + isoburn_igopt_set_level(*imgen_opts, num_value); + ext= 0; + if(iso_read_image_feature_named(*features, "rock_ridge", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_rockridge * !!num_value; + if(iso_read_image_feature_named(*features, "joliet", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_joliet * !!num_value; + if(iso_read_image_feature_named(*features, "iso1999", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_iso1999 * !!num_value; + if(iso_read_image_feature_named(*features, "aaip", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_aaip * !!num_value; + if(iso_read_image_feature_named(*features, "record_md5_session", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_session_md5 * !!num_value; + if(iso_read_image_feature_named(*features, "record_md5_files", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_file_md5 * !!num_value; + isoburn_igopt_set_extensions(*imgen_opts, ext); + + ext= 0; + if(iso_read_image_feature_named(*features, "omit_version_numbers", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) { + if((num_value & 3) == 2) + ext|= isoburn_igopt_only_iso_versions; + else if(num_value & 3) + ext|= isoburn_igopt_omit_version_numbers; + } + if(iso_read_image_feature_named(*features, "allow_deep_paths", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_allow_deep_paths * !!num_value; + if(iso_read_image_feature_named(*features, "allow_longer_paths", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_allow_longer_paths * !!num_value; + if(iso_read_image_feature_named(*features, "max_37_char_filenames", NULL, + &type, &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_max_37_char_filenames * !!num_value; + if(iso_read_image_feature_named(*features, "no_force_dots", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) { + if(num_value & 1) + ext|= isoburn_igopt_only_iso_versions; + if(num_value & 2) + ext|= isoburn_igopt_no_force_dots; + } + if(iso_read_image_feature_named(*features, "allow_lowercase", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_allow_lowercase * !!num_value; + if(iso_read_image_feature_named(*features, "allow_full_ascii", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_allow_full_ascii * !!num_value; + if(iso_read_image_feature_named(*features, "joliet_longer_paths", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_joliet_longer_paths * !!num_value; + if(iso_read_image_feature_named(*features, "rrip_version_1_10", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_rrip_version_1_10 * !!num_value; + if(iso_read_image_feature_named(*features, "aaip_susp_1_10", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_aaip_susp_1_10 * !!num_value; + if(iso_read_image_feature_named(*features, "allow_dir_id_ext", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_allow_dir_id_ext * !!num_value; + if(iso_read_image_feature_named(*features, "joliet_long_names", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_joliet_long_names * !!num_value; + if(iso_read_image_feature_named(*features, "joliet_utf16", NULL, &type, + &num_value, &pt_value, &pt_size) == 1) + ext|= isoburn_igopt_joliet_utf16 * !!num_value; + isoburn_igopt_set_relaxed(*imgen_opts, ext); + + if(iso_read_image_feature_named(*features, "untranslated_name_len", NULL, + &type, &num_value, &pt_value, &pt_size) == 1) + isoburn_igopt_set_untranslated_name_len(*imgen_opts, num_value); + + ret= 1; +ex:; + if(msg != NULL) + free(msg); + if(ropts != NULL) + iso_read_opts_free(ropts); + if(write_opts != NULL) + iso_write_opts_free(write_opts); + return(ret); +} + + /* API function. See libisoburn.h */ int isoburn_attach_image(struct burn_drive *d, IsoImage *image) diff --git a/libisoburn/libisoburn.h b/libisoburn/libisoburn.h index 2120619a..91d0008f 100644 --- a/libisoburn/libisoburn.h +++ b/libisoburn/libisoburn.h @@ -1310,7 +1310,7 @@ int isoburn_igopt_get_extensions(struct isoburn_imgen_opts *o, int *ext); prefixed ES fields. This saves 5 to 10 bytes per file and might avoid problems with readers which only accept RRIP. SUSP-1.10 allows it, SUSP-1.12 frowns on it. - bit12= only_iso_numbers + bit12= only_iso_versions Same as bit1 omit_version_number but restricted to the names in the eventual Joliet tree. @since 0.5.4 @@ -2447,6 +2447,30 @@ int isoburn_set_read_pacifier(struct burn_drive *drive, int isoburn_get_img_partition_offset(struct burn_drive *drive, uint32_t *block_offset_2k); +/** Assess features of the importable directory trees and an estimation of the + write options which would cause the recognized features. + @since 1.5.6 + @param d The drive with the ISO filesystem + @param read_opts The read options which would be used by + isoburn_read_image() + @param features Returned information which may be inquired by + iso_read_image_features_*() or by + iso_read_image_feature_named(). + Dispose by iso_read_image_features_destroy() when + no longer needed. + @param imgen_opts Returned set of write options which were derived + from the features. + Dispose by isoburn_igopt_destroy when no longer + needed. + @param flag Bitfield for control purposes, submit 0 for now. + @return 1= success, <= 0 = error +*/ +int isoburn_assess_written_features(struct burn_drive *d, + struct isoburn_read_opts *read_opts, + IsoReadImageFeatures **features, + struct isoburn_imgen_opts **imgen_opts, + int flag); + /** Set the IsoImage to be used with a drive. This eventually releases the reference to the old IsoImage attached to the drive. diff --git a/libisoburn/libisoburn.ver b/libisoburn/libisoburn.ver index 3da3df2f..07fe0423 100644 --- a/libisoburn/libisoburn.ver +++ b/libisoburn/libisoburn.ver @@ -1,6 +1,7 @@ LIBISOBURN1 { global: isoburn_activate_session; +isoburn_assess_written_features; isoburn_attach_image; isoburn_attach_start_lba; isoburn_conv_name_chars;