]>
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 | ||
17 | ||
24b2c7a7 TT |
18 | #include "resize2fs.h" |
19 | ||
20 | #define E2FSPROGS_VERSION "1.10" | |
21 | #define E2FSPROGS_DATE "27-Apr-97" | |
22 | ||
23 | char *program_name, *device_name; | |
24 | ||
c762c8e6 | 25 | static volatile void usage (char *prog) |
24b2c7a7 | 26 | { |
f4b2a6db | 27 | fprintf (stderr, "usage: %s [-d debug_flags] [-f] [-F] [-p] device new-size\n", prog); |
24b2c7a7 TT |
28 | exit (1); |
29 | } | |
30 | ||
63b44fbe TT |
31 | static 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; | |
f4b2a6db TT |
39 | if (max == 0) |
40 | return; | |
63b44fbe TT |
41 | if (cur == 0) { |
42 | if (progress) | |
43 | ext2fs_progress_close(progress); | |
44 | progress = 0; | |
45 | switch (pass) { | |
a8519a2d TT |
46 | case E2_RSZ_EXTEND_ITABLE_PASS: |
47 | label = "Extending the inode table"; | |
63b44fbe TT |
48 | break; |
49 | case E2_RSZ_BLOCK_RELOC_PASS: | |
50 | label = "Relocating blocks"; | |
51 | break; | |
a8519a2d TT |
52 | case E2_RSZ_INODE_SCAN_PASS: |
53 | label = "Scanning inode table"; | |
63b44fbe TT |
54 | 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; | |
a8519a2d TT |
61 | default: |
62 | label = "Unknown pass?!?"; | |
63 | break; | |
63b44fbe TT |
64 | } |
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 | ||
f4b2a6db TT |
82 | static 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 | ||
24b2c7a7 TT |
103 | void main (int argc, char ** argv) |
104 | { | |
105 | errcode_t retval; | |
106 | ext2_filsys fs; | |
107 | int c; | |
05e112a1 | 108 | int flags = 0; |
c762c8e6 | 109 | int flush = 0; |
f4b2a6db | 110 | int force = 0; |
c762c8e6 | 111 | int fd; |
f4b2a6db TT |
112 | blk_t new_size = 0; |
113 | blk_t max_size = 0; | |
24b2c7a7 | 114 | io_manager io_ptr; |
f4b2a6db TT |
115 | char *tmp; |
116 | ||
117 | initialize_ext2_error_table(); | |
24b2c7a7 TT |
118 | |
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 | ||
f4b2a6db | 125 | while ((c = getopt (argc, argv, "d:fFhp")) != EOF) { |
24b2c7a7 TT |
126 | switch (c) { |
127 | case 'h': | |
128 | usage(program_name); | |
129 | break; | |
f4b2a6db TT |
130 | case 'f': |
131 | force = 1; | |
132 | break; | |
c762c8e6 TT |
133 | case 'F': |
134 | flush = 1; | |
135 | break; | |
05e112a1 TT |
136 | case 'd': |
137 | flags |= atoi(optarg); | |
138 | break; | |
139 | case 'p': | |
140 | flags |= RESIZE_PERCENT_COMPLETE; | |
141 | break; | |
24b2c7a7 | 142 | default: |
f4b2a6db | 143 | usage(program_name); |
24b2c7a7 TT |
144 | } |
145 | } | |
f4b2a6db TT |
146 | if (optind == argc) |
147 | usage(program_name); | |
24b2c7a7 | 148 | device_name = argv[optind++]; |
f4b2a6db TT |
149 | 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 | ||
c762c8e6 TT |
162 | 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 | ||
05e112a1 TT |
183 | 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 | ||
1e1da29f | 189 | retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0, |
24b2c7a7 TT |
190 | 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 | } | |
f4b2a6db TT |
197 | |
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 | } | |
a8519a2d TT |
229 | retval = resize_fs(fs, new_size, flags, |
230 | ((flags & RESIZE_PERCENT_COMPLETE) ? | |
231 | resize_progress_func : 0)); | |
1e1da29f TT |
232 | if (retval) { |
233 | com_err(program_name, retval, "while trying to resize %s", | |
234 | device_name); | |
235 | ext2fs_close (fs); | |
236 | } | |
24b2c7a7 TT |
237 | exit (0); |
238 | } |