New API call iso_write_opts_set_max_ce_entries()

This commit is contained in:
Thomas Schmitt 2023-01-22 16:03:44 +01:00
parent 7109ba5675
commit bd415402f4
9 changed files with 270 additions and 41 deletions

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2007 Mario Danic * Copyright (c) 2007 Mario Danic
* Copyright (c) 2009 - 2019 Thomas Schmitt * Copyright (c) 2009 - 2023 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * 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 * modify it under the terms of the GNU General Public License version 2
@ -205,17 +205,24 @@ size_t calc_dirent_len(Ecma119Image *t, Ecma119Node *n)
* taking into account the continuation areas. * taking into account the continuation areas.
*/ */
static static
size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce) ssize_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce)
{ {
size_t i, len; size_t i, len;
ssize_t ret;
size_t ce_len = 0; size_t ce_len = 0;
/* size of "." and ".." entries */ /* size of "." and ".." entries */
len = 34 + 34; len = 34 + 34;
if (t->opts->rockridge) { if (t->opts->rockridge) {
len += rrip_calc_len(t, dir, 1, 34, &ce_len, *ce); ret = rrip_calc_len(t, dir, 1, 34, &ce_len, *ce);
if (ret < 0)
return ret;
len += ret;
*ce += ce_len; *ce += ce_len;
len += rrip_calc_len(t, dir, 2, 34, &ce_len, *ce); ret = rrip_calc_len(t, dir, 2, 34, &ce_len, *ce);
if (ret < 0)
return ret;
len += ret;
*ce += ce_len; *ce += ce_len;
} }
@ -228,8 +235,10 @@ size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce)
for (section = 0; section < nsections; ++section) { for (section = 0; section < nsections; ++section) {
size_t dirent_len = calc_dirent_len(t, child); size_t dirent_len = calc_dirent_len(t, child);
if (t->opts->rockridge) { if (t->opts->rockridge) {
dirent_len += rrip_calc_len(t, child, 0, dirent_len, &ce_len, ret = rrip_calc_len(t, child, 0, dirent_len, &ce_len, *ce);
*ce); if (ret < 0)
return ret;
dirent_len += ret;
*ce += ce_len; *ce += ce_len;
} }
remaining = BLOCK_SIZE - (len % BLOCK_SIZE); remaining = BLOCK_SIZE - (len % BLOCK_SIZE);
@ -255,14 +264,18 @@ size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce)
} }
static static
void calc_dir_pos(Ecma119Image *t, Ecma119Node *dir) int calc_dir_pos(Ecma119Image *t, Ecma119Node *dir)
{ {
size_t i, len; size_t i, len;
ssize_t ret;
size_t ce_len = 0; size_t ce_len = 0;
t->ndirs++; t->ndirs++;
dir->info.dir->block = t->curblock; dir->info.dir->block = t->curblock;
len = calc_dir_size(t, dir, &ce_len); ret = calc_dir_size(t, dir, &ce_len);
if (ret < 0)
return (int) ret;
len = ret;
t->curblock += DIV_UP(len, BLOCK_SIZE); t->curblock += DIV_UP(len, BLOCK_SIZE);
if (t->opts->rockridge) { if (t->opts->rockridge) {
t->curblock += DIV_UP(ce_len, BLOCK_SIZE); t->curblock += DIV_UP(ce_len, BLOCK_SIZE);
@ -270,9 +283,12 @@ void calc_dir_pos(Ecma119Image *t, Ecma119Node *dir)
for (i = 0; i < dir->info.dir->nchildren; i++) { for (i = 0; i < dir->info.dir->nchildren; i++) {
Ecma119Node *child = dir->info.dir->children[i]; Ecma119Node *child = dir->info.dir->children[i];
if (child->type == ECMA119_DIR) { if (child->type == ECMA119_DIR) {
calc_dir_pos(t, child); ret = calc_dir_pos(t, child);
if (ret < 0)
return (int) ret;
} }
} }
return ISO_SUCCESS;
} }
/** /**
@ -305,6 +321,7 @@ int ecma119_writer_compute_data_blocks(IsoImageWriter *writer)
Ecma119Image *target; Ecma119Image *target;
uint32_t path_table_size; uint32_t path_table_size;
size_t ndirs; size_t ndirs;
int ret;
if (writer == NULL) { if (writer == NULL) {
return ISO_ASSERT_FAILURE; return ISO_ASSERT_FAILURE;
@ -315,7 +332,9 @@ int ecma119_writer_compute_data_blocks(IsoImageWriter *writer)
/* compute position of directories */ /* compute position of directories */
iso_msg_debug(target->image->id, "Computing position of dir structure"); iso_msg_debug(target->image->id, "Computing position of dir structure");
target->ndirs = 0; target->ndirs = 0;
calc_dir_pos(target, target->root); ret = calc_dir_pos(target, target->root);
if (ret < 0)
return ret;
/* compute length of pathlist */ /* compute length of pathlist */
iso_msg_debug(target->image->id, "Computing length of pathlist"); iso_msg_debug(target->image->id, "Computing length of pathlist");
@ -338,7 +357,9 @@ int ecma119_writer_compute_data_blocks(IsoImageWriter *writer)
/* Take into respect the second directory tree */ /* Take into respect the second directory tree */
ndirs = target->ndirs; ndirs = target->ndirs;
target->ndirs = 0; target->ndirs = 0;
calc_dir_pos(target, target->partition_root); ret = calc_dir_pos(target, target->partition_root);
if (ret < 0)
return ret;
if (target->ndirs != ndirs) { if (target->ndirs != ndirs) {
iso_msg_submit(target->image->id, ISO_ASSERT_FAILURE, 0, iso_msg_submit(target->image->id, ISO_ASSERT_FAILURE, 0,
"Number of directories differs in ECMA-119 partiton_tree"); "Number of directories differs in ECMA-119 partiton_tree");
@ -2737,6 +2758,8 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img)
target->filesrc_start = 0; target->filesrc_start = 0;
target->filesrc_blocks = 0; target->filesrc_blocks = 0;
target->curr_ce_entries = 0;
target->joliet_ucs2_failures = 0; target->joliet_ucs2_failures = 0;
/* If partitions get appended, then the backup GPT cannot be part of /* If partitions get appended, then the backup GPT cannot be part of
@ -3611,6 +3634,8 @@ int iso_write_opts_new(IsoWriteOpts **opts, int profile)
wopts->hfsp_block_size = 0; wopts->hfsp_block_size = 0;
memset(wopts->gpt_disk_guid, 0, 16); memset(wopts->gpt_disk_guid, 0, 16);
wopts->gpt_disk_guid_mode = 0; wopts->gpt_disk_guid_mode = 0;
wopts->max_ce_entries = 31; /* Linux hates >= RR_MAX_CE_ENTRIES = 32 */
wopts->max_ce_drop_attr = 2; /* If needed drop non-isofs fattr and ACL */
*opts = wopts; *opts = wopts;
return ISO_SUCCESS; return ISO_SUCCESS;
@ -4403,6 +4428,17 @@ int iso_write_opts_set_gpt_guid(IsoWriteOpts *opts, uint8_t guid[16], int mode)
return ISO_SUCCESS; return ISO_SUCCESS;
} }
int iso_write_opts_set_max_ce_entries(IsoWriteOpts *opts, uint32_t num,
int flag)
{
if (num > 100000)
return ISO_TOO_MANY_CE;
if (num == 0)
num = 1;
opts->max_ce_entries = num;
opts->max_ce_drop_attr = flag & 15;
return ISO_SUCCESS;
}
/* /*
* @param flag * @param flag

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 - 2019 Thomas Schmitt * Copyright (c) 2009 - 2023 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * 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 * modify it under the terms of the GNU General Public License version 2
@ -543,6 +543,17 @@ struct iso_write_opts {
*/ */
uint8_t gpt_disk_guid[16]; uint8_t gpt_disk_guid[16];
int gpt_disk_guid_mode; int gpt_disk_guid_mode;
/* Maximum number of CE entries per file */
uint32_t max_ce_entries;
/* Whether to try dropping AAIP data on too many CE:
bit0-3 = Mode:
0 = throw ISO_TOO_MANY_CE, without trying to drop anything
1 = drop non-isofs fattr
2 = drop ACL if dropping non-isofs fattr does not suffice
*/
int max_ce_drop_attr;
}; };
typedef struct ecma119_image Ecma119Image; typedef struct ecma119_image Ecma119Image;
@ -913,6 +924,8 @@ struct ecma119_image
uint32_t filesrc_start; uint32_t filesrc_start;
uint32_t filesrc_blocks; uint32_t filesrc_blocks;
/* Number of CE entries in currently processed node */
uint32_t curr_ce_entries;
}; };
#define BP(a,b) [(b) - (a) + 1] #define BP(a,b) [(b) - (a) + 1]

View File

@ -4,7 +4,7 @@
/* /*
* Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic * Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic
* Copyright (c) 2009-2022 Thomas Schmitt * Copyright (c) 2009-2023 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * 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 * modify it under the terms of the GNU General Public License version 2
@ -2684,6 +2684,39 @@ int iso_write_opts_set_efi_bootp(IsoWriteOpts *opts, char *image_path,
int iso_write_opts_set_gpt_guid(IsoWriteOpts *opts, uint8_t guid[16], int iso_write_opts_set_gpt_guid(IsoWriteOpts *opts, uint8_t guid[16],
int mode); int mode);
/**
* Set the maximum number of SUSP CE entries and thus continuation areas.
* Each continuation area can hold at most 2048 bytes of SUSP data (Rock Ridge
* or AAIP). The first area can be smaller. There might be some waste at the
* end of each area.
* When the maximum number is exceeded during ISO filesystem production
* then possibly xattr and ACL get removed or error ISO_TOO_MANY_CE gets
* reported and filesystem production is prevented.
*
* Files with 32 or more CE entries do not show up in mounted filesystems on
* Linux. So the default setting is 31 with drop mode 2. If a higher limit is
* chosen and 31 gets surpassed, then a warning message gets reported.
*
* @param opts
* The option set to be manipulated.
* @param num
* The maximum number of CE entries per file.
* Not more than 100000 may be set here.
* 0 gets silently mapped to 1, because the root directory needs one CE.
* @param flag
* bit0-bit3 = Drop mode: What to do with AAIP data on too many CE:
* 0 = throw ISO_TOO_MANY_CE, without dropping anything
* 1 = permanently drop non-isofs fattr from IsoNode and
* retry filesystem production
* 2 = drop ACL if dropping non-isofs fattr does not suffice
* @return
* ISO_SUCCESS or ISO_TOO_MANY_CE
*
* @since 1.5.6
*/
int iso_write_opts_set_max_ce_entries(IsoWriteOpts *opts, uint32_t num,
int flag);
/** /**
* Generate a pseudo-random GUID suitable for iso_write_opts_set_gpt_guid(). * Generate a pseudo-random GUID suitable for iso_write_opts_set_gpt_guid().
* *
@ -9401,6 +9434,16 @@ int iso_conv_name_chars(IsoWriteOpts *opts, char *name, size_t name_len,
/** Undefined IsoReadImageFeatures name (SORRY, HIGH, -426) */ /** Undefined IsoReadImageFeatures name (SORRY, HIGH, -426) */
#define ISO_UNDEF_READ_FEATURE 0xE030FE56 #define ISO_UNDEF_READ_FEATURE 0xE030FE56
/** Too many CE entries for single file (FAILURE,HIGH, -427) */
#define ISO_TOO_MANY_CE 0xE830FE55
/** Too many CE entries for single file when mounted by Linux
(WARNING,HIGH, -428) */
#define ISO_TOO_MANY_CE_FOR_LINUX 0xD030FE54
/** Too many CE entries for single file, omitting attributes
(WARNING,HIGH, -429) */
#define ISO_CE_REMOVING_ATTR 0xD030FE53
/* Internal developer note: /* Internal developer note:

View File

@ -350,6 +350,7 @@ 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_joliet_utf16; iso_write_opts_set_joliet_utf16;
iso_write_opts_set_max_37_char_filenames; iso_write_opts_set_max_37_char_filenames;
iso_write_opts_set_max_ce_entries;
iso_write_opts_set_ms_block; iso_write_opts_set_ms_block;
iso_write_opts_set_no_force_dots; iso_write_opts_set_no_force_dots;
iso_write_opts_set_old_empty; iso_write_opts_set_old_empty;

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 - 2022 Thomas Schmitt * Copyright (c) 2009 - 2023 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * 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 * modify it under the terms of the GNU General Public License version 2
@ -567,6 +567,12 @@ const char *iso_error_to_msg(int errcode)
return "Cannot obtain size of zisofs compressed stream"; return "Cannot obtain size of zisofs compressed stream";
case ISO_UNDEF_READ_FEATURE: case ISO_UNDEF_READ_FEATURE:
return "Undefined IsoReadImageFeatures name"; return "Undefined IsoReadImageFeatures name";
case ISO_TOO_MANY_CE:
return "Too many CE entries for single file";
case ISO_TOO_MANY_CE_FOR_LINUX:
return "Too many CE entries for single file when mounted by Linux";
case ISO_CE_REMOVING_ATTR:
return "Too many CE entries for single file, removing attributes";
default: default:
return "Unknown error"; return "Unknown error";
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 - 2020 Thomas Schmitt * Copyright (c) 2009 - 2023 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * 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 * modify it under the terms of the GNU General Public License version 2
@ -2046,9 +2046,56 @@ int iso_node_set_attrs(IsoNode *node, size_t num_attrs, char **names,
} }
ret = 1; ret = 1;
ex:; ex:;
/* Dispose eventual merged list */ /* Dispose merged list if it was created */
iso_node_merge_xattr(node, num_attrs, names, value_lengths, values, iso_node_merge_xattr(node, num_attrs, names, value_lengths, values,
&m_num, &m_names, &m_value_lengths, &m_values, 1 << 15); &m_num, &m_names, &m_value_lengths, &m_values, 1 << 15);
/* Dispose ACL if saved */
iso_node_get_acl_text(node, &a_acl, &d_acl, 1 << 15);
return ret;
}
/* @param flag
bit0= delete ACL, too
*/
int iso_node_remove_fattr(IsoNode *node, int flag)
{
int ret;
size_t num_attrs, *value_lengths = NULL, i, w;
char **names = NULL, **values = NULL;
ret = iso_node_get_attrs(node, &num_attrs, &names, &value_lengths, &values,
flag & 1);
if (ret < 0)
goto ex;
/* Delete variables of all namespaces except isofs */
w = 0;
for (i = 0; i < num_attrs; i++) {
if (strncmp(names[i], "isofs.", 6) != 0) {
free(names[i]);
names[i] = NULL;
free(values[i]);
values[i] = NULL;
continue;
}
if (w != i) {
/* move i to w , nullify i */
names[w] = names[i];
names[i] = NULL;
values[w] = values[i];
values[i] = NULL;
value_lengths[w] = value_lengths[i];
}
w++;
}
num_attrs = w;
ret = iso_node_set_attrs(node, num_attrs, names, value_lengths, values,
(flag & 1) | 8);
ex:;
if (names != NULL)
iso_node_get_attrs(NULL, &num_attrs, &names, &value_lengths, &values,
1 << 15);
return ret; return ret;
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2009 - 2020 Thomas Schmitt * Copyright (c) 2009 - 2023 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * 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 * modify it under the terms of the GNU General Public License version 2
@ -422,6 +422,12 @@ int iso_aa_get_attrs(unsigned char *aa_string, size_t *num_attrs,
int iso_aa_lookup_attr(unsigned char *aa_string, char *name, int iso_aa_lookup_attr(unsigned char *aa_string, char *name,
size_t *value_length, char **value, int flag); size_t *value_length, char **value, int flag);
/**
* Delete variables of all namespaces except isofs
*
* @param flag bit0= delete ACL, too
*/
int iso_node_remove_fattr(IsoNode *node, int flag);
/** /**
* Function to identify and manage ZF parameters which do not stem from ZF * Function to identify and manage ZF parameters which do not stem from ZF

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2007 Mario Danic * Copyright (c) 2007 Mario Danic
* Copyright (c) 2009 - 2022 Thomas Schmitt * Copyright (c) 2009 - 2023 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * 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 * modify it under the terms of the GNU General Public License version 2
@ -618,13 +618,15 @@ int rrip_add_SL(Ecma119Image *t, struct susp_info *susp, uint8_t **comp,
/* @param flag bit1= care about crossing block boundaries */ /* @param flag bit1= care about crossing block boundaries */
static static
int susp_calc_add_to_ce(size_t *ce, size_t base_ce, int add, int flag) int susp_calc_add_to_ce(Ecma119Image *t, size_t *ce, size_t base_ce, int add,
int flag)
{ {
if (flag & 2) { if (flag & 2) {
/* Account for inserted CE before size exceeds block size */ /* Account for inserted CE before size exceeds block size */
if ((*ce + base_ce + add + ISO_CE_ENTRY_SIZE - 1) / BLOCK_SIZE != if ((*ce + base_ce + add + ISO_CE_ENTRY_SIZE - 1) / BLOCK_SIZE !=
(*ce + base_ce) / BLOCK_SIZE) { (*ce + base_ce) / BLOCK_SIZE) {
/* Insert CE and padding */ /* Insert CE and padding */
t->curr_ce_entries++;
*ce += ISO_CE_ENTRY_SIZE; *ce += ISO_CE_ENTRY_SIZE;
if ((*ce + base_ce) % BLOCK_SIZE) if ((*ce + base_ce) % BLOCK_SIZE)
*ce += BLOCK_SIZE - ((*ce + base_ce) % BLOCK_SIZE); *ce += BLOCK_SIZE - ((*ce + base_ce) % BLOCK_SIZE);
@ -658,12 +660,12 @@ int aaip_add_AL(Ecma119Image *t, struct susp_info *susp,
es_extra = 5; es_extra = 5;
if (*sua_free < num_data + es_extra || *ce_len > 0) { if (*sua_free < num_data + es_extra || *ce_len > 0) {
if (es_extra > 0) if (es_extra > 0)
susp_calc_add_to_ce(ce_len, ce_mem, es_extra, flag & 2); susp_calc_add_to_ce(t, ce_len, ce_mem, es_extra, flag & 2);
done = 0; done = 0;
for (aapt = *data; !done; aapt += aapt[2]) { for (aapt = *data; !done; aapt += aapt[2]) {
done = !(aapt[4] & 1); done = !(aapt[4] & 1);
len = aapt[2]; len = aapt[2];
susp_calc_add_to_ce(ce_len, ce_mem, len, flag & 2); susp_calc_add_to_ce(t, ce_len, ce_mem, len, flag & 2);
count += len; count += len;
} }
} else { } else {
@ -704,7 +706,7 @@ int aaip_add_AL(Ecma119Image *t, struct susp_info *susp,
} else { } else {
ret = susp_append(t, susp, cpt); ret = susp_append(t, susp, cpt);
} }
if (ret == -1) if (ret < 0)
return ret; return ret;
} }
free(*data); free(*data);
@ -1078,7 +1080,7 @@ int add_zf_field(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
/* Account for field size */ /* Account for field size */
if (*sua_free < 16 || *ce_len > 0) { if (*sua_free < 16 || *ce_len > 0) {
susp_calc_add_to_ce(ce_len, base_ce, 16, flag & 2); susp_calc_add_to_ce(t, ce_len, base_ce, 16, flag & 2);
} else { } else {
*sua_free -= 16; *sua_free -= 16;
} }
@ -1139,6 +1141,7 @@ int aaip_xinfo_cloner(void *old_data, void **new_data, int flag)
* <0= error: * <0= error:
* -1= not enough SUA space for 28 bytes of CE entry * -1= not enough SUA space for 28 bytes of CE entry
* -2= out of memory * -2= out of memory
* (int) ISO_TOO_MANY_CE
*/ */
static static
int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space, int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
@ -1150,17 +1153,20 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
size_t num_aapt = 0, sua_free = 0; size_t num_aapt = 0, sua_free = 0;
int ret; int ret;
uint8_t *aapt; uint8_t *aapt;
uint32_t curr_ce_entries_mem;
#ifdef Libisofs_ce_calc_debug_extrA #ifdef Libisofs_ce_calc_debug_extrA
if (n->node->name != NULL) if (n->node->name != NULL)
fprintf(stderr, "libburn_DEBUG: susp_calc_nm_sl_al : %.f %s \n", fprintf(stderr, "libburn_DEBUG: susp_calc_nm_sl_al : %u %.f %s \n",
(unsigned int) t->curr_ce_entries,
(double) base_ce, n->node->name); (double) base_ce, n->node->name);
#endif /* Libisofs_ce_calc_debug_extrA */ #endif /* Libisofs_ce_calc_debug_extrA */
su_mem = *su_size; su_mem = *su_size;
ce_mem = *ce; ce_mem = *ce;
curr_ce_entries_mem = t->curr_ce_entries;
if (*ce > 0 && !(flag & 1)) if (*ce > 0 && !(flag & 1))
goto unannounced_ca; goto unannounced_ca;
@ -1175,10 +1181,11 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
} }
if (flag & 1) { if (flag & 1) {
/* Account for 28 bytes of CE field */ /* Account for 28 bytes of CE field */
if (*su_size + 28 > space) if (*su_size + 28 > space)
return -1; return -1;
*su_size += 28; *su_size += 28;
t->curr_ce_entries++;
} }
/* NM entry */ /* NM entry */
@ -1196,7 +1203,7 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
of the name will always fit into the directory entry.) of the name will always fit into the directory entry.)
*/; */;
susp_calc_add_to_ce(ce, base_ce, 5 + namelen, flag & 2); susp_calc_add_to_ce(t, ce, base_ce, 5 + namelen, flag & 2);
*su_size = space; *su_size = space;
} }
if (n->type == ECMA119_SYMLINK) { if (n->type == ECMA119_SYMLINK) {
@ -1267,7 +1274,7 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
* and another SL entry * and another SL entry
*/ */
/* Will fill up old SL and write it */ /* Will fill up old SL and write it */
susp_calc_add_to_ce(ce, base_ce, 255, flag & 2); susp_calc_add_to_ce(t, ce, base_ce, 255, flag & 2);
sl_len = 5 + (clen - fit); /* Start new SL */ sl_len = 5 + (clen - fit); /* Start new SL */
} else { } else {
/* /*
@ -1276,15 +1283,16 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
* anything in this SL * anything in this SL
*/ */
/* Will write non-full old SL */ /* Will write non-full old SL */
susp_calc_add_to_ce(ce, base_ce, sl_len, flag & 2); susp_calc_add_to_ce(t, ce, base_ce, sl_len,
flag & 2);
/* Will write another full SL */ /* Will write another full SL */
susp_calc_add_to_ce(ce, base_ce, 255, flag & 2); susp_calc_add_to_ce(t, ce, base_ce, 255, flag & 2);
sl_len = 5 + (clen - 250) + 2; /* Start new SL */ sl_len = 5 + (clen - 250) + 2; /* Start new SL */
} }
} else { } else {
/* case 2, create a new SL entry */ /* case 2, create a new SL entry */
/* Will write non-full old SL */ /* Will write non-full old SL */
susp_calc_add_to_ce(ce, base_ce, sl_len, flag & 2); susp_calc_add_to_ce(t, ce, base_ce, sl_len, flag & 2);
sl_len = 5 + clen; /* Start new SL */ sl_len = 5 + clen; /* Start new SL */
} }
} else { } else {
@ -1307,7 +1315,7 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
/* the whole SL fits into the SUA */ /* the whole SL fits into the SUA */
*su_size += sl_len; *su_size += sl_len;
} else { } else {
susp_calc_add_to_ce(ce, base_ce, sl_len, flag & 2); susp_calc_add_to_ce(t, ce, base_ce, sl_len, flag & 2);
} }
} }
@ -1367,6 +1375,7 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
/* Crossed a block boundary */ /* Crossed a block boundary */
*su_size = su_mem; *su_size = su_mem;
*ce = ce_mem; *ce = ce_mem;
t->curr_ce_entries = curr_ce_entries_mem;
return 0; return 0;
} }
} }
@ -1376,6 +1385,7 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
unannounced_ca:; unannounced_ca:;
*su_size = su_mem; *su_size = su_mem;
*ce = ce_mem; *ce = ce_mem;
t->curr_ce_entries = curr_ce_entries_mem;
return 0; return 0;
} }
@ -1422,6 +1432,21 @@ int add_aa_string(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
} }
static
void iso_msg_too_many_ce(Ecma119Image *t, Ecma119Node *n, int err)
{
if (n->node->name != NULL) {
iso_msg_submit(t->image->id, err, 0,
"Too many CE entries for file with name: %s",
n->node->name);
} else {
iso_msg_submit(t->image->id, err, 0,
"Too many CE entries for a single file",
n->node->name);
}
}
/** /**
* Compute the length needed for write all RR and SUSP entries for a given * Compute the length needed for write all RR and SUSP entries for a given
* node. * node.
@ -1438,13 +1463,15 @@ int add_aa_string(Ecma119Image *t, Ecma119Node *n, struct susp_info *info,
* @return * @return
* The size needed for the RR entries in the System Use Area * The size needed for the RR entries in the System Use Area
*/ */
size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up, ssize_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up,
size_t *ce, size_t base_ce) size_t *ce, size_t base_ce)
{ {
size_t su_size, space; size_t su_size, space;
int ret; int ret, retry = 0;
size_t aaip_sua_free= 0, aaip_len= 0; size_t aaip_sua_free= 0, aaip_len= 0;
try_again:
/* Directory record length must be even (ECMA-119, 9.1.13). Maximum is 254. /* Directory record length must be even (ECMA-119, 9.1.13). Maximum is 254.
*/ */
space = 254 - used_up - (used_up % 2); space = 254 - used_up - (used_up % 2);
@ -1457,6 +1484,7 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up,
*ce = 0; *ce = 0;
su_size = 0; su_size = 0;
t->curr_ce_entries = 0;
/* If AAIP enabled and announced by ER : account for 5 bytes of ES */; /* If AAIP enabled and announced by ER : account for 5 bytes of ES */;
if (t->opts->aaip && !t->opts->aaip_susp_1_10) if (t->opts->aaip && !t->opts->aaip_susp_1_10)
@ -1506,9 +1534,18 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up,
if (ret == 0) /* Retry with CE but no block crossing */ if (ret == 0) /* Retry with CE but no block crossing */
ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, base_ce, 1); ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, base_ce, 1);
if (ret == 0) /* Retry with aligned CE and block hopping */ if (ret == 0) /* Retry with aligned CE and block hopping */
ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, base_ce, 1 | 2); ret = susp_calc_nm_sl_al(t, n, space, &su_size, ce, base_ce,
1 | 2);
if (ret == -2) if (ret == -2)
return ISO_OUT_OF_MEM; return ISO_OUT_OF_MEM;
/* -1 should not occur. By tradition it would not cause return */
if (ret < -2) {
if (n->node->name != NULL)
iso_msg_submit(t->image->id, ret, 0,
"SUSP planning failed for file with name: %s",
n->node->name);
return ret;
}
} else { } else {
@ -1524,6 +1561,7 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up,
* ER needs a Continuation Area, thus we also need a CE entry * ER needs a Continuation Area, thus we also need a CE entry
*/ */
su_size += 7 + 28; /* SP + CE */ su_size += 7 + 28; /* SP + CE */
t->curr_ce_entries++;
/* ER of RRIP */ /* ER of RRIP */
if (t->opts->rrip_version_1_10) { if (t->opts->rrip_version_1_10) {
*ce = 237; *ce = 237;
@ -1546,6 +1584,40 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t used_up,
} }
} }
if (t->curr_ce_entries > t->opts->max_ce_entries) {
/* If permitted by API setting: Remove non-isofs-non-ACL fattr */
retry++;
if (retry == 1) {
if ((t->opts->max_ce_drop_attr & 15) >= 1) {
ret = iso_node_remove_fattr(n->node, 0);
if (ret > 0) {
iso_msg_too_many_ce(t, n, ISO_CE_REMOVING_ATTR);
iso_msg_submit(t->image->id, ISO_CE_REMOVING_ATTR, 0,
"Removed non-isofs attributes");
goto try_again;
}
}
} else if (retry == 2) {
if ((t->opts->max_ce_drop_attr & 15) >= 2) {
ret = iso_node_remove_fattr(n->node, 1);
if (ret > 0) {
iso_msg_submit(t->image->id, ISO_CE_REMOVING_ATTR, 0,
"Removed ACL");
goto try_again;
}
}
}
iso_msg_too_many_ce(t, n, ISO_TOO_MANY_CE);
return (ssize_t) (int) ISO_TOO_MANY_CE;
} else if (t->curr_ce_entries >= 32) {
if (n->node->name != NULL)
iso_msg_submit(t->image->id, ISO_TOO_MANY_CE_FOR_LINUX, 0,
"SUSP planning risky for file with name: %s",
n->node->name);
iso_msg_submit(t->image->id, ISO_TOO_MANY_CE_FOR_LINUX, 0,
"Too many CE entries for single file when mounted by Linux");
}
/* /*
* The System Use field inside the directory record must be padded if * The System Use field inside the directory record must be padded if
* it is an odd number (ECMA-119, 9.1.13) * it is an odd number (ECMA-119, 9.1.13)
@ -1762,6 +1834,9 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
ret = ISO_OUT_OF_MEM; ret = ISO_OUT_OF_MEM;
goto add_susp_cleanup; goto add_susp_cleanup;
} }
/* -1 should not occur. By tradition it would not cause return */
if (ret < -2)
goto add_susp_cleanup;
/* NM entry */ /* NM entry */
if (5 + namelen <= sua_free) { if (5 + namelen <= sua_free) {
@ -2064,6 +2139,8 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
/* Compute length of AAIP string of root node */ /* Compute length of AAIP string of root node */
aaip_sua_free= 0; aaip_sua_free= 0;
/* (just to give t->curr_ce_entries a defined state) */
t->curr_ce_entries = 0;
ret = add_aa_string(t, n, NULL, &aaip_sua_free, &aaip_len, ce_mem, ret = add_aa_string(t, n, NULL, &aaip_sua_free, &aaip_len, ce_mem,
1 | 2); 1 | 2);
if (ret < 0) if (ret < 0)

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2007 Mario Danic * Copyright (c) 2007 Mario Danic
* Copyright (c) 2009 - 2020 Thomas Schmitt * Copyright (c) 2009 - 2023 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * 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 * modify it under the terms of the GNU General Public License version 2
@ -203,8 +203,8 @@ struct susp_sys_user_entry
* @return * @return
* The size needed for the RR entries in the System Use Area * The size needed for the RR entries in the System Use Area
*/ */
size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space, ssize_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space,
size_t *ce, size_t base_ce); size_t *ce, size_t base_ce);
/** /**
* Fill a struct susp_info with the RR/SUSP entries needed for a given * Fill a struct susp_info with the RR/SUSP entries needed for a given