main.c revision 2a3013b80704b7d9128cbe2c746550e570eb5a02
1/* 2 * main.c --- ext2 resizer main program 3 * 4 * Copyright (C) 1997 Theodore Ts'o 5 * 6 * %Begin-Header% 7 * All rights reserved. 8 * %End-Header% 9 */ 10 11#ifdef HAVE_GETOPT_H 12#include <getopt.h> 13#endif 14#include <fcntl.h> 15#include <sys/ioctl.h> 16 17 18#include "resize2fs.h" 19 20#include "./version.h" 21 22char *program_name, *device_name; 23 24static volatile void usage (char *prog) 25{ 26 fprintf (stderr, "usage: %s [-d debug_flags] [-f] [-F] [-p] device new-size\n", prog); 27 exit (1); 28} 29 30static errcode_t resize_progress_func(ext2_resize_t rfs, int pass, 31 unsigned long cur, unsigned long max) 32{ 33 ext2_sim_progmeter progress; 34 const char *label; 35 errcode_t retval; 36 37 progress = (ext2_sim_progmeter) rfs->prog_data; 38 if (max == 0) 39 return 0; 40 if (cur == 0) { 41 if (progress) 42 ext2fs_progress_close(progress); 43 progress = 0; 44 switch (pass) { 45 case E2_RSZ_EXTEND_ITABLE_PASS: 46 label = "Extending the inode table"; 47 break; 48 case E2_RSZ_BLOCK_RELOC_PASS: 49 label = "Relocating blocks"; 50 break; 51 case E2_RSZ_INODE_SCAN_PASS: 52 label = "Scanning inode table"; 53 break; 54 case E2_RSZ_INODE_REF_UPD_PASS: 55 label = "Updating inode references"; 56 break; 57 case E2_RSZ_MOVE_ITABLE_PASS: 58 label = "Moving inode table"; 59 break; 60 default: 61 label = "Unknown pass?!?"; 62 break; 63 } 64 printf("Begin pass %d (max = %lu)\n", pass, max); 65 retval = ext2fs_progress_init(&progress, label, 30, 66 40, max, 0); 67 if (retval) 68 progress = 0; 69 rfs->prog_data = (void *) progress; 70 } 71 if (progress) 72 ext2fs_progress_update(progress, cur); 73 if (cur >= max) { 74 if (progress) 75 ext2fs_progress_close(progress); 76 progress = 0; 77 rfs->prog_data = 0; 78 } 79 return 0; 80} 81 82static void check_mount(char *device) 83{ 84 errcode_t retval; 85 int mount_flags; 86 87 retval = ext2fs_check_if_mounted(device, &mount_flags); 88 if (retval) { 89 com_err("ext2fs_check_if_mount", retval, 90 "while determining whether %s is mounted.", 91 device); 92 return; 93 } 94 if (!(mount_flags & EXT2_MF_MOUNTED)) 95 return; 96 97 fprintf(stderr, "%s is mounted; can't resize a " 98 "mounted filesystem!\n\n", device); 99 exit(1); 100} 101 102 103void main (int argc, char ** argv) 104{ 105 errcode_t retval; 106 ext2_filsys fs; 107 int c; 108 int flags = 0; 109 int flush = 0; 110 int force = 0; 111 int fd; 112 blk_t new_size = 0; 113 blk_t max_size = 0; 114 io_manager io_ptr; 115 char *tmp; 116 struct ext2fs_sb *s; 117 118 initialize_ext2_error_table(); 119 120 fprintf (stderr, "resize2fs %s (%s)\n", 121 E2FSPROGS_VERSION, E2FSPROGS_DATE); 122 fprintf(stderr, "Copyright 1998 by Theodore Ts'o and PowerQuest, Inc. All Rights Reserved.\n\n"); 123 if (argc && *argv) 124 program_name = *argv; 125 126 while ((c = getopt (argc, argv, "d:fFhp")) != EOF) { 127 switch (c) { 128 case 'h': 129 usage(program_name); 130 break; 131 case 'f': 132 force = 1; 133 break; 134 case 'F': 135 flush = 1; 136 break; 137 case 'd': 138 flags |= atoi(optarg); 139 break; 140 case 'p': 141 flags |= RESIZE_PERCENT_COMPLETE; 142 break; 143 default: 144 usage(program_name); 145 } 146 } 147 if (optind == argc) 148 usage(program_name); 149 device_name = argv[optind++]; 150 if (optind < argc) { 151 new_size = strtoul(argv[optind++], &tmp, 0); 152 if (*tmp) { 153 com_err(program_name, 0, "bad filesystem size - %s", 154 argv[optind - 1]); 155 exit(1); 156 } 157 } 158 if (optind < argc) 159 usage(program_name); 160 161 check_mount(device_name); 162 163 if (flush) { 164#ifdef BLKFLSBUF 165 fd = open(device_name, O_RDONLY, 0); 166 167 if (fd < 0) { 168 com_err("open", errno, "while opening %s for flushing", 169 device_name); 170 exit(1); 171 } 172 if (ioctl(fd, BLKFLSBUF, 0) < 0) { 173 com_err("BLKFLSBUF", errno, "while trying to flush %s", 174 device_name); 175 exit(1); 176 } 177 close(fd); 178#else 179 fprintf(stderr, "BLKFLSBUF not supported"); 180 exit(1); 181#endif /* BLKFLSBUF */ 182 } 183 184 if (flags & RESIZE_DEBUG_IO) { 185 io_ptr = test_io_manager; 186 test_io_backing_manager = unix_io_manager; 187 } else 188 io_ptr = unix_io_manager; 189 190 retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0, 191 io_ptr, &fs); 192 if (retval) { 193 com_err (program_name, retval, "while trying to open %s", 194 device_name); 195 printf ("Couldn't find valid filesystem superblock.\n"); 196 exit (1); 197 } 198 /* 199 * Check for compatibility with the feature sets. We need to 200 * be more stringent than ext2fs_open(). 201 */ 202 s = (struct ext2fs_sb *) fs->super; 203 if ((s->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) || 204 (s->s_feature_incompat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) { 205 com_err(program_name, EXT2_ET_UNSUPP_FEATURE, 206 "(%s)", device_name); 207 exit(1); 208 } 209 210 /* 211 * Get the size of the containing partition, and use this for 212 * defaults and for making sure the new filesystme doesn't 213 * exceed the partition size. 214 */ 215 retval = ext2fs_get_device_size(device_name, fs->blocksize, 216 &max_size); 217 if (retval) { 218 com_err(program_name, retval, 219 "while trying to determine filesystem size"); 220 exit(1); 221 } 222 if (!new_size) 223 new_size = max_size; 224 if (!force && (new_size > max_size)) { 225 fprintf(stderr, "The containing partition (or device)" 226 " is only %d blocks.\nYou requested a new size" 227 " of %d blocks.\n\n", max_size, 228 new_size); 229 exit(1); 230 } 231 if (new_size == fs->super->s_blocks_count) { 232 fprintf(stderr, "The filesystem is already %d blocks " 233 "long. Nothing to do!\n\n", new_size); 234 exit(0); 235 } 236 if (!force && (fs->super->s_lastcheck < fs->super->s_mtime)) { 237 fprintf(stderr, "Please run 'e2fsck -f %s' first.\n\n", 238 device_name); 239 exit(1); 240 } 241 retval = resize_fs(fs, new_size, flags, 242 ((flags & RESIZE_PERCENT_COMPLETE) ? 243 resize_progress_func : 0)); 244 if (retval) { 245 com_err(program_name, retval, "while trying to resize %s", 246 device_name); 247 ext2fs_close (fs); 248 } 249 exit (0); 250} 251