From f8f2dcb6b091f224153986ac9477cca1115bdf5f Mon Sep 17 00:00:00 2001 From: Vreixo Formoso Date: Tue, 25 Dec 2007 18:35:10 +0100 Subject: [PATCH] RockRidge support, now RR/SUSP entries are correctly written. This also fix a little bug, ensuring SP is written first to the "." entry of the directory record. --- src/ecma119.c | 10 +++--- src/rockridge.c | 90 ++++++++++++++++++++++++++++++++++++++++++++----- src/rockridge.h | 2 +- 3 files changed, 88 insertions(+), 14 deletions(-) diff --git a/src/ecma119.c b/src/ecma119.c index aad9254..ad831d1 100644 --- a/src/ecma119.c +++ b/src/ecma119.c @@ -368,8 +368,8 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir) 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); + info.ce_block = dir->info.dir.block + div_up(dir->info.dir.len, + BLOCK_SIZE); } /* write the "." and ".." entries first */ @@ -379,8 +379,9 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir) return ret; } } + len = 34 + info.suf_len; write_one_dir_record(t, dir, 0, buf, 1, &info); - buf += 34 + info.suf_len; + buf += len; if (t->rockridge) { ret = rrip_get_susp_fields(t, dir, 2, 255 - 32, &info); @@ -388,8 +389,9 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir) return ret; } } + len = 34 + info.suf_len; write_one_dir_record(t, dir, 1, buf, 1, &info); - buf += 34 + info.suf_len; + buf += len; for (i = 0; i < dir->info.dir.nchildren; i++) { Ecma119Node *child = dir->info.dir.children[i]; diff --git a/src/rockridge.c b/src/rockridge.c index 5e9047a..b76342c 100644 --- a/src/rockridge.c +++ b/src/rockridge.c @@ -11,6 +11,7 @@ #include "node.h" #include "ecma119_tree.h" #include "error.h" +#include "writer.h" #include @@ -717,6 +718,16 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type, */ space--; + /* + * SP must be the first entry for the "." record of the root directory + */ + if (type == 1 && n->parent == NULL) { + ret = susp_add_SP(t, info); + if (ret < 0) { + goto add_susp_cleanup; + } + } + /* PX and TF, we are sure they always fit in SUA */ ret = rrip_add_PX(t, node, info); if (ret < 0) { @@ -1009,12 +1020,9 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type, /* * "." for root directory * we need to write SP and ER entries. The first fits in SUA, - * ER needs a Continuation Area, thus we also need a CE entry + * ER needs a Continuation Area, thus we also need a CE entry. + * Note that SP entry was already added above */ - ret = susp_add_SP(t, info); - if (ret < 0) { - goto add_susp_cleanup; - } ret = susp_add_CE(t, 182, info); /* 182 is ER length */ if (ret < 0) { goto add_susp_cleanup; @@ -1026,6 +1034,12 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type, } } + /* + * The System Use field inside the directory record must be padded if + * it is an odd number (ECMA-119, 9.1.13) + */ + info->suf_len += (info->suf_len % 2); + return ISO_SUCCESS; add_susp_cleanup:; @@ -1033,15 +1047,73 @@ add_susp_cleanup:; return ret; } +/** + * 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) + uint8_t *buf) { - //TODO to implement + size_t i; + size_t pos = 0; + + for (i = 0; i < info->n_susp_fields; i++) { + memcpy(buf + pos, info->susp_fields[i], info->susp_fields[i][2]); + pos += info->susp_fields[i][2]; + } + + /* free susp_fields */ + for (i = 0; i < info->n_susp_fields; ++i) { + free(info->susp_fields[i]); + } + free(info->susp_fields); + info->susp_fields = NULL; + info->n_susp_fields = 0; + info->suf_len = 0; } +/** + * 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) { - //TODO to implement - return -1; + size_t i; + uint8_t padding[BLOCK_SIZE]; + int ret = ISO_SUCCESS; + + if (info->n_ce_susp_fields == 0) { + return ret; + } + + for (i = 0; i < info->n_ce_susp_fields; i++) { + ret = iso_write(t, info->ce_susp_fields[i], + info->ce_susp_fields[i][2]); + if (ret < 0) { + goto write_ce_field_cleanup; + } + } + + /* pad continuation area until block size */ + i = BLOCK_SIZE - (info->ce_len % BLOCK_SIZE); + if (i > 0 && i < BLOCK_SIZE) { + memset(padding, 0, i); + ret = iso_write(t, padding, i); + } + +write_ce_field_cleanup:; + /* free ce_susp_fields */ + for (i = 0; i < info->n_ce_susp_fields; ++i) { + free(info->ce_susp_fields[i]); + } + free(info->ce_susp_fields); + info->ce_susp_fields = NULL; + info->n_ce_susp_fields = 0; + info->ce_len = 0; + return ret; } diff --git a/src/rockridge.h b/src/rockridge.h index 188df4e..81e2854 100644 --- a/src/rockridge.h +++ b/src/rockridge.h @@ -97,7 +97,7 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type, * updated propertly. */ void rrip_write_susp_fields(Ecma119Image *t, struct susp_info *info, - void *buf); + uint8_t *buf); /** * Write the Continuation Area entries for the given struct susp_info, using