diff options
Diffstat (limited to 'e2fsprogs/old_e2fsprogs/tune2fs.c')
-rw-r--r-- | e2fsprogs/old_e2fsprogs/tune2fs.c | 710 |
1 files changed, 0 insertions, 710 deletions
diff --git a/e2fsprogs/old_e2fsprogs/tune2fs.c b/e2fsprogs/old_e2fsprogs/tune2fs.c deleted file mode 100644 index bbe30e5a0..000000000 --- a/e2fsprogs/old_e2fsprogs/tune2fs.c +++ /dev/null | |||
@@ -1,710 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * tune2fs.c - Change the file system parameters on an ext2 file system | ||
4 | * | ||
5 | * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr> | ||
6 | * Laboratoire MASI, Institut Blaise Pascal | ||
7 | * Universite Pierre et Marie Curie (Paris VI) | ||
8 | * | ||
9 | * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o. | ||
10 | * | ||
11 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * History: | ||
16 | * 93/06/01 - Creation | ||
17 | * 93/10/31 - Added the -c option to change the maximal mount counts | ||
18 | * 93/12/14 - Added -l flag to list contents of superblock | ||
19 | * M.J.E. Mol (marcel@duteca.et.tudelft.nl) | ||
20 | * F.W. ten Wolde (franky@duteca.et.tudelft.nl) | ||
21 | * 93/12/29 - Added the -e option to change errors behavior | ||
22 | * 94/02/27 - Ported to use the ext2fs library | ||
23 | * 94/03/06 - Added the checks interval from Uwe Ohse (uwe@tirka.gun.de) | ||
24 | */ | ||
25 | |||
26 | #include <sys/types.h> | ||
27 | #include <fcntl.h> | ||
28 | #include <stdio.h> | ||
29 | #include <stdlib.h> | ||
30 | #include <string.h> | ||
31 | #include <time.h> | ||
32 | #include <unistd.h> | ||
33 | #include <getopt.h> | ||
34 | |||
35 | #include "e2fsbb.h" | ||
36 | #include "ext2fs/ext2_fs.h" | ||
37 | #include "ext2fs/ext2fs.h" | ||
38 | #include "uuid/uuid.h" | ||
39 | #include "e2p/e2p.h" | ||
40 | #include "ext2fs/kernel-jbd.h" | ||
41 | #include "util.h" | ||
42 | #include "blkid/blkid.h" | ||
43 | |||
44 | #include "libbb.h" | ||
45 | |||
46 | static char * device_name = NULL; | ||
47 | static char * new_label, *new_last_mounted, *new_UUID; | ||
48 | static char * io_options; | ||
49 | static int c_flag, C_flag, e_flag, f_flag, g_flag, i_flag, l_flag, L_flag; | ||
50 | static int m_flag, M_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag; | ||
51 | static time_t last_check_time; | ||
52 | static int print_label; | ||
53 | static int max_mount_count, mount_count, mount_flags; | ||
54 | static unsigned long interval, reserved_blocks; | ||
55 | static unsigned reserved_ratio; | ||
56 | static unsigned long resgid, resuid; | ||
57 | static unsigned short errors; | ||
58 | static int open_flag; | ||
59 | static char *features_cmd; | ||
60 | static char *mntopts_cmd; | ||
61 | |||
62 | static int journal_size, journal_flags; | ||
63 | static char *journal_device = NULL; | ||
64 | |||
65 | static const char *please_fsck = "Please run e2fsck on the filesystem\n"; | ||
66 | |||
67 | static __u32 ok_features[3] = { | ||
68 | EXT3_FEATURE_COMPAT_HAS_JOURNAL | EXT2_FEATURE_COMPAT_DIR_INDEX, | ||
69 | EXT2_FEATURE_INCOMPAT_FILETYPE, | ||
70 | EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER | ||
71 | }; | ||
72 | |||
73 | /* | ||
74 | * Remove an external journal from the filesystem | ||
75 | */ | ||
76 | static void remove_journal_device(ext2_filsys fs) | ||
77 | { | ||
78 | char *journal_path; | ||
79 | ext2_filsys jfs; | ||
80 | char buf[1024]; | ||
81 | journal_superblock_t *jsb; | ||
82 | int i, nr_users; | ||
83 | errcode_t retval; | ||
84 | int commit_remove_journal = 0; | ||
85 | io_manager io_ptr; | ||
86 | |||
87 | if (f_flag) | ||
88 | commit_remove_journal = 1; /* force removal even if error */ | ||
89 | |||
90 | uuid_unparse(fs->super->s_journal_uuid, buf); | ||
91 | journal_path = blkid_get_devname(NULL, "UUID", buf); | ||
92 | |||
93 | if (!journal_path) { | ||
94 | journal_path = | ||
95 | ext2fs_find_block_device(fs->super->s_journal_dev); | ||
96 | if (!journal_path) | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | io_ptr = unix_io_manager; | ||
101 | retval = ext2fs_open(journal_path, EXT2_FLAG_RW| | ||
102 | EXT2_FLAG_JOURNAL_DEV_OK, 0, | ||
103 | fs->blocksize, io_ptr, &jfs); | ||
104 | if (retval) { | ||
105 | bb_error_msg("Failed to open external journal"); | ||
106 | goto no_valid_journal; | ||
107 | } | ||
108 | if (!(jfs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { | ||
109 | bb_error_msg("%s is not a journal device", journal_path); | ||
110 | goto no_valid_journal; | ||
111 | } | ||
112 | |||
113 | /* Get the journal superblock */ | ||
114 | if ((retval = io_channel_read_blk(jfs->io, 1, -1024, buf))) { | ||
115 | bb_error_msg("Failed to read journal superblock"); | ||
116 | goto no_valid_journal; | ||
117 | } | ||
118 | |||
119 | jsb = (journal_superblock_t *) buf; | ||
120 | if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) || | ||
121 | (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) { | ||
122 | bb_error_msg("Journal superblock not found!"); | ||
123 | goto no_valid_journal; | ||
124 | } | ||
125 | |||
126 | /* Find the filesystem UUID */ | ||
127 | nr_users = ntohl(jsb->s_nr_users); | ||
128 | for (i=0; i < nr_users; i++) { | ||
129 | if (memcmp(fs->super->s_uuid, | ||
130 | &jsb->s_users[i*16], 16) == 0) | ||
131 | break; | ||
132 | } | ||
133 | if (i >= nr_users) { | ||
134 | bb_error_msg("Filesystem's UUID not found on journal device"); | ||
135 | commit_remove_journal = 1; | ||
136 | goto no_valid_journal; | ||
137 | } | ||
138 | nr_users--; | ||
139 | for (i=0; i < nr_users; i++) | ||
140 | memcpy(&jsb->s_users[i*16], &jsb->s_users[(i+1)*16], 16); | ||
141 | jsb->s_nr_users = htonl(nr_users); | ||
142 | |||
143 | /* Write back the journal superblock */ | ||
144 | if ((retval = io_channel_write_blk(jfs->io, 1, -1024, buf))) { | ||
145 | bb_error_msg("Failed to write journal superblock"); | ||
146 | goto no_valid_journal; | ||
147 | } | ||
148 | |||
149 | commit_remove_journal = 1; | ||
150 | |||
151 | no_valid_journal: | ||
152 | if (commit_remove_journal == 0) | ||
153 | bb_error_msg_and_die("Journal NOT removed"); | ||
154 | fs->super->s_journal_dev = 0; | ||
155 | uuid_clear(fs->super->s_journal_uuid); | ||
156 | ext2fs_mark_super_dirty(fs); | ||
157 | puts("Journal removed"); | ||
158 | free(journal_path); | ||
159 | } | ||
160 | |||
161 | /* Helper function for remove_journal_inode */ | ||
162 | static int release_blocks_proc(ext2_filsys fs, blk_t *blocknr, | ||
163 | int blockcnt EXT2FS_ATTR((unused)), | ||
164 | void *private EXT2FS_ATTR((unused))) | ||
165 | { | ||
166 | blk_t block; | ||
167 | int group; | ||
168 | |||
169 | block = *blocknr; | ||
170 | ext2fs_unmark_block_bitmap(fs->block_map,block); | ||
171 | group = ext2fs_group_of_blk(fs, block); | ||
172 | fs->group_desc[group].bg_free_blocks_count++; | ||
173 | fs->super->s_free_blocks_count++; | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * Remove the journal inode from the filesystem | ||
179 | */ | ||
180 | static void remove_journal_inode(ext2_filsys fs) | ||
181 | { | ||
182 | struct ext2_inode inode; | ||
183 | errcode_t retval; | ||
184 | ino_t ino = fs->super->s_journal_inum; | ||
185 | char *msg = "to read"; | ||
186 | char *s = "journal inode"; | ||
187 | |||
188 | retval = ext2fs_read_inode(fs, ino, &inode); | ||
189 | if (retval) | ||
190 | goto REMOVE_JOURNAL_INODE_ERROR; | ||
191 | if (ino == EXT2_JOURNAL_INO) { | ||
192 | retval = ext2fs_read_bitmaps(fs); | ||
193 | if (retval) { | ||
194 | msg = "to read bitmaps"; | ||
195 | s = ""; | ||
196 | goto REMOVE_JOURNAL_INODE_ERROR; | ||
197 | } | ||
198 | retval = ext2fs_block_iterate(fs, ino, 0, NULL, | ||
199 | release_blocks_proc, NULL); | ||
200 | if (retval) { | ||
201 | msg = "clearing"; | ||
202 | goto REMOVE_JOURNAL_INODE_ERROR; | ||
203 | } | ||
204 | memset(&inode, 0, sizeof(inode)); | ||
205 | ext2fs_mark_bb_dirty(fs); | ||
206 | fs->flags &= ~EXT2_FLAG_SUPER_ONLY; | ||
207 | } else | ||
208 | inode.i_flags &= ~EXT2_IMMUTABLE_FL; | ||
209 | retval = ext2fs_write_inode(fs, ino, &inode); | ||
210 | if (retval) { | ||
211 | msg = "writing"; | ||
212 | REMOVE_JOURNAL_INODE_ERROR: | ||
213 | bb_error_msg_and_die("Failed %s %s", msg, s); | ||
214 | } | ||
215 | fs->super->s_journal_inum = 0; | ||
216 | ext2fs_mark_super_dirty(fs); | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * Update the default mount options | ||
221 | */ | ||
222 | static void update_mntopts(ext2_filsys fs, char *mntopts) | ||
223 | { | ||
224 | struct ext2_super_block *sb= fs->super; | ||
225 | |||
226 | if (e2p_edit_mntopts(mntopts, &sb->s_default_mount_opts, ~0)) | ||
227 | bb_error_msg_and_die("Invalid mount option set: %s", mntopts); | ||
228 | ext2fs_mark_super_dirty(fs); | ||
229 | } | ||
230 | |||
231 | /* | ||
232 | * Update the feature set as provided by the user. | ||
233 | */ | ||
234 | static void update_feature_set(ext2_filsys fs, char *features) | ||
235 | { | ||
236 | int sparse, old_sparse, filetype, old_filetype; | ||
237 | int journal, old_journal, dxdir, old_dxdir; | ||
238 | struct ext2_super_block *sb= fs->super; | ||
239 | __u32 old_compat, old_incompat, old_ro_compat; | ||
240 | |||
241 | old_compat = sb->s_feature_compat; | ||
242 | old_ro_compat = sb->s_feature_ro_compat; | ||
243 | old_incompat = sb->s_feature_incompat; | ||
244 | |||
245 | old_sparse = sb->s_feature_ro_compat & | ||
246 | EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; | ||
247 | old_filetype = sb->s_feature_incompat & | ||
248 | EXT2_FEATURE_INCOMPAT_FILETYPE; | ||
249 | old_journal = sb->s_feature_compat & | ||
250 | EXT3_FEATURE_COMPAT_HAS_JOURNAL; | ||
251 | old_dxdir = sb->s_feature_compat & | ||
252 | EXT2_FEATURE_COMPAT_DIR_INDEX; | ||
253 | if (e2p_edit_feature(features, &sb->s_feature_compat, ok_features)) | ||
254 | bb_error_msg_and_die("Invalid filesystem option set: %s", features); | ||
255 | sparse = sb->s_feature_ro_compat & | ||
256 | EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; | ||
257 | filetype = sb->s_feature_incompat & | ||
258 | EXT2_FEATURE_INCOMPAT_FILETYPE; | ||
259 | journal = sb->s_feature_compat & | ||
260 | EXT3_FEATURE_COMPAT_HAS_JOURNAL; | ||
261 | dxdir = sb->s_feature_compat & | ||
262 | EXT2_FEATURE_COMPAT_DIR_INDEX; | ||
263 | if (old_journal && !journal) { | ||
264 | if ((mount_flags & EXT2_MF_MOUNTED) && | ||
265 | !(mount_flags & EXT2_MF_READONLY)) { | ||
266 | bb_error_msg_and_die( | ||
267 | "The has_journal flag may only be " | ||
268 | "cleared when the filesystem is\n" | ||
269 | "unmounted or mounted " | ||
270 | "read-only"); | ||
271 | } | ||
272 | if (sb->s_feature_incompat & | ||
273 | EXT3_FEATURE_INCOMPAT_RECOVER) { | ||
274 | bb_error_msg_and_die( | ||
275 | "The needs_recovery flag is set. " | ||
276 | "%s before clearing the has_journal flag.", | ||
277 | please_fsck); | ||
278 | } | ||
279 | if (sb->s_journal_inum) { | ||
280 | remove_journal_inode(fs); | ||
281 | } | ||
282 | if (sb->s_journal_dev) { | ||
283 | remove_journal_device(fs); | ||
284 | } | ||
285 | } | ||
286 | if (journal && !old_journal) { | ||
287 | /* | ||
288 | * If adding a journal flag, let the create journal | ||
289 | * code below handle creating setting the flag and | ||
290 | * creating the journal. We supply a default size if | ||
291 | * necessary. | ||
292 | */ | ||
293 | if (!journal_size) | ||
294 | journal_size = -1; | ||
295 | sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL; | ||
296 | } | ||
297 | if (dxdir && !old_dxdir) { | ||
298 | if (!sb->s_def_hash_version) | ||
299 | sb->s_def_hash_version = EXT2_HASH_TEA; | ||
300 | if (uuid_is_null((unsigned char *) sb->s_hash_seed)) | ||
301 | uuid_generate((unsigned char *) sb->s_hash_seed); | ||
302 | } | ||
303 | |||
304 | if (sb->s_rev_level == EXT2_GOOD_OLD_REV && | ||
305 | (sb->s_feature_compat || sb->s_feature_ro_compat || | ||
306 | sb->s_feature_incompat)) | ||
307 | ext2fs_update_dynamic_rev(fs); | ||
308 | if ((sparse != old_sparse) || | ||
309 | (filetype != old_filetype)) { | ||
310 | sb->s_state &= ~EXT2_VALID_FS; | ||
311 | printf("\n%s\n", please_fsck); | ||
312 | } | ||
313 | if ((old_compat != sb->s_feature_compat) || | ||
314 | (old_ro_compat != sb->s_feature_ro_compat) || | ||
315 | (old_incompat != sb->s_feature_incompat)) | ||
316 | ext2fs_mark_super_dirty(fs); | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | * Add a journal to the filesystem. | ||
321 | */ | ||
322 | static void add_journal(ext2_filsys fs) | ||
323 | { | ||
324 | if (fs->super->s_feature_compat & | ||
325 | EXT3_FEATURE_COMPAT_HAS_JOURNAL) { | ||
326 | bb_error_msg_and_die("The filesystem already has a journal"); | ||
327 | } | ||
328 | if (journal_device) { | ||
329 | make_journal_device(journal_device, fs, 0, 0); | ||
330 | } else if (journal_size) { | ||
331 | make_journal_blocks(fs, journal_size, journal_flags, 0); | ||
332 | /* | ||
333 | * If the filesystem wasn't mounted, we need to force | ||
334 | * the block group descriptors out. | ||
335 | */ | ||
336 | if ((mount_flags & EXT2_MF_MOUNTED) == 0) | ||
337 | fs->flags &= ~EXT2_FLAG_SUPER_ONLY; | ||
338 | } | ||
339 | print_check_message(fs); | ||
340 | } | ||
341 | |||
342 | /* | ||
343 | * Busybox stuff | ||
344 | */ | ||
345 | static char * x_blkid_get_devname(const char *token) | ||
346 | { | ||
347 | char * dev_name; | ||
348 | |||
349 | if (!(dev_name = blkid_get_devname(NULL, token, NULL))) | ||
350 | bb_error_msg_and_die("Unable to resolve '%s'", token); | ||
351 | return dev_name; | ||
352 | } | ||
353 | |||
354 | #ifdef CONFIG_E2LABEL | ||
355 | static void parse_e2label_options(int argc, char ** argv) | ||
356 | { | ||
357 | if ((argc < 2) || (argc > 3)) | ||
358 | bb_show_usage(); | ||
359 | io_options = strchr(argv[1], '?'); | ||
360 | if (io_options) | ||
361 | *io_options++ = 0; | ||
362 | device_name = x_blkid_get_devname(argv[1]); | ||
363 | if (argc == 3) { | ||
364 | open_flag = EXT2_FLAG_RW | EXT2_FLAG_JOURNAL_DEV_OK; | ||
365 | L_flag = 1; | ||
366 | new_label = argv[2]; | ||
367 | } else | ||
368 | print_label++; | ||
369 | } | ||
370 | #else | ||
371 | #define parse_e2label_options(x,y) | ||
372 | #endif | ||
373 | |||
374 | static time_t parse_time(char *str) | ||
375 | { | ||
376 | struct tm ts; | ||
377 | |||
378 | if (strcmp(str, "now") == 0) { | ||
379 | return time(0); | ||
380 | } | ||
381 | memset(&ts, 0, sizeof(ts)); | ||
382 | #ifdef HAVE_STRPTIME | ||
383 | strptime(str, "%Y%m%d%H%M%S", &ts); | ||
384 | #else | ||
385 | sscanf(str, "%4d%2d%2d%2d%2d%2d", &ts.tm_year, &ts.tm_mon, | ||
386 | &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec); | ||
387 | ts.tm_year -= 1900; | ||
388 | ts.tm_mon -= 1; | ||
389 | if (ts.tm_year < 0 || ts.tm_mon < 0 || ts.tm_mon > 11 || | ||
390 | ts.tm_mday < 0 || ts.tm_mday > 31 || ts.tm_hour > 23 || | ||
391 | ts.tm_min > 59 || ts.tm_sec > 61) | ||
392 | ts.tm_mday = 0; | ||
393 | #endif | ||
394 | if (ts.tm_mday == 0) { | ||
395 | bb_error_msg_and_die("can't parse date/time specifier: %s", str); | ||
396 | } | ||
397 | return mktime(&ts); | ||
398 | } | ||
399 | |||
400 | static void parse_tune2fs_options(int argc, char **argv) | ||
401 | { | ||
402 | int c; | ||
403 | char * tmp; | ||
404 | |||
405 | printf("tune2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); | ||
406 | while ((c = getopt(argc, argv, "c:e:fg:i:jlm:o:r:s:u:C:J:L:M:O:T:U:")) != EOF) | ||
407 | switch (c) | ||
408 | { | ||
409 | case 'c': | ||
410 | max_mount_count = xatou_range(optarg, 0, 16000); | ||
411 | if (max_mount_count == 0) | ||
412 | max_mount_count = -1; | ||
413 | c_flag = 1; | ||
414 | open_flag = EXT2_FLAG_RW; | ||
415 | break; | ||
416 | case 'C': | ||
417 | mount_count = xatou_range(optarg, 0, 16000); | ||
418 | C_flag = 1; | ||
419 | open_flag = EXT2_FLAG_RW; | ||
420 | break; | ||
421 | case 'e': | ||
422 | if (strcmp (optarg, "continue") == 0) | ||
423 | errors = EXT2_ERRORS_CONTINUE; | ||
424 | else if (strcmp (optarg, "remount-ro") == 0) | ||
425 | errors = EXT2_ERRORS_RO; | ||
426 | else if (strcmp (optarg, "panic") == 0) | ||
427 | errors = EXT2_ERRORS_PANIC; | ||
428 | else { | ||
429 | bb_error_msg_and_die("bad error behavior - %s", optarg); | ||
430 | } | ||
431 | e_flag = 1; | ||
432 | open_flag = EXT2_FLAG_RW; | ||
433 | break; | ||
434 | case 'f': /* Force */ | ||
435 | f_flag = 1; | ||
436 | break; | ||
437 | case 'g': | ||
438 | resgid = bb_strtoul(optarg, NULL, 10); | ||
439 | if (errno) | ||
440 | resgid = xgroup2gid(optarg); | ||
441 | g_flag = 1; | ||
442 | open_flag = EXT2_FLAG_RW; | ||
443 | break; | ||
444 | case 'i': | ||
445 | interval = strtoul(optarg, &tmp, 0); | ||
446 | switch (*tmp) { | ||
447 | case 's': | ||
448 | tmp++; | ||
449 | break; | ||
450 | case '\0': | ||
451 | case 'd': | ||
452 | case 'D': /* days */ | ||
453 | interval *= 86400; | ||
454 | if (*tmp != '\0') | ||
455 | tmp++; | ||
456 | break; | ||
457 | case 'm': | ||
458 | case 'M': /* months! */ | ||
459 | interval *= 86400 * 30; | ||
460 | tmp++; | ||
461 | break; | ||
462 | case 'w': | ||
463 | case 'W': /* weeks */ | ||
464 | interval *= 86400 * 7; | ||
465 | tmp++; | ||
466 | break; | ||
467 | } | ||
468 | if (*tmp || interval > (365 * 86400)) { | ||
469 | bb_error_msg_and_die("bad interval - %s", optarg); | ||
470 | } | ||
471 | i_flag = 1; | ||
472 | open_flag = EXT2_FLAG_RW; | ||
473 | break; | ||
474 | case 'j': | ||
475 | if (!journal_size) | ||
476 | journal_size = -1; | ||
477 | open_flag = EXT2_FLAG_RW; | ||
478 | break; | ||
479 | case 'J': | ||
480 | parse_journal_opts(&journal_device, &journal_flags, &journal_size, optarg); | ||
481 | open_flag = EXT2_FLAG_RW; | ||
482 | break; | ||
483 | case 'l': | ||
484 | l_flag = 1; | ||
485 | break; | ||
486 | case 'L': | ||
487 | new_label = optarg; | ||
488 | L_flag = 1; | ||
489 | open_flag = EXT2_FLAG_RW | | ||
490 | EXT2_FLAG_JOURNAL_DEV_OK; | ||
491 | break; | ||
492 | case 'm': | ||
493 | reserved_ratio = xatou_range(optarg, 0, 50); | ||
494 | m_flag = 1; | ||
495 | open_flag = EXT2_FLAG_RW; | ||
496 | break; | ||
497 | case 'M': | ||
498 | new_last_mounted = optarg; | ||
499 | M_flag = 1; | ||
500 | open_flag = EXT2_FLAG_RW; | ||
501 | break; | ||
502 | case 'o': | ||
503 | if (mntopts_cmd) { | ||
504 | bb_error_msg_and_die("-o may only be specified once"); | ||
505 | } | ||
506 | mntopts_cmd = optarg; | ||
507 | open_flag = EXT2_FLAG_RW; | ||
508 | break; | ||
509 | |||
510 | case 'O': | ||
511 | if (features_cmd) { | ||
512 | bb_error_msg_and_die("-O may only be specified once"); | ||
513 | } | ||
514 | features_cmd = optarg; | ||
515 | open_flag = EXT2_FLAG_RW; | ||
516 | break; | ||
517 | case 'r': | ||
518 | reserved_blocks = xatoul(optarg); | ||
519 | r_flag = 1; | ||
520 | open_flag = EXT2_FLAG_RW; | ||
521 | break; | ||
522 | case 's': | ||
523 | s_flag = atoi(optarg); | ||
524 | open_flag = EXT2_FLAG_RW; | ||
525 | break; | ||
526 | case 'T': | ||
527 | T_flag = 1; | ||
528 | last_check_time = parse_time(optarg); | ||
529 | open_flag = EXT2_FLAG_RW; | ||
530 | break; | ||
531 | case 'u': | ||
532 | resuid = bb_strtoul(optarg, NULL, 10); | ||
533 | if (errno) | ||
534 | resuid = xuname2uid(optarg); | ||
535 | u_flag = 1; | ||
536 | open_flag = EXT2_FLAG_RW; | ||
537 | break; | ||
538 | case 'U': | ||
539 | new_UUID = optarg; | ||
540 | U_flag = 1; | ||
541 | open_flag = EXT2_FLAG_RW | | ||
542 | EXT2_FLAG_JOURNAL_DEV_OK; | ||
543 | break; | ||
544 | default: | ||
545 | bb_show_usage(); | ||
546 | } | ||
547 | if (optind < argc - 1 || optind == argc) | ||
548 | bb_show_usage(); | ||
549 | if (!open_flag && !l_flag) | ||
550 | bb_show_usage(); | ||
551 | io_options = strchr(argv[optind], '?'); | ||
552 | if (io_options) | ||
553 | *io_options++ = 0; | ||
554 | device_name = x_blkid_get_devname(argv[optind]); | ||
555 | } | ||
556 | |||
557 | static void tune2fs_clean_up(void) | ||
558 | { | ||
559 | if (ENABLE_FEATURE_CLEAN_UP && device_name) free(device_name); | ||
560 | if (ENABLE_FEATURE_CLEAN_UP && journal_device) free(journal_device); | ||
561 | } | ||
562 | |||
563 | int tune2fs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
564 | int tune2fs_main(int argc, char **argv) | ||
565 | { | ||
566 | errcode_t retval; | ||
567 | ext2_filsys fs; | ||
568 | struct ext2_super_block *sb; | ||
569 | io_manager io_ptr; | ||
570 | |||
571 | if (ENABLE_FEATURE_CLEAN_UP) | ||
572 | atexit(tune2fs_clean_up); | ||
573 | |||
574 | if (ENABLE_E2LABEL && (applet_name[0] == 'e')) /* e2label */ | ||
575 | parse_e2label_options(argc, argv); | ||
576 | else | ||
577 | parse_tune2fs_options(argc, argv); /* tune2fs */ | ||
578 | |||
579 | io_ptr = unix_io_manager; | ||
580 | retval = ext2fs_open2(device_name, io_options, open_flag, | ||
581 | 0, 0, io_ptr, &fs); | ||
582 | if (retval) | ||
583 | bb_error_msg_and_die("No valid superblock on %s", device_name); | ||
584 | sb = fs->super; | ||
585 | if (print_label) { | ||
586 | /* For e2label emulation */ | ||
587 | printf("%.*s\n", (int) sizeof(sb->s_volume_name), | ||
588 | sb->s_volume_name); | ||
589 | return 0; | ||
590 | } | ||
591 | retval = ext2fs_check_if_mounted(device_name, &mount_flags); | ||
592 | if (retval) | ||
593 | bb_error_msg_and_die("can't determine if %s is mounted", device_name); | ||
594 | /* Normally we only need to write out the superblock */ | ||
595 | fs->flags |= EXT2_FLAG_SUPER_ONLY; | ||
596 | |||
597 | if (c_flag) { | ||
598 | sb->s_max_mnt_count = max_mount_count; | ||
599 | ext2fs_mark_super_dirty(fs); | ||
600 | printf("Setting maximal mount count to %d\n", max_mount_count); | ||
601 | } | ||
602 | if (C_flag) { | ||
603 | sb->s_mnt_count = mount_count; | ||
604 | ext2fs_mark_super_dirty(fs); | ||
605 | printf("Setting current mount count to %d\n", mount_count); | ||
606 | } | ||
607 | if (e_flag) { | ||
608 | sb->s_errors = errors; | ||
609 | ext2fs_mark_super_dirty(fs); | ||
610 | printf("Setting error behavior to %u\n", errors); | ||
611 | } | ||
612 | if (g_flag) { | ||
613 | sb->s_def_resgid = resgid; | ||
614 | ext2fs_mark_super_dirty(fs); | ||
615 | printf("Setting reserved blocks gid to %lu\n", resgid); | ||
616 | } | ||
617 | if (i_flag) { | ||
618 | sb->s_checkinterval = interval; | ||
619 | ext2fs_mark_super_dirty(fs); | ||
620 | printf("Setting interval between check %lu seconds\n", interval); | ||
621 | } | ||
622 | if (m_flag) { | ||
623 | sb->s_r_blocks_count = (sb->s_blocks_count / 100) | ||
624 | * reserved_ratio; | ||
625 | ext2fs_mark_super_dirty(fs); | ||
626 | printf("Setting reserved blocks percentage to %u (%u blocks)\n", | ||
627 | reserved_ratio, sb->s_r_blocks_count); | ||
628 | } | ||
629 | if (r_flag) { | ||
630 | if (reserved_blocks >= sb->s_blocks_count/2) | ||
631 | bb_error_msg_and_die("reserved blocks count is too big (%lu)", reserved_blocks); | ||
632 | sb->s_r_blocks_count = reserved_blocks; | ||
633 | ext2fs_mark_super_dirty(fs); | ||
634 | printf("Setting reserved blocks count to %lu\n", reserved_blocks); | ||
635 | } | ||
636 | if (s_flag == 1) { | ||
637 | if (sb->s_feature_ro_compat & | ||
638 | EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) | ||
639 | bb_error_msg("\nThe filesystem already has sparse superblocks"); | ||
640 | else { | ||
641 | sb->s_feature_ro_compat |= | ||
642 | EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; | ||
643 | sb->s_state &= ~EXT2_VALID_FS; | ||
644 | ext2fs_mark_super_dirty(fs); | ||
645 | printf("\nSparse superblock flag set. %s", please_fsck); | ||
646 | } | ||
647 | } | ||
648 | if (s_flag == 0) { | ||
649 | if (!(sb->s_feature_ro_compat & | ||
650 | EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) | ||
651 | bb_error_msg("\nThe filesystem already has sparse superblocks disabled"); | ||
652 | else { | ||
653 | sb->s_feature_ro_compat &= | ||
654 | ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; | ||
655 | sb->s_state &= ~EXT2_VALID_FS; | ||
656 | fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; | ||
657 | ext2fs_mark_super_dirty(fs); | ||
658 | printf("\nSparse superblock flag cleared. %s", please_fsck); | ||
659 | } | ||
660 | } | ||
661 | if (T_flag) { | ||
662 | sb->s_lastcheck = last_check_time; | ||
663 | ext2fs_mark_super_dirty(fs); | ||
664 | printf("Setting time filesystem last checked to %s\n", | ||
665 | ctime(&last_check_time)); | ||
666 | } | ||
667 | if (u_flag) { | ||
668 | sb->s_def_resuid = resuid; | ||
669 | ext2fs_mark_super_dirty(fs); | ||
670 | printf("Setting reserved blocks uid to %lu\n", resuid); | ||
671 | } | ||
672 | if (L_flag) { | ||
673 | if (strlen(new_label) > sizeof(sb->s_volume_name)) | ||
674 | bb_error_msg("Warning: label too long, truncating"); | ||
675 | memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name)); | ||
676 | safe_strncpy(sb->s_volume_name, new_label, | ||
677 | sizeof(sb->s_volume_name)); | ||
678 | ext2fs_mark_super_dirty(fs); | ||
679 | } | ||
680 | if (M_flag) { | ||
681 | memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted)); | ||
682 | safe_strncpy(sb->s_last_mounted, new_last_mounted, | ||
683 | sizeof(sb->s_last_mounted)); | ||
684 | ext2fs_mark_super_dirty(fs); | ||
685 | } | ||
686 | if (mntopts_cmd) | ||
687 | update_mntopts(fs, mntopts_cmd); | ||
688 | if (features_cmd) | ||
689 | update_feature_set(fs, features_cmd); | ||
690 | if (journal_size || journal_device) | ||
691 | add_journal(fs); | ||
692 | |||
693 | if (U_flag) { | ||
694 | if ((strcasecmp(new_UUID, "null") == 0) || | ||
695 | (strcasecmp(new_UUID, "clear") == 0)) { | ||
696 | uuid_clear(sb->s_uuid); | ||
697 | } else if (strcasecmp(new_UUID, "time") == 0) { | ||
698 | uuid_generate_time(sb->s_uuid); | ||
699 | } else if (strcasecmp(new_UUID, "random") == 0) { | ||
700 | uuid_generate(sb->s_uuid); | ||
701 | } else if (uuid_parse(new_UUID, sb->s_uuid)) { | ||
702 | bb_error_msg_and_die("Invalid UUID format"); | ||
703 | } | ||
704 | ext2fs_mark_super_dirty(fs); | ||
705 | } | ||
706 | |||
707 | if (l_flag) | ||
708 | list_super (sb); | ||
709 | return (ext2fs_close (fs) ? 1 : 0); | ||
710 | } | ||