New configuration option --enable-dir-rec-size-check
This commit is contained in:
parent
24e3f44715
commit
17d297b3de
@ -27,8 +27,10 @@ libisofs_libisofs_la_LDFLAGS = \
|
||||
# ts B00927: Enabling use of libjte (Jigdo Template Extraction)
|
||||
# ts C40713: Enabling system adapter for Linux chattr(1) flags
|
||||
# ts C41009: Enabling system adapter for project id of XFS-style quota
|
||||
# Also enabling zlib, libjte, and directory size prediction check.
|
||||
libisofs_libisofs_la_CFLAGS = $(LIBACL_DEF) $(XATTR_DEF) $(LFA_DEF) \
|
||||
$(PROJID_DEF) $(ZLIB_DEF) $(LIBJTE_DEF)
|
||||
$(PROJID_DEF) $(ZLIB_DEF) $(LIBJTE_DEF) \
|
||||
$(DIR_REC_SIZE_CHECK)
|
||||
|
||||
# ts A90114 : added aaip_0_2.*
|
||||
|
||||
|
15
configure.ac
15
configure.ac
@ -348,6 +348,21 @@ else
|
||||
fi
|
||||
AC_SUBST(LIBJTE_DEF)
|
||||
|
||||
|
||||
dnl ts C50224
|
||||
AC_ARG_ENABLE(dir-rec-size-check,
|
||||
[ --enable-dir-rec-size-check Detailed check of directory size prediction, default=no],
|
||||
, dir_rec_size_check=no)
|
||||
if test x$enable_dir_rec_size_check = xyes; then
|
||||
DIR_REC_SIZE_CHECK="-DLibisofs_dir_rec_size_checK"
|
||||
echo "enabled detailed check of directory size prediction"
|
||||
else
|
||||
DIR_REC_SIZE_CHECK=
|
||||
echo "disabled detailed check of directory size prediction"
|
||||
fi
|
||||
AC_SUBST(DIR_REC_SIZE_CHECK)
|
||||
|
||||
|
||||
# Library versioning normally serves a complex purpose.
|
||||
# Since libisofs obeys strict ABI backward compatibility, it needs only the
|
||||
# simple feature to declare function names "global:" or "local:". Only the
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2007 Mario Danic
|
||||
* Copyright (c) 2009 - 2023 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2025 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
|
||||
@ -58,9 +58,6 @@
|
||||
#endif /* ! Xorriso_standalonE */
|
||||
|
||||
|
||||
int iso_write_opts_clone(IsoWriteOpts *in, IsoWriteOpts **out, int flag);
|
||||
|
||||
|
||||
/*
|
||||
* TODO #00011 : guard against bad path table usage with more than 65535 dirs
|
||||
* image with more than 65535 directories have path_table related problems
|
||||
@ -68,6 +65,256 @@ int iso_write_opts_clone(IsoWriteOpts *in, IsoWriteOpts **out, int flag);
|
||||
* that are parent of another folder.
|
||||
*/
|
||||
|
||||
|
||||
int iso_write_opts_clone(IsoWriteOpts *in, IsoWriteOpts **out, int flag);
|
||||
|
||||
|
||||
#ifdef Libisofs_dir_rec_size_checK
|
||||
|
||||
static
|
||||
char *ecma119_path_not_threadsafe(Ecma119Node *dir, Ecma119Node *node)
|
||||
{
|
||||
int loop_count, len = 0, pos;
|
||||
Ecma119Node *parent;
|
||||
static char path[1024];
|
||||
|
||||
if (node->iso_name == NULL) {
|
||||
strcpy(path, "/");
|
||||
return path;
|
||||
}
|
||||
|
||||
/* Determine path length */
|
||||
/* Slash, leafname, zero byte */
|
||||
len = 1 + strlen(node->iso_name) + 1;
|
||||
parent = dir;
|
||||
for (loop_count = 0; loop_count < 512; loop_count++) {
|
||||
if (parent == NULL)
|
||||
break;
|
||||
if (parent->iso_name == NULL)
|
||||
break;
|
||||
/* Slash, name */
|
||||
len += 1 + strlen(parent->iso_name);
|
||||
parent = parent->parent;
|
||||
}
|
||||
if (len >= 1024 || loop_count >= 512) {
|
||||
strcpy(path, "_oversized_path_/");
|
||||
strcat(path, node->iso_name);
|
||||
return path;
|
||||
}
|
||||
|
||||
/* Compose path */
|
||||
pos= len - 1;
|
||||
path[pos] = 0;
|
||||
pos -= strlen(node->iso_name);
|
||||
memcpy(path + pos, node->iso_name, strlen(node->iso_name));
|
||||
pos--;
|
||||
path[pos] = '/';
|
||||
parent = dir;
|
||||
for (loop_count = 0; loop_count < 512; loop_count++) {
|
||||
if (parent == NULL)
|
||||
break;
|
||||
if (parent->iso_name == NULL)
|
||||
break;
|
||||
pos -= strlen(parent->iso_name);
|
||||
memcpy(path + pos, parent->iso_name, strlen(parent->iso_name));
|
||||
pos--;
|
||||
path[pos] = '/';
|
||||
parent = parent->parent;
|
||||
}
|
||||
|
||||
if (pos > 0) {
|
||||
/* Should not happen */
|
||||
for (; pos >= 0; pos--)
|
||||
path[pos] = ' ';
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Record the size predictions about directory records and continuation areas
|
||||
during the calculation stage or compare the written sizes with the
|
||||
recorded predictions.
|
||||
|
||||
@param mode 0= initialize
|
||||
1= record directory record size
|
||||
2= compare and complain directory record size
|
||||
3= report both mismatch counts if non-zero
|
||||
4= return dir_rec mismatch count but do not report
|
||||
5= free allocated memory
|
||||
6= record continuation area size
|
||||
7= compare and complain continuation area size
|
||||
8= return continuation area mismatch count but do not report
|
||||
@return with modes 0, 1, 2, 6, 7:
|
||||
-1= out of memory
|
||||
0= comparison yielded mismatch or list not yet initialized
|
||||
1= successful operation or comparison yielded match
|
||||
2= list overflow
|
||||
with mode 3, 4, 8:
|
||||
the number of mismatches (3 returns the sum of 4 and 8)
|
||||
with mode 5
|
||||
1
|
||||
*/
|
||||
static
|
||||
int dir_rec_size_check(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *node,
|
||||
off_t byte_adr, uint32_t rec_size, int mode)
|
||||
{
|
||||
static uint32_t *rec_size_list = NULL, *ce_size_list = NULL;
|
||||
static int list_size = 1000, write_idx = 0, read_idx = 0;
|
||||
static int ce_list_size = 1000, ce_write_idx = 0, ce_read_idx = 0;
|
||||
static int mismatch_count= 0, ce_mismatch_count, max_complaints= 10;
|
||||
static int permanent_overflow = 0;
|
||||
|
||||
void *newpt;
|
||||
off_t block;
|
||||
|
||||
if (mode == 0) {
|
||||
/* Initialize */
|
||||
write_idx = 0;
|
||||
read_idx = 0;
|
||||
mismatch_count = 0;
|
||||
ce_write_idx = 0;
|
||||
ce_read_idx = 0;
|
||||
ce_mismatch_count = 0;
|
||||
permanent_overflow = 0;
|
||||
if (rec_size_list == NULL) {
|
||||
rec_size_list= calloc(list_size, sizeof(uint32_t));
|
||||
if (rec_size_list == NULL)
|
||||
return -1;
|
||||
}
|
||||
if (ce_size_list == NULL) {
|
||||
ce_size_list= calloc(ce_list_size, sizeof(uint32_t));
|
||||
if (ce_size_list == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else if (mode == 1) {
|
||||
/* Record */
|
||||
if (rec_size_list == NULL)
|
||||
return 0;
|
||||
if (write_idx >= list_size) {
|
||||
if (permanent_overflow)
|
||||
return 2;
|
||||
newpt = realloc(rec_size_list, list_size * 2 * sizeof(uint32_t));
|
||||
if (newpt == NULL) {
|
||||
permanent_overflow = 1;
|
||||
return 2;
|
||||
}
|
||||
rec_size_list= newpt;
|
||||
list_size *= 2;
|
||||
if (write_idx >= list_size) {
|
||||
permanent_overflow = 1;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
rec_size_list[write_idx] = rec_size;
|
||||
write_idx++;
|
||||
|
||||
} else if (mode == 2) {
|
||||
/* Compare and complain */
|
||||
if (rec_size_list == NULL)
|
||||
return 0;
|
||||
if (read_idx >= list_size)
|
||||
return 2;
|
||||
read_idx++;
|
||||
if (rec_size_list[read_idx - 1] != rec_size) {
|
||||
mismatch_count++;
|
||||
if (mismatch_count <= max_complaints) {
|
||||
iso_msg_submit(-1, ISO_DIR_REC_SIZE_MISMATCH, 0,
|
||||
"Directory record size calculation mismatch: LBA %lu '%s' : %lu -> %lu",
|
||||
(unsigned long) t->curblock,
|
||||
ecma119_path_not_threadsafe(dir, node),
|
||||
(unsigned long) rec_size_list[read_idx - 1],
|
||||
(unsigned long) rec_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (mode == 3) {
|
||||
/* Report mismatch count */
|
||||
if (mismatch_count > 0) {
|
||||
iso_msg_submit(-1, ISO_DIR_REC_SIZE_MISMATCH, 0,
|
||||
"Number of directory record size calculation mismatches: %lu",
|
||||
(unsigned long) mismatch_count);
|
||||
}
|
||||
if (ce_mismatch_count > 0) {
|
||||
iso_msg_submit(-1, ISO_DIR_REC_SIZE_MISMATCH, 0,
|
||||
"Number of continuation area size calculation mismatches: %lu",
|
||||
(unsigned long) ce_mismatch_count);
|
||||
}
|
||||
return mismatch_count + ce_mismatch_count;
|
||||
|
||||
} else if (mode == 4) {
|
||||
return mismatch_count;
|
||||
|
||||
} else if (mode == 5) {
|
||||
/* Free allocated memory */
|
||||
if (rec_size_list != NULL) {
|
||||
free(rec_size_list);
|
||||
rec_size_list = NULL;
|
||||
}
|
||||
if (ce_size_list != NULL) {
|
||||
free(ce_size_list);
|
||||
ce_size_list = NULL;
|
||||
}
|
||||
|
||||
} else if (mode == 6) {
|
||||
/* Record continuation area size */
|
||||
if (ce_size_list == NULL)
|
||||
return 0;
|
||||
if (ce_write_idx >= ce_list_size) {
|
||||
if (permanent_overflow)
|
||||
return 2;
|
||||
newpt = realloc(ce_size_list, ce_list_size * 2 * sizeof(uint32_t));
|
||||
if (newpt == NULL) {
|
||||
permanent_overflow = 1;
|
||||
return 2;
|
||||
}
|
||||
ce_size_list= newpt;
|
||||
ce_list_size *= 2;
|
||||
if (ce_write_idx >= ce_list_size) {
|
||||
permanent_overflow = 1;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
ce_size_list[ce_write_idx] = rec_size;
|
||||
ce_write_idx++;
|
||||
|
||||
} else if (mode == 7) {
|
||||
/* Compare and complain continuation area size*/
|
||||
if (ce_size_list == NULL)
|
||||
return 0;
|
||||
if (ce_read_idx >= ce_list_size)
|
||||
return 2;
|
||||
ce_read_idx++;
|
||||
if (ce_size_list[ce_read_idx - 1] != rec_size) {
|
||||
ce_mismatch_count++;
|
||||
if (ce_mismatch_count <= max_complaints) {
|
||||
if (byte_adr < 0)
|
||||
byte_adr = t->bytes_written +
|
||||
t->opts->ms_block * BLOCK_SIZE - rec_size;
|
||||
block = byte_adr / BLOCK_SIZE;
|
||||
iso_msg_submit(-1, ISO_DIR_REC_SIZE_MISMATCH, 0,
|
||||
"Continuation area size calculation mismatch: LBA %lu+%lu '%s' : %lu -> %lu",
|
||||
(unsigned long) block,
|
||||
(unsigned long) (byte_adr - block * BLOCK_SIZE),
|
||||
ecma119_path_not_threadsafe(dir, node),
|
||||
(unsigned long) ce_size_list[ce_read_idx - 1],
|
||||
(unsigned long) rec_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (mode == 8) {
|
||||
return ce_mismatch_count;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* Libisofs_dir_rec_size_checK */
|
||||
|
||||
|
||||
static
|
||||
void ecma119_image_free(Ecma119Image *t)
|
||||
{
|
||||
@ -211,22 +458,45 @@ ssize_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce)
|
||||
size_t i, len;
|
||||
ssize_t ret;
|
||||
size_t ce_len = 0;
|
||||
size_t dirent_len;
|
||||
|
||||
len = 0;
|
||||
/* size of "." and ".." entries */
|
||||
len = 34 + 34;
|
||||
dirent_len = 34;
|
||||
if (t->opts->rockridge) {
|
||||
ret = rrip_calc_len(t, dir, 1, 34, &ce_len, *ce);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
len += ret;
|
||||
dirent_len += ret;
|
||||
*ce += ce_len;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_dir_rec_size_checK
|
||||
|
||||
/* Record calculated size */
|
||||
dir_rec_size_check(t, NULL, NULL, (off_t) -1, (uint32_t) dirent_len, 1);
|
||||
|
||||
#endif /* Libisofs_dir_rec_size_checK */
|
||||
|
||||
len += dirent_len;
|
||||
|
||||
dirent_len = 34;
|
||||
if (t->opts->rockridge) {
|
||||
ret = rrip_calc_len(t, dir, 2, 34, &ce_len, *ce);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
len += ret;
|
||||
dirent_len += ret;
|
||||
*ce += ce_len;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_dir_rec_size_checK
|
||||
|
||||
dir_rec_size_check(t, NULL, NULL, (off_t) -1, (uint32_t) dirent_len, 1);
|
||||
|
||||
#endif /* Libisofs_dir_rec_size_checK */
|
||||
|
||||
len += dirent_len;
|
||||
|
||||
for (i = 0; i < dir->info.dir->nchildren; ++i) {
|
||||
size_t remaining;
|
||||
int section, nsections;
|
||||
@ -234,7 +504,7 @@ ssize_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce)
|
||||
|
||||
nsections = (child->type == ECMA119_FILE) ? child->info.file->nsections : 1;
|
||||
for (section = 0; section < nsections; ++section) {
|
||||
size_t dirent_len = calc_dirent_len(t, child);
|
||||
dirent_len = calc_dirent_len(t, child);
|
||||
if (t->opts->rockridge) {
|
||||
ret = rrip_calc_len(t, child, 0, dirent_len, &ce_len, *ce);
|
||||
if (ret < 0)
|
||||
@ -249,6 +519,14 @@ ssize_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce)
|
||||
} else {
|
||||
len += dirent_len;
|
||||
}
|
||||
|
||||
#ifdef Libisofs_dir_rec_size_checK
|
||||
|
||||
dir_rec_size_check(t, dir, child, (off_t) -1,
|
||||
(uint32_t) dirent_len, 1);
|
||||
|
||||
#endif /* Libisofs_dir_rec_size_checK */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -280,6 +558,22 @@ int calc_dir_pos(Ecma119Image *t, Ecma119Node *dir)
|
||||
t->curblock += DIV_UP(len, BLOCK_SIZE);
|
||||
if (t->opts->rockridge) {
|
||||
t->curblock += DIV_UP(ce_len, BLOCK_SIZE);
|
||||
|
||||
#ifdef Libisofs_dir_rec_size_checK
|
||||
|
||||
/* Record ce_len */
|
||||
if (ce_len > 0xffffffff) {
|
||||
iso_msg_submit(-1, ISO_INSANE_CE_SIZE, 0,
|
||||
"Continuation area size of 4 GiB or more predicted : LBA %lu '%s'",
|
||||
(unsigned long) t->curblock,
|
||||
ecma119_path_not_threadsafe(dir->parent, dir));
|
||||
ce_len= 0xffffffff;
|
||||
}
|
||||
dir_rec_size_check(t, dir->parent, dir, (off_t) -1, (uint32_t) ce_len,
|
||||
6);
|
||||
|
||||
#endif /* Libisofs_dir_rec_size_checK */
|
||||
|
||||
}
|
||||
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
||||
Ecma119Node *child = dir->info.dir->children[i];
|
||||
@ -330,6 +624,13 @@ int ecma119_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
|
||||
target = writer->target;
|
||||
|
||||
#ifdef Libisofs_dir_rec_size_checK
|
||||
|
||||
/* Initialize directory size check facility */
|
||||
dir_rec_size_check(target, NULL, NULL, (off_t) -1, (uint32_t) 0, 0);
|
||||
|
||||
#endif /* Libisofs_dir_rec_size_checK */
|
||||
|
||||
/* compute position of directories */
|
||||
iso_msg_debug(target->image->id, "Computing position of dir structure");
|
||||
target->ndirs = 0;
|
||||
@ -395,16 +696,22 @@ int ecma119_writer_compute_data_blocks(IsoImageWriter *writer)
|
||||
* SUSP entries for the given directory record. It will be NULL for the
|
||||
* root directory record in the PVD (ECMA-119, 8.4.18) (in order to
|
||||
* distinguish it from the "." entry in the root directory)
|
||||
* @param extent
|
||||
* Number of the extent in the file described by this record
|
||||
* @param flag
|
||||
* bit0= This is a root directory entry in a volume descriptor.
|
||||
* Do not compare by dir_rec_size_check.
|
||||
*/
|
||||
static
|
||||
void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id,
|
||||
uint8_t *buf, size_t len_fi, struct susp_info *info,
|
||||
int extent)
|
||||
void write_one_dir_record(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *node,
|
||||
int file_id, uint8_t *buf, size_t len_fi,
|
||||
struct susp_info *info, int extent, int flag)
|
||||
{
|
||||
uint32_t len;
|
||||
uint32_t block;
|
||||
uint8_t len_dr; /*< size of dir entry without SUSP fields */
|
||||
int multi_extend = 0;
|
||||
uint32_t written_size = 0;
|
||||
int multi_extend = 0, ret;
|
||||
uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id
|
||||
: (uint8_t*)node->iso_name;
|
||||
|
||||
@ -461,13 +768,31 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id,
|
||||
rec->flags[0] = ((node->type == ECMA119_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
|
||||
iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
|
||||
rec->len_fi[0] = len_fi;
|
||||
written_size = len_dr;
|
||||
|
||||
/*
|
||||
* and finally write the SUSP fields.
|
||||
*/
|
||||
if (info != NULL) {
|
||||
rrip_write_susp_fields(t, info, buf + len_dr);
|
||||
ret= rrip_write_susp_fields(t, info, buf + len_dr);
|
||||
if (ret < 0) {
|
||||
|
||||
/* >>> ??? how to react on failure of susp_update_CE_sizes ? */;
|
||||
|
||||
} else {
|
||||
written_size += ret;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Libisofs_dir_rec_size_checK
|
||||
|
||||
/* Check written record size against calculated size */
|
||||
written_size += (written_size % 2);
|
||||
if (!(flag & 1))
|
||||
dir_rec_size_check(t, dir, node, (off_t) -1, written_size, 2);
|
||||
|
||||
#endif /* Libisofs_dir_rec_size_checK */
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
@ -612,12 +937,13 @@ int ecma119_writer_write_vol_desc(IsoImageWriter *writer)
|
||||
t->partition_l_table_pos - t->eff_partition_offset, 4);
|
||||
iso_msb(vol.m_path_table_pos,
|
||||
t->partition_m_table_pos - t->eff_partition_offset, 4);
|
||||
write_one_dir_record(t, t->partition_root, 0,
|
||||
vol.root_dir_record, 1, NULL, 0);
|
||||
write_one_dir_record(t, NULL, t->partition_root, 0,
|
||||
vol.root_dir_record, 1, NULL, 0, 1);
|
||||
} else {
|
||||
iso_lsb(vol.l_path_table_pos, t->l_path_table_pos, 4);
|
||||
iso_msb(vol.m_path_table_pos, t->m_path_table_pos, 4);
|
||||
write_one_dir_record(t, t->root, 0, vol.root_dir_record, 1, NULL, 0);
|
||||
write_one_dir_record(t, NULL, t->root, 0, vol.root_dir_record, 1, NULL,
|
||||
0, 1);
|
||||
}
|
||||
|
||||
strncpy_pad((char*)vol.vol_set_id, volset_id, 128);
|
||||
@ -657,6 +983,10 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent)
|
||||
size_t fi_len, len;
|
||||
struct susp_info info;
|
||||
|
||||
#ifdef Libisofs_dir_rec_size_checK
|
||||
off_t bw_mem;
|
||||
#endif /* Libisofs_dir_rec_size_checK */
|
||||
|
||||
/* buf will point to current write position on buffer */
|
||||
uint8_t *buf;
|
||||
|
||||
@ -683,7 +1013,7 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent)
|
||||
}
|
||||
}
|
||||
len = 34 + info.suf_len;
|
||||
write_one_dir_record(t, dir, 0, buf, 1, &info, 0);
|
||||
write_one_dir_record(t, parent, dir, 0, buf, 1, &info, 0, 0);
|
||||
buf += len;
|
||||
|
||||
if (t->opts->rockridge) {
|
||||
@ -693,7 +1023,8 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent)
|
||||
}
|
||||
}
|
||||
len = 34 + info.suf_len;
|
||||
write_one_dir_record(t, parent, 1, buf, 1, &info, 0);
|
||||
write_one_dir_record(t, (parent != NULL ? parent->parent : NULL), parent,
|
||||
1, buf, 1, &info, 0, 0);
|
||||
buf += len;
|
||||
|
||||
for (i = 0; i < dir->info.dir->nchildren; i++) {
|
||||
@ -730,7 +1061,8 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent)
|
||||
buf = buffer;
|
||||
}
|
||||
/* write the directory entry in any case */
|
||||
write_one_dir_record(t, child, -1, buf, fi_len, &info, section);
|
||||
write_one_dir_record(t, dir, child, -1, buf, fi_len, &info,
|
||||
section, 0);
|
||||
buf += len;
|
||||
}
|
||||
}
|
||||
@ -742,9 +1074,27 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent)
|
||||
}
|
||||
|
||||
/* write the Continuation Area if needed */
|
||||
if (info.ce_len > 0) {
|
||||
|
||||
#ifdef Libisofs_dir_rec_size_checK
|
||||
bw_mem = t->bytes_written + t->opts->ms_block * BLOCK_SIZE;
|
||||
#endif /* Libisofs_dir_rec_size_checK */
|
||||
|
||||
if (info.ce_len > 0)
|
||||
ret = rrip_write_ce_fields(t, &info);
|
||||
|
||||
#ifdef Libisofs_dir_rec_size_checK
|
||||
|
||||
if (info.ce_written_len > 0xffffffff) {
|
||||
iso_msg_submit(-1, ISO_INSANE_CE_SIZE, 0,
|
||||
"Continuation area size of 4 GiB or more written : LBA %lu '%s'",
|
||||
(unsigned long) bw_mem / BLOCK_SIZE,
|
||||
ecma119_path_not_threadsafe(dir->parent, dir));
|
||||
info.ce_written_len= 0xffffffff;
|
||||
}
|
||||
dir_rec_size_check(t, dir->parent, dir, bw_mem,
|
||||
(uint32_t) info.ce_written_len, 7);
|
||||
|
||||
#endif /* Libisofs_dir_rec_size_checK */
|
||||
|
||||
ex:;
|
||||
LIBISO_FREE_MEM(buffer);
|
||||
@ -958,7 +1308,7 @@ static
|
||||
int ecma119_writer_write_data(IsoImageWriter *writer)
|
||||
{
|
||||
int ret;
|
||||
Ecma119Image *t;
|
||||
Ecma119Image *t = NULL;
|
||||
uint32_t curblock;
|
||||
char *msg = NULL;
|
||||
|
||||
@ -992,6 +1342,18 @@ int ecma119_writer_write_data(IsoImageWriter *writer)
|
||||
}
|
||||
ret = ISO_SUCCESS;
|
||||
ex:;
|
||||
|
||||
#ifdef Libisofs_dir_rec_size_checK
|
||||
|
||||
if (t != NULL) {
|
||||
/* Report number of mismatches */
|
||||
dir_rec_size_check(t, NULL, NULL, (off_t) -1, (uint32_t) 0, 3);
|
||||
/* Free allocated memory */
|
||||
dir_rec_size_check(t, NULL, NULL, (off_t) -1, (uint32_t) 0, 5);
|
||||
}
|
||||
|
||||
#endif /* Libisofs_dir_rec_size_checK */
|
||||
|
||||
LIBISO_FREE_MEM(msg);
|
||||
return ret;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic
|
||||
* Copyright (c) 2009-2024 Thomas Schmitt
|
||||
* Copyright (c) 2009-2025 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
|
||||
@ -8933,7 +8933,7 @@ int iso_image_get_session_md5(IsoImage *image, uint32_t *start_lba,
|
||||
uint32_t *end_lba, char md5[16], int flag);
|
||||
|
||||
/**
|
||||
* Obtain the recorded MD5 checksum of a data file from the loaded * ISO image.
|
||||
* Obtain the recorded MD5 checksum of a data file from the loaded ISO image.
|
||||
* Such a checksum may be stored with others in a contiguous array at the end
|
||||
* of the loaded session. The data file then has an xattr "isofs.cx" which
|
||||
* gives the index in that array.
|
||||
@ -9903,6 +9903,12 @@ int iso_conv_name_chars(IsoWriteOpts *opts, char *name, size_t name_len,
|
||||
(SORRY,HIGH, -439) */
|
||||
#define ISO_PROJID_NO_OPEN_LOCAL 0xE030FE49
|
||||
|
||||
/** Size calculation mismatch with directory record or continuation area
|
||||
(WARNING,HIGH, -440) */
|
||||
#define ISO_DIR_REC_SIZE_MISMATCH 0xD030FE48
|
||||
|
||||
/** More than 4294967295 bytes of Continuation area (WARNING,HIGH, -441) */
|
||||
#define ISO_INSANE_CE_SIZE 0xD030FE47
|
||||
|
||||
|
||||
/* Internal developer note:
|
||||
|
@ -593,6 +593,10 @@ const char *iso_error_to_msg(int errcode)
|
||||
return "Error with setting XFS-style project id of local file";
|
||||
case ISO_PROJID_NO_OPEN_LOCAL:
|
||||
return "Failure to open local file for XFS-style project id";
|
||||
case ISO_DIR_REC_SIZE_MISMATCH:
|
||||
return "Size calculation mismatch with directory record or continuation area";
|
||||
case ISO_INSANE_CE_SIZE:
|
||||
return "More than 4294967295 bytes of Continuation area";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Vreixo Formoso
|
||||
* Copyright (c) 2007 Mario Danic
|
||||
* Copyright (c) 2009 - 2024 Thomas Schmitt
|
||||
* Copyright (c) 2009 - 2025 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
|
||||
@ -2259,21 +2259,23 @@ int susp_update_CE_sizes(Ecma119Image *t, struct susp_info *info, int flag)
|
||||
* If info does not contain any SUSP entry this function just return.
|
||||
* After written, the info susp_fields array will be freed, and the counters
|
||||
* updated properly.
|
||||
* @return <0 error
|
||||
* >=0 number of written bytes
|
||||
*/
|
||||
void rrip_write_susp_fields(Ecma119Image *t, struct susp_info *info,
|
||||
uint8_t *buf)
|
||||
int rrip_write_susp_fields(Ecma119Image *t, struct susp_info *info,
|
||||
uint8_t *buf)
|
||||
{
|
||||
size_t i;
|
||||
size_t pos = 0;
|
||||
int ret;
|
||||
|
||||
if (info->n_susp_fields == 0) {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = susp_update_CE_sizes(t, info, 0);
|
||||
if (ret < 0)
|
||||
return;
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < info->n_susp_fields; i++) {
|
||||
memcpy(buf + pos, info->susp_fields[i], info->susp_fields[i][2]);
|
||||
@ -2288,6 +2290,8 @@ void rrip_write_susp_fields(Ecma119Image *t, struct susp_info *info,
|
||||
info->susp_fields = NULL;
|
||||
info->n_susp_fields = 0;
|
||||
info->suf_len = 0;
|
||||
|
||||
return (int) pos;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2328,6 +2332,9 @@ int rrip_write_ce_fields(Ecma119Image *t, struct susp_info *info)
|
||||
written += info->ce_susp_fields[i][2];
|
||||
}
|
||||
|
||||
/* Memorize the really written payload before padding */
|
||||
info->ce_written_len = written;
|
||||
|
||||
/* pad continuation area until block size */
|
||||
i = BLOCK_SIZE - (info->ce_len % BLOCK_SIZE);
|
||||
if (i > 0 && i < BLOCK_SIZE) {
|
||||
|
@ -76,6 +76,11 @@ struct susp_info
|
||||
/* Marks the start index in ce_susp_fields of the current node */
|
||||
size_t current_ce_start;
|
||||
|
||||
/* Tells the really written number of Continuation Area payload bytes
|
||||
after rrip_write_ce_fields() wrote them to the output stream.
|
||||
*/
|
||||
uint64_t ce_written_len;
|
||||
|
||||
};
|
||||
|
||||
/* Step to increase allocated size of susp_info.ce_susp_fields */
|
||||
@ -235,8 +240,9 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
|
||||
* If info does not contain any SUSP entry this function just return.
|
||||
* After written, the info susp_fields array will be freed, and the counters
|
||||
* updated properly.
|
||||
* @return the number of written bytes
|
||||
*/
|
||||
void rrip_write_susp_fields(Ecma119Image *t, struct susp_info *info,
|
||||
int rrip_write_susp_fields(Ecma119Image *t, struct susp_info *info,
|
||||
uint8_t *buf);
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user