diff --git a/libisofs/ecma119.c b/libisofs/ecma119.c index 6120a78..d967d1d 100644 --- a/libisofs/ecma119.c +++ b/libisofs/ecma119.c @@ -1576,6 +1576,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img) target->aaip = opts->aaip; target->always_gmt = opts->always_gmt; target->untranslated_name_len = opts->untranslated_name_len; + target->allow_dir_id_ext = opts->allow_dir_id_ext; target->omit_version_numbers = opts->omit_version_numbers | opts->max_37_char_filenames; target->allow_deep_paths = opts->allow_deep_paths; @@ -2364,6 +2365,7 @@ int iso_write_opts_new(IsoWriteOpts **opts, int profile) wopts->appended_partitions[i] = NULL; wopts->ascii_disc_label[0] = 0; wopts->will_cancel = 0; + wopts->allow_dir_id_ext = 0; wopts->untranslated_name_len = 0; *opts = wopts; @@ -2469,6 +2471,15 @@ int iso_write_opts_set_untranslated_name_len(IsoWriteOpts *opts, int len) return opts->untranslated_name_len; } +int iso_write_opts_set_allow_dir_id_ext(IsoWriteOpts *opts, int allow) +{ + if (opts == NULL) { + return ISO_NULL_POINTER; + } + opts->allow_dir_id_ext = allow ? 1 : 0; + return ISO_SUCCESS; +} + int iso_write_opts_set_omit_version_numbers(IsoWriteOpts *opts, int omit) { if (opts == NULL) { diff --git a/libisofs/ecma119.h b/libisofs/ecma119.h index 2df584e..76ffa05 100644 --- a/libisofs/ecma119.h +++ b/libisofs/ecma119.h @@ -87,6 +87,14 @@ struct iso_write_opts { * but it is supposed to work on most moderns systems. Use with caution. */ + /** + * Convert directory names for ECMA-119 the same way as other file names + * but do not force dots or add version numbers. + * This violates ECMA-119 by allowing one "." and especially ISO level 1 + * by allowing DOS style 8.3 names rather than only 8 characters. + */ + unsigned int allow_dir_id_ext :1; + /** * Omit the version number (";1") at the end of the ISO-9660 identifiers. * Version numbers are usually not used. @@ -425,6 +433,7 @@ struct ecma119_image unsigned int always_gmt :1; /* relaxed constraints */ + unsigned int allow_dir_id_ext :1; unsigned int omit_version_numbers :2; unsigned int allow_deep_paths :1; unsigned int allow_longer_paths :1; diff --git a/libisofs/ecma119_tree.c b/libisofs/ecma119_tree.c index 4fc7fb2..ebd21ff 100644 --- a/libisofs/ecma119_tree.c +++ b/libisofs/ecma119_tree.c @@ -32,7 +32,7 @@ static int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name) { - int ret, relaxed, free_ascii_name= 0; + int ret, relaxed, free_ascii_name= 0, force_dots = 0, max_len; char *ascii_name; char *isoname= NULL; @@ -58,7 +58,7 @@ int get_iso_name(Ecma119Image *img, IsoNode *iso, char **name) } else { relaxed = (int)img->allow_lowercase; } - if (iso->type == LIBISO_DIR) { + if (iso->type == LIBISO_DIR && !(img->allow_dir_id_ext)) { if (img->untranslated_name_len > 0) { if (strlen(ascii_name) > img->untranslated_name_len) { needs_transl:; @@ -85,24 +85,27 @@ needs_transl:; } } } else { + force_dots = !((img->no_force_dots & 1) || iso->type == LIBISO_DIR); if (img->untranslated_name_len > 0) { if (strlen(ascii_name) > img->untranslated_name_len) goto needs_transl; isoname = strdup(ascii_name); } else if (img->max_37_char_filenames) { - isoname = iso_r_fileid(ascii_name, 36, relaxed, - (img->no_force_dots & 1) ? 0 : 1); + isoname = iso_r_fileid(ascii_name, 36, relaxed, force_dots); } else if (img->iso_level == 1) { - if (relaxed) { - isoname = iso_r_fileid(ascii_name, 11, relaxed, - (img->no_force_dots & 1) ? 0 : 1); + if (relaxed || !force_dots) { + if (strchr(ascii_name, '.') == NULL) + max_len = 8; + else + max_len = 11; + isoname = iso_r_fileid(ascii_name, max_len, relaxed, + force_dots); } else { isoname = iso_1_fileid(ascii_name); } } else { - if (relaxed) { - isoname = iso_r_fileid(ascii_name, 30, relaxed, - (img->no_force_dots & 1) ? 0 : 1); + if (relaxed || !force_dots) { + isoname = iso_r_fileid(ascii_name, 30, relaxed, force_dots); } else { isoname = iso_2_fileid(ascii_name); } @@ -587,10 +590,11 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len, /* compute name and extension */ dot = strrchr(full_name, '.'); - if (dot != NULL && children[i]->type != ECMA119_DIR) { + if (dot != NULL && + (children[i]->type != ECMA119_DIR || img->allow_dir_id_ext)) { /* - * File (not dir) with extension + * File (normally not dir) with extension * Note that we don't need to check for placeholders, as * tree reparent happens later, so no placeholders can be * here at this time. @@ -630,10 +634,10 @@ int mangle_single_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len, name[max] = '\0'; } } else { - /* Directory, or file without extension */ + /* Directory (normally), or file without extension */ if (children[i]->type == ECMA119_DIR) { max = max_dir_len - digits; - dot = NULL; /* dots have no meaning in dirs */ + dot = NULL; /* dots (normally) have no meaning in dirs */ } else { max = max_file_len - digits; } diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index b7558d9..331d669 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -1372,6 +1372,22 @@ int iso_write_opts_set_aaip(IsoWriteOpts *opts, int enable); */ int iso_write_opts_set_untranslated_name_len(IsoWriteOpts *opts, int len); +/** + * Convert directory names for ECMA-119 similar to other file names, but do + * not force a dot or add a version number. + * This violates ECMA-119 by allowing one "." and especially ISO level 1 + * by allowing DOS style 8.3 names rather than only 8 characters. + * (mkisofs and its clones seem to do this violation.) + * @param opts + * The option set to be manipulated. + * @param allow + * 1= allow dots , 0= disallow dots and convert them + * @return + * 1 success, < 0 error + * @since 0.6.42 + */ +int iso_write_opts_set_allow_dir_id_ext(IsoWriteOpts *opts, int allow); + /** * Omit the version number (";1") at the end of the ISO-9660 identifiers. * This breaks ECMA-119 specification, but version numbers are usually not diff --git a/libisofs/libisofs.ver b/libisofs/libisofs.ver index 85ed462..dbf02ff 100644 --- a/libisofs/libisofs.ver +++ b/libisofs/libisofs.ver @@ -255,6 +255,7 @@ iso_write_opts_new; iso_write_opts_set_aaip; iso_write_opts_set_aaip_susp_1_10; iso_write_opts_set_allow_deep_paths; +iso_write_opts_set_allow_dir_id_ext; iso_write_opts_set_allow_full_ascii; iso_write_opts_set_allow_longer_paths; iso_write_opts_set_allow_lowercase;