clear_problem_context(&pctx);
- end = fs->block_map->start +
+ end = ext2fs_get_block_bitmap_start(fs->block_map) +
(EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
&save_blocks_count);
const char *descr,
ext2fs_inode_bitmap *ret)
{
- errcode_t retval;
__u32 start, end, real_end;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
const char *descr,
ext2fs_block_bitmap *ret)
{
- errcode_t retval;
__u32 start, end, real_end;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
bm1, bm2));
}
+errcode_t ext2fs_set_inode_bitmap_range(ext2fs_inode_bitmap bmap,
+ ext2_ino_t start, unsigned int num,
+ void *in)
+{
+ return (ext2fs_set_generic_bitmap_range(bmap,
+ EXT2_ET_MAGIC_INODE_BITMAP,
+ start, num, in));
+}
+
+errcode_t ext2fs_get_inode_bitmap_range(ext2fs_inode_bitmap bmap,
+ ext2_ino_t start, unsigned int num,
+ void *out)
+{
+ return (ext2fs_get_generic_bitmap_range(bmap,
+ EXT2_ET_MAGIC_INODE_BITMAP,
+ start, num, out));
+}
+
+errcode_t ext2fs_set_block_bitmap_range(ext2fs_block_bitmap bmap,
+ blk_t start, unsigned int num,
+ void *in)
+{
+ return (ext2fs_set_generic_bitmap_range(bmap,
+ EXT2_ET_MAGIC_BLOCK_BITMAP,
+ start, num, in));
+}
+
+errcode_t ext2fs_get_block_bitmap_range(ext2fs_block_bitmap bmap,
+ blk_t start, unsigned int num,
+ void *out)
+{
+ return (ext2fs_get_generic_bitmap_range(bmap,
+ EXT2_ET_MAGIC_BLOCK_BITMAP,
+ start, num, out));
+}
typedef struct struct_ext2_filsys *ext2_filsys;
-struct ext2fs_struct_generic_bitmap {
- errcode_t magic;
- ext2_filsys fs;
- __u32 start, end;
- __u32 real_end;
- char * description;
- char * bitmap;
- errcode_t base_error_code;
- __u32 reserved[7];
-};
-
#define EXT2FS_MARK_ERROR 0
#define EXT2FS_UNMARK_ERROR 1
#define EXT2FS_TEST_ERROR 2
/* bitmaps.c */
extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap);
extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap);
+extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
+ ext2fs_generic_bitmap *dest);
extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
ext2fs_block_bitmap bm2);
extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
ext2fs_inode_bitmap bm2);
+extern errcode_t ext2fs_set_inode_bitmap_range(ext2fs_inode_bitmap bmap,
+ ext2_ino_t start, unsigned int num,
+ void *in);
+extern errcode_t ext2fs_get_inode_bitmap_range(ext2fs_inode_bitmap bmap,
+ ext2_ino_t start, unsigned int num,
+ void *out);
+extern errcode_t ext2fs_set_block_bitmap_range(ext2fs_block_bitmap bmap,
+ blk_t start, unsigned int num,
+ void *in);
+extern errcode_t ext2fs_get_block_bitmap_range(ext2fs_block_bitmap bmap,
+ blk_t start, unsigned int num,
+ void *out);
/* block.c */
extern errcode_t ext2fs_compare_generic_bitmap(errcode_t magic, errcode_t neq,
ext2fs_generic_bitmap bm1,
ext2fs_generic_bitmap bm2);
+extern errcode_t ext2fs_get_generic_bitmap_range(ext2fs_generic_bitmap bmap,
+ errcode_t magic,
+ __u32 start, __u32 num,
+ void *out);
+extern errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap,
+ errcode_t magic,
+ __u32 start, __u32 num,
+ void *in);
/* getsize.c */
extern errcode_t ext2fs_get_device_size(const char *file, int blocksize,
#include "ext2_fs.h"
#include "ext2fs.h"
+struct ext2fs_struct_generic_bitmap {
+ errcode_t magic;
+ ext2_filsys fs;
+ __u32 start, end;
+ __u32 real_end;
+ char * description;
+ char * bitmap;
+ errcode_t base_error_code;
+ __u32 reserved[7];
+};
+
/*
* Used by previously inlined function, so we have to export this and
* not change the function signature
i <= map->real_end && i > map->end;
i++, j++)
ext2fs_set_bit(j, map->bitmap);
-}
+}
+
+errcode_t ext2fs_get_generic_bitmap_range(ext2fs_generic_bitmap bmap,
+ errcode_t magic,
+ __u32 start, __u32 num,
+ void *out)
+{
+ if (!bmap || (bmap->magic != magic))
+ return magic;
+
+ if ((start < bmap->start) || (start+num-1 > bmap->real_end))
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ memcpy(out, bmap->bitmap + (start >> 3), (num+7) >> 3);
+ return 0;
+}
+
+errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap,
+ errcode_t magic,
+ __u32 start, __u32 num,
+ void *in)
+{
+ if (!bmap || (bmap->magic != magic))
+ return magic;
+
+ if ((start < bmap->start) || (start+num-1 > bmap->real_end))
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ memcpy(bmap->bitmap + (start >> 3), in, (num+7) >> 3);
+ return 0;
+}
int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
int i;
- if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+ if ((block < bitmap->start) || (block+num-1 > bitmap->real_end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
block, bitmap->description);
return 0;
*/
errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
{
- char *ptr;
- int c, size;
- char zero_buf[1024];
- ssize_t actual;
- errcode_t retval;
+ ext2fs_generic_bitmap bmap;
+ errcode_t err, retval;
+ ssize_t actual;
+ __u32 itr, cnt, size;
+ int c, total_size;
+ char buf[1024];
if (flags & IMAGER_FLAG_INODEMAP) {
if (!fs->inode_map) {
if (retval)
return retval;
}
- ptr = fs->inode_map->bitmap;
+ bmap = fs->inode_map;
+ err = EXT2_ET_MAGIC_INODE_BITMAP;
+ itr = 1;
+ cnt = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
} else {
if (!fs->block_map) {
if (retval)
return retval;
}
- ptr = fs->block_map->bitmap;
+ bmap = fs->block_map;
+ err = EXT2_ET_MAGIC_BLOCK_BITMAP;
+ itr = fs->super->s_first_data_block;
+ cnt = EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count;
size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
}
- size = size * fs->group_desc_count;
-
- actual = write(fd, ptr, size);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != size) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
+ total_size = size * fs->group_desc_count;
+
+ while (cnt > 0) {
+ size = sizeof(buf);
+ if (size > (cnt >> 3))
+ size = (cnt >> 3);
+
+ retval = ext2fs_get_generic_bitmap_range(bmap,
+ err, itr, size << 3, buf);
+ if (retval)
+ return retval;
+
+ actual = write(fd, buf, size);
+ if (actual == -1)
+ return errno;
+ if (actual != (int) size)
+ return EXT2_ET_SHORT_READ;
+
+ itr += size << 3;
+ cnt -= size << 3;
}
- size = size % fs->blocksize;
- memset(zero_buf, 0, sizeof(zero_buf));
+
+ size = total_size % fs->blocksize;
+ memset(buf, 0, sizeof(buf));
if (size) {
size = fs->blocksize - size;
while (size) {
c = size;
- if (c > (int) sizeof(zero_buf))
- c = sizeof(zero_buf);
- actual = write(fd, zero_buf, c);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != c) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
- }
+ if (c > (int) sizeof(buf))
+ c = sizeof(buf);
+ actual = write(fd, buf, c);
+ if (actual == -1)
+ return errno;
+ if (actual != c)
+ return EXT2_ET_SHORT_WRITE;
size -= c;
}
}
- retval = 0;
-errout:
- return (retval);
+ return 0;
}
*/
errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
{
- char *ptr, *buf = 0;
- int size;
- ssize_t actual;
- errcode_t retval;
+ ext2fs_generic_bitmap bmap;
+ errcode_t err, retval;
+ __u32 itr, cnt;
+ char buf[1024];
+ unsigned int size;
+ ssize_t actual;
if (flags & IMAGER_FLAG_INODEMAP) {
if (!fs->inode_map) {
if (retval)
return retval;
}
- ptr = fs->inode_map->bitmap;
+ bmap = fs->inode_map;
+ err = EXT2_ET_MAGIC_INODE_BITMAP;
+ itr = 1;
+ cnt = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
size = (EXT2_INODES_PER_GROUP(fs->super) / 8);
} else {
if (!fs->block_map) {
if (retval)
return retval;
}
- ptr = fs->block_map->bitmap;
+ bmap = fs->block_map;
+ err = EXT2_ET_MAGIC_BLOCK_BITMAP;
+ itr = fs->super->s_first_data_block;
+ cnt = EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count;
size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
}
- size = size * fs->group_desc_count;
- buf = malloc(size);
- if (!buf)
- return ENOMEM;
+ while (cnt > 0) {
+ size = sizeof(buf);
+ if (size > (cnt >> 3))
+ size = (cnt >> 3);
- actual = read(fd, buf, size);
- if (actual == -1) {
- retval = errno;
- goto errout;
- }
- if (actual != size) {
- retval = EXT2_ET_SHORT_WRITE;
- goto errout;
+ actual = read(fd, buf, size);
+ if (actual == -1)
+ return errno;
+ if (actual != (int) size)
+ return EXT2_ET_SHORT_READ;
+
+ retval = ext2fs_set_generic_bitmap_range(bmap,
+ err, itr, size << 3, buf);
+ if (retval)
+ return retval;
+
+ itr += size << 3;
+ cnt -= size << 3;
}
- memcpy(ptr, buf, size);
-
- retval = 0;
-errout:
- if (buf)
- free(buf);
- return (retval);
+ return 0;
}
int block_nbytes, inode_nbytes;
unsigned int nbits;
errcode_t retval;
- char *block_bitmap, *inode_bitmap;
char *block_buf, *inode_buf;
int lazy_flag = 0;
blk_t blk;
+ blk_t blk_itr = fs->super->s_first_data_block;
+ ext2_ino_t ino_itr = 1;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
EXT2_FEATURE_COMPAT_LAZY_BG))
lazy_flag = 1;
inode_nbytes = block_nbytes = 0;
- block_bitmap = inode_bitmap = 0;
if (do_block) {
- block_bitmap = fs->block_map->bitmap;
block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
retval = ext2fs_get_mem(fs->blocksize, &block_buf);
if (retval)
memset(block_buf, 0xff, fs->blocksize);
}
if (do_inode) {
- inode_bitmap = fs->inode_map->bitmap;
inode_nbytes = (size_t)
((EXT2_INODES_PER_GROUP(fs->super)+7) / 8);
retval = ext2fs_get_mem(fs->blocksize, &inode_buf);
}
for (i = 0; i < fs->group_desc_count; i++) {
- if (!block_bitmap || !do_block)
+ if (!do_block)
goto skip_block_bitmap;
if (lazy_flag && fs->group_desc[i].bg_flags &
EXT2_BG_BLOCK_UNINIT)
goto skip_this_block_bitmap;
- memcpy(block_buf, block_bitmap, block_nbytes);
+ retval = ext2fs_get_block_bitmap_range(fs->block_map,
+ blk_itr, block_nbytes << 3, block_buf);
+ if (retval)
+ return retval;
+
if (i == fs->group_desc_count - 1) {
/* Force bitmap padding for the last group */
nbits = ((fs->super->s_blocks_count
return EXT2_ET_BLOCK_BITMAP_WRITE;
}
skip_this_block_bitmap:
- block_bitmap += block_nbytes;
+ blk_itr += block_nbytes << 3;
skip_block_bitmap:
- if (!inode_bitmap || !do_inode)
+ if (!do_inode)
continue;
if (lazy_flag && fs->group_desc[i].bg_flags &
EXT2_BG_INODE_UNINIT)
goto skip_this_inode_bitmap;
- memcpy(inode_buf, inode_bitmap, inode_nbytes);
+ retval = ext2fs_get_inode_bitmap_range(fs->inode_map,
+ ino_itr, inode_nbytes << 3, inode_buf);
+ if (retval)
+ return retval;
+
blk = fs->group_desc[i].bg_inode_bitmap;
if (blk) {
#ifdef EXT2_BIG_ENDIAN_BITMAPS
return EXT2_ET_INODE_BITMAP_WRITE;
}
skip_this_inode_bitmap:
- inode_bitmap += inode_nbytes;
+ ino_itr += inode_nbytes << 3;
}
if (do_block) {
char *block_bitmap = 0, *inode_bitmap = 0;
char *buf;
errcode_t retval;
- int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
- int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8;
+ unsigned int block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+ unsigned inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
int lazy_flag = 0;
+ int do_image = fs->flags & EXT2_FLAG_IMAGE_FILE;
+ unsigned int cnt;
blk_t blk;
+ blk_t blk_itr = fs->super->s_first_data_block;
+ blk_t blk_cnt;
+ ext2_ino_t ino_itr = 1;
+ ext2_ino_t ino_cnt;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
if (retval)
goto cleanup;
- block_bitmap = fs->block_map->bitmap;
- }
+ retval = ext2fs_get_mem(do_image ? fs->blocksize :
+ block_nbytes, &block_bitmap);
+ if (retval)
+ goto cleanup;
+ } else
+ block_nbytes = 0;
if (do_inode) {
if (fs->inode_map)
ext2fs_free_inode_bitmap(fs->inode_map);
retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map);
if (retval)
goto cleanup;
- inode_bitmap = fs->inode_map->bitmap;
- }
+ retval = ext2fs_get_mem(do_image ? fs->blocksize :
+ inode_nbytes, &inode_bitmap);
+ if (retval)
+ goto cleanup;
+ } else
+ inode_nbytes = 0;
ext2fs_free_mem(&buf);
if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
- if (inode_bitmap) {
- blk = (fs->image_header->offset_inodemap /
- fs->blocksize);
- retval = io_channel_read_blk(fs->image_io, blk,
- -(inode_nbytes * fs->group_desc_count),
- inode_bitmap);
+ blk = (fs->image_header->offset_inodemap / fs->blocksize);
+ ino_cnt = fs->super->s_inodes_count;
+ while (inode_nbytes > 0) {
+ retval = io_channel_read_blk(fs->image_io, blk++,
+ 1, inode_bitmap);
+ if (retval)
+ goto cleanup;
+ cnt = fs->blocksize << 3;
+ if (cnt > ino_cnt)
+ cnt = ino_cnt;
+ retval = ext2fs_set_inode_bitmap_range(fs->inode_map,
+ ino_itr, cnt, inode_bitmap);
if (retval)
goto cleanup;
+ ino_itr += fs->blocksize << 3;
+ ino_cnt -= fs->blocksize << 3;
+ inode_nbytes -= fs->blocksize;
}
- if (block_bitmap) {
- blk = (fs->image_header->offset_blockmap /
- fs->blocksize);
- retval = io_channel_read_blk(fs->image_io, blk,
- -(block_nbytes * fs->group_desc_count),
- block_bitmap);
+ blk = (fs->image_header->offset_blockmap /
+ fs->blocksize);
+ blk_cnt = EXT2_BLOCKS_PER_GROUP(fs->super) *
+ fs->group_desc_count;
+ while (block_nbytes > 0) {
+ retval = io_channel_read_blk(fs->image_io, blk++,
+ 1, block_bitmap);
+ if (retval)
+ goto cleanup;
+ cnt = fs->blocksize << 3;
+ if (cnt > blk_cnt)
+ cnt = blk_cnt;
+ retval = ext2fs_set_block_bitmap_range(fs->block_map,
+ blk_itr, cnt, block_bitmap);
if (retval)
goto cleanup;
+ blk_itr += fs->blocksize << 3;
+ blk_cnt -= fs->blocksize << 3;
+ block_nbytes -= fs->blocksize;
}
- return 0;
+ goto success_cleanup;
}
for (i = 0; i < fs->group_desc_count; i++) {
#endif
} else
memset(block_bitmap, 0xff, block_nbytes);
- block_bitmap += block_nbytes;
+ cnt = block_nbytes << 3;
+ retval = ext2fs_set_block_bitmap_range(fs->block_map,
+ blk_itr, cnt, block_bitmap);
+ if (retval)
+ goto cleanup;
+ blk_itr += block_nbytes << 3;
}
if (inode_bitmap) {
blk = fs->group_desc[i].bg_inode_bitmap;
#endif
} else
memset(inode_bitmap, 0xff, inode_nbytes);
- inode_bitmap += inode_nbytes;
+ cnt = inode_nbytes << 3;
+ retval = ext2fs_set_inode_bitmap_range(fs->inode_map,
+ ino_itr, cnt, inode_bitmap);
+ if (retval)
+ goto cleanup;
+ ino_itr += inode_nbytes << 3;
}
}
+success_cleanup:
+ if (inode_bitmap)
+ ext2fs_free_mem(&inode_bitmap);
+ if (block_bitmap)
+ ext2fs_free_mem(&block_bitmap);
return 0;
cleanup:
ext2fs_free_mem(&fs->inode_map);
fs->inode_map = 0;
}
+ if (inode_bitmap)
+ ext2fs_free_mem(&inode_bitmap);
+ if (block_bitmap)
+ ext2fs_free_mem(&block_bitmap);
if (buf)
ext2fs_free_mem(&buf);
return retval;
blk_t super_blk, old_desc_blk, new_desc_blk;
char *block_bitmap=NULL, *inode_bitmap=NULL;
int inode_blocks_per_group, old_desc_blocks, reserved_gdt;
+ int block_nbytes, inode_nbytes;
int has_super;
+ blk_t blk_itr = fs->super->s_first_data_block;
+ ext2_ino_t ino_itr = 1;
+
+ block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
+ inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
if (fs->block_map)
- block_bitmap = fs->block_map->bitmap;
+ block_bitmap = malloc(block_nbytes);
if (fs->inode_map)
- inode_bitmap = fs->inode_map->bitmap;
+ inode_bitmap = malloc(inode_nbytes);
inode_blocks_per_group = ((fs->super->s_inodes_per_group *
EXT2_INODE_SIZE(fs->super)) +
fs->group_desc[i].bg_used_dirs_count);
if (block_bitmap) {
fputs(_(" Free blocks: "), stdout);
+ ext2fs_get_block_bitmap_range(fs->block_map,
+ blk_itr, block_nbytes << 3, block_bitmap);
print_free (i, block_bitmap,
fs->super->s_blocks_per_group,
fs->super->s_first_data_block);
fputc('\n', stdout);
- block_bitmap += fs->super->s_blocks_per_group / 8;
+ blk_itr += fs->super->s_blocks_per_group;
}
if (inode_bitmap) {
fputs(_(" Free inodes: "), stdout);
+ ext2fs_get_inode_bitmap_range(fs->inode_map,
+ ino_itr, inode_nbytes << 3, inode_bitmap);
print_free (i, inode_bitmap,
fs->super->s_inodes_per_group, 1);
fputc('\n', stdout);
- inode_bitmap += fs->super->s_inodes_per_group / 8;
+ ino_itr += fs->super->s_inodes_per_group;
}
}
}