New API call iso_write_opts_set_rr_reloc()

This commit is contained in:
Thomas Schmitt 2012-03-09 19:59:51 +01:00
parent e49f9672bc
commit 76f2a5f4d3
6 changed files with 283 additions and 21 deletions

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2007 Mario Danic
* Copyright (c) 2009 - 2011 Thomas Schmitt
* Copyright (c) 2009 - 2012 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -89,6 +89,14 @@ void ecma119_image_free(Ecma119Image *t)
writer->free_data(writer);
free(writer);
}
#ifdef Libisofs_with_rr_reloc_diR
if (t->rr_reloc_dir != NULL)
free(t->rr_reloc_dir);
#endif /* Libisofs_with_rr_reloc_diR */
if (t->input_charset != NULL)
free(t->input_charset);
if (t->output_charset != NULL)
@ -1673,6 +1681,22 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->rrip_1_10_px_ino = opts->rrip_1_10_px_ino;
target->aaip_susp_1_10 = opts->aaip_susp_1_10;
target->dir_rec_mtime = opts->dir_rec_mtime;
#ifdef Libisofs_with_rr_reloc_diR
target->rr_reloc_dir = NULL;
if (opts->rr_reloc_dir != NULL) {
target->rr_reloc_dir = strdup(opts->rr_reloc_dir);
if (target->rr_reloc_dir == NULL) {
ret = ISO_OUT_OF_MEM;
goto target_cleanup;
}
}
target->rr_reloc_flags = opts->rr_reloc_flags;
target->rr_reloc_node = NULL;
#endif /* Libisofs_with_rr_reloc_diR */
target->sort_files = opts->sort_files;
target->replace_uid = opts->replace_uid ? 1 : 0;
@ -2310,6 +2334,69 @@ int bs_set_size(struct burn_source *bs, off_t size)
return 1;
}
#ifdef Libisofs_with_rr_reloc_diR
static
int dive_to_depth_8(IsoDir *dir, int depth)
{
int ret;
IsoNode *pos;
if (depth >= 8)
return 1;
pos = dir->children;
for (pos = dir->children; pos != NULL; pos = pos->next) {
if (pos->type != LIBISO_DIR)
continue;
ret = dive_to_depth_8((IsoDir *) pos, depth + 1);
if (ret != 0)
return ret;
}
return 0;
}
static
int make_reloc_dir_if_needed(IsoImage *img, IsoWriteOpts *opts, int flag)
{
int ret;
IsoDir *dir;
/* Two forms to express the root directory */
if (opts->rr_reloc_dir == NULL)
return 1;
if (opts->rr_reloc_dir[0] == 0)
return 1;
if (strchr(opts->rr_reloc_dir, '/') != NULL)
return 0;
/* Check existence of opts->rr_reloc_dir */
ret = iso_dir_get_node(img->root, opts->rr_reloc_dir, NULL);
if (ret > 0)
return 1;
if (ret < 0)
return ret;
/* Check whether there is a directory of depth 8 (root is depth 1) */
ret = dive_to_depth_8(img->root, 1);
if (ret < 0)
return ret;
if (ret == 0)
return 1;
/* Make IsoDir with same permissions as root directory */
ret = iso_tree_add_new_dir(img->root, opts->rr_reloc_dir, &dir);
if (ret < 0)
return ret;
opts->rr_reloc_flags |= 2; /* Auto-created relocation directory */
return 1;
}
#endif /* Libisofs_with_rr_reloc_diR */
int iso_image_create_burn_source(IsoImage *image, IsoWriteOpts *opts,
struct burn_source **burn_src)
{
@ -2326,6 +2413,16 @@ int iso_image_create_burn_source(IsoImage *image, IsoWriteOpts *opts,
return ISO_OUT_OF_MEM;
}
#ifdef Libisofs_with_rr_reloc_diR
if (!opts->allow_deep_paths) {
ret = make_reloc_dir_if_needed(image, opts, 0);
if (ret < 0)
return ret;
}
#endif /* Libisofs_with_rr_reloc_diR */
ret = ecma119_image_new(image, opts, &target);
if (ret < 0) {
free(source);
@ -2434,6 +2531,13 @@ int iso_write_opts_new(IsoWriteOpts **opts, int profile)
wopts->fifo_size = 1024; /* 2 MB buffer */
wopts->sort_files = 1; /* file sorting is always good */
#ifdef Libisofs_with_rr_reloc_diR
wopts->rr_reloc_dir = NULL;
wopts->rr_reloc_flags = 0;
#endif /* Libisofs_with_rr_reloc_diR */
wopts->system_area_data = NULL;
wopts->system_area_options = 0;
wopts->vol_creation_time = 0;
@ -2470,6 +2574,14 @@ void iso_write_opts_free(IsoWriteOpts *opts)
return;
}
free(opts->output_charset);
#ifdef Libisofs_with_rr_reloc_diR
if (opts->rr_reloc_dir != NULL)
free(opts->rr_reloc_dir);
#endif /* Libisofs_with_rr_reloc_diR */
if (opts->system_area_data != NULL)
free(opts->system_area_data);
for (i = 0; i < ISO_MAX_PARTITIONS; i++)
@ -2711,6 +2823,22 @@ int iso_write_opts_set_dir_rec_mtime(IsoWriteOpts *opts, int allow)
return ISO_SUCCESS;
}
int iso_write_opts_set_rr_reloc(IsoWriteOpts *opts, char *name, int flags)
{
if (opts->rr_reloc_dir != name) {
if (opts->rr_reloc_dir != NULL)
free(opts->rr_reloc_dir);
opts->rr_reloc_dir = NULL;
if (name != NULL) {
opts->rr_reloc_dir = strdup(name);
if (opts->rr_reloc_dir == NULL)
return ISO_OUT_OF_MEM;
}
}
opts->rr_reloc_flags = flags & 1;
return ISO_SUCCESS;
}
int iso_write_opts_set_sort_files(IsoWriteOpts *opts, int sort)
{
if (opts == NULL) {

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 - 2011 Thomas Schmitt
* Copyright (c) 2009 - 2012 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -206,6 +206,24 @@ struct iso_write_opts {
*/
unsigned int dir_rec_mtime :3;
/**
* This describes the directory where to store Rock Ridge relocated
* directories.
* If not relaxation "allow_deep_paths" is in effect, it is necessary to
* relocate directories so that no ECMA-119 file path has more than
* 8 components. For Rock Ridge the relocated directories are linked forth
* and back to a placeholder at their original position in path level 8
* (entries CL and PL). Directories marked by entry RE are to be considered
* artefacts of relocation and shall not be read into a Rock Ridge tree.
* For plain ECMA-119, the relocation directory is just a normal directory
* which contains normal files and directories.
*/
char *rr_reloc_dir; /* IsoNode name in root directory */
int rr_reloc_flags; /* bit0= mark auto-created rr_reloc_dir by RE
bit1= directory was auto-created
(cannot be set via API)
*/
/**
* Compute MD5 checksum for the whole session and record it as index 0 of
* the checksum blocks after the data area of the session. The layout and
@ -482,6 +500,12 @@ struct ecma119_image
*/
unsigned int dir_rec_mtime :3;
/* The ECMA-119 directory where to store Rock Ridge relocated directories.
*/
char *rr_reloc_dir; /* IsoNode name in root directory */
int rr_reloc_flags;
Ecma119Node *rr_reloc_node; /* Directory node in ecma119_image */
unsigned int md5_session_checksum :1;
unsigned int md5_file_checksums :2;

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 Thomas Schmitt
* Copyright (c) 2009 - 2012 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -434,6 +434,20 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
if (ret < 0) {
goto ex;
}
#ifdef Libisofs_with_rr_reloc_diR
if (depth == 1) { /* root is default */
image->rr_reloc_node = node;
} else if (depth == 2) { /* directories in root may be used */
if (image->rr_reloc_dir != NULL)
if (strcmp(iso->name, image->rr_reloc_dir) == 0)
image->rr_reloc_node = node;
}
#endif /* Libisofs_with_rr_reloc_diR */
}
ret = ISO_SUCCESS;
pos = dir->children;
@ -750,7 +764,7 @@ int mangle_dir(Ecma119Image *img, Ecma119Node *dir, int max_file_len,
}
static
int mangle_tree(Ecma119Image *img, int recurse)
int mangle_tree(Ecma119Image *img, Ecma119Node *dir, int recurse)
{
int max_file, max_dir;
Ecma119Node *root;
@ -765,7 +779,9 @@ int mangle_tree(Ecma119Image *img, int recurse)
} else {
max_file = max_dir = 31;
}
if (img->eff_partition_offset > 0) {
if (dir != NULL) {
root = dir;
} else if (img->eff_partition_offset > 0) {
root = img->partition_root;
} else {
root = img->root;
@ -891,17 +907,34 @@ int reorder_tree(Ecma119Image *img, Ecma119Node *dir, int level, int pathlen)
{
int ret;
size_t max_path;
Ecma119Node *root;
Ecma119Node *reloc;
max_path = pathlen + 1 + max_child_name_len(dir);
if (level > 8 || max_path > 255) {
if (img->eff_partition_offset > 0) {
root = img->partition_root;
} else {
root = img->root;
#ifdef Libisofs_with_rr_reloc_diR
reloc = img->rr_reloc_node;
if (reloc == NULL) {
if (img->eff_partition_offset > 0) {
reloc = img->partition_root;
} else {
reloc = img->root;
}
}
ret = reparent(dir, root);
#else
if (img->eff_partition_offset > 0) {
reloc = img->partition_root;
} else {
reloc = img->root;
}
#endif /* ! Libisofs_with_rr_reloc_diR */
ret = reparent(dir, reloc);
if (ret < 0) {
return ret;
}
@ -1115,6 +1148,8 @@ int ecma119_tree_create(Ecma119Image *img)
img->root = root;
}
/* >>> ts B20307 : Shouldn't relocation be done here ? */
iso_msg_debug(img->image->id, "Matching hardlinks...");
ret = match_hardlinks(img, root, 0);
if (ret < 0) {
@ -1125,14 +1160,14 @@ int ecma119_tree_create(Ecma119Image *img)
sort_tree(root);
iso_msg_debug(img->image->id, "Mangling names...");
ret = mangle_tree(img, 1);
ret = mangle_tree(img, NULL, 1);
if (ret < 0) {
return ret;
}
if (img->rockridge && !img->allow_deep_paths) {
/* reorder the tree, acording to RRIP, 4.1.5 */
/* Relocate deep directories, acording to RRIP, 4.1.5 */
ret = reorder_tree(img, root, 1, 0);
if (ret < 0) {
return ret;
@ -1143,7 +1178,15 @@ int ecma119_tree_create(Ecma119Image *img)
* above could insert new directories into the root.
* Note that recurse = 0, as we don't need to recurse.
*/
ret = mangle_tree(img, 0);
/* >>> ts B20307 : Shouldn't one mangle _after_ relocating ? */
#ifdef Libisofs_with_rr_reloc_diR
ret = mangle_tree(img, img->rr_reloc_node, 0);
#else
ret = mangle_tree(img, NULL, 0);
#endif
if (ret < 0) {
return ret;
}

View File

@ -1536,6 +1536,45 @@ int iso_write_opts_set_omit_version_numbers(IsoWriteOpts *opts, int omit);
*/
int iso_write_opts_set_allow_deep_paths(IsoWriteOpts *opts, int allow);
/**
* This call describes the directory where to store Rock Ridge relocated
* directories.
* If not iso_write_opts_set_allow_deep_paths(,1) is in effect, then it is
* necessary to relocate directories so that no ECMA-119 file path
* has more than 8 components. These directories are grafted into either
* the root directory of the ISO image or into a dedicated relocation
* directory.
* For Rock Ridge, the relocated directories are linked forth and back to
* placeholders at their original positions in path level 8. Directories
* marked by Rock Ridge entry RE are to be considered artefacts of relocation
* and shall not be read into a Rock Ridge tree. Instead they are to be read
* via their placeholders and their links.
* For plain ECMA-119, the relocation directory and the relocated directories
* are just normal directories which contain normal files and directories.
* @param opts
* The option set to be manipulated.
* @param name
* The name of the relocation directory in the root directory. Do not
* prepend "/". An empty name or NULL will direct relocated directories
* into the root directory. This is the default.
* If the given name does not exist in the root directory when
* iso_image_create_burn_source() is called, and if there are directories
* at path level 8, then directory /name will be created automatically.
* The name given by this call will be compared with iso_node_get_name()
* of the directories in the root directory, not with the final ECMA-119
* names of those directories.
* @parm flags
* Bitfield for control purposes.
* bit0= Mark the relocation directory by a Rock Ridge RE entry, if it
* gets created during iso_image_create_burn_source(). This will
* make it invisible for most Rock Ridge readers.
* bit1= not settable via API (used internally)
* @return
* 1 success, < 0 error
* @since 1.2.2
*/
int iso_write_opts_set_rr_reloc(IsoWriteOpts *opts, char *name, int flags);
/**
* Allow path in the ISO-9660 tree to have more than 255 characters.
* This breaks ECMA-119 specification. Use with caution.
@ -7170,6 +7209,11 @@ struct burn_source {
/* currently none being tested */
/* Perform the operations promised by iso_write_opts_set_rr_reloc() */
#define Libisofs_with_rr_reloc_diR yes
/* ---------------------------- Experiments ---------------------------- */

View File

@ -301,6 +301,7 @@ iso_write_opts_set_relaxed_vol_atts;
iso_write_opts_set_replace_mode;
iso_write_opts_set_replace_timestamps;
iso_write_opts_set_rockridge;
iso_write_opts_set_rr_reloc;
iso_write_opts_set_rrip_1_10_px_ino;
iso_write_opts_set_rrip_version_1_10;
iso_write_opts_set_scdbackup_tag;

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2007 Mario Danic
* Copyright (c) 2009 - 2011 Thomas Schmitt
* Copyright (c) 2009 - 2012 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -406,12 +406,15 @@ int rrip_SL_append_comp(size_t *n, uint8_t ***comps, char *s, int size, char fl)
#ifdef Libisofs_with_rrip_rR
/**
* Add to the given tree node a RR System Use Entry. This is an obsolete
* entry from before RRIP-1.10. Nevertheless mkisofs produces it and there
* is the suspicion that Solaris takes it as indication for Rock Ridge.
* Add a RR System Use Entry to the given tree node. This is an obsolete
* entry from before RRIP-1.10. Nevertheless mkisofs produces it. There
* is the suspicion that some operating systems could take it as indication
* for Rock Ridge.
*
* I once saw a copy of a RRIP spec which mentioned RR. Here i just use
* the same constant 5 bytes as produced by mkisofs.
* The meaning of the payload byte is documented e.g. in
* /usr/src/linux/fs/isofs/rock.h
* It announces the presence of entries PX, PN, SL, NM, CL, PL, RE, TF
* by payload byte bits 0 to 7.
*/
static
int rrip_add_RR(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp)
@ -426,7 +429,14 @@ int rrip_add_RR(Ecma119Image *t, Ecma119Node *n, struct susp_info *susp)
RR[1] = 'R';
RR[2] = 5;
RR[3] = 1;
RR[4] = 0201;
/* <<< ts B20307 : Not all directories have NM, many files have more entries */
RR[4] = 0x89; /* TF, NM , PX */
/* >>> ts B20307 : find out whether n carries
PX, PN, SL, NM, CL, PL, RE, TF and mark by bit0 to bit7 in RR[4]
*/
return susp_append(t, susp, RR);
}
@ -1422,6 +1432,18 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
goto add_susp_cleanup;
}
}
#ifdef Libisofs_with_rr_reloc_diR
} else if(t->rr_reloc_node == n && n != t->root &&
(t->rr_reloc_flags & 3) == 3) {
/* The dedicated relocation directory shall be marked by RE */
ret = rrip_add_RE(t, node, info);
if (ret < 0)
goto add_susp_cleanup;
#endif /* Libisofs_with_rr_reloc_diR */
}
} else if (n->type == ECMA119_SPECIAL) {
if (S_ISBLK(n->node->mode) || S_ISCHR(n->node->mode)) {