diff options
Diffstat (limited to 'e2fsprogs/ext2fs/block.c')
-rw-r--r-- | e2fsprogs/ext2fs/block.c | 438 |
1 files changed, 0 insertions, 438 deletions
diff --git a/e2fsprogs/ext2fs/block.c b/e2fsprogs/ext2fs/block.c deleted file mode 100644 index 0a757b2..0000000 --- a/e2fsprogs/ext2fs/block.c +++ /dev/null @@ -1,438 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * block.c --- iterate over all blocks in an inode - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include <stdio.h> -#include <string.h> -#if HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -struct block_context { - ext2_filsys fs; - int (*func)(ext2_filsys fs, - blk_t *blocknr, - e2_blkcnt_t bcount, - blk_t ref_blk, - int ref_offset, - void *priv_data); - e2_blkcnt_t bcount; - int bsize; - int flags; - errcode_t errcode; - char *ind_buf; - char *dind_buf; - char *tind_buf; - void *priv_data; -}; - -static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, - int ref_offset, struct block_context *ctx) -{ - int ret = 0, changed = 0; - int i, flags, limit, offset; - blk_t *block_nr; - - limit = ctx->fs->blocksize >> 2; - if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && - !(ctx->flags & BLOCK_FLAG_DATA_ONLY)) - ret = (*ctx->func)(ctx->fs, ind_block, - BLOCK_COUNT_IND, ref_block, - ref_offset, ctx->priv_data); - if (!*ind_block || (ret & BLOCK_ABORT)) { - ctx->bcount += limit; - return ret; - } - if (*ind_block >= ctx->fs->super->s_blocks_count || - *ind_block < ctx->fs->super->s_first_data_block) { - ctx->errcode = EXT2_ET_BAD_IND_BLOCK; - ret |= BLOCK_ERROR; - return ret; - } - ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block, - ctx->ind_buf); - if (ctx->errcode) { - ret |= BLOCK_ERROR; - return ret; - } - - block_nr = (blk_t *) ctx->ind_buf; - offset = 0; - if (ctx->flags & BLOCK_FLAG_APPEND) { - for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) { - flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount, - *ind_block, offset, - ctx->priv_data); - changed |= flags; - if (flags & BLOCK_ABORT) { - ret |= BLOCK_ABORT; - break; - } - offset += sizeof(blk_t); - } - } else { - for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) { - if (*block_nr == 0) - continue; - flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount, - *ind_block, offset, - ctx->priv_data); - changed |= flags; - if (flags & BLOCK_ABORT) { - ret |= BLOCK_ABORT; - break; - } - offset += sizeof(blk_t); - } - } - if (changed & BLOCK_CHANGED) { - ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block, - ctx->ind_buf); - if (ctx->errcode) - ret |= BLOCK_ERROR | BLOCK_ABORT; - } - if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && - !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && - !(ret & BLOCK_ABORT)) - ret |= (*ctx->func)(ctx->fs, ind_block, - BLOCK_COUNT_IND, ref_block, - ref_offset, ctx->priv_data); - return ret; -} - -static int block_iterate_dind(blk_t *dind_block, blk_t ref_block, - int ref_offset, struct block_context *ctx) -{ - int ret = 0, changed = 0; - int i, flags, limit, offset; - blk_t *block_nr; - - limit = ctx->fs->blocksize >> 2; - if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE | - BLOCK_FLAG_DATA_ONLY))) - ret = (*ctx->func)(ctx->fs, dind_block, - BLOCK_COUNT_DIND, ref_block, - ref_offset, ctx->priv_data); - if (!*dind_block || (ret & BLOCK_ABORT)) { - ctx->bcount += limit*limit; - return ret; - } - if (*dind_block >= ctx->fs->super->s_blocks_count || - *dind_block < ctx->fs->super->s_first_data_block) { - ctx->errcode = EXT2_ET_BAD_DIND_BLOCK; - ret |= BLOCK_ERROR; - return ret; - } - ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block, - ctx->dind_buf); - if (ctx->errcode) { - ret |= BLOCK_ERROR; - return ret; - } - - block_nr = (blk_t *) ctx->dind_buf; - offset = 0; - if (ctx->flags & BLOCK_FLAG_APPEND) { - for (i = 0; i < limit; i++, block_nr++) { - flags = block_iterate_ind(block_nr, - *dind_block, offset, - ctx); - changed |= flags; - if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { - ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); - break; - } - offset += sizeof(blk_t); - } - } else { - for (i = 0; i < limit; i++, block_nr++) { - if (*block_nr == 0) { - ctx->bcount += limit; - continue; - } - flags = block_iterate_ind(block_nr, - *dind_block, offset, - ctx); - changed |= flags; - if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { - ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); - break; - } - offset += sizeof(blk_t); - } - } - if (changed & BLOCK_CHANGED) { - ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block, - ctx->dind_buf); - if (ctx->errcode) - ret |= BLOCK_ERROR | BLOCK_ABORT; - } - if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && - !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && - !(ret & BLOCK_ABORT)) - ret |= (*ctx->func)(ctx->fs, dind_block, - BLOCK_COUNT_DIND, ref_block, - ref_offset, ctx->priv_data); - return ret; -} - -static int block_iterate_tind(blk_t *tind_block, blk_t ref_block, - int ref_offset, struct block_context *ctx) -{ - int ret = 0, changed = 0; - int i, flags, limit, offset; - blk_t *block_nr; - - limit = ctx->fs->blocksize >> 2; - if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE | - BLOCK_FLAG_DATA_ONLY))) - ret = (*ctx->func)(ctx->fs, tind_block, - BLOCK_COUNT_TIND, ref_block, - ref_offset, ctx->priv_data); - if (!*tind_block || (ret & BLOCK_ABORT)) { - ctx->bcount += limit*limit*limit; - return ret; - } - if (*tind_block >= ctx->fs->super->s_blocks_count || - *tind_block < ctx->fs->super->s_first_data_block) { - ctx->errcode = EXT2_ET_BAD_TIND_BLOCK; - ret |= BLOCK_ERROR; - return ret; - } - ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block, - ctx->tind_buf); - if (ctx->errcode) { - ret |= BLOCK_ERROR; - return ret; - } - - block_nr = (blk_t *) ctx->tind_buf; - offset = 0; - if (ctx->flags & BLOCK_FLAG_APPEND) { - for (i = 0; i < limit; i++, block_nr++) { - flags = block_iterate_dind(block_nr, - *tind_block, - offset, ctx); - changed |= flags; - if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { - ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); - break; - } - offset += sizeof(blk_t); - } - } else { - for (i = 0; i < limit; i++, block_nr++) { - if (*block_nr == 0) { - ctx->bcount += limit*limit; - continue; - } - flags = block_iterate_dind(block_nr, - *tind_block, - offset, ctx); - changed |= flags; - if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { - ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); - break; - } - offset += sizeof(blk_t); - } - } - if (changed & BLOCK_CHANGED) { - ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block, - ctx->tind_buf); - if (ctx->errcode) - ret |= BLOCK_ERROR | BLOCK_ABORT; - } - if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && - !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && - !(ret & BLOCK_ABORT)) - ret |= (*ctx->func)(ctx->fs, tind_block, - BLOCK_COUNT_TIND, ref_block, - ref_offset, ctx->priv_data); - - return ret; -} - -errcode_t ext2fs_block_iterate2(ext2_filsys fs, - ext2_ino_t ino, - int flags, - char *block_buf, - int (*func)(ext2_filsys fs, - blk_t *blocknr, - e2_blkcnt_t blockcnt, - blk_t ref_blk, - int ref_offset, - void *priv_data), - void *priv_data) -{ - int i; - int got_inode = 0; - int ret = 0; - blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */ - struct ext2_inode inode; - errcode_t retval; - struct block_context ctx; - int limit; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - /* - * Check to see if we need to limit large files - */ - if (flags & BLOCK_FLAG_NO_LARGE) { - ctx.errcode = ext2fs_read_inode(fs, ino, &inode); - if (ctx.errcode) - return ctx.errcode; - got_inode = 1; - if (!LINUX_S_ISDIR(inode.i_mode) && - (inode.i_size_high != 0)) - return EXT2_ET_FILE_TOO_BIG; - } - - retval = ext2fs_get_blocks(fs, ino, blocks); - if (retval) - return retval; - - limit = fs->blocksize >> 2; - - ctx.fs = fs; - ctx.func = func; - ctx.priv_data = priv_data; - ctx.flags = flags; - ctx.bcount = 0; - if (block_buf) { - ctx.ind_buf = block_buf; - } else { - retval = ext2fs_get_mem(fs->blocksize * 3, &ctx.ind_buf); - if (retval) - return retval; - } - ctx.dind_buf = ctx.ind_buf + fs->blocksize; - ctx.tind_buf = ctx.dind_buf + fs->blocksize; - - /* - * Iterate over the HURD translator block (if present) - */ - if ((fs->super->s_creator_os == EXT2_OS_HURD) && - !(flags & BLOCK_FLAG_DATA_ONLY)) { - ctx.errcode = ext2fs_read_inode(fs, ino, &inode); - if (ctx.errcode) - goto abort_exit; - got_inode = 1; - if (inode.osd1.hurd1.h_i_translator) { - ret |= (*ctx.func)(fs, - &inode.osd1.hurd1.h_i_translator, - BLOCK_COUNT_TRANSLATOR, - 0, 0, priv_data); - if (ret & BLOCK_ABORT) - goto abort_exit; - } - } - - /* - * Iterate over normal data blocks - */ - for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) { - if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) { - ret |= (*ctx.func)(fs, &blocks[i], - ctx.bcount, 0, i, priv_data); - if (ret & BLOCK_ABORT) - goto abort_exit; - } - } - if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { - ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK, - 0, EXT2_IND_BLOCK, &ctx); - if (ret & BLOCK_ABORT) - goto abort_exit; - } else - ctx.bcount += limit; - if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { - ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK, - 0, EXT2_DIND_BLOCK, &ctx); - if (ret & BLOCK_ABORT) - goto abort_exit; - } else - ctx.bcount += limit * limit; - if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { - ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK, - 0, EXT2_TIND_BLOCK, &ctx); - if (ret & BLOCK_ABORT) - goto abort_exit; - } - -abort_exit: - if (ret & BLOCK_CHANGED) { - if (!got_inode) { - retval = ext2fs_read_inode(fs, ino, &inode); - if (retval) - return retval; - } - for (i=0; i < EXT2_N_BLOCKS; i++) - inode.i_block[i] = blocks[i]; - retval = ext2fs_write_inode(fs, ino, &inode); - if (retval) - return retval; - } - - if (!block_buf) - ext2fs_free_mem(&ctx.ind_buf); - - return (ret & BLOCK_ERROR) ? ctx.errcode : 0; -} - -/* - * Emulate the old ext2fs_block_iterate function! - */ - -struct xlate { - int (*func)(ext2_filsys fs, - blk_t *blocknr, - int bcount, - void *priv_data); - void *real_private; -}; - -#ifdef __TURBOC__ -# pragma argsused -#endif -static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt, - blk_t ref_block EXT2FS_ATTR((unused)), - int ref_offset EXT2FS_ATTR((unused)), - void *priv_data) -{ - struct xlate *xl = (struct xlate *) priv_data; - - return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private); -} - -errcode_t ext2fs_block_iterate(ext2_filsys fs, - ext2_ino_t ino, - int flags, - char *block_buf, - int (*func)(ext2_filsys fs, - blk_t *blocknr, - int blockcnt, - void *priv_data), - void *priv_data) -{ - struct xlate xl; - - xl.real_private = priv_data; - xl.func = func; - - return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags, - block_buf, xlate_func, &xl); -} - |