2 * main.c --- ext2 resizer main program
4 * Copyright (C) 1997, 1998 by Theodore Ts'o and
7 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 by Theodore Ts'o
10 * This file may be redistributed under the terms of the GNU Public
26 #include "resize2fs.h"
28 #include "../version.h"
30 char *program_name, *device_name, *io_options;
32 static void usage (char *prog)
34 fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-p] "
35 "device [new_size]\n\n"), prog);
40 static errcode_t resize_progress_func(ext2_resize_t rfs, int pass,
41 unsigned long cur, unsigned long max)
43 ext2_sim_progmeter progress;
47 progress = (ext2_sim_progmeter) rfs->prog_data;
52 ext2fs_progress_close(progress);
55 case E2_RSZ_EXTEND_ITABLE_PASS:
56 label = _("Extending the inode table");
58 case E2_RSZ_BLOCK_RELOC_PASS:
59 label = _("Relocating blocks");
61 case E2_RSZ_INODE_SCAN_PASS:
62 label = _("Scanning inode table");
64 case E2_RSZ_INODE_REF_UPD_PASS:
65 label = _("Updating inode references");
67 case E2_RSZ_MOVE_ITABLE_PASS:
68 label = _("Moving inode table");
71 label = _("Unknown pass?!?");
74 printf(_("Begin pass %d (max = %lu)\n"), pass, max);
75 retval = ext2fs_progress_init(&progress, label, 30,
79 rfs->prog_data = (void *) progress;
82 ext2fs_progress_update(progress, cur);
85 ext2fs_progress_close(progress);
92 static void check_mount(char *device)
97 retval = ext2fs_check_if_mounted(device, &mount_flags);
99 com_err("ext2fs_check_if_mount", retval,
100 _("while determining whether %s is mounted."),
104 if (!(mount_flags & EXT2_MF_MOUNTED))
107 fprintf(stderr, _("%s is mounted; can't resize a "
108 "mounted filesystem!\n\n"), device);
112 int main (int argc, char ** argv)
125 char *new_size_str = 0;
127 unsigned int sys_page_size = 4096;
131 setlocale(LC_MESSAGES, "");
132 setlocale(LC_CTYPE, "");
133 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
134 textdomain(NLS_CAT_NAME);
137 initialize_ext2_error_table();
139 fprintf (stderr, "resize2fs %s (%s)\n",
140 E2FSPROGS_VERSION, E2FSPROGS_DATE);
142 program_name = *argv;
144 while ((c = getopt (argc, argv, "d:fFhp")) != EOF) {
156 flags |= atoi(optarg);
159 flags |= RESIZE_PERCENT_COMPLETE;
168 device_name = argv[optind++];
170 new_size_str = argv[optind++];
174 io_options = strchr(device_name, '?');
178 check_mount(device_name);
181 fd = open(device_name, O_RDONLY, 0);
184 com_err("open", errno,
185 _("while opening %s for flushing"),
189 retval = ext2fs_sync_device(fd, 1);
191 com_err(argv[0], retval,
192 _("while trying to flush %s"),
199 if (flags & RESIZE_DEBUG_IO) {
200 io_ptr = test_io_manager;
201 test_io_backing_manager = unix_io_manager;
203 io_ptr = unix_io_manager;
205 retval = ext2fs_open2(device_name, io_options, EXT2_FLAG_RW,
208 com_err (program_name, retval, _("while trying to open %s"),
210 printf (_("Couldn't find valid filesystem superblock.\n"));
214 * Check for compatibility with the feature sets. We need to
215 * be more stringent than ext2fs_open().
217 if (fs->super->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) {
218 com_err(program_name, EXT2_ET_UNSUPP_FEATURE,
219 "(%s)", device_name);
223 /* Determine the system page size if possible */
225 #if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
226 #define _SC_PAGESIZE _SC_PAGE_SIZE
229 sysval = sysconf(_SC_PAGESIZE);
231 sys_page_size = sysval;
232 #endif /* _SC_PAGESIZE */
233 #endif /* HAVE_SYSCONF */
236 * Get the size of the containing partition, and use this for
237 * defaults and for making sure the new filesystme doesn't
238 * exceed the partition size.
240 retval = ext2fs_get_device_size(device_name, fs->blocksize,
243 com_err(program_name, retval,
244 _("while trying to determine filesystem size"));
248 new_size = parse_num_blocks(new_size_str,
249 fs->super->s_log_block_size);
251 com_err(program_name, 0, _("bad filesystem size - %s"),
257 /* Round down to an even multiple of a pagesize */
258 if (sys_page_size > fs->blocksize)
259 new_size &= ~((sys_page_size / fs->blocksize)-1);
263 * If we are resizing a plain file, and it's not big enough,
264 * automatically extend it in a sparse fashion by writing the
265 * last requested block.
267 if ((new_size > max_size) &&
268 (stat(device_name, &st_buf) == 0) &&
269 S_ISREG(st_buf.st_mode) &&
270 ((tmp = malloc(fs->blocksize)) != 0)) {
271 memset(tmp, 0, fs->blocksize);
272 retval = io_channel_write_blk(fs->io, new_size-1, 1, tmp);
277 if (!force && (new_size > max_size)) {
278 fprintf(stderr, _("The containing partition (or device)"
279 " is only %d (%dk) blocks.\nYou requested a new size"
280 " of %d blocks.\n\n"), max_size,
281 fs->blocksize / 1024, new_size);
284 if (new_size == fs->super->s_blocks_count) {
285 fprintf(stderr, _("The filesystem is already %d blocks "
286 "long. Nothing to do!\n\n"), new_size);
289 if (!force && ((fs->super->s_lastcheck < fs->super->s_mtime) ||
290 (fs->super->s_state & EXT2_ERROR_FS) ||
291 ((fs->super->s_state & EXT2_VALID_FS) == 0))) {
292 fprintf(stderr, _("Please run 'e2fsck -f %s' first.\n\n"),
296 printf("Resizing the filesystem on %s to %d (%dk) blocks.\n",
297 device_name, new_size, fs->blocksize / 1024);
298 retval = resize_fs(fs, &new_size, flags,
299 ((flags & RESIZE_PERCENT_COMPLETE) ?
300 resize_progress_func : 0));
302 com_err(program_name, retval, _("while trying to resize %s"),
307 printf(_("The filesystem on %s is now %d blocks long.\n\n"),
308 device_name, new_size);