Fixed bugs in fsck: . incorrect handling of corrupted compressed bodies, reported by Mathieu Bélanger<b747xx@xxxxxxxxx> . use LE32_TO_CPU when reading adler32 checksum of logical clusters of ccreg40 objects. Signed-off-by: Edward Shishkin <edward.shishkin@xxxxxxxxx> --- reiser4progs-1.0.6-orig/plugin/object/ccreg40/ccreg40_repair.c | 161 ++++------ 1 file changed, 77 insertions(+), 84 deletions(-) --- reiser4progs-1.0.6-orig/plugin/object/ccreg40/ccreg40_repair.c.orig +++ reiser4progs-1.0.6-orig/plugin/object/ccreg40/ccreg40_repair.c @@ -21,9 +21,10 @@ typedef struct ccreg40_hint { obj40_stat_hint_t stat; /* Item seek, found and next item offsets. */ - uint64_t seek; - uint64_t found; - uint64_t maxreal; + uint64_t prev_found; /* (key) offset found in the previous iteration */ + uint64_t seek; /* expected offset for lookup */ + uint64_t found; /* what has been really found */ + uint64_t maxreal; /* maximal (key) offset in the found item */ /* Bytes all clusters takes on disk. */ uint32_t bytes; @@ -120,91 +121,64 @@ static int64_t ccreg40_read_item(reiser4 } static errno_t ccreg40_check_crc(ccreg40_hint_t *hint) { - uint32_t adler, disk; - uint64_t offset; - - offset = (hint->seek % hint->clsize) - sizeof(uint32_t); - + uint32_t adler, disk, offset; + + aal_assert("edward-2", hint->bytes > sizeof(uint32_t)); + + offset = hint->bytes - sizeof(uint32_t); + adler = aux_adler32(0, (char *)hint->data, offset); - disk = *(uint32_t *)(hint->data + offset); - - return adler == disk ? 0 : RE_FATAL; -} + disk = LE32_TO_CPU(*(uint32_t *)(hint->data + offset)); -static errno_t cc_write_item(reiser4_place_t *place, void *data) { - return ccreg40_set_cluster_size(place, *(uint32_t *)data); + return adler == disk ? 0 : RE_FATAL; } static errno_t ccreg40_check_cluster(reiser4_object_t *cc, ccreg40_hint_t *hint, uint8_t mode) { - trans_hint_t trans; - uint64_t offset; errno_t result; errno_t res; int start; - int last; - + uint32_t lcl_size; + result = 0; - start = (ccreg40_clstart(hint->seek, hint->clsize) == hint->seek); - last = (hint->sdsize == hint->seek); - - if ((cc->body.plug == NULL) || (hint->seek && start) || - !ccreg40_clsame(hint->seek, hint->found, hint->clsize)) - { - /* Cluster is over. */ - if (start || (last && !cc->body.plug)) { - /* The previous cluster is not compressed: - 1) there were @hint->clsize bytes in it; - 2) file size is reached and no more items found. */ - uint64_t clstart, clsize; + /* true, if the found item is the + first one in the disk cluster */ + start = (ccreg40_clstart(hint->found, hint->clsize) == hint->found); + + if ((cc->body.plug == NULL) || + (hint->seek && start) || + !ccreg40_clsame(hint->prev_found, hint->found, hint->clsize)) { + /* Cluster is over */ - clstart = ccreg40_clstart(hint->seek, hint->clsize); - clstart -= (start ? hint->clsize : 0); - - clsize = (start ? hint->clsize : hint->sdsize - clstart); - - /* If there is a hole in the previous cluster, - overwrite it. */ - if (hint->hole) { - fsck_mess("The file [%s] (%s): the not-compressed " - "cluster at [%llu] offset has some items " - "missed.%s", - print_inode(obj40_core, &cc->info.object), - reiser4_psobj(cc)->p.label, hint->clstart, - hint->mode != RM_CHECK ? " Filled with " - "zeroes." : ""); - - if (hint->mode == RM_BUILD) { - res = obj40_write(cc, &trans, - hint->data, - clstart, clsize, - reiser4_psctail(cc), - cc_write_item, - &hint->clsize); - if (res < 0) return res; - - hint->bytes += trans.bytes; - } else if (hint->hole) { - result = RE_FATAL; - } - } - } else if (hint->hole || ccreg40_check_crc(hint)) { - /* 1. There is a hole at the end of the cluster && - 2. Not the last cluster or sdsize is not equal to - the real amount of bytes. - - There are holes in the middle of the cluster or - checksum does not match. Delete the whole cluster. */ - + if (hint->prev_found > hint->sdsize) { + /* cluster is orphan */ hint->bytes = 0; result = RE_FATAL; - - /* Start offset of the cluster to be deleted. */ - hint->clstart = ccreg40_clstart(hint->seek, + + /* set offset of the cluster to be deleted. */ + hint->clstart = ccreg40_clstart(hint->prev_found, + hint->clsize); + fsck_mess("The file [%s] (%s): the cluster at [%llu] " + "offset %u bytes long is orphan.%s", + print_inode(obj40_core, &cc->info.object), + reiser4_psobj(cc)->p.label, hint->clstart, + hint->clsize, hint->mode != RM_CHECK ? + " Removed." : ""); + } + /** + * If there still is a hole in the logical cluster, + * then check a checksum (no hole means no checksum) + */ + else if (hint->hole && ccreg40_check_crc(hint)) { + /* wrong checksum */ + hint->bytes = 0; + result = RE_FATAL; + + /* set offset of the cluster to be deleted. */ + hint->clstart = ccreg40_clstart(hint->prev_found, hint->clsize); - fsck_mess("The file [%s] (%s): the cluster at [%llu] " "offset %u bytes long is corrupted.%s", print_inode(obj40_core, &cc->info.object), @@ -212,32 +186,40 @@ static errno_t ccreg40_check_cluster(rei hint->clsize, hint->mode != RM_CHECK ? " Removed." : ""); } - /* Fini all the data related to the previous cluster. */ hint->stat.bytes += hint->bytes; hint->bytes = 0; hint->adler = 0; - hint->hole = 0; - + if (!cc->body.plug) return result; - + /* Update the cluster data. */ aal_memset(hint->data, 0, hint->clsize); } /* An item found. */ - offset = ccreg40_clstart(hint->found, hint->clsize); - offset = offset >= hint->seek ? offset : hint->seek; - - /* A hole b/w items or in the beginning found. */ - if (hint->found - offset) - hint->hole = 1; - + aal_assert("edward-1", + ccreg40_clstart(hint->found, hint->clsize) == + ccreg40_clstart(hint->maxreal, hint->clsize)); + if ((res = ccreg40_read_item(&cc->body, hint))) return res; - + + hint->prev_found = hint->found; hint->bytes += objcall(&cc->body, object->bytes); + /** + * Calculate a size of logical cluster + * and figure out, if there is a hole + * for the found items in the logical cluster. + */ + lcl_size = 0; + if (ccreg40_clsame(hint->found, hint->sdsize - 1, hint->clsize)) + lcl_size = hint->sdsize % hint->clsize; + if (lcl_size == 0) + lcl_size = hint->clsize; + hint->hole = (hint->bytes != lcl_size); + return result; } @@ -331,3 +313,14 @@ errno_t ccreg40_check_struct(reiser4_obj } #endif + +/* + Local variables: + c-indentation-style: "K&R" + mode-name: "LC" + c-basic-offset: 8 + tab-width: 8 + fill-column: 80 + scroll-step: 1 + End: +*/