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