Handle reallocation of directories.
This commit is contained in:
parent
ca1385cce1
commit
041858360a
@ -72,6 +72,10 @@ print_dir(Ecma119Node *dir, int level)
|
||||
printf("%s-[S] ", sp);
|
||||
print_permissions(iso_node_get_permissions(child->node));
|
||||
printf(" %s\n", child->iso_name);
|
||||
} else if (child->type == ECMA119_PLACEHOLDER) {
|
||||
printf("%s-[RD] ", sp);
|
||||
print_permissions(iso_node_get_permissions(child->node));
|
||||
printf(" %s\n", child->iso_name);
|
||||
} else {
|
||||
printf("%s-[????] ", sp);
|
||||
}
|
||||
|
@ -632,6 +632,7 @@ int ecma119_image_new(IsoImage *src, Ecma119WriteOpts *opts,
|
||||
target->iso_level = opts->level;
|
||||
target->rockridge = 1; //TODO
|
||||
target->omit_version_numbers = opts->omit_version_numbers;
|
||||
target->allow_deep_paths = 0; //TODO
|
||||
target->sort_files = opts->sort_files;
|
||||
|
||||
target->now = time(NULL);
|
||||
|
@ -34,6 +34,7 @@ struct ecma119_image {
|
||||
|
||||
/* relaxed constraints */
|
||||
unsigned int omit_version_numbers:1;
|
||||
unsigned int allow_deep_paths:1;
|
||||
|
||||
// int relaxed_constraints; /**< see ecma119_relaxed_constraints_flag */
|
||||
//
|
||||
|
@ -229,8 +229,8 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
|
||||
return ret;
|
||||
}
|
||||
max_path = pathlen + 1 + (iso_name ? strlen(iso_name) : 0);
|
||||
if (!image->rockridge) { //TODO !rockridge && !relaxed_paths
|
||||
if (depth > 8 || max_path > 255) {
|
||||
if (!image->rockridge && !image->allow_deep_paths) {
|
||||
if ((iso->type == LIBISO_DIR && depth > 8) || max_path > 255) {
|
||||
iso_msg_note(image->image, LIBISO_FILE_IGNORED,
|
||||
"File \"%s\" can't be added, because depth > 8 "
|
||||
"or path length over 255", iso->name);
|
||||
@ -553,6 +553,144 @@ int mangle_tree(Ecma119Image *img)
|
||||
return mangle_dir(img, img->root, max_file, max_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ECMA-119 node representing a placeholder for a relocated
|
||||
* dir.
|
||||
*
|
||||
* See IEEE P1282, section 4.1.5 for details
|
||||
*/
|
||||
static
|
||||
int create_placeholder(Ecma119Node *parent,
|
||||
Ecma119Node *real, Ecma119Node **node)
|
||||
{
|
||||
Ecma119Node *ret;
|
||||
|
||||
ret = calloc(1, sizeof(Ecma119Node));
|
||||
if (ret == NULL) {
|
||||
return ISO_MEM_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO
|
||||
* If real is a dir, while placeholder is a file, ISO name restricctions
|
||||
* are different, what to do?
|
||||
*/
|
||||
ret->iso_name = strdup(real->iso_name);
|
||||
if (ret->iso_name == NULL) {
|
||||
free(ret);
|
||||
return ISO_MEM_ERROR;
|
||||
}
|
||||
|
||||
/* take a ref to the IsoNode */
|
||||
ret->node = real->node;
|
||||
iso_node_ref(real->node);
|
||||
ret->parent = parent;
|
||||
ret->type = ECMA119_PLACEHOLDER;
|
||||
ret->info.real_me = real;
|
||||
|
||||
*node = ret;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
size_t max_child_name_len(Ecma119Node *dir)
|
||||
{
|
||||
size_t ret = 0, i;
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
size_t len = strlen(dir->info.dir.children[i]->iso_name);
|
||||
ret = MAX(ret, len);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Relocates a directory, as specified in Rock Ridge Specification
|
||||
* (see IEEE P1282, section 4.1.5). This is needed when the number of levels
|
||||
* on a directory hierarchy exceeds 8, or the length of a path is higher
|
||||
* than 255 characters, as specified in ECMA-119, section 6.8.2.1
|
||||
*/
|
||||
static
|
||||
int reparent(Ecma119Node *child, Ecma119Node *parent)
|
||||
{
|
||||
int ret;
|
||||
size_t i;
|
||||
Ecma119Node *placeholder;
|
||||
|
||||
/* replace the child in the original parent with a placeholder */
|
||||
for ( i = 0; i < child->parent->info.dir.nchildren; i++) {
|
||||
if (child->parent->info.dir.children[i] == child) {
|
||||
ret = create_placeholder(child->parent, child, &placeholder);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
child->parent->info.dir.children[i] = placeholder;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* just for debug, this should never happen... */
|
||||
if (i == child->parent->info.dir.nchildren) {
|
||||
return ISO_ERROR;
|
||||
}
|
||||
|
||||
/* add the child to its new parent */
|
||||
child->parent = parent;
|
||||
parent->info.dir.nchildren++;
|
||||
parent->info.dir.children = realloc( parent->info.dir.children,
|
||||
sizeof(void*) * parent->info.dir.nchildren );
|
||||
parent->info.dir.children[parent->info.dir.nchildren - 1] = child;
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder the tree, if necessary, to ensure that
|
||||
* - the depth is at most 8
|
||||
* - each path length is at most 255 characters
|
||||
* This restriction is imposed by ECMA-119 specification (ECMA-119, 6.8.2.1).
|
||||
*
|
||||
* @param dir
|
||||
* Dir we are currently processing
|
||||
* @param level
|
||||
* Level of the directory in the hierarchy
|
||||
* @param pathlen
|
||||
* Length of the path until dir, including it
|
||||
* @return
|
||||
* 1 success, < 0 error
|
||||
*/
|
||||
static
|
||||
int reorder_tree(Ecma119Image *img, Ecma119Node *dir, int level, int pathlen)
|
||||
{
|
||||
int ret;
|
||||
size_t max_path;
|
||||
|
||||
max_path = pathlen + 1 + max_child_name_len(dir);
|
||||
|
||||
if (level > 8 || max_path > 255) {
|
||||
ret = reparent(dir, img->root);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* we are appended to the root's children now, so there is no
|
||||
* need to recurse (the root will hit us again)
|
||||
*/
|
||||
} else {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
Ecma119Node *child = dir->info.dir.children[i];
|
||||
if (child->type == ECMA119_DIR) {
|
||||
int newpathlen = pathlen + 1 + strlen(child->iso_name);
|
||||
ret = reorder_tree(img, child, level + 1, newpathlen);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ISO_SUCCESS;
|
||||
}
|
||||
|
||||
int ecma119_tree_create(Ecma119Image *img)
|
||||
{
|
||||
@ -578,6 +716,11 @@ int ecma119_tree_create(Ecma119Image *img)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (img->rockridge && !img->allow_deep_paths) {
|
||||
/* reorder the tree, acording to RRIP, 4.1.5 */
|
||||
reorder_tree(img, img->root, 1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO
|
||||
* - reparent if RR
|
||||
|
@ -47,11 +47,13 @@ struct ecma119_node
|
||||
|
||||
IsoNode *node; /*< reference to the iso node */
|
||||
|
||||
/**< file, symlink, directory or placeholder */
|
||||
/**< file, symlink, special, directory or placeholder */
|
||||
enum ecma119_node_type type;
|
||||
union {
|
||||
IsoFileSrc *file;
|
||||
struct ecma119_dir_info dir;
|
||||
/** this field points to the relocated directory. */
|
||||
Ecma119Node *real_me;
|
||||
} info;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user