From c3af3553dfa1583a9c0378ab49835b56d3725904 Mon Sep 17 00:00:00 2001 From: Vreixo Formoso Date: Mon, 24 Dec 2007 16:29:57 +0100 Subject: [PATCH] Define functions to generate and write the RR/SUSP fields. --- src/ecma119.c | 83 +++++++++++++++++++++++++++++++++++++++---------- src/rockridge.c | 16 ++++++++++ src/rockridge.h | 76 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 154 insertions(+), 21 deletions(-) diff --git a/src/ecma119.c b/src/ecma119.c index 45b1f27..aad9254 100644 --- a/src/ecma119.c +++ b/src/ecma119.c @@ -78,7 +78,7 @@ size_t calc_dir_size(Ecma119Image *t, Ecma119Node *dir, size_t *ce) size_t ce_len = 0; /* size of "." and ".." entries */ - len += 34 + 34; + len = 34 + 34; if (t->rockridge) { len += rrip_calc_len(t, dir, 1, 255 - 34, &ce_len); *ce += ce_len; @@ -188,23 +188,24 @@ int ecma119_writer_compute_data_blocks(IsoImageWriter *writer) * Write a single directory record (ECMA-119, 9.1) * * @param file_id - * if >= 0, we use it instead of the filename (for "." and ".." entries). - * As a magic number, file_id == 3 means that we are writing the root - * directory record in the PVD (ECMA-119, 8.4.18) (in order to distinguish - * it from the "." entry in the root directory) + * if >= 0, we use it instead of the filename (for "." and ".." entries). * @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) + * entry will be len + 33 + padding if needed (ECMA-119, 9.1.12) + * @param info + * 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) */ static void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id, - uint8_t *buf, size_t len_fi) + uint8_t *buf, size_t len_fi, struct susp_info *info) { uint32_t len; uint32_t block; - uint8_t len_dr; - uint8_t f_id = (uint8_t) ((file_id == 3) ? 0 : file_id); - uint8_t *name = (file_id >= 0) ? &f_id : (uint8_t*)node->iso_name; + uint8_t len_dr; /*< size of dir entry without SUSP fields */ + uint8_t *name = (file_id >= 0) ? (uint8_t*)&file_id : + (uint8_t*)node->iso_name; struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf; @@ -240,13 +241,18 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id, if (file_id == 1 && node->parent) node = node->parent; - rec->len_dr[0] = len_dr; + rec->len_dr[0] = len_dr + (info != NULL ? info->suf_len : 0); iso_bb(rec->block, block, 4); iso_bb(rec->length, len, 4); iso_datetime_7(rec->recording_time, t->now); rec->flags[0] = (node->type == ECMA119_DIR) ? 2 : 0; iso_bb(rec->vol_seq_number, 1, 2); rec->len_fi[0] = len_fi; + + /* and finally write the SUSP fields */ + if (info != NULL) { + rrip_write_susp_fields(t, info, buf + len_dr); + } } /** @@ -303,7 +309,7 @@ int ecma119_writer_write_vol_desc(IsoImageWriter *writer) 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, 3, vol.root_dir_record, 1); + write_one_dir_record(t, t->root, 0, vol.root_dir_record, 1, NULL); if (volset_id) strncpy((char*)vol.vol_set_id, volset_id, 128); @@ -347,19 +353,43 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir) uint8_t buffer[BLOCK_SIZE]; size_t i; size_t fi_len, len; + struct susp_info info; /* buf will point to current write position on buffer */ uint8_t *buf = buffer; /* initialize buffer with 0s */ memset(buffer, 0, BLOCK_SIZE); + + /* + * set susp_info to 0's, this way code for both plain ECMA-119 and + * RR is very similar + */ + memset(&info, 0, sizeof(struct susp_info)); + if (t->rockridge) { + /* initialize the ce_block, it might be needed */ + info.ce_block = div_up(dir->info.dir.block + dir->info.dir.len, + BLOCK_SIZE); + } /* write the "." and ".." entries first */ - write_one_dir_record(t, dir, 0, buf, 1); - buf += 34; + if (t->rockridge) { + ret = rrip_get_susp_fields(t, dir, 1, 255 - 32, &info); + if (ret < 0) { + return ret; + } + } + write_one_dir_record(t, dir, 0, buf, 1, &info); + buf += 34 + info.suf_len; - write_one_dir_record(t, dir, 1, buf, 1); - buf += 34; + if (t->rockridge) { + ret = rrip_get_susp_fields(t, dir, 2, 255 - 32, &info); + if (ret < 0) { + return ret; + } + } + write_one_dir_record(t, dir, 1, buf, 1, &info); + buf += 34 + info.suf_len; for (i = 0; i < dir->info.dir.nchildren; i++) { Ecma119Node *child = dir->info.dir.children[i]; @@ -370,6 +400,16 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir) if (child->type == ECMA119_FILE && !t->omit_version_numbers) { len += 2; } + + /* get the SUSP fields if rockridge is enabled */ + if (t->rockridge) { + ret = rrip_get_susp_fields(t, child, 0, 255 - len, &info); + if (ret < 0) { + return ret; + } + len += info.suf_len; + } + if ( (buf + len - buffer) > BLOCK_SIZE ) { /* dir doesn't fit in current block */ ret = iso_write(t, buffer, BLOCK_SIZE); @@ -380,12 +420,21 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir) buf = buffer; } /* write the directory entry in any case */ - write_one_dir_record(t, child, -1, buf, fi_len); + write_one_dir_record(t, child, -1, buf, fi_len, &info); buf += len; } /* write the last block */ ret = iso_write(t, buffer, BLOCK_SIZE); + if (ret < 0) { + return ret; + } + + /* write the Continuation Area if needed */ + if (info.ce_len > 0) { + ret = rrip_write_ce_fields(t, &info); + } + return ret; } diff --git a/src/rockridge.c b/src/rockridge.c index 8150488..35e18f6 100644 --- a/src/rockridge.c +++ b/src/rockridge.c @@ -199,6 +199,22 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, return su_size; } +int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type, + size_t space, struct susp_info *info) +{ + //TODO to implement + return -1; +} +void rrip_write_susp_fields(Ecma119Image *t, struct susp_info *info, + void *buf) +{ + //TODO to implement +} +int rrip_write_ce_fields(Ecma119Image *t, struct susp_info *info) +{ + //TODO to implement + return -1; +} diff --git a/src/rockridge.h b/src/rockridge.h index ca00d6e..d54e61f 100644 --- a/src/rockridge.h +++ b/src/rockridge.h @@ -7,11 +7,20 @@ * published by the Free Software Foundation. See COPYING file for details. */ -/** - * Functions and structures used for Rock Ridge support. +/** + * This header defines the functions and structures needed to add RockRidge + * extensions to an ISO image. * - * See IEEE P1282, Rock Ridge Interchange Protocol, Draft Standard version - * 1.12 for further details. + * References: + * + * - SUSP (IEEE 1281). + * System Use Sharing Protocol, draft standard version 1.12. + * + * - RRIP (IEEE 1282) + * Rock Ridge Interchange Protocol, Draft Standard version 1.12. + * + * - ECMA-119 (ISO-9660) + * Volume and File Structure of CDROM for Information Interchange. */ #ifndef LIBISO_ROCKRIDGE_H @@ -19,6 +28,30 @@ #include "ecma119.h" + +/** + * This contains the information about the System Use Fields (SUSP, 4.1), + * that will be written in the System Use Areas, both in the ISO directory + * record System Use field (ECMA-119, 9.1.13) or in a Continuation Area as + * defined by SUSP. + */ +struct susp_info +{ + /** Number of SUSP fields in the System Use field */ + size_t n_susp_fields; + uint8_t **susp_fields; + + /** Length of the part of the SUSP area that fits in the dirent. */ + int suf_len; + + /** Length of the part of the SUSP area that will go in a CE area. */ + uint32_t ce_block; + uint32_t ce_len; + + size_t n_ce_susp_fields; + uint8_t **ce_susp_fields; +}; + /** * Compute the length needed for write all RR and SUSP entries for a given * node. @@ -36,4 +69,39 @@ size_t rrip_calc_len(Ecma119Image *t, Ecma119Node *n, int type, size_t space, size_t *ce); +/** + * Fill a struct susp_info with the RR/SUSP entries needed for a given + * node. + * + * @param type + * 0 normal entry, 1 "." entry for that node (it is a dir), 2 ".." + * for that node (i.e., it will refer to the parent) + * @param space + * Available space in the System Use Area for the directory record. + * @param info + * Pointer to the struct susp_info where the entries will be stored. + * If some entries need to go to a Continuation Area, they will be added + * to the existing ce_susp_fields, and ce_len will be incremented + * propertly. Please ensure ce_block is initialized propertly. + */ +int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type, + size_t space, struct susp_info *info); + +/** + * Write the given SUSP fields into buf. Note that Continuation Area + * fields are not written. + * 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 propertly. + */ +void rrip_write_susp_fields(Ecma119Image *t, struct susp_info *info, + void *buf); + +/** + * Write the Continuation Area entries for the given struct susp_info, using + * the iso_write() function. + * After written, the ce_susp_fields array will be freed. + */ +int rrip_write_ce_fields(Ecma119Image *t, struct susp_info *info); + #endif /* LIBISO_ROCKRIDGE_H */