blob: 7e25a8a580e309ed4cef064ed3bf517ea169f2e1 [file] [log] [blame]
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +00001/*
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
Theodore Ts'oc762c8e1997-06-17 03:52:12 +000011#ifdef HAVE_GETOPT_H
12#include <getopt.h>
13#endif
14#include <fcntl.h>
15#include <sys/ioctl.h>
16
17
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +000018#include "resize2fs.h"
19
20#define E2FSPROGS_VERSION "1.10"
21#define E2FSPROGS_DATE "27-Apr-97"
22
23char *program_name, *device_name;
24
Theodore Ts'oc762c8e1997-06-17 03:52:12 +000025static volatile void usage (char *prog)
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +000026{
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +000027 fprintf (stderr, "usage: %s [-d debug_flags] [-f] [-F] [-p] device new-size\n", prog);
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +000028 exit (1);
29}
30
Theodore Ts'o63b44fb1998-02-13 22:58:18 +000031static void resize_progress_func(ext2_resize_t rfs, int pass,
32 unsigned long cur, unsigned long max)
33{
34 ext2_sim_progmeter progress;
35 const char *label;
36 errcode_t retval;
37
38 progress = (ext2_sim_progmeter) rfs->prog_data;
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +000039 if (max == 0)
40 return;
Theodore Ts'o63b44fb1998-02-13 22:58:18 +000041 if (cur == 0) {
42 if (progress)
43 ext2fs_progress_close(progress);
44 progress = 0;
45 switch (pass) {
Theodore Ts'oa8519a21998-02-16 22:16:20 +000046 case E2_RSZ_EXTEND_ITABLE_PASS:
47 label = "Extending the inode table";
Theodore Ts'o63b44fb1998-02-13 22:58:18 +000048 break;
49 case E2_RSZ_BLOCK_RELOC_PASS:
50 label = "Relocating blocks";
51 break;
Theodore Ts'oa8519a21998-02-16 22:16:20 +000052 case E2_RSZ_INODE_SCAN_PASS:
53 label = "Scanning inode table";
Theodore Ts'o63b44fb1998-02-13 22:58:18 +000054 break;
55 case E2_RSZ_INODE_REF_UPD_PASS:
56 label = "Updating inode references";
57 break;
58 case E2_RSZ_MOVE_ITABLE_PASS:
59 label = "Moving inode table";
60 break;
Theodore Ts'oa8519a21998-02-16 22:16:20 +000061 default:
62 label = "Unknown pass?!?";
63 break;
Theodore Ts'o63b44fb1998-02-13 22:58:18 +000064 }
65 printf("Begin pass %d (max = %lu)\n", pass, max);
66 retval = ext2fs_progress_init(&progress, label, 30,
67 40, max, 0);
68 if (retval)
69 progress = 0;
70 rfs->prog_data = (void *) progress;
71 }
72 if (progress)
73 ext2fs_progress_update(progress, cur);
74 if (cur >= max) {
75 if (progress)
76 ext2fs_progress_close(progress);
77 progress = 0;
78 rfs->prog_data = 0;
79 }
80}
81
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +000082static void check_mount(char *device_name)
83{
84 errcode_t retval;
85 int mount_flags;
86
87 retval = ext2fs_check_if_mounted(device_name, &mount_flags);
88 if (retval) {
89 com_err("ext2fs_check_if_mount", retval,
90 "while determining whether %s is mounted.",
91 device_name);
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_name);
99 exit(1);
100}
101
102
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000103void main (int argc, char ** argv)
104{
105 errcode_t retval;
106 ext2_filsys fs;
107 int c;
Theodore Ts'o05e112a1997-06-14 07:28:44 +0000108 int flags = 0;
Theodore Ts'oc762c8e1997-06-17 03:52:12 +0000109 int flush = 0;
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000110 int force = 0;
Theodore Ts'oc762c8e1997-06-17 03:52:12 +0000111 int fd;
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000112 blk_t new_size = 0;
113 blk_t max_size = 0;
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000114 io_manager io_ptr;
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000115 char *tmp;
116
117 initialize_ext2_error_table();
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000118
119 fprintf (stderr, "resize2fs %s, %s for EXT2 FS %s, %s\n",
120 E2FSPROGS_VERSION, E2FSPROGS_DATE,
121 EXT2FS_VERSION, EXT2FS_DATE);
122 if (argc && *argv)
123 program_name = *argv;
124
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000125 while ((c = getopt (argc, argv, "d:fFhp")) != EOF) {
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000126 switch (c) {
127 case 'h':
128 usage(program_name);
129 break;
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000130 case 'f':
131 force = 1;
132 break;
Theodore Ts'oc762c8e1997-06-17 03:52:12 +0000133 case 'F':
134 flush = 1;
135 break;
Theodore Ts'o05e112a1997-06-14 07:28:44 +0000136 case 'd':
137 flags |= atoi(optarg);
138 break;
139 case 'p':
140 flags |= RESIZE_PERCENT_COMPLETE;
141 break;
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000142 default:
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000143 usage(program_name);
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000144 }
145 }
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000146 if (optind == argc)
147 usage(program_name);
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000148 device_name = argv[optind++];
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000149 if (optind < argc) {
150 new_size = strtoul(argv[optind++], &tmp, 0);
151 if (*tmp) {
152 com_err(program_name, 0, "bad filesystem size - %s",
153 argv[optind - 1]);
154 exit(1);
155 }
156 }
157 if (optind < argc)
158 usage(program_name);
159
160 check_mount(device_name);
161
Theodore Ts'oc762c8e1997-06-17 03:52:12 +0000162 if (flush) {
163#ifdef BLKFLSBUF
164 fd = open(device_name, O_RDONLY, 0);
165
166 if (fd < 0) {
167 com_err("open", errno, "while opening %s for flushing",
168 device_name);
169 exit(1);
170 }
171 if (ioctl(fd, BLKFLSBUF, 0) < 0) {
172 com_err("BLKFLSBUF", errno, "while trying to flush %s",
173 device_name);
174 exit(1);
175 }
176 close(fd);
177#else
178 fprintf(stderr, "BLKFLSBUF not supported");
179 exit(1);
180#endif /* BLKFLSBUF */
181 }
182
Theodore Ts'o05e112a1997-06-14 07:28:44 +0000183 if (flags & RESIZE_DEBUG_IO) {
184 io_ptr = test_io_manager;
185 test_io_backing_manager = unix_io_manager;
186 } else
187 io_ptr = unix_io_manager;
188
Theodore Ts'o1e1da291997-06-09 14:51:29 +0000189 retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0,
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000190 io_ptr, &fs);
191 if (retval) {
192 com_err (program_name, retval, "while trying to open %s",
193 device_name);
194 printf ("Couldn't find valid filesystem superblock.\n");
195 exit (1);
196 }
Theodore Ts'of4b2a6d1998-02-21 04:20:44 +0000197
198 /*
199 * Get the size of the containing partition, and use this for
200 * defaults and for making sure the new filesystme doesn't
201 * exceed the partition size.
202 */
203 retval = ext2fs_get_device_size(device_name, fs->blocksize,
204 &max_size);
205 if (retval) {
206 com_err(program_name, retval,
207 "while trying to determine filesystem size");
208 exit(1);
209 }
210 if (!new_size)
211 new_size = max_size;
212 if (!force && (new_size > max_size)) {
213 fprintf(stderr, "The containing partition (or device)"
214 " is only %d blocks.\nYou requested a new size"
215 " of %d blocks.\n\n", max_size,
216 new_size);
217 exit(1);
218 }
219 if (new_size == fs->super->s_blocks_count) {
220 fprintf(stderr, "The filesystem is already %d blocks "
221 "long. Nothing to do!\n\n", new_size);
222 exit(0);
223 }
224 if (!force && (fs->super->s_lastcheck < fs->super->s_mtime)) {
225 fprintf(stderr, "Please run 'e2fsck -f %s' first.\n\n",
226 device_name);
227 exit(1);
228 }
Theodore Ts'oa8519a21998-02-16 22:16:20 +0000229 retval = resize_fs(fs, new_size, flags,
230 ((flags & RESIZE_PERCENT_COMPLETE) ?
231 resize_progress_func : 0));
Theodore Ts'o1e1da291997-06-09 14:51:29 +0000232 if (retval) {
233 com_err(program_name, retval, "while trying to resize %s",
234 device_name);
235 ext2fs_close (fs);
236 }
Theodore Ts'o24b2c7a1997-06-07 20:42:58 +0000237 exit (0);
238}