/*
 * main.c --- ext2 resizer main program
 *
 * Copyright (C) 1997, 1998 by Theodore Ts'o and
 * 	PowerQuest, Inc.
 *
 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 by Theodore Ts'o
 *
 * %Begin-Header%
 * This file may be redistributed under the terms of the GNU Public
 * License.
 * %End-Header%
 */

#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE

#include "config.h"
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#else
extern char *optarg;
extern int optind;
#endif
#include <unistd.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "e2p/e2p.h"

#include "resize2fs.h"

#include "../version.h"

char *program_name;
static char *device_name, *io_options;

static void usage (char *prog)
{
	fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-M] [-P] "
			   "[-p] device [new_size]\n\n"), prog);

	exit (1);
}

static errcode_t resize_progress_func(ext2_resize_t rfs, int pass,
				      unsigned long cur, unsigned long max)
{
	ext2_sim_progmeter progress;
	const char	*label;
	errcode_t	retval;

	progress = (ext2_sim_progmeter) rfs->prog_data;
	if (max == 0)
		return 0;
	if (cur == 0) {
		if (progress)
			ext2fs_progress_close(progress);
		progress = 0;
		switch (pass) {
		case E2_RSZ_EXTEND_ITABLE_PASS:
			label = _("Extending the inode table");
			break;
		case E2_RSZ_BLOCK_RELOC_PASS:
			label = _("Relocating blocks");
			break;
		case E2_RSZ_INODE_SCAN_PASS:
			label = _("Scanning inode table");
			break;
		case E2_RSZ_INODE_REF_UPD_PASS:
			label = _("Updating inode references");
			break;
		case E2_RSZ_MOVE_ITABLE_PASS:
			label = _("Moving inode table");
			break;
		default:
			label = _("Unknown pass?!?");
			break;
		}
		printf(_("Begin pass %d (max = %lu)\n"), pass, max);
		retval = ext2fs_progress_init(&progress, label, 30,
					      40, max, 0);
		if (retval)
			progress = 0;
		rfs->prog_data = (void *) progress;
	}
	if (progress)
		ext2fs_progress_update(progress, cur);
	if (cur >= max) {
		if (progress)
			ext2fs_progress_close(progress);
		progress = 0;
		rfs->prog_data = 0;
	}
	return 0;
}

static void determine_fs_stride(ext2_filsys fs)
{
	unsigned int	group;
	unsigned long long sum;
	unsigned int	has_sb, prev_has_sb = 0, num;
	int		i_stride, b_stride;

	if (fs->stride)
		return;
	num = 0; sum = 0;
	for (group = 0; group < fs->group_desc_count; group++) {
		has_sb = ext2fs_bg_has_super(fs, group);
		if (group == 0 || has_sb != prev_has_sb)
			goto next;
		b_stride = ext2fs_block_bitmap_loc(fs, group) -
			ext2fs_block_bitmap_loc(fs, group - 1) -
			fs->super->s_blocks_per_group;
		i_stride = ext2fs_inode_bitmap_loc(fs, group) -
			ext2fs_inode_bitmap_loc(fs, group - 1) -
			fs->super->s_blocks_per_group;
		if (b_stride != i_stride ||
		    b_stride < 0)
			goto next;

		/* printf("group %d has stride %d\n", group, b_stride); */
		sum += b_stride;
		num++;

	next:
		prev_has_sb = has_sb;
	}

	if (fs->group_desc_count > 12 && num < 3)
		sum = 0;

	if (num)
		fs->stride = sum / num;
	else
		fs->stride = 0;

	fs->super->s_raid_stride = fs->stride;
	ext2fs_mark_super_dirty(fs);

#if 0
	if (fs->stride)
		printf("Using RAID stride of %d\n", fs->stride);
#endif
}

static void bigalloc_check(ext2_filsys fs, int force)
{
	if (!force && EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
				EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
		fprintf(stderr, "%s", _("\nResizing bigalloc file systems has "
					"not been fully tested.  Proceed at\n"
					"your own risk!  Use the force option "
					"if you want to go ahead anyway.\n\n"));
		exit(1);
	}
}

int main (int argc, char ** argv)
{
	errcode_t	retval;
	ext2_filsys	fs;
	int		c;
	int		flags = 0;
	int		flush = 0;
	int		force = 0;
	int		io_flags = 0;
	int		force_min_size = 0;
	int		print_min_size = 0;
	int		fd, ret;
	blk64_t		new_size = 0;
	blk64_t		max_size = 0;
	blk64_t		min_size = 0;
	io_manager	io_ptr;
	char		*new_size_str = 0;
	int		use_stride = -1;
	ext2fs_struct_stat st_buf;
	__s64		new_file_size;
	unsigned int	sys_page_size = 4096;
	unsigned int	blocksize;
	long		sysval;
	int		len, mount_flags;
	char		*mtpt;

#ifdef ENABLE_NLS
	setlocale(LC_MESSAGES, "");
	setlocale(LC_CTYPE, "");
	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
	textdomain(NLS_CAT_NAME);
	set_com_err_gettext(gettext);
#endif

	add_error_table(&et_ext2_error_table);

	fprintf (stderr, "resize2fs %s (%s)\n",
		 E2FSPROGS_VERSION, E2FSPROGS_DATE);
	if (argc && *argv)
		program_name = *argv;

	while ((c = getopt (argc, argv, "d:fFhMPpS:")) != EOF) {
		switch (c) {
		case 'h':
			usage(program_name);
			break;
		case 'f':
			force = 1;
			break;
		case 'F':
			flush = 1;
			break;
		case 'M':
			force_min_size = 1;
			break;
		case 'P':
			print_min_size = 1;
			break;
		case 'd':
			flags |= atoi(optarg);
			break;
		case 'p':
			flags |= RESIZE_PERCENT_COMPLETE;
			break;
		case 'S':
			use_stride = atoi(optarg);
			break;
		default:
			usage(program_name);
		}
	}
	if (optind == argc)
		usage(program_name);

	device_name = argv[optind++];
	if (optind < argc)
		new_size_str = argv[optind++];
	if (optind < argc)
		usage(program_name);

	io_options = strchr(device_name, '?');
	if (io_options)
		*io_options++ = 0;

	/*
	 * Figure out whether or not the device is mounted, and if it is
	 * where it is mounted.
	 */
	len=80;
	while (1) {
		mtpt = malloc(len);
		if (!mtpt)
			return ENOMEM;
		mtpt[len-1] = 0;
		retval = ext2fs_check_mount_point(device_name, &mount_flags,
						  mtpt, len);
		if (retval) {
			com_err("ext2fs_check_mount_point", retval,
				_("while determining whether %s is mounted."),
				device_name);
			exit(1);
		}
		if (!(mount_flags & EXT2_MF_MOUNTED) || (mtpt[len-1] == 0))
			break;
		free(mtpt);
		len = 2 * len;
	}

	fd = ext2fs_open_file(device_name, O_RDWR, 0);
	if (fd < 0) {
		com_err("open", errno, _("while opening %s"),
			device_name);
		exit(1);
	}

	ret = ext2fs_fstat(fd, &st_buf);
	if (ret < 0) {
		com_err("open", errno,
			_("while getting stat information for %s"),
			device_name);
		exit(1);
	}

	if (flush) {
		retval = ext2fs_sync_device(fd, 1);
		if (retval) {
			com_err(argv[0], retval,
				_("while trying to flush %s"),
				device_name);
			exit(1);
		}
	}

	if (!S_ISREG(st_buf.st_mode )) {
		close(fd);
		fd = -1;
	}

#ifdef CONFIG_TESTIO_DEBUG
	if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
		io_ptr = test_io_manager;
		test_io_backing_manager = unix_io_manager;
	} else
#endif
		io_ptr = unix_io_manager;

	if (!(mount_flags & EXT2_MF_MOUNTED))
		io_flags = EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE;

	io_flags |= EXT2_FLAG_64BITS;

	retval = ext2fs_open2(device_name, io_options, io_flags,
			      0, 0, io_ptr, &fs);
	if (retval) {
		com_err(program_name, retval, _("while trying to open %s"),
			device_name);
		printf("%s", _("Couldn't find valid filesystem superblock.\n"));
		exit (1);
	}
	fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;

	/*
	 * Before acting on an unmounted filesystem, make sure it's ok,
	 * unless the user is forcing it.
	 *
	 * We do ERROR and VALID checks even if we're only printing the
	 * minimimum size, because traversal of a badly damaged filesystem
	 * can cause issues as well.  We don't require it to be fscked after
	 * the last mount time in this case, though, as this is a bit less
	 * risky.
	 */
	if (!force && !(mount_flags & EXT2_MF_MOUNTED)) {
		int checkit = 0;

		if (fs->super->s_state & EXT2_ERROR_FS)
			checkit = 1;

		if ((fs->super->s_state & EXT2_VALID_FS) == 0)
			checkit = 1;

		if ((fs->super->s_lastcheck < fs->super->s_mtime) &&
		    !print_min_size)
			checkit = 1;

		if (checkit) {
			fprintf(stderr,
				_("Please run 'e2fsck -f %s' first.\n\n"),
				device_name);
			exit(1);
		}
	}

	/*
	 * Check for compatibility with the feature sets.  We need to
	 * be more stringent than ext2fs_open().
	 */
	if (fs->super->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) {
		com_err(program_name, EXT2_ET_UNSUPP_FEATURE,
			"(%s)", device_name);
		exit(1);
	}

	min_size = calculate_minimum_resize_size(fs, flags);

	if (print_min_size) {
		printf(_("Estimated minimum size of the filesystem: %llu\n"),
		       min_size);
		exit(0);
	}

	/* Determine the system page size if possible */
#ifdef HAVE_SYSCONF
#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
#define _SC_PAGESIZE _SC_PAGE_SIZE
#endif
#ifdef _SC_PAGESIZE
	sysval = sysconf(_SC_PAGESIZE);
	if (sysval > 0)
		sys_page_size = sysval;
#endif /* _SC_PAGESIZE */
#endif /* HAVE_SYSCONF */

	/*
	 * Get the size of the containing partition, and use this for
	 * defaults and for making sure the new filesystem doesn't
	 * exceed the partition size.
	 */
	blocksize = fs->blocksize;
	retval = ext2fs_get_device_size2(device_name, blocksize,
					 &max_size);
	if (retval) {
		com_err(program_name, retval, "%s",
			_("while trying to determine filesystem size"));
		exit(1);
	}
	if (force_min_size)
		new_size = min_size;
	else if (new_size_str) {
		new_size = parse_num_blocks2(new_size_str,
					     fs->super->s_log_block_size);
		if (new_size == 0) {
			com_err(program_name, 0,
				_("Invalid new size: %s\n"), new_size_str);
			exit(1);
		}
	} else {
		new_size = max_size;
		/* Round down to an even multiple of a pagesize */
		if (sys_page_size > blocksize)
			new_size &= ~((sys_page_size / blocksize)-1);
	}
	if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
				       EXT4_FEATURE_INCOMPAT_64BIT)) {
		/* Take 16T down to 2^32-1 blocks */
		if (new_size == (1ULL << 32))
			new_size--;
		else if (new_size > (1ULL << 32)) {
			com_err(program_name, 0, "%s",
				_("New size too large to be "
				  "expressed in 32 bits\n"));
			exit(1);
		}
	}

	if (!force && new_size < min_size) {
		com_err(program_name, 0,
			_("New size smaller than minimum (%llu)\n"), min_size);
		exit(1);
	}
	if (use_stride >= 0) {
		if (use_stride >= (int) fs->super->s_blocks_per_group) {
			com_err(program_name, 0, "%s",
				_("Invalid stride length"));
			exit(1);
		}
		fs->stride = fs->super->s_raid_stride = use_stride;
		ext2fs_mark_super_dirty(fs);
	} else
		  determine_fs_stride(fs);

	/*
	 * If we are resizing a plain file, and it's not big enough,
	 * automatically extend it in a sparse fashion by writing the
	 * last requested block.
	 */
	new_file_size = ((__u64) new_size) * blocksize;
	if ((__u64) new_file_size >
	    (((__u64) 1) << (sizeof(st_buf.st_size)*8 - 1)) - 1)
		fd = -1;
	if ((new_file_size > st_buf.st_size) &&
	    (fd > 0)) {
		if ((ext2fs_llseek(fd, new_file_size-1, SEEK_SET) >= 0) &&
		    (write(fd, "0", 1) == 1))
			max_size = new_size;
	}
	if (!force && (new_size > max_size)) {
		fprintf(stderr, _("The containing partition (or device)"
			" is only %llu (%dk) blocks.\nYou requested a new size"
			" of %llu blocks.\n\n"), max_size,
			blocksize / 1024, new_size);
		exit(1);
	}
	if (new_size == ext2fs_blocks_count(fs->super)) {
		fprintf(stderr, _("The filesystem is already %llu (%dk) "
			"blocks long.  Nothing to do!\n\n"), new_size,
			blocksize / 1024);
		exit(0);
	}
	if (mount_flags & EXT2_MF_MOUNTED) {
		bigalloc_check(fs, force);
		retval = online_resize_fs(fs, mtpt, &new_size, flags);
	} else {
		bigalloc_check(fs, force);
		printf(_("Resizing the filesystem on "
			 "%s to %llu (%dk) blocks.\n"),
		       device_name, new_size, blocksize / 1024);
		retval = resize_fs(fs, &new_size, flags,
				   ((flags & RESIZE_PERCENT_COMPLETE) ?
				    resize_progress_func : 0));
	}
	free(mtpt);
	if (retval) {
		com_err(program_name, retval, _("while trying to resize %s"),
			device_name);
		fprintf(stderr,
			_("Please run 'e2fsck -fy %s' to fix the filesystem\n"
			  "after the aborted resize operation.\n"),
			device_name);
		ext2fs_close_free(&fs);
		exit(1);
	}
	printf(_("The filesystem on %s is now %llu (%dk) blocks long.\n\n"),
	       device_name, new_size, blocksize / 1024);

	if ((st_buf.st_size > new_file_size) &&
	    (fd > 0)) {
#ifdef HAVE_FTRUNCATE64
		retval = ftruncate64(fd, new_file_size);
#else
		retval = 0;
		/* Only truncate if new_file_size doesn't overflow off_t */
		if (((off_t) new_file_size) == new_file_size)
			retval = ftruncate(fd, (off_t) new_file_size);
#endif
		if (retval)
			com_err(program_name, retval,
				_("while trying to truncate %s"),
				device_name);
	}
	if (fd > 0)
		close(fd);
	remove_error_table(&et_ext2_error_table);
	return (0);
}
