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