From a485e91d1ac9102ec6842a9cc586d314c2a8e44d Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Tue, 24 Jun 2025 13:26:33 +0200 Subject: [PATCH] Enhanced reporting with --enable-dir-rec-size-check --- libisofs/ecma119.c | 126 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 95 insertions(+), 31 deletions(-) diff --git a/libisofs/ecma119.c b/libisofs/ecma119.c index 649c4e7..7d99a9a 100644 --- a/libisofs/ecma119.c +++ b/libisofs/ecma119.c @@ -72,21 +72,31 @@ int iso_write_opts_clone(IsoWriteOpts *in, IsoWriteOpts **out, int flag); #ifdef Libisofs_dir_rec_size_checK +/* @param file_id : 0= '.' node , 1= '..' node , else= normal node + */ static -char *ecma119_path_not_threadsafe(Ecma119Node *dir, Ecma119Node *node) +char *ecma119_path_not_threadsafe(Ecma119Node *dir, Ecma119Node *node, + int file_id) { - int loop_count, len = 0, pos; + int loop_count, len = 0, pos, l; Ecma119Node *parent; + char *iso_name = NULL; static char path[1024]; - if (node->iso_name == NULL) { + if (file_id != 0 && file_id != 1) + iso_name = node->iso_name; + if (iso_name == NULL && (dir == NULL || dir->iso_name == NULL)) { strcpy(path, "/"); - return path; + goto return_path; } /* Determine path length */ - /* Slash, leafname, zero byte */ - len = 1 + strlen(node->iso_name) + 1; + /* Zero byte */ + len = 1; + if (iso_name != NULL) { + /* Slash, leafname */ + len += 1 + strlen(iso_name); + } parent = dir; for (loop_count = 0; loop_count < 512; loop_count++) { if (parent == NULL) @@ -98,18 +108,25 @@ char *ecma119_path_not_threadsafe(Ecma119Node *dir, Ecma119Node *node) parent = parent->parent; } if (len >= 1024 || loop_count >= 512) { +oversized_path:; strcpy(path, "_oversized_path_/"); - strcat(path, node->iso_name); - return path; + if (iso_name != NULL) + strcat(path, iso_name); + /* Make sure that the path is not oversized and can take add-ons */ + if (strlen(path) >= 1024 - 3) + path[1024 - 4] = 0; + goto 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] = '/'; + if (iso_name != NULL) { + pos -= strlen(iso_name); + memcpy(path + pos, iso_name, strlen(iso_name)); + pos--; + path[pos] = '/'; + } parent = dir; for (loop_count = 0; loop_count < 512; loop_count++) { if (parent == NULL) @@ -129,6 +146,21 @@ char *ecma119_path_not_threadsafe(Ecma119Node *dir, Ecma119Node *node) path[pos] = ' '; } +return_path:; + if (file_id == 0 || file_id == 1) { + if (strlen(path) + 3 >= 1024) + goto oversized_path; + l = strlen(path); + if (l > 0) + l--; + if (path[l] != '/') + strcat(path, "/"); + if (file_id == 0) { + strcat(path, "."); + } else { + strcat(path, ".."); + } + } return path; } @@ -138,6 +170,10 @@ char *ecma119_path_not_threadsafe(Ecma119Node *dir, Ecma119Node *node) during the calculation stage or compare the written sizes with the recorded predictions. + @param file_id directory type for modes 2 and 7: + 0='.' , 1='..' , <0 any other type , >1 reserved + @param byte_adr byte address of the directory record for mode 1 + byte address of the continuation area for mode 7 @param mode 0= initialize 1= record directory record size 2= compare and complain directory record size @@ -159,7 +195,8 @@ char *ecma119_path_not_threadsafe(Ecma119Node *dir, Ecma119Node *node) */ static int dir_rec_size_check(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *node, - off_t byte_adr, uint32_t rec_size, int mode) + int file_id, 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; @@ -222,10 +259,14 @@ int dir_rec_size_check(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *node, if (rec_size_list[read_idx - 1] != rec_size) { mismatch_count++; if (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, "Directory record size calculation mismatch: LBA %lu '%s' : %lu -> %lu", - (unsigned long) t->curblock, - ecma119_path_not_threadsafe(dir, node), + (unsigned long) block, + ecma119_path_not_threadsafe(dir, node, file_id), (unsigned long) rec_size_list[read_idx - 1], (unsigned long) rec_size); } @@ -300,7 +341,7 @@ int dir_rec_size_check(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *node, "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), + ecma119_path_not_threadsafe(dir, node, file_id), (unsigned long) ce_size_list[ce_read_idx - 1], (unsigned long) rec_size); } @@ -475,7 +516,8 @@ ssize_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce) #ifdef Libisofs_dir_rec_size_checK /* Record calculated size */ - dir_rec_size_check(t, NULL, NULL, (off_t) -1, (uint32_t) dirent_len, 1); + dir_rec_size_check(t, NULL, NULL, -1, (off_t) -1, (uint32_t) dirent_len, + 1); #endif /* Libisofs_dir_rec_size_checK */ @@ -492,7 +534,8 @@ ssize_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce) #ifdef Libisofs_dir_rec_size_checK - dir_rec_size_check(t, NULL, NULL, (off_t) -1, (uint32_t) dirent_len, 1); + dir_rec_size_check(t, NULL, NULL, -1, (off_t) -1, (uint32_t) dirent_len, + 1); #endif /* Libisofs_dir_rec_size_checK */ @@ -523,7 +566,7 @@ ssize_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce) #ifdef Libisofs_dir_rec_size_checK - dir_rec_size_check(t, dir, child, (off_t) -1, + dir_rec_size_check(t, dir, child, -1, (off_t) -1, (uint32_t) dirent_len, 1); #endif /* Libisofs_dir_rec_size_checK */ @@ -567,11 +610,11 @@ int calc_dir_pos(Ecma119Image *t, Ecma119Node *dir) 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)); + ecma119_path_not_threadsafe(dir->parent, dir, -1)); ce_len= 0xffffffff; } - dir_rec_size_check(t, dir->parent, dir, (off_t) -1, (uint32_t) ce_len, - 6); + dir_rec_size_check(t, dir->parent, dir, -1, (off_t) -1, + (uint32_t) ce_len, 6); #endif /* Libisofs_dir_rec_size_checK */ @@ -628,7 +671,7 @@ int ecma119_writer_compute_data_blocks(IsoImageWriter *writer) #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); + dir_rec_size_check(target, NULL, NULL, -1, (off_t) -1, (uint32_t) 0, 0); #endif /* Libisofs_dir_rec_size_checK */ @@ -688,8 +731,16 @@ int ecma119_writer_compute_data_blocks(IsoImageWriter *writer) /** * Write a single directory record (ECMA-119, 9.1) * + * @param t + * the overall control object + * @param check_dir + * the directory node which shall be reported as parent of node or file_id + * in a possible call to dir_rec_size_check() + * @param node + * the node which shall be represented by the directory record * @param file_id - * if >= 0, we use it instead of the filename (for "." and ".." entries). + * if >= 0, special file identifier to override node->iso_name: + * 0="." , 1="..". Both written with len_fi 1. * @param len_fi * Computed length of the file identifier. Total size of the directory * entry will be len + 33 + padding if needed (ECMA-119, 9.1.12) @@ -711,11 +762,14 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *node, uint32_t len; uint32_t block; uint8_t len_dr; /*< size of dir entry without SUSP fields */ - 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; +#ifdef Libisofs_dir_rec_size_checK + uint32_t written_size = 0; +#endif + struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf; IsoNode *iso; @@ -769,7 +823,10 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *node, 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; + +#ifdef Libisofs_dir_rec_size_checK written_size = len_dr; +#endif /* * and finally write the SUSP fields. @@ -780,8 +837,13 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *node, /* >>> ??? how to react on failure of susp_update_CE_sizes ? */; +#ifdef Libisofs_dir_rec_size_checK + } else { written_size += ret; + +#endif + } } @@ -790,7 +852,9 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *node, /* 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); + dir_rec_size_check(t, check_dir, node, file_id, + t->bytes_written + (off_t) t->opts->ms_block * (off_t) BLOCK_SIZE, + written_size, 2); #endif /* Libisofs_dir_rec_size_checK */ @@ -1014,7 +1078,7 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent) } } len = 34 + info.suf_len; - write_one_dir_record(t, parent, dir, 0, buf, 1, &info, 0, 0); + write_one_dir_record(t, dir, dir, 0, buf, 1, &info, 0, 0); buf += len; if (t->opts->rockridge) { @@ -1092,10 +1156,10 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent) 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)); + ecma119_path_not_threadsafe(dir->parent, dir, -1)); info.ce_written_len= 0xffffffff; } - dir_rec_size_check(t, dir->parent, dir, bw_mem, + dir_rec_size_check(t, dir->parent, dir, -1, bw_mem, (uint32_t) info.ce_written_len, 7); #endif /* Libisofs_dir_rec_size_checK */ @@ -1351,9 +1415,9 @@ ex:; if (t != NULL) { /* Report number of mismatches */ - dir_rec_size_check(t, NULL, NULL, (off_t) -1, (uint32_t) 0, 3); + dir_rec_size_check(t, NULL, NULL, -1, (off_t) -1, (uint32_t) 0, 3); /* Free allocated memory */ - dir_rec_size_check(t, NULL, NULL, (off_t) -1, (uint32_t) 0, 5); + dir_rec_size_check(t, NULL, NULL, -1, (off_t) -1, (uint32_t) 0, 5); } #endif /* Libisofs_dir_rec_size_checK */