blob: f5b5f249063c4e10253cce1e2be5dc2e6496d825 [file] [log] [blame]
/*
* resize2fs.c - Resize the ext2 filesystem.
*
* Copyright (C) 1996 Theodore Ts'o
*
* This file can be redistributed under the terms of the GNU General
* Public License
*/
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/ext2_fs.h>
#include "ext2fs/ext2fs.h"
#include "../version.h"
const char * program_name = "resize2fs";
char * device_name = NULL;
static volatile void usage (void)
{
fprintf (stderr, "usage: %s device\n", program_name);
exit (1);
}
errcode_t ext2fs_resize_inode_bitmap(ext2_filsys fs,
ext2fs_inode_bitmap ibmap)
{
ino_t new_end, new_real_end;
size_t size, new_size;
char *new_bitmap, *old_bitmap;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
EXT2_CHECK_MAGIC(ibmap, EXT2_ET_MAGIC_INODE_BITMAP);
new_end = fs->super->s_inodes_count;
new_real_end = (EXT2_INODES_PER_GROUP(fs->super)
* fs->group_desc_count);
if (new_real_end == ibmap->real_end) {
ibmap->end = new_end;
return 0;
}
size = ((ibmap->real_end - ibmap->start) / 8) + 1;
new_size = ((new_real_end - ibmap->start) / 8) + 1;
new_bitmap = malloc(size);
if (!new_bitmap)
return ENOMEM;
if (size > new_size)
size = new_size;
memcpy(new_bitmap, ibmap->bitmap, size);
if (new_size > size)
memset(new_bitmap + size, 0, new_size - size);
old_bitmap = ibmap->bitmap;
ibmap->bitmap = new_bitmap;
free(old_bitmap);
ibmap->end = new_end;
ibmap->real_end = new_real_end;
}
errcode_t ext2fs_resize_block_bitmap(ext2_filsys fs,
ext2fs_inode_bitmap bbmap)
{
ino_t new_end, new_real_end;
size_t size, new_size;
char *new_bitmap, *old_bitmap;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
EXT2_CHECK_MAGIC(bbmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
new_end = fs->super->s_inodes_count;
new_real_end = (EXT2_INODES_PER_GROUP(fs->super)
* fs->group_desc_count);
if (new_real_end == bbmap->real_end) {
bbmap->end = new_end;
return 0;
}
size = ((bbmap->real_end - bbmap->start) / 8) + 1;
new_size = ((new_real_end - bbmap->start) / 8) + 1;
new_bitmap = malloc(size);
if (!new_bitmap)
return ENOMEM;
if (size > new_size)
size = new_size;
memcpy(new_bitmap, bbmap->bitmap, size);
if (new_size > size)
memset(new_bitmap + size, 0, new_size - size);
old_bitmap = bbmap->bitmap;
bbmap->bitmap = new_bitmap;
free(old_bitmap);
bbmap->end = new_end;
bbmap->real_end = new_real_end;
}
errcode_t ext2fs_resize(ext2_filsys fs, blk_t new_size)
{
__u32 new_block_groups, new_desc_blocks;
if (new_size = fs->super->s_blocks_count)
return 0;
new_block_groups = (fs->super->s_blocks_count -
fs->super->s_first_data_block +
EXT2_BLOCKS_PER_GROUP(fs->super) - 1)
/ EXT2_BLOCKS_PER_GROUP(fs->super);
if (new_block_groups == 0)
return EXT2_ET_TOOSMALL;
new_desc_blocks = (new_block_groups +
EXT2_DESC_PER_BLOCK(fs->super) - 1)
/ EXT2_DESC_PER_BLOCK(fs->super);
}
void main (int argc, char ** argv)
{
errcode_t retval;
ext2_filsys fs;
int c;
fprintf (stderr, "resize2fs %s, %s for EXT2 FS %s, %s\n",
E2FSPROGS_VERSION, E2FSPROGS_DATE,
EXT2FS_VERSION, EXT2FS_DATE);
if (argc && *argv)
program_name = *argv;
while ((c = getopt (argc, argv, "h")) != EOF) {
switch (c) {
case 'h':
usage();
break;
default:
usage ();
}
}
if (optind > argc - 1)
usage ();
device_name = argv[optind++];
initialize_ext2_error_table();
retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0,
unix_io_manager, &fs);
if (retval) {
com_err (program_name, retval, "while trying to open %s",
device_name);
printf ("Couldn't find valid filesystem superblock.\n");
exit (1);
}
retval = ext2fs_read_bitmaps (fs);
if (retval) {
com_err (program_name, retval,
"while trying to read the bitmaps", device_name);
ext2fs_close (fs);
exit (1);
}
ext2fs_close (fs);
exit (0);
}