]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
libext2: Add BLOCK_FLAG_READ_ONLY flag to ext2fs_block_iterate2()
authorTheodore Ts'o <tytso@mit.edu>
Sun, 3 Feb 2008 02:26:54 +0000 (21:26 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 10 Feb 2008 13:04:09 +0000 (08:04 -0500)
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" <tytso@mit.edu>
lib/ext2fs/block.c
lib/ext2fs/dir_iterate.c
lib/ext2fs/ext2_err.et.in
lib/ext2fs/ext2fs.h
lib/ext2fs/read_bb.c

index 07a64157e6f407b80543922d3ef1612a56474338..381d31c78191602332e70f14a61d4cccbe6a4149 100644 (file)
@@ -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);
index 003c0a3bdfbbbebed5b33d869c54db0a244efc6e..3e7b7b06eebe93d207bbb6544fab4023d22bd717 100644 (file)
@@ -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);
index eda4bb4ef1a000b71a1042f8baa1f93f82e21336..2f442192f12ab9a74c10729ef587bd69ef5cffab 100644 (file)
@@ -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
 
index 19213b8e3f2e5ff950f36d6ab0c9a83435e3fc1a..731033fa8b3bfbb09f09f573109254b892e8dafb 100644 (file)
@@ -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
 
index c717adcd2fe99b8f3fdf1511232d887d9c66fb6e..ff7e29242ea48886359c0fcfda9806b44b872140 100644 (file)
@@ -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;