New API call iso_write_opts_set_joliet_long_names()

This commit is contained in:
Thomas Schmitt 2011-03-26 15:38:08 +01:00
parent d8a56f60ef
commit 559e9b564d
8 changed files with 84 additions and 28 deletions

View File

@ -1650,6 +1650,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->allow_full_ascii = opts->allow_full_ascii; target->allow_full_ascii = opts->allow_full_ascii;
target->relaxed_vol_atts = opts->relaxed_vol_atts; target->relaxed_vol_atts = opts->relaxed_vol_atts;
target->joliet_longer_paths = opts->joliet_longer_paths; target->joliet_longer_paths = opts->joliet_longer_paths;
target->joliet_long_names = opts->joliet_long_names;
target->rrip_version_1_10 = opts->rrip_version_1_10; target->rrip_version_1_10 = opts->rrip_version_1_10;
target->rrip_1_10_px_ino = opts->rrip_1_10_px_ino; target->rrip_1_10_px_ino = opts->rrip_1_10_px_ino;
target->aaip_susp_1_10 = opts->aaip_susp_1_10; target->aaip_susp_1_10 = opts->aaip_susp_1_10;
@ -2641,6 +2642,15 @@ int iso_write_opts_set_joliet_longer_paths(IsoWriteOpts *opts, int allow)
return ISO_SUCCESS; return ISO_SUCCESS;
} }
int iso_write_opts_set_joliet_long_names(IsoWriteOpts *opts, int allow)
{
if (opts == NULL) {
return ISO_NULL_POINTER;
}
opts->joliet_long_names = allow ? 1 : 0;
return ISO_SUCCESS;
}
int iso_write_opts_set_rrip_version_1_10(IsoWriteOpts *opts, int oldvers) int iso_write_opts_set_rrip_version_1_10(IsoWriteOpts *opts, int oldvers)
{ {
if (opts == NULL) { if (opts == NULL) {

View File

@ -161,6 +161,11 @@ struct iso_write_opts {
*/ */
unsigned int joliet_longer_paths :1; unsigned int joliet_longer_paths :1;
/**
* Allow Joliet names up to 103 characters rather than 64.
*/
unsigned int joliet_long_names :1;
/** /**
* Write Rock Ridge info as of specification RRIP-1.10 rather than * Write Rock Ridge info as of specification RRIP-1.10 rather than
* RRIP-1.12: signature "RRIP_1991A" rather than "IEEE_1282", * RRIP-1.12: signature "RRIP_1991A" rather than "IEEE_1282",
@ -459,6 +464,9 @@ struct ecma119_image
/** Allow paths on Joliet tree to be larger than 240 bytes */ /** Allow paths on Joliet tree to be larger than 240 bytes */
unsigned int joliet_longer_paths :1; unsigned int joliet_longer_paths :1;
/** Allow Joliet names up to 103 characters rather than 64 */
unsigned int joliet_long_names :1;
/** Write old fashioned RRIP-1.10 rather than RRIP-1.12 */ /** Write old fashioned RRIP-1.10 rather than RRIP-1.12 */
unsigned int rrip_version_1_10 :1; unsigned int rrip_version_1_10 :1;

View File

@ -19,6 +19,7 @@
#include "filesrc.h" #include "filesrc.h"
#include "eltorito.h" #include "eltorito.h"
#include "libisofs.h" #include "libisofs.h"
#include "util.h"
#include <stdlib.h> #include <stdlib.h>
@ -42,12 +43,11 @@ int get_joliet_name(Ecma119Image *t, IsoNode *iso, uint16_t **name)
iso_msg_debug(t->image->id, "Can't convert %s", iso->name); iso_msg_debug(t->image->id, "Can't convert %s", iso->name);
return ret; return ret;
} }
/* TODO #00022 : support relaxed constraints in joliet filenames */
if (iso->type == LIBISO_DIR) { if (iso->type == LIBISO_DIR) {
jname = iso_j_dir_id(ucs_name); jname = iso_j_dir_id(ucs_name, t->joliet_long_names << 1);
} else { } else {
jname = iso_j_file_id(ucs_name, !!(t->no_force_dots & 2)); jname = iso_j_file_id(ucs_name,
(t->joliet_long_names << 1) | !!(t->no_force_dots & 2));
} }
free(ucs_name); free(ucs_name);
if (jname != NULL) { if (jname != NULL) {
@ -303,8 +303,15 @@ int joliet_create_mangled_name(uint16_t *dest, uint16_t *src, int digits,
int ret, pos; int ret, pos;
uint16_t *ucsnumber; uint16_t *ucsnumber;
char fmt[16]; char fmt[16];
char nstr[72]; /* The only caller of this function allocates dest with 66 char nstr[72];
elements and limits digits to < 8 */ /* was: The only caller of this function allocates dest
with 66 elements and limits digits to < 8
But this does not match the usage of nstr which has to take
the decimal representation of an int.
*/
if (digits >= 8)
return ISO_ASSERT_FAILURE;
sprintf(fmt, "%%0%dd", digits); sprintf(fmt, "%%0%dd", digits);
sprintf(nstr, fmt, number); sprintf(nstr, fmt, number);
@ -337,7 +344,7 @@ static
int mangle_single_dir(Ecma119Image *t, JolietNode *dir) int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
{ {
int ret; int ret;
int i, nchildren; int i, nchildren, maxchar = 64;
JolietNode **children; JolietNode **children;
IsoHTable *table; IsoHTable *table;
int need_sort = 0; int need_sort = 0;
@ -345,6 +352,9 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
nchildren = dir->info.dir->nchildren; nchildren = dir->info.dir->nchildren;
children = dir->info.dir->children; children = dir->info.dir->children;
if (t->joliet_long_names)
maxchar = 103;
/* a hash table will temporary hold the names, for fast searching */ /* a hash table will temporary hold the names, for fast searching */
ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash, ret = iso_htable_create((nchildren * 100) / 80, iso_str_hash,
(compare_function_t)ucscmp, &table); (compare_function_t)ucscmp, &table);
@ -361,7 +371,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
for (i = 0; i < nchildren; ++i) { for (i = 0; i < nchildren; ++i) {
uint16_t *name, *ext; uint16_t *name, *ext;
uint16_t full_name[66]; uint16_t full_name[LIBISO_JOLIET_NAME_MAX];
int max; /* computed max len for name, without extension */ int max; /* computed max len for name, without extension */
int j = i; int j = i;
int digits = 1; /* characters to change per name */ int digits = 1; /* characters to change per name */
@ -380,7 +390,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
* A max of 7 characters is good enought, it allows handling up to * A max of 7 characters is good enought, it allows handling up to
* 9,999,999 files with same name. * 9,999,999 files with same name.
*/ */
/* Important: joliet_create_mangled_name() relies on digits < 72 */ /* Important: joliet_create_mangled_name() relies on digits < 8 */
while (digits < 8) { while (digits < 8) {
int ok, k; int ok, k;
@ -403,7 +413,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
ext = dot + 1; ext = dot + 1;
extlen = ucslen(ext); extlen = ucslen(ext);
max = 65 - extlen - 1 - digits; max = maxchar + 1 - extlen - 1 - digits;
if (max <= 0) { if (max <= 0) {
/* this can happen if extension is too long */ /* this can happen if extension is too long */
if (extlen + max > 3) { if (extlen + max > 3) {
@ -413,7 +423,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
*/ */
extlen = extlen + max - 1; extlen = extlen + max - 1;
ext[extlen] = 0; ext[extlen] = 0;
max = 66 - extlen - 1 - digits; max = maxchar + 2 - extlen - 1 - digits;
} else { } else {
/* /*
* error, we don't support extensions < 3 * error, we don't support extensions < 3
@ -430,10 +440,10 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
} else { } else {
/* Directory, or file without extension */ /* Directory, or file without extension */
if (children[i]->type == JOLIET_DIR) { if (children[i]->type == JOLIET_DIR) {
max = 65 - digits; max = maxchar + 1 - digits;
dot = NULL; /* dots have no meaning in dirs */ dot = NULL; /* dots have no meaning in dirs */
} else { } else {
max = 65 - digits; max = maxchar + 1 - digits;
} }
name = full_name; name = full_name;
if (max < ucslen(name)) { if (max < ucslen(name)) {
@ -446,7 +456,7 @@ int mangle_single_dir(Ecma119Image *t, JolietNode *dir)
ok = 1; ok = 1;
/* change name of each file */ /* change name of each file */
for (k = i; k <= j; ++k) { for (k = i; k <= j; ++k) {
uint16_t tmp[66]; uint16_t tmp[LIBISO_JOLIET_NAME_MAX];
while (1) { while (1) {
ret = joliet_create_mangled_name(tmp, name, digits, ret = joliet_create_mangled_name(tmp, name, digits,
change, ext); change, ext);

View File

@ -18,6 +18,10 @@
#include "libisofs.h" #include "libisofs.h"
#include "ecma119.h" #include "ecma119.h"
/* was formerly 66 = 64 + 2. Now 105 = 103 + 2.
*/
#define LIBISO_JOLIET_NAME_MAX 105
enum joliet_node_type { enum joliet_node_type {
JOLIET_FILE, JOLIET_FILE,
JOLIET_DIR JOLIET_DIR

View File

@ -1585,6 +1585,15 @@ int iso_write_opts_set_relaxed_vol_atts(IsoWriteOpts *opts, int allow);
*/ */
int iso_write_opts_set_joliet_longer_paths(IsoWriteOpts *opts, int allow); int iso_write_opts_set_joliet_longer_paths(IsoWriteOpts *opts, int allow);
/**
* Allow leaf names in the Joliet tree to have up to 103 characters.
* Normal limit is 64.
* This breaks Joliet specification. Use with caution.
*
* @since 1.0.6
*/
int iso_write_opts_set_joliet_long_names(IsoWriteOpts *opts, int allow);
/** /**
* Write Rock Ridge info as of specification RRIP-1.10 rather than RRIP-1.12: * Write Rock Ridge info as of specification RRIP-1.10 rather than RRIP-1.12:
* signature "RRIP_1991A" rather than "IEEE_1282", field PX without file * signature "RRIP_1991A" rather than "IEEE_1282", field PX without file

View File

@ -282,6 +282,7 @@ iso_write_opts_set_hardlinks;
iso_write_opts_set_iso1999; iso_write_opts_set_iso1999;
iso_write_opts_set_iso_level; iso_write_opts_set_iso_level;
iso_write_opts_set_joliet; iso_write_opts_set_joliet;
iso_write_opts_set_joliet_long_names;
iso_write_opts_set_joliet_longer_paths; iso_write_opts_set_joliet_longer_paths;
iso_write_opts_set_max_37_char_filenames; iso_write_opts_set_max_37_char_filenames;
iso_write_opts_set_ms_block; iso_write_opts_set_ms_block;

View File

@ -16,6 +16,7 @@
#include "util.h" #include "util.h"
#include "libisofs.h" #include "libisofs.h"
#include "messages.h" #include "messages.h"
#include "joliet.h"
#include "../version.h" #include "../version.h"
#include <stdlib.h> #include <stdlib.h>
@ -916,16 +917,20 @@ ex:;
/* /*
bit0= no_force_dots bit0= no_force_dots
bit1= allow 103 characters rather than 64
*/ */
uint16_t *iso_j_file_id(const uint16_t *src, int flag) uint16_t *iso_j_file_id(const uint16_t *src, int flag)
{ {
uint16_t *dot; uint16_t *dot;
size_t lname, lext, lnname, lnext, pos, i; size_t lname, lext, lnname, lnext, pos, i, maxchar = 64;
uint16_t dest[66]; /* 66 = 64 (name + ext) + 1 (.) + 1 (\0) */ uint16_t dest[LIBISO_JOLIET_NAME_MAX];
/* was: 66 = 64 (name + ext) + 1 (.) + 1 (\0) */
if (src == NULL) { if (src == NULL) {
return NULL; return NULL;
} }
if (flag & 2)
maxchar = 103;
dot = ucsrchr(src, '.'); dot = ucsrchr(src, '.');
@ -937,14 +942,15 @@ uint16_t *iso_j_file_id(const uint16_t *src, int flag)
*/ */
if (dot == NULL || cmp_ucsbe(dot + 1, '\0') == 0) { if (dot == NULL || cmp_ucsbe(dot + 1, '\0') == 0) {
lname = ucslen(src); lname = ucslen(src);
lnname = (lname > 64) ? 64 : lname; lnname = (lname > maxchar) ? maxchar : lname;
lext = lnext = 0; lext = lnext = 0;
} else { } else {
lext = ucslen(dot + 1); lext = ucslen(dot + 1);
lname = ucslen(src) - lext - 1; lname = ucslen(src) - lext - 1;
lnext = (ucslen(src) > 65 && lext > 3) ? (lname < 61 ? 64 - lname : 3) lnext = (ucslen(src) > maxchar + 1 && lext > 3)
? (lname < maxchar - 3 ? maxchar - lname : 3)
: lext; : lext;
lnname = (ucslen(src) > 65) ? 64 - lnext : lname; lnname = (ucslen(src) > maxchar + 1) ? maxchar - lnext : lname;
} }
if (lnname == 0 && lnext == 0) { if (lnname == 0 && lnext == 0) {
@ -986,18 +992,22 @@ is_done:;
return ucsdup(dest); return ucsdup(dest);
} }
uint16_t *iso_j_dir_id(const uint16_t *src) /* @param flag bit1= allow 103 characters rather than 64
*/
uint16_t *iso_j_dir_id(const uint16_t *src, int flag)
{ {
size_t len, i; size_t len, i, maxchar = 64;
uint16_t dest[65]; /* 65 = 64 + 1 (\0) */ uint16_t dest[LIBISO_JOLIET_NAME_MAX]; /* was: 65 = 64 + 1 (\0) */
if (src == NULL) { if (src == NULL) {
return NULL; return NULL;
} }
if (flag & 2)
maxchar = 103;
len = ucslen(src); len = ucslen(src);
if (len > 64) { if (len > maxchar) {
len = 64; len = maxchar;
} }
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
uint16_t c = src[i]; uint16_t c = src[i];

View File

@ -153,13 +153,15 @@ char *iso_r_fileid(const char *src, size_t len, int relaxed, int forcedot);
/** /**
* Create a Joliet file identifier that consists of name and extension. The * Create a Joliet file identifier that consists of name and extension. The
* combined name and extension length will not exceed 128 bytes, and the * combined name and extension length will normally not exceed 64 characters
* name and extension will be separated (.). All characters consist of * (= 128 bytes). The name and the extension will be separated (.).
* 2 bytes and the resulting string is NULL-terminated by a 2-byte NULL. * All characters consist of 2 bytes and the resulting string is
* NULL-terminated by a 2-byte NULL.
* *
* Note that version number and (;1) is not appended. * Note that version number and (;1) is not appended.
* @param flag * @param flag
* bit0= no_force_dots * bit0= no_force_dots
* bit1= allow 103 characters rather than 64
* @return * @return
* NULL if the original name and extension both are of length 0. * NULL if the original name and extension both are of length 0.
*/ */
@ -171,10 +173,12 @@ uint16_t *iso_j_file_id(const uint16_t *src, int flag);
* and the name and extension will be separated (.). All characters consist of * and the name and extension will be separated (.). All characters consist of
* 2 bytes and the resulting string is NULL-terminated by a 2-byte NULL. * 2 bytes and the resulting string is NULL-terminated by a 2-byte NULL.
* *
* @param flag
* bit1= allow 103 characters rather than 64
* @return * @return
* NULL if the original name and extension both are of length 0. * NULL if the original name and extension both are of length 0.
*/ */
uint16_t *iso_j_dir_id(const uint16_t *src); uint16_t *iso_j_dir_id(const uint16_t *src, int flag);
/** /**
* Like strlen, but for Joliet strings. * Like strlen, but for Joliet strings.