Implemented relaxed iso constraints & Cunit based unit-tests
This commit is contained in:
@ -269,45 +269,62 @@ calc_file_pos(struct ecma119_write_target *t,
|
||||
t->curfile = 0;
|
||||
}
|
||||
|
||||
struct ecma119_write_target*
|
||||
|
||||
/**
|
||||
* Create a new ecma119_write_target from the given volume number of the
|
||||
* given volume set.
|
||||
*
|
||||
* \pre \p volnum is less than \p volset-\>volset_size.
|
||||
* \post For each node in the tree, writer_data has been allocated.
|
||||
* \post The directory heirarchy has been reorganised to be ecma119-compatible.
|
||||
*/
|
||||
static struct ecma119_write_target*
|
||||
ecma119_target_new(struct iso_volset *volset,
|
||||
int volnum,
|
||||
int level,
|
||||
int flags)
|
||||
const struct ecma119_source_opts *opts)
|
||||
{
|
||||
struct ecma119_write_target *t =
|
||||
calloc(1, sizeof(struct ecma119_write_target));
|
||||
size_t i, j, cur;
|
||||
struct iso_tree_node *iso_root =
|
||||
(struct iso_tree_node*) volset->volume[volnum]->root;
|
||||
(struct iso_tree_node*) volset->volume[opts->volnum]->root;
|
||||
|
||||
//TODO default values here, need an API for this
|
||||
t->cache_inodes = 1;
|
||||
t->replace_mode = 1;
|
||||
t->dir_mode = 0555;
|
||||
t->file_mode = 0444;
|
||||
t->gid = 0;
|
||||
t->uid = 0;
|
||||
t->input_charset = "UTF-8";
|
||||
t->ouput_charset = "UTF-8";
|
||||
t->sort_files = 1;
|
||||
t->cache_inodes = opts->no_cache_inodes ? 0 : 1;
|
||||
t->replace_mode = opts->default_mode ? 0 : 1;
|
||||
if ( opts->replace_dir_mode )
|
||||
t->replace_mode |= 0x02;
|
||||
if ( opts->replace_file_mode )
|
||||
t->replace_mode |= 0x04;
|
||||
if ( opts->replace_gid )
|
||||
t->replace_mode |= 0x08;
|
||||
if ( opts->replace_uid )
|
||||
t->replace_mode |= 0x10;
|
||||
t->dir_mode = opts->dir_mode;
|
||||
t->file_mode = opts->file_mode;
|
||||
t->gid = opts->gid;
|
||||
t->uid = opts->uid;
|
||||
|
||||
//TODO get defailt values for current locale, no UTF-8
|
||||
t->input_charset = opts->input_charset ? opts->input_charset : "UTF-8";
|
||||
t->ouput_charset = opts->ouput_charset ? opts->ouput_charset : "UTF-8";
|
||||
t->sort_files = opts->sort_files;
|
||||
|
||||
t->file_table = iso_file_table_new(t->cache_inodes);
|
||||
volset->refcount++;
|
||||
t->iso_level = level;
|
||||
t->iso_level = opts->level;
|
||||
t->block_size = 2048;
|
||||
t->relaxed_constraints = opts->relaxed_constraints;
|
||||
|
||||
t->rockridge = (flags & ECMA119_ROCKRIDGE) ? 1 : 0;
|
||||
t->joliet = (flags & ECMA119_JOLIET) ? 1 : 0;
|
||||
t->rockridge = (opts->flags & ECMA119_ROCKRIDGE) ? 1 : 0;
|
||||
t->joliet = (opts->flags & ECMA119_JOLIET) ? 1 : 0;
|
||||
|
||||
t->catalog = volset->volume[volnum]->bootcat;
|
||||
t->catalog = volset->volume[opts->volnum]->bootcat;
|
||||
t->eltorito = t->catalog ? 1 : 0;
|
||||
|
||||
t->root = ecma119_tree_create(t, iso_root);
|
||||
if (t->joliet)
|
||||
t->joliet_root = joliet_tree_create(t, iso_root);
|
||||
t->volset = volset;
|
||||
t->volnum = volnum;
|
||||
t->volnum = opts->volnum;
|
||||
t->now = time(NULL);
|
||||
|
||||
if (t->rockridge)
|
||||
@ -811,15 +828,13 @@ bs_free_data(struct burn_source *bs)
|
||||
}
|
||||
|
||||
struct burn_source *iso_source_new_ecma119(struct iso_volset *volset,
|
||||
int volnum,
|
||||
int level,
|
||||
int flags)
|
||||
struct ecma119_source_opts *opts)
|
||||
{
|
||||
struct burn_source *ret = calloc(1, sizeof(struct burn_source));
|
||||
ret->refcount = 1;
|
||||
ret->read = bs_read;
|
||||
ret->get_size = bs_get_size;
|
||||
ret->free_data = bs_free_data;
|
||||
ret->data = ecma119_target_new(volset, volnum, level, flags);
|
||||
ret->data = ecma119_target_new(volset, opts);
|
||||
return ret;
|
||||
}
|
||||
|
@ -65,6 +65,8 @@ struct ecma119_write_target
|
||||
unsigned int iso_level:2;
|
||||
unsigned int eltorito:1;
|
||||
|
||||
int relaxed_constraints; /**< see ecma119_relaxed_constraints_flag */
|
||||
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
|
||||
int replace_mode; /**< Replace ownership and modes of files
|
||||
@ -168,19 +170,6 @@ struct ecma119_write_target
|
||||
} state_files;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new ecma119_write_target from the given volume number of the
|
||||
* given volume set.
|
||||
*
|
||||
* \pre \p volnum is less than \p volset-\>volset_size.
|
||||
* \post For each node in the tree, writer_data has been allocated.
|
||||
* \post The directory heirarchy has been reorganised to be ecma119-compatible.
|
||||
*/
|
||||
struct ecma119_write_target *ecma119_target_new(struct iso_volset *volset,
|
||||
int volnum,
|
||||
int level,
|
||||
int flags);
|
||||
|
||||
#define BP(a,b) [(b) - (a) + 1]
|
||||
|
||||
struct ecma119_pri_vol_desc
|
||||
|
@ -74,12 +74,23 @@ create_ecma119_node(struct ecma119_write_target *t,
|
||||
char *(*iso_name)(const char *, const char *) = ISO_ISDIR(iso) ?
|
||||
((t->iso_level == 1) ? iso_1_dirid : iso_2_dirid)
|
||||
: ((t->iso_level == 1) ? iso_1_fileid : iso_2_fileid);
|
||||
char *(*iso_r_name)(const char *, const char *, int) =
|
||||
ISO_ISDIR(iso) ? iso_r_dirid : iso_r_fileid;
|
||||
|
||||
assert(t && (!parent || parent->type == ECMA119_DIR) && iso );
|
||||
|
||||
ret = calloc(1, sizeof(struct ecma119_tree_node));
|
||||
|
||||
ret->iso_name = iso->name ? iso_name(iso->name, t->input_charset) : NULL;
|
||||
/*
|
||||
* If selected one ISO relaxed constraints other than NO_DIR_REALOCATION,
|
||||
* we use the function that computes the relaxed name, otherwise normal
|
||||
* function for specified level is used.
|
||||
*/
|
||||
ret->iso_name = iso->name ?
|
||||
( t->relaxed_constraints & ~ECMA119_NO_DIR_REALOCATION ?
|
||||
iso_r_name(iso->name, t->input_charset, t->relaxed_constraints) :
|
||||
iso_name(iso->name, t->input_charset)
|
||||
) : NULL;
|
||||
ret->dirent_len = calc_dirent_len(ret);
|
||||
ret->attrib = iso->attrib;
|
||||
if ( t->rockridge && t->replace_mode )
|
||||
@ -507,7 +518,8 @@ ecma119_tree_create(struct ecma119_write_target *t,
|
||||
struct iso_tree_node *iso_root)
|
||||
{
|
||||
t->root = create_tree(t, NULL, iso_root);
|
||||
reorder_tree(t, t->root, t->root);
|
||||
if ( !(t->relaxed_constraints & ECMA119_NO_DIR_REALOCATION) )
|
||||
reorder_tree(t, t->root, t->root);
|
||||
sort_tree(t->root);
|
||||
mangle_all(t->root);
|
||||
return t->root;
|
||||
|
@ -64,6 +64,69 @@ enum eltorito_boot_media_type {
|
||||
ELTORITO_NO_EMUL
|
||||
};
|
||||
|
||||
enum ecma119_relaxed_constraints_flag {
|
||||
ECMA119_OMIT_VERSION_NUMBERS = (1<<0),
|
||||
/* 37 char filenames involves no version number */
|
||||
ECMA119_37_CHAR_FILENAMES = (1<<1) | (1<<0),
|
||||
ECMA119_NO_DIR_REALOCATION = (1<<2),
|
||||
ECMA119_RELAXED_FILENAMES = (1<<3)
|
||||
};
|
||||
|
||||
/**
|
||||
* Holds the options for the image generation.
|
||||
*/
|
||||
struct ecma119_source_opts {
|
||||
int volnum; /**< The volume in the set which you want to write (usually 0) */
|
||||
int level; /**< ISO level to write at. */
|
||||
int flags; /**< Which extensions to support. */
|
||||
int relaxed_constraints; /**< see ecma119_relaxed_constraints_flag */
|
||||
unsigned int no_cache_inodes:1;
|
||||
/**< If use inode caching or not. Set it to 1 to prevent
|
||||
* inode caching.
|
||||
* Usage of inode caching allows detection of hard-links,
|
||||
* which contents are only written once to disc this way.
|
||||
* Don't use inode caching in systems with non unique inodes
|
||||
* per device.
|
||||
*/
|
||||
unsigned int sort_files:1;
|
||||
/**< If files should be sorted based on their weight. */
|
||||
unsigned int default_mode:1;
|
||||
/**<
|
||||
* The default values for files and directory permissions,
|
||||
* gid and uid. This option can be overwritten when set
|
||||
* one of the following.
|
||||
* 0 to use useful values, 1 to use node modes (this are
|
||||
* the same as filesystem ones if not changed after added
|
||||
* to tree).
|
||||
*/
|
||||
unsigned int replace_dir_mode:1;
|
||||
/**<
|
||||
* When 1, permissions for all dirs will be replaced by the
|
||||
* specified in dir_mode field.
|
||||
*/
|
||||
unsigned int replace_file_mode:1;
|
||||
/**<
|
||||
* When 1, permissions for all files will be replaced by the
|
||||
* specified in file_mode field.
|
||||
*/
|
||||
unsigned int replace_uid:1;
|
||||
/**<
|
||||
* When 1, uid of all nodes (both files and dirs) will be
|
||||
* replaced by the specified in uid field.
|
||||
*/
|
||||
unsigned int replace_gid:1;
|
||||
/**<
|
||||
* When 1, gid of all nodes (both files and dirs) will be
|
||||
* replaced by the specified in gid field.
|
||||
*/
|
||||
mode_t dir_mode; /**< Mode to use on dirs when replace_dir_mode is set. */
|
||||
mode_t file_mode; /**< Mode to use on files when replace_file_mode is set. */
|
||||
gid_t gid; /**< gid to use when replace_gid is set. */
|
||||
uid_t uid; /**< uid to use when replace_uid is set. */
|
||||
char *input_charset; /**< NULL to use default charset */
|
||||
char *ouput_charset; /**< NULL to use default charset */
|
||||
};
|
||||
|
||||
/**
|
||||
* This will hold the error code for some functions, if them fail.
|
||||
*/
|
||||
@ -433,33 +496,19 @@ void iso_tree_node_set_sort_weight(struct iso_tree_node *node, int w);
|
||||
*/
|
||||
void iso_tree_print(const struct iso_tree_node *root, int spaces);
|
||||
|
||||
|
||||
/**
|
||||
* Holds the options for the image generation.
|
||||
*/
|
||||
//struct ecma119_source_opts {
|
||||
// int volnum; /**< The volume in the set which you want to write (usually 0) */
|
||||
// int level; /**< ISO level to write at. */
|
||||
// int flags; /**< Which extensions to support. */
|
||||
//};
|
||||
|
||||
/** Create a burn_source which can be used as a data source for a track
|
||||
*
|
||||
* The volume set used to create the libburn_source can _not_ be modified
|
||||
* until the libburn_source is freed.
|
||||
*
|
||||
* \param volumeset The volume set from which you want to write
|
||||
* \param volnum The volume in the set which you want to write (usually 0)
|
||||
* \param level ISO level to write at.
|
||||
* \param flags Which extensions to support.
|
||||
* \param opts The options for image generation
|
||||
*
|
||||
* \pre \p volumeset is non-NULL
|
||||
* \pre \p volnum is less than \p volset->volset_size.
|
||||
* \return A burn_source to be used for the data source for a track
|
||||
*/
|
||||
struct burn_source* iso_source_new_ecma119 (struct iso_volset *volumeset,
|
||||
int volnum,
|
||||
int level,
|
||||
int flags);
|
||||
struct burn_source* iso_source_new_ecma119(struct iso_volset *volumeset,
|
||||
struct ecma119_source_opts *opts);
|
||||
|
||||
#endif /* LIBISO_LIBISOFS_H */
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <limits.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "libisofs.h"
|
||||
|
||||
/* avoids warning and names in iso, joliet and rockridge can't be > 255 bytes
|
||||
* anyway. There are at most 31 characters in iso level 1, 255 for rockridge,
|
||||
@ -401,6 +402,33 @@ char *iso_2_dirid(const char *src, const char *icharset)
|
||||
return iso_dirid(src, 31, icharset);
|
||||
}
|
||||
|
||||
char *iso_r_dirid(const char *src, const char *icharset, int flags)
|
||||
{
|
||||
char *ret = str2ascii(src, icharset);
|
||||
size_t size, len, i;
|
||||
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
size = flags & ECMA119_37_CHAR_FILENAMES ? 37 : 31;
|
||||
|
||||
len = strlen(ret);
|
||||
if (len > size) {
|
||||
ret[size] = '\0';
|
||||
len = size;
|
||||
}
|
||||
|
||||
if (flags & ECMA119_RELAXED_FILENAMES)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
char c = toupper(ret[i]);
|
||||
ret[i] = valid_d_char(c) ? c : '_';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *iso_1_fileid(const char *src_arg, const char *icharset)
|
||||
{
|
||||
char *src = str2ascii(src_arg, icharset);
|
||||
@ -470,7 +498,7 @@ char *iso_2_fileid(const char *src_arg, const char *icharset)
|
||||
extension, we need to calculate their new lengths (lnname and
|
||||
lnext). If the original filename is too long, we start by trimming
|
||||
the extension, but keep a minimum extension length of 3. */
|
||||
if (dot == NULL || dot == src || *(dot + 1) == '\0') {
|
||||
if (dot == NULL || *(dot + 1) == '\0') {
|
||||
lname = strlen(src);
|
||||
lnname = (lname > 30) ? 30 : lname;
|
||||
lext = lnext = 0;
|
||||
@ -511,6 +539,85 @@ char *iso_2_fileid(const char *src_arg, const char *icharset)
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *
|
||||
iso_r_fileid(const char *src_arg, const char *icharset, int flag)
|
||||
{
|
||||
char *src = str2ascii(src_arg, icharset);
|
||||
char *dest;
|
||||
char *dot;
|
||||
int lname, lext, lnname, lnext, pos, i;
|
||||
|
||||
size_t size = flag & (1<<1) ? 37 : 33;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
dest = malloc(size+1);
|
||||
|
||||
if (flag & ECMA119_RELAXED_FILENAMES) {
|
||||
strncpy(dest, src, size);
|
||||
dest[size] = '\0'; /* ensure 37 / 33 max length */
|
||||
pos = strlen(dest);
|
||||
pos = pos < (size == 37 ? 37 : 31) ? pos : (size == 37 ? 37 : 31);
|
||||
if ( !(flag & ECMA119_OMIT_VERSION_NUMBERS) ) {
|
||||
dest[pos++] = ';';
|
||||
dest[pos++] = '1';
|
||||
}
|
||||
dest[pos] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* no relaxed filenames */
|
||||
dot = strrchr(src, '.');
|
||||
|
||||
size_t max = size == 37 ? 36 : 30;
|
||||
/* Since the maximum length can be divided freely over the name and
|
||||
extension, we need to calculate their new lengths (lnname and
|
||||
lnext). If the original filename is too long, we start by trimming
|
||||
the extension, but keep a minimum extension length of 3. */
|
||||
if (dot == NULL || *(dot + 1) == '\0') {
|
||||
lname = strlen(src);
|
||||
lnname = (lname > max) ? max : lname;
|
||||
lext = lnext = 0;
|
||||
} else {
|
||||
lext = strlen(dot + 1);
|
||||
lname = strlen(src) - lext - 1;
|
||||
lnext = (strlen(src) > max + 1 && lext > 3)
|
||||
? (lname < max - 3 ? max - lname : 3) : lext;
|
||||
lnname = (strlen(src) > max +1) ? max - lnext : lname;
|
||||
}
|
||||
|
||||
if (lnname == 0 && lnext == 0) {
|
||||
free(src);
|
||||
free(dest);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
/* Convert up to lnname characters of the filename. */
|
||||
for (i = 0; i < lnname; i++) {
|
||||
char c = toupper(src[i]);
|
||||
|
||||
dest[pos++] = valid_d_char(c) ? c : '_';
|
||||
}
|
||||
dest[pos++] = '.';
|
||||
/* Convert up to lnext characters of the extension, if any. */
|
||||
for (i = 0; i < lnext; i++) {
|
||||
char c = toupper(src[lname + 1 + i]);
|
||||
|
||||
dest[pos++] = valid_d_char(c) ? c : '_';
|
||||
}
|
||||
if ( !(flag & ECMA119_OMIT_VERSION_NUMBERS) ) {
|
||||
dest[pos++] = ';';
|
||||
dest[pos++] = '1';
|
||||
}
|
||||
dest[pos] = '\0';
|
||||
dest = (char *)realloc(dest, pos + 1);
|
||||
|
||||
free(src);
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *
|
||||
iso_p_fileid(const char *src, const char *icharset)
|
||||
{
|
||||
|
@ -49,6 +49,11 @@ char *iso_1_dirid(const char *src, const char *);
|
||||
*/
|
||||
char *iso_2_dirid(const char *src, const char *);
|
||||
|
||||
/**
|
||||
* Create a directory identifier with relaxed constraints
|
||||
*/
|
||||
char *iso_r_dirid(const char *src, const char *icharset, int flags);
|
||||
|
||||
/**
|
||||
* Create a level 1 file identifier that consists of a name, extension and
|
||||
* version number. The resulting string will have a file name of maximum
|
||||
@ -67,6 +72,11 @@ char *iso_1_fileid(const char *src, const char *);
|
||||
*/
|
||||
char *iso_2_fileid(const char *src, const char *);
|
||||
|
||||
/**
|
||||
* Create a file identifier with relaxed constraints.
|
||||
*/
|
||||
char *iso_r_fileid(const char *src, const char *icharset, int flags);
|
||||
|
||||
/**
|
||||
* Create a Joliet file or directory identifier that consists of a name,
|
||||
* extension and version number. The combined name and extension length will
|
||||
|
Reference in New Issue
Block a user