diff --git a/libisofs/ecma119.c b/libisofs/ecma119.c index d1d3d8d..a6cf556 100644 --- a/libisofs/ecma119.c +++ b/libisofs/ecma119.c @@ -3492,3 +3492,102 @@ int iso_write_opts_set_hfsp_block_size(IsoWriteOpts *opts, } +/* + * @param flag + * Bitfield for control purposes. + * bit0-bit7= Name space + * 0= generic (to_charset is valid, no reserved characters, + * no length limits) + * 1= Rock Ridge (to_charset is valid) + * 2= Joliet (to_charset gets overriden by UCS-2 or UTF-16) + * 3= ECMA-119 (dull ISO 9660 character set) + * 4= HFS+ (to_charset gets overridden by UTF-16BE) + * bit15= Reverse operation (best to be done only with results of + * previous conversions) + */ +int iso_conv_name_chars(IsoWriteOpts *opts, char *in_name, size_t name_len, + char **result, size_t *result_len, int flag) +{ + int name_space, ret, reverse; + size_t i; + char *from_charset, *to_charset, *conved = NULL, *smashed = NULL, *name; + char *tr; + size_t conved_len; + uint16_t *ucs; + + name = in_name; + from_charset = iso_get_local_charset(0); + name_space = flag & 0xff; + reverse = !!(flag & (1 << 15)); + if (name_space == 0) { /* generic */ + to_charset = opts->output_charset; + + } else if (name_space == 1) { /* Rock Ridge */ + to_charset = opts->output_charset; + if (!reverse) { + LIBISO_ALLOC_MEM(smashed, char, name_len + 1); + memcpy(smashed, name, name_len); + smashed[name_len] = 0; + for (i = 0; i < name_len; i++) + if (smashed[i] == '/') + smashed[i] = '_'; + name = smashed; + + /* >>> ??? truncate to 255 chars */ + } + + } else if (name_space == 2) { /* Joliet */ + if (opts->joliet_utf16) + to_charset = "UTF-16BE"; + else + to_charset = "UCS-2BE"; + /* ( Smashing happens after conversion ) */ + + } else if (name_space == 3) { /* ECMA-119 */ + to_charset = "ASCII"; + + /* >>> ??? Use an IsoWriteOpts+char of get_iso_name() */ + + } else if (name_space == 4) { /* HFS+ */ + to_charset= "UTF-16BE"; + + /* >>> ??? any other conversions for HFS+ ? */; + + } else { + ret = ISO_WRONG_ARG_VALUE; + goto ex; + } + if (reverse) { + tr = from_charset; + from_charset = to_charset; + to_charset = tr; + } + + ret = strnconvl(name, from_charset, to_charset, name_len, + &conved, &conved_len); + if (ret != ISO_SUCCESS) + goto ex; + + if (name_space == 2 && !reverse) { /* Joliet */ + + /* >>> ??? Rather use iso_j_dir_id()/iso_j_file_id() + ??? Or even an IsoWriteOpts version of get_joliet_name() ? + */ + + ucs = (uint16_t *) conved; + iso_smash_chars_for_joliet(ucs); + } else if (name_space == 3 && !reverse) { /* ECMA-119 */ + + /* >>> smash all forbidden characters ? (or use get_iso_name() ) */; + + } + + *result = conved; + *result_len = conved_len; + return ISO_SUCCESS; +ex: + LIBISO_FREE_MEM(smashed); + return ret; +} + + diff --git a/libisofs/fs_image.c b/libisofs/fs_image.c index 1cc2968..f9ac389 100644 --- a/libisofs/fs_image.c +++ b/libisofs/fs_image.c @@ -1258,6 +1258,9 @@ char *get_name(_ImageFsData *fsdata, const char *str, size_t len) return NULL; /* aborted */ } /* fallback */ + + /* >>> create a hopefully unique name */; + } } diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 497bc5b..a1fff9e 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -7109,6 +7109,51 @@ int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes, int *bless_max, int flag); +/* ----------------------------- Character sets ---------------------------- */ + +/** + * >>> *** NOT COMPLETELY IMPLEMENTED YET *** + * >>> Convert the characters in name from local charset to another charset or + * >>> to the representation of a particular ISO image name space. + * >>> In the latter case it is assumed that the conversion result does not + * >>> collide with any other converted name in the same directory. + * >>> I.e. this function does not take into respect possible name changes + * >>> due to collision handling. + * + * @param opts + * Defines output charset, UCS-2 versus UTF-16 for Joliet, + * and naming restrictions. + * @param name + * The input text which shall be converted. + * @param result + * Will return the conversion result. Terminated by a trailing zero byte. + * Use free() to dispose it when no longer needed. + * @param result_len + * Will return the number of bytes in result (excluding trailing zero) + * @param flag + * Bitfield for control purposes. + * bit0-bit7= Name space + * 0= generic (to_charset is valid, + * no reserved characters, no length limits) + * 1= Rock Ridge (to_charset is valid) + * 2= Joliet (to_charset gets overridden by UCS-2 or UTF-16) + * 3= ECMA-119 (to_charset gets overridden by + * dull ISO 9660 subset of ASCII) + * 4= HFS+ (to_charset gets overridden by UTF-16BE) + * bit8= Input text is a directory name + * (matters for Joliet and ECMA-119) + * bit15= Reverse operation (best to be done only with results of + * previous conversions) + * @return + * 1 means success, <0 means error + * + * @since 1.3.6 + */ +int iso_conv_name_chars(IsoWriteOpts *opts, char *name, size_t name_len, + char **result, size_t *result_len, int flag); + + + /************ Error codes and return values for libisofs ********************/ /** successfully execution */ diff --git a/libisofs/libisofs.ver b/libisofs/libisofs.ver index 79bc576..b4f605f 100644 --- a/libisofs/libisofs.ver +++ b/libisofs/libisofs.ver @@ -19,6 +19,7 @@ el_torito_set_load_seg; el_torito_set_load_size; el_torito_set_no_bootable; el_torito_set_selection_crit; +iso_conv_name_chars; iso_data_source_new_from_file; iso_data_source_ref; iso_data_source_unref; diff --git a/libisofs/util.c b/libisofs/util.c index 0250d40..2d79411 100644 --- a/libisofs/util.c +++ b/libisofs/util.c @@ -241,8 +241,8 @@ ex:; return retval; } -int strnconv(const char *str, const char *icharset, const char *ocharset, - size_t len, char **output) +int strnconvl(const char *str, const char *icharset, const char *ocharset, + size_t len, char **output, size_t *out_len) { size_t inbytes; size_t outbytes; @@ -291,6 +291,15 @@ ex:; return retval; } +int strnconv(const char *str, const char *icharset, const char *ocharset, + size_t len, char **output) +{ + size_t l; + + return strnconvl(str, icharset, ocharset, len, output, &l); +} + + /** * Convert a str in a specified codeset to WCHAR_T. * The result must be free() when no more needed @@ -2227,3 +2236,13 @@ void iso_handle_split_utf16(uint16_t *utf_word) set_ucsbe(utf_word, '_'); } + +void iso_smash_chars_for_joliet(uint16_t *name) +{ + size_t i; + + for (i = 0; name[i] != 0; i++) + if (! valid_j_char(name[i])) + set_ucsbe(name + i, '_'); +} + diff --git a/libisofs/util.h b/libisofs/util.h index 2e9321d..f311333 100644 --- a/libisofs/util.h +++ b/libisofs/util.h @@ -56,9 +56,16 @@ int iso_init_locale(int flag); int strconv(const char *input, const char *icharset, const char *ocharset, char **output); +/* Like strconv but processing len input bytes rather than strlen(input) + */ int strnconv(const char *str, const char *icharset, const char *ocharset, size_t len, char **output); +/* Like strnconv but also returning the number of bytes in *output. + */ +int strnconvl(const char *str, const char *icharset, const char *ocharset, + size_t len, char **output, size_t *out_len); + /** * Convert a given string from any input charset to ASCII * @@ -204,6 +211,11 @@ uint16_t *iso_j_file_id(const uint16_t *src, int flag); */ uint16_t *iso_j_dir_id(const uint16_t *src, int flag); +/** + * Maps forbidden Joliet characters to UCS-2 '_' + */ +void iso_smash_chars_for_joliet(uint16_t *name); + /** * Like strlen, but for Joliet strings. */