From 357d1863d64ce807c2904e101fc87d3f6be2f3ca Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 2 Feb 2008 21:26:54 -0500 Subject: [PATCH] libext2: Add BLOCK_FLAG_READ_ONLY flag to ext2fs_block_iterate2() This flag allows the caller to promise that it will not try to modify the block numbers returned by the iterator. Signed-off-by: "Theodore Ts'o" --- lib/ext2fs/block.c | 22 +++++++++++++++++++++- lib/ext2fs/dir_iterate.c | 2 +- lib/ext2fs/ext2_err.et.in | 3 +++ lib/ext2fs/ext2fs.h | 4 ++++ lib/ext2fs/read_bb.c | 4 ++-- 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/ext2fs/block.c b/lib/ext2fs/block.c index 07a6415..381d31c 100644 --- a/lib/ext2fs/block.c +++ b/lib/ext2fs/block.c @@ -36,6 +36,16 @@ struct block_context { void *priv_data; }; +#define check_for_ro_violation(ctx, ret) \ + do { \ + if (((ctx)->flags & BLOCK_FLAG_READ_ONLY) && \ + ((ret) & BLOCK_CHANGED)) { \ + (ctx)->errcode = EXT2_ET_RO_BLOCK_ITERATE; \ + return BLOCK_ABORT; \ + } \ + } while (0) + + static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, int ref_offset, struct block_context *ctx) { @@ -49,6 +59,7 @@ static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, ret = (*ctx->func)(ctx->fs, ind_block, BLOCK_COUNT_IND, ref_block, ref_offset, ctx->priv_data); + check_for_ro_violation(ctx, ret); if (!*ind_block || (ret & BLOCK_ABORT)) { ctx->bcount += limit; return ret; @@ -95,6 +106,7 @@ static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, offset += sizeof(blk_t); } } + check_for_ro_violation(ctx, changed); if (changed & BLOCK_CHANGED) { ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block, ctx->ind_buf); @@ -107,6 +119,7 @@ static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, ret |= (*ctx->func)(ctx->fs, ind_block, BLOCK_COUNT_IND, ref_block, ref_offset, ctx->priv_data); + check_for_ro_violation(ctx, ret); return ret; } @@ -123,6 +136,7 @@ static int block_iterate_dind(blk_t *dind_block, blk_t ref_block, ret = (*ctx->func)(ctx->fs, dind_block, BLOCK_COUNT_DIND, ref_block, ref_offset, ctx->priv_data); + check_for_ro_violation(ctx, ret); if (!*dind_block || (ret & BLOCK_ABORT)) { ctx->bcount += limit*limit; return ret; @@ -171,6 +185,7 @@ static int block_iterate_dind(blk_t *dind_block, blk_t ref_block, offset += sizeof(blk_t); } } + check_for_ro_violation(ctx, changed); if (changed & BLOCK_CHANGED) { ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block, ctx->dind_buf); @@ -183,6 +198,7 @@ static int block_iterate_dind(blk_t *dind_block, blk_t ref_block, ret |= (*ctx->func)(ctx->fs, dind_block, BLOCK_COUNT_DIND, ref_block, ref_offset, ctx->priv_data); + check_for_ro_violation(ctx, ret); return ret; } @@ -199,6 +215,7 @@ static int block_iterate_tind(blk_t *tind_block, blk_t ref_block, ret = (*ctx->func)(ctx->fs, tind_block, BLOCK_COUNT_TIND, ref_block, ref_offset, ctx->priv_data); + check_for_ro_violation(ctx, ret); if (!*tind_block || (ret & BLOCK_ABORT)) { ctx->bcount += limit*limit*limit; return ret; @@ -247,6 +264,7 @@ static int block_iterate_tind(blk_t *tind_block, blk_t ref_block, offset += sizeof(blk_t); } } + check_for_ro_violation(ctx, changed); if (changed & BLOCK_CHANGED) { ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block, ctx->tind_buf); @@ -259,7 +277,7 @@ static int block_iterate_tind(blk_t *tind_block, blk_t ref_block, ret |= (*ctx->func)(ctx->fs, tind_block, BLOCK_COUNT_TIND, ref_block, ref_offset, ctx->priv_data); - + check_for_ro_violation(ctx, ret); return ret; } @@ -334,6 +352,7 @@ errcode_t ext2fs_block_iterate2(ext2_filsys fs, &inode.osd1.hurd1.h_i_translator, BLOCK_COUNT_TRANSLATOR, 0, 0, priv_data); + check_for_ro_violation(&ctx, ret); if (ret & BLOCK_ABORT) goto abort_exit; } @@ -350,6 +369,7 @@ errcode_t ext2fs_block_iterate2(ext2_filsys fs, goto abort_exit; } } + check_for_ro_violation(&ctx, ret); if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK, 0, EXT2_IND_BLOCK, &ctx); diff --git a/lib/ext2fs/dir_iterate.c b/lib/ext2fs/dir_iterate.c index 003c0a3..3e7b7b0 100644 --- a/lib/ext2fs/dir_iterate.c +++ b/lib/ext2fs/dir_iterate.c @@ -78,7 +78,7 @@ errcode_t ext2fs_dir_iterate2(ext2_filsys fs, ctx.func = func; ctx.priv_data = priv_data; ctx.errcode = 0; - retval = ext2fs_block_iterate2(fs, dir, 0, 0, + retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_READ_ONLY, 0, ext2fs_process_dir_block, &ctx); if (!block_buf) ext2fs_free_mem(&ctx.buf); diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in index eda4bb4..2f44219 100644 --- a/lib/ext2fs/ext2_err.et.in +++ b/lib/ext2fs/ext2_err.et.in @@ -326,5 +326,8 @@ ec EXT2_ET_TDB_ERR_NOEXIST, ec EXT2_ET_TDB_ERR_RDONLY, "TDB: Write not permitted" +ec EXT2_ET_RO_BLOCK_ITERATE, + "Attempt to modify a block mapping via a read-only block iterator" + end diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 19213b8..731033f 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -259,6 +259,9 @@ struct struct_ext2_filsys { * BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be * called for data blocks only. * + * BLOCK_FLAG_READ_ONLY is a promise by the caller that it will not + * modify returned block number. + * * BLOCK_FLAG_NO_LARGE is for internal use only. It informs * ext2fs_block_iterate2 that large files won't be accepted. */ @@ -266,6 +269,7 @@ struct struct_ext2_filsys { #define BLOCK_FLAG_HOLE 1 #define BLOCK_FLAG_DEPTH_TRAVERSE 2 #define BLOCK_FLAG_DATA_ONLY 4 +#define BLOCK_FLAG_READ_ONLY 8 #define BLOCK_FLAG_NO_LARGE 0x1000 diff --git a/lib/ext2fs/read_bb.c b/lib/ext2fs/read_bb.c index c717adc..ff7e292 100644 --- a/lib/ext2fs/read_bb.c +++ b/lib/ext2fs/read_bb.c @@ -86,8 +86,8 @@ errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list) rb.bb_list = *bb_list; rb.err = 0; - retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, 0, 0, - mark_bad_block, &rb); + retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, BLOCK_FLAG_READ_ONLY, + 0, mark_bad_block, &rb); if (retval) return retval; -- 1.8.3.1