]>
Commit | Line | Data |
---|---|---|
3839e657 | 1 | /* |
4d0f2283 | 2 | * tune2fs.c - Change the file system parameters on an ext2 file system |
3839e657 TT |
3 | * |
4 | * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr> | |
5 | * Laboratoire MASI, Institut Blaise Pascal | |
6 | * Universite Pierre et Marie Curie (Paris VI) | |
7 | * | |
4d0f2283 | 8 | * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o. |
19c78dc0 TT |
9 | * |
10 | * %Begin-Header% | |
11 | * This file may be redistributed under the terms of the GNU Public | |
12 | * License. | |
13 | * %End-Header% | |
3839e657 TT |
14 | */ |
15 | ||
16 | /* | |
17 | * History: | |
18 | * 93/06/01 - Creation | |
19 | * 93/10/31 - Added the -c option to change the maximal mount counts | |
20 | * 93/12/14 - Added -l flag to list contents of superblock | |
21 | * M.J.E. Mol (marcel@duteca.et.tudelft.nl) | |
22 | * F.W. ten Wolde (franky@duteca.et.tudelft.nl) | |
23 | * 93/12/29 - Added the -e option to change errors behavior | |
24 | * 94/02/27 - Ported to use the ext2fs library | |
25 | * 94/03/06 - Added the checks interval from Uwe Ohse (uwe@tirka.gun.de) | |
26 | */ | |
27 | ||
ebabf2ad | 28 | #define _XOPEN_SOURCE 600 /* for inclusion of strptime() */ |
b969b1b8 | 29 | #define _BSD_SOURCE /* for inclusion of strcasecmp() */ |
3839e657 | 30 | #include <fcntl.h> |
f3db3566 | 31 | #include <grp.h> |
a418d3ad | 32 | #ifdef HAVE_GETOPT_H |
3839e657 | 33 | #include <getopt.h> |
373b8337 TT |
34 | #else |
35 | extern char *optarg; | |
36 | extern int optind; | |
a418d3ad | 37 | #endif |
f3db3566 | 38 | #include <pwd.h> |
3839e657 | 39 | #include <stdio.h> |
f38cf3cb | 40 | #ifdef HAVE_STDLIB_H |
3839e657 | 41 | #include <stdlib.h> |
f38cf3cb | 42 | #endif |
3839e657 TT |
43 | #include <string.h> |
44 | #include <time.h> | |
45 | #include <unistd.h> | |
f3db3566 | 46 | #include <sys/types.h> |
64d588cf | 47 | #include <libgen.h> |
36585791 | 48 | #include <limits.h> |
3839e657 | 49 | |
54c637d4 | 50 | #include "ext2fs/ext2_fs.h" |
3839e657 TT |
51 | #include "ext2fs/ext2fs.h" |
52 | #include "et/com_err.h" | |
1e3472c5 | 53 | #include "uuid/uuid.h" |
3839e657 | 54 | #include "e2p/e2p.h" |
dc2ec525 | 55 | #include "jfs_user.h" |
63985320 | 56 | #include "util.h" |
ed1b33e8 | 57 | #include "blkid/blkid.h" |
771e8db9 | 58 | #include "quota/mkquota.h" |
3839e657 TT |
59 | |
60 | #include "../version.h" | |
d9c56d3c | 61 | #include "nls-enable.h" |
3839e657 | 62 | |
771e8db9 AK |
63 | #define QOPT_ENABLE (1) |
64 | #define QOPT_DISABLE (-1) | |
65 | ||
66 | extern int ask_yn(const char *string, int def); | |
67 | ||
ec43da2f TT |
68 | const char *program_name = "tune2fs"; |
69 | char *device_name; | |
70 | char *new_label, *new_last_mounted, *new_UUID; | |
71 | char *io_options; | |
4d0f2283 | 72 | static int c_flag, C_flag, e_flag, f_flag, g_flag, i_flag, l_flag, L_flag; |
771e8db9 | 73 | static int m_flag, M_flag, Q_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag; |
64d588cf | 74 | static int I_flag; |
d4de4aa9 | 75 | static time_t last_check_time; |
83238153 | 76 | static int print_label; |
63985320 | 77 | static int max_mount_count, mount_count, mount_flags; |
4efbac6f VAH |
78 | static unsigned long interval; |
79 | static blk64_t reserved_blocks; | |
ce911145 | 80 | static double reserved_ratio; |
63985320 TT |
81 | static unsigned long resgid, resuid; |
82 | static unsigned short errors; | |
83238153 TT |
83 | static int open_flag; |
84 | static char *features_cmd; | |
a0c3fd5e | 85 | static char *mntopts_cmd; |
0c17cb25 TT |
86 | static int stride, stripe_width; |
87 | static int stride_set, stripe_width_set; | |
6cb27404 | 88 | static char *extended_cmd; |
721b367a | 89 | static unsigned long new_inode_size; |
9a976ac7 | 90 | static char *ext_mount_opts; |
771e8db9 | 91 | static int usrquota, grpquota; |
3839e657 | 92 | |
63985320 TT |
93 | int journal_size, journal_flags; |
94 | char *journal_device; | |
95 | ||
64d588cf AK |
96 | static struct list_head blk_move_list; |
97 | ||
98 | struct blk_move { | |
99 | struct list_head list; | |
7117f8d6 VAH |
100 | blk64_t old_loc; |
101 | blk64_t new_loc; | |
64d588cf AK |
102 | }; |
103 | ||
104 | ||
63985320 | 105 | static const char *please_fsck = N_("Please run e2fsck on the filesystem.\n"); |
1e3472c5 | 106 | |
14b596d4 | 107 | #ifdef CONFIG_BUILD_FINDFS |
3e699064 | 108 | void do_findfs(int argc, char **argv); |
14b596d4 | 109 | #endif |
3e699064 | 110 | |
818180cd | 111 | static void usage(void) |
3839e657 | 112 | { |
b21e38a0 | 113 | fprintf(stderr, |
bb145b01 | 114 | _("Usage: %s [-c max_mounts_count] [-e errors_behavior] " |
b21e38a0 | 115 | "[-g group]\n" |
ff662d5d TT |
116 | "\t[-i interval[d|m|w]] [-j] [-J journal_options] [-l]\n" |
117 | "\t[-m reserved_blocks_percent] " | |
118 | "[-o [^]mount_options[,...]] \n" | |
119 | "\t[-r reserved_blocks_count] [-u user] [-C mount_count] " | |
120 | "[-L volume_label]\n" | |
6cb27404 TT |
121 | "\t[-M last_mounted_dir] [-O [^]feature[,...]]\n" |
122 | "\t[-E extended-option[,...]] [-T last_check_time] " | |
64d588cf | 123 | "[-U UUID]\n\t[ -I new_inode_size ] device\n"), program_name); |
ec43da2f | 124 | exit(1); |
3839e657 TT |
125 | } |
126 | ||
896938d5 | 127 | static __u32 ok_features[3] = { |
558df544 | 128 | /* Compat */ |
843049c4 | 129 | EXT3_FEATURE_COMPAT_HAS_JOURNAL | |
558df544 TT |
130 | EXT2_FEATURE_COMPAT_DIR_INDEX, |
131 | /* Incompat */ | |
a49670e6 TT |
132 | EXT2_FEATURE_INCOMPAT_FILETYPE | |
133 | EXT3_FEATURE_INCOMPAT_EXTENTS | | |
c2d4300b | 134 | EXT4_FEATURE_INCOMPAT_FLEX_BG, |
558df544 TT |
135 | /* R/O compat */ |
136 | EXT2_FEATURE_RO_COMPAT_LARGE_FILE | | |
2be8fe43 TT |
137 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE| |
138 | EXT4_FEATURE_RO_COMPAT_DIR_NLINK| | |
139 | EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE| | |
4e988cb4 | 140 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM | |
771e8db9 AK |
141 | EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER | |
142 | EXT4_FEATURE_RO_COMPAT_QUOTA | |
896938d5 TT |
143 | }; |
144 | ||
7c4a2ef5 | 145 | static __u32 clear_ok_features[3] = { |
558df544 | 146 | /* Compat */ |
7c4a2ef5 | 147 | EXT3_FEATURE_COMPAT_HAS_JOURNAL | |
037914e2 | 148 | EXT2_FEATURE_COMPAT_RESIZE_INODE | |
558df544 TT |
149 | EXT2_FEATURE_COMPAT_DIR_INDEX, |
150 | /* Incompat */ | |
a49670e6 TT |
151 | EXT2_FEATURE_INCOMPAT_FILETYPE | |
152 | EXT4_FEATURE_INCOMPAT_FLEX_BG, | |
558df544 | 153 | /* R/O compat */ |
4e988cb4 | 154 | EXT2_FEATURE_RO_COMPAT_LARGE_FILE | |
2be8fe43 TT |
155 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE| |
156 | EXT4_FEATURE_RO_COMPAT_DIR_NLINK| | |
157 | EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE| | |
771e8db9 AK |
158 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM | |
159 | EXT4_FEATURE_RO_COMPAT_QUOTA | |
896938d5 TT |
160 | }; |
161 | ||
dc2ec525 TT |
162 | /* |
163 | * Remove an external journal from the filesystem | |
164 | */ | |
165 | static void remove_journal_device(ext2_filsys fs) | |
166 | { | |
4ea7bd04 | 167 | char *journal_path; |
dc2ec525 TT |
168 | ext2_filsys jfs; |
169 | char buf[1024]; | |
170 | journal_superblock_t *jsb; | |
171 | int i, nr_users; | |
172 | errcode_t retval; | |
4d0f2283 | 173 | int commit_remove_journal = 0; |
2a29f135 | 174 | io_manager io_ptr; |
4d0f2283 TT |
175 | |
176 | if (f_flag) | |
177 | commit_remove_journal = 1; /* force removal even if error */ | |
dc2ec525 | 178 | |
2d15576d | 179 | uuid_unparse(fs->super->s_journal_uuid, buf); |
ed1b33e8 | 180 | journal_path = blkid_get_devname(NULL, "UUID", buf); |
2d15576d | 181 | |
4ea7bd04 TT |
182 | if (!journal_path) { |
183 | journal_path = | |
2d15576d | 184 | ext2fs_find_block_device(fs->super->s_journal_dev); |
4ea7bd04 | 185 | if (!journal_path) |
2d15576d AD |
186 | return; |
187 | } | |
dc2ec525 | 188 | |
2a29f135 | 189 | #ifdef CONFIG_TESTIO_DEBUG |
f38cf3cb TT |
190 | if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) { |
191 | io_ptr = test_io_manager; | |
192 | test_io_backing_manager = unix_io_manager; | |
193 | } else | |
2a29f135 | 194 | #endif |
f38cf3cb | 195 | io_ptr = unix_io_manager; |
4ea7bd04 | 196 | retval = ext2fs_open(journal_path, EXT2_FLAG_RW| |
dc2ec525 | 197 | EXT2_FLAG_JOURNAL_DEV_OK, 0, |
2a29f135 | 198 | fs->blocksize, io_ptr, &jfs); |
dc2ec525 TT |
199 | if (retval) { |
200 | com_err(program_name, retval, | |
201 | _("while trying to open external journal")); | |
4d0f2283 | 202 | goto no_valid_journal; |
dc2ec525 TT |
203 | } |
204 | if (!(jfs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { | |
7141b54b | 205 | fprintf(stderr, _("%s is not a journal device.\n"), |
4ea7bd04 | 206 | journal_path); |
4d0f2283 | 207 | goto no_valid_journal; |
dc2ec525 TT |
208 | } |
209 | ||
210 | /* Get the journal superblock */ | |
24a117ab | 211 | if ((retval = io_channel_read_blk64(jfs->io, 1, -1024, buf))) { |
dc2ec525 TT |
212 | com_err(program_name, retval, |
213 | _("while reading journal superblock")); | |
4d0f2283 | 214 | goto no_valid_journal; |
dc2ec525 TT |
215 | } |
216 | ||
217 | jsb = (journal_superblock_t *) buf; | |
218 | if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) || | |
219 | (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) { | |
54434927 | 220 | fputs(_("Journal superblock not found!\n"), stderr); |
4d0f2283 | 221 | goto no_valid_journal; |
dc2ec525 TT |
222 | } |
223 | ||
224 | /* Find the filesystem UUID */ | |
225 | nr_users = ntohl(jsb->s_nr_users); | |
ec43da2f | 226 | for (i = 0; i < nr_users; i++) { |
dc2ec525 TT |
227 | if (memcmp(fs->super->s_uuid, |
228 | &jsb->s_users[i*16], 16) == 0) | |
229 | break; | |
230 | } | |
231 | if (i >= nr_users) { | |
efc6f628 | 232 | fputs(_("Filesystem's UUID not found on journal device.\n"), |
54434927 | 233 | stderr); |
4d0f2283 TT |
234 | commit_remove_journal = 1; |
235 | goto no_valid_journal; | |
dc2ec525 TT |
236 | } |
237 | nr_users--; | |
ec43da2f | 238 | for (i = 0; i < nr_users; i++) |
dc2ec525 TT |
239 | memcpy(&jsb->s_users[i*16], &jsb->s_users[(i+1)*16], 16); |
240 | jsb->s_nr_users = htonl(nr_users); | |
241 | ||
242 | /* Write back the journal superblock */ | |
24a117ab | 243 | if ((retval = io_channel_write_blk64(jfs->io, 1, -1024, buf))) { |
dc2ec525 TT |
244 | com_err(program_name, retval, |
245 | "while writing journal superblock."); | |
4d0f2283 | 246 | goto no_valid_journal; |
dc2ec525 TT |
247 | } |
248 | ||
4d0f2283 TT |
249 | commit_remove_journal = 1; |
250 | ||
251 | no_valid_journal: | |
252 | if (commit_remove_journal == 0) { | |
54434927 | 253 | fputs(_("Journal NOT removed\n"), stderr); |
4d0f2283 TT |
254 | exit(1); |
255 | } | |
dc2ec525 | 256 | fs->super->s_journal_dev = 0; |
ed1b33e8 | 257 | uuid_clear(fs->super->s_journal_uuid); |
dc2ec525 | 258 | ext2fs_mark_super_dirty(fs); |
54434927 | 259 | fputs(_("Journal removed\n"), stdout); |
4ea7bd04 | 260 | free(journal_path); |
dc2ec525 TT |
261 | } |
262 | ||
194686bb | 263 | /* Helper function for remove_journal_inode */ |
7117f8d6 VAH |
264 | static int release_blocks_proc(ext2_filsys fs, blk64_t *blocknr, |
265 | e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), | |
266 | blk64_t ref_block EXT2FS_ATTR((unused)), | |
267 | int ref_offset EXT2FS_ATTR((unused)), | |
54434927 | 268 | void *private EXT2FS_ATTR((unused))) |
194686bb | 269 | { |
7117f8d6 | 270 | blk64_t block; |
194686bb TT |
271 | int group; |
272 | ||
273 | block = *blocknr; | |
3c041a51 | 274 | ext2fs_unmark_block_bitmap2(fs->block_map, block); |
6493f8e8 | 275 | group = ext2fs_group_of_blk2(fs, block); |
d7cca6b0 | 276 | ext2fs_bg_free_blocks_count_set(fs, group, ext2fs_bg_free_blocks_count(fs, group) + 1); |
4e988cb4 | 277 | ext2fs_group_desc_csum_set(fs, group); |
fe75afbf | 278 | ext2fs_free_blocks_count_add(fs->super, EXT2FS_CLUSTER_RATIO(fs)); |
194686bb TT |
279 | return 0; |
280 | } | |
281 | ||
282 | /* | |
283 | * Remove the journal inode from the filesystem | |
284 | */ | |
285 | static void remove_journal_inode(ext2_filsys fs) | |
286 | { | |
287 | struct ext2_inode inode; | |
288 | errcode_t retval; | |
289 | ino_t ino = fs->super->s_journal_inum; | |
efc6f628 | 290 | |
194686bb TT |
291 | retval = ext2fs_read_inode(fs, ino, &inode); |
292 | if (retval) { | |
293 | com_err(program_name, retval, | |
294 | _("while reading journal inode")); | |
295 | exit(1); | |
296 | } | |
297 | if (ino == EXT2_JOURNAL_INO) { | |
298 | retval = ext2fs_read_bitmaps(fs); | |
299 | if (retval) { | |
300 | com_err(program_name, retval, | |
301 | _("while reading bitmaps")); | |
302 | exit(1); | |
303 | } | |
7117f8d6 VAH |
304 | retval = ext2fs_block_iterate3(fs, ino, |
305 | BLOCK_FLAG_READ_ONLY, NULL, | |
306 | release_blocks_proc, NULL); | |
194686bb TT |
307 | if (retval) { |
308 | com_err(program_name, retval, | |
309 | _("while clearing journal inode")); | |
310 | exit(1); | |
311 | } | |
312 | memset(&inode, 0, sizeof(inode)); | |
313 | ext2fs_mark_bb_dirty(fs); | |
194686bb TT |
314 | fs->flags &= ~EXT2_FLAG_SUPER_ONLY; |
315 | } else | |
316 | inode.i_flags &= ~EXT2_IMMUTABLE_FL; | |
317 | retval = ext2fs_write_inode(fs, ino, &inode); | |
318 | if (retval) { | |
319 | com_err(program_name, retval, | |
320 | _("while writing journal inode")); | |
321 | exit(1); | |
322 | } | |
323 | fs->super->s_journal_inum = 0; | |
324 | ext2fs_mark_super_dirty(fs); | |
325 | } | |
dc2ec525 | 326 | |
a0c3fd5e TT |
327 | /* |
328 | * Update the default mount options | |
329 | */ | |
330 | static void update_mntopts(ext2_filsys fs, char *mntopts) | |
331 | { | |
ec43da2f | 332 | struct ext2_super_block *sb = fs->super; |
a0c3fd5e TT |
333 | |
334 | if (e2p_edit_mntopts(mntopts, &sb->s_default_mount_opts, ~0)) { | |
335 | fprintf(stderr, _("Invalid mount option set: %s\n"), | |
336 | mntopts); | |
337 | exit(1); | |
338 | } | |
339 | ext2fs_mark_super_dirty(fs); | |
340 | } | |
341 | ||
079ad63d TT |
342 | static void request_fsck_afterwards(ext2_filsys fs) |
343 | { | |
344 | static int requested = 0; | |
345 | ||
346 | if (requested++) | |
347 | return; | |
348 | fs->super->s_state &= ~EXT2_VALID_FS; | |
349 | printf("\n%s\n", _(please_fsck)); | |
350 | if (mount_flags & EXT2_MF_READONLY) | |
351 | printf(_("(and reboot afterwards!)\n")); | |
352 | } | |
353 | ||
63985320 TT |
354 | /* |
355 | * Update the feature set as provided by the user. | |
356 | */ | |
c8c071a0 | 357 | static void update_feature_set(ext2_filsys fs, char *features) |
63985320 | 358 | { |
ec43da2f | 359 | struct ext2_super_block *sb = fs->super; |
079ad63d | 360 | struct ext2_group_desc *gd; |
885bf6b8 | 361 | __u32 old_features[3]; |
079ad63d | 362 | int i, type_err; |
7c4a2ef5 | 363 | unsigned int mask_err; |
2eb3b20e | 364 | |
885bf6b8 TT |
365 | #define FEATURE_ON(type, mask) (!(old_features[(type)] & (mask)) && \ |
366 | ((&sb->s_feature_compat)[(type)] & (mask))) | |
367 | #define FEATURE_OFF(type, mask) ((old_features[(type)] & (mask)) && \ | |
368 | !((&sb->s_feature_compat)[(type)] & (mask))) | |
369 | #define FEATURE_CHANGED(type, mask) ((mask) & \ | |
370 | (old_features[(type)] ^ (&sb->s_feature_compat)[(type)])) | |
371 | ||
372 | old_features[E2P_FEATURE_COMPAT] = sb->s_feature_compat; | |
373 | old_features[E2P_FEATURE_INCOMPAT] = sb->s_feature_incompat; | |
374 | old_features[E2P_FEATURE_RO_INCOMPAT] = sb->s_feature_ro_compat; | |
375 | ||
7c4a2ef5 TT |
376 | if (e2p_edit_feature2(features, &sb->s_feature_compat, |
377 | ok_features, clear_ok_features, | |
378 | &type_err, &mask_err)) { | |
379 | if (!mask_err) | |
380 | fprintf(stderr, | |
381 | _("Invalid filesystem option set: %s\n"), | |
382 | features); | |
383 | else if (type_err & E2P_FEATURE_NEGATE_FLAG) | |
384 | fprintf(stderr, _("Clearing filesystem feature '%s' " | |
385 | "not supported.\n"), | |
386 | e2p_feature2string(type_err & | |
387 | E2P_FEATURE_TYPE_MASK, | |
388 | mask_err)); | |
389 | else | |
390 | fprintf(stderr, _("Setting filesystem feature '%s' " | |
391 | "not supported.\n"), | |
392 | e2p_feature2string(type_err, mask_err)); | |
63985320 TT |
393 | exit(1); |
394 | } | |
885bf6b8 TT |
395 | |
396 | if (FEATURE_OFF(E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { | |
63985320 TT |
397 | if ((mount_flags & EXT2_MF_MOUNTED) && |
398 | !(mount_flags & EXT2_MF_READONLY)) { | |
2be8fe43 | 399 | fputs(_("The has_journal feature may only be " |
54434927 TT |
400 | "cleared when the filesystem is\n" |
401 | "unmounted or mounted " | |
402 | "read-only.\n"), stderr); | |
63985320 TT |
403 | exit(1); |
404 | } | |
405 | if (sb->s_feature_incompat & | |
406 | EXT3_FEATURE_INCOMPAT_RECOVER) { | |
54434927 TT |
407 | fputs(_("The needs_recovery flag is set. " |
408 | "Please run e2fsck before clearing\n" | |
409 | "the has_journal flag.\n"), stderr); | |
63985320 TT |
410 | exit(1); |
411 | } | |
63985320 | 412 | if (sb->s_journal_inum) { |
194686bb | 413 | remove_journal_inode(fs); |
63985320 | 414 | } |
de49f015 | 415 | if (sb->s_journal_dev) { |
dc2ec525 | 416 | remove_journal_device(fs); |
de49f015 | 417 | } |
63985320 | 418 | } |
885bf6b8 TT |
419 | |
420 | if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { | |
63985320 TT |
421 | /* |
422 | * If adding a journal flag, let the create journal | |
7a0516a3 BS |
423 | * code below handle setting the flag and creating the |
424 | * journal. We supply a default size if necessary. | |
63985320 | 425 | */ |
dc2ec525 TT |
426 | if (!journal_size) |
427 | journal_size = -1; | |
08dd830d | 428 | sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL; |
63985320 | 429 | } |
885bf6b8 TT |
430 | |
431 | if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX)) { | |
843049c4 | 432 | if (!sb->s_def_hash_version) |
d1070d91 | 433 | sb->s_def_hash_version = EXT2_HASH_HALF_MD4; |
843049c4 TT |
434 | if (uuid_is_null((unsigned char *) sb->s_hash_seed)) |
435 | uuid_generate((unsigned char *) sb->s_hash_seed); | |
436 | } | |
dc2ec525 | 437 | |
a49670e6 | 438 | if (FEATURE_OFF(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { |
c2d4300b JS |
439 | if (ext2fs_check_desc(fs)) { |
440 | fputs(_("Clearing the flex_bg flag would " | |
441 | "cause the the filesystem to be\n" | |
442 | "inconsistent.\n"), stderr); | |
443 | exit(1); | |
444 | } | |
445 | } | |
dc2ec525 | 446 | |
2be8fe43 TT |
447 | if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT, |
448 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) { | |
449 | if ((mount_flags & EXT2_MF_MOUNTED) && | |
450 | !(mount_flags & EXT2_MF_READONLY)) { | |
451 | fputs(_("The huge_file feature may only be " | |
452 | "cleared when the filesystem is\n" | |
453 | "unmounted or mounted " | |
454 | "read-only.\n"), stderr); | |
455 | exit(1); | |
456 | } | |
457 | } | |
458 | ||
079ad63d TT |
459 | if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT, |
460 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { | |
7117f8d6 VAH |
461 | for (i = 0; i < fs->group_desc_count; i++) { |
462 | gd = ext2fs_group_desc(fs, fs->group_desc, i); | |
079ad63d TT |
463 | gd->bg_itable_unused = 0; |
464 | gd->bg_flags = EXT2_BG_INODE_ZEROED; | |
465 | ext2fs_group_desc_csum_set(fs, i); | |
466 | } | |
467 | fs->flags &= ~EXT2_FLAG_SUPER_ONLY; | |
468 | } | |
469 | ||
470 | if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT, | |
471 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { | |
7117f8d6 VAH |
472 | for (i = 0; i < fs->group_desc_count; i++) { |
473 | gd = ext2fs_group_desc(fs, fs->group_desc, i); | |
079ad63d TT |
474 | if ((gd->bg_flags & EXT2_BG_INODE_ZEROED) == 0) { |
475 | /* | |
476 | * XXX what we really should do is zap | |
477 | * uninitialized inode tables instead. | |
478 | */ | |
479 | request_fsck_afterwards(fs); | |
480 | break; | |
481 | } | |
482 | gd->bg_itable_unused = 0; | |
483 | gd->bg_flags = 0; | |
484 | gd->bg_checksum = 0; | |
485 | } | |
486 | fs->flags &= ~EXT2_FLAG_SUPER_ONLY; | |
487 | } | |
488 | ||
771e8db9 AK |
489 | if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT, |
490 | EXT4_FEATURE_RO_COMPAT_QUOTA)) { | |
491 | /* | |
492 | * Set the Q_flag here and handle the quota options in the code | |
493 | * below. | |
494 | */ | |
495 | if (!Q_flag) { | |
496 | Q_flag = 1; | |
497 | /* Enable both user quota and group quota by default */ | |
498 | usrquota = QOPT_ENABLE; | |
499 | grpquota = QOPT_ENABLE; | |
500 | } | |
501 | sb->s_feature_ro_compat &= ~EXT4_FEATURE_RO_COMPAT_QUOTA; | |
502 | } | |
503 | ||
504 | if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT, | |
505 | EXT4_FEATURE_RO_COMPAT_QUOTA)) { | |
506 | /* | |
507 | * Set the Q_flag here and handle the quota options in the code | |
508 | * below. | |
509 | */ | |
510 | if (Q_flag) | |
511 | fputs(_("\nWarning: '^quota' option overrides '-Q'" | |
512 | "arguments.\n"), stderr); | |
513 | Q_flag = 1; | |
514 | /* Disable both user quota and group quota by default */ | |
515 | usrquota = QOPT_DISABLE; | |
516 | grpquota = QOPT_DISABLE; | |
517 | } | |
518 | ||
63985320 TT |
519 | if (sb->s_rev_level == EXT2_GOOD_OLD_REV && |
520 | (sb->s_feature_compat || sb->s_feature_ro_compat || | |
521 | sb->s_feature_incompat)) | |
522 | ext2fs_update_dynamic_rev(fs); | |
885bf6b8 TT |
523 | |
524 | if (FEATURE_CHANGED(E2P_FEATURE_RO_INCOMPAT, | |
525 | EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) || | |
2be8fe43 TT |
526 | FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT, |
527 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE) || | |
885bf6b8 | 528 | FEATURE_CHANGED(E2P_FEATURE_INCOMPAT, |
037914e2 TT |
529 | EXT2_FEATURE_INCOMPAT_FILETYPE) || |
530 | FEATURE_CHANGED(E2P_FEATURE_COMPAT, | |
558df544 TT |
531 | EXT2_FEATURE_COMPAT_RESIZE_INODE) || |
532 | FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT, | |
079ad63d TT |
533 | EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) |
534 | request_fsck_afterwards(fs); | |
885bf6b8 TT |
535 | |
536 | if ((old_features[E2P_FEATURE_COMPAT] != sb->s_feature_compat) || | |
537 | (old_features[E2P_FEATURE_INCOMPAT] != sb->s_feature_incompat) || | |
538 | (old_features[E2P_FEATURE_RO_INCOMPAT] != sb->s_feature_ro_compat)) | |
2eb3b20e | 539 | ext2fs_mark_super_dirty(fs); |
63985320 TT |
540 | } |
541 | ||
542 | /* | |
543 | * Add a journal to the filesystem. | |
544 | */ | |
545 | static void add_journal(ext2_filsys fs) | |
546 | { | |
547 | unsigned long journal_blocks; | |
548 | errcode_t retval; | |
16ed5b3a | 549 | ext2_filsys jfs; |
2a29f135 | 550 | io_manager io_ptr; |
63985320 TT |
551 | |
552 | if (fs->super->s_feature_compat & | |
553 | EXT3_FEATURE_COMPAT_HAS_JOURNAL) { | |
54434927 | 554 | fputs(_("The filesystem already has a journal.\n"), stderr); |
2d15576d | 555 | goto err; |
63985320 | 556 | } |
63985320 TT |
557 | if (journal_device) { |
558 | check_plausibility(journal_device); | |
559 | check_mount(journal_device, 0, _("journal")); | |
2a29f135 | 560 | #ifdef CONFIG_TESTIO_DEBUG |
f38cf3cb TT |
561 | if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) { |
562 | io_ptr = test_io_manager; | |
563 | test_io_backing_manager = unix_io_manager; | |
564 | } else | |
2a29f135 | 565 | #endif |
f38cf3cb | 566 | io_ptr = unix_io_manager; |
16ed5b3a TT |
567 | retval = ext2fs_open(journal_device, EXT2_FLAG_RW| |
568 | EXT2_FLAG_JOURNAL_DEV_OK, 0, | |
2a29f135 | 569 | fs->blocksize, io_ptr, &jfs); |
16ed5b3a TT |
570 | if (retval) { |
571 | com_err(program_name, retval, | |
1d08d9bf | 572 | _("\n\twhile trying to open journal on %s\n"), |
16ed5b3a | 573 | journal_device); |
2d15576d | 574 | goto err; |
16ed5b3a | 575 | } |
63985320 TT |
576 | printf(_("Creating journal on device %s: "), |
577 | journal_device); | |
4055ef73 | 578 | fflush(stdout); |
2d15576d | 579 | |
16ed5b3a | 580 | retval = ext2fs_add_journal_device(fs, jfs); |
2d15576d | 581 | ext2fs_close(jfs); |
63985320 | 582 | if (retval) { |
ec43da2f TT |
583 | com_err(program_name, retval, |
584 | _("while adding filesystem to journal on %s"), | |
585 | journal_device); | |
2d15576d | 586 | goto err; |
63985320 | 587 | } |
54434927 | 588 | fputs(_("done\n"), stdout); |
63985320 | 589 | } else if (journal_size) { |
54434927 | 590 | fputs(_("Creating journal inode: "), stdout); |
63985320 | 591 | fflush(stdout); |
2537b6d0 TT |
592 | journal_blocks = figure_journal_size(journal_size, fs); |
593 | ||
63985320 TT |
594 | retval = ext2fs_add_journal_inode(fs, journal_blocks, |
595 | journal_flags); | |
596 | if (retval) { | |
7141b54b | 597 | fprintf(stderr, "\n"); |
63985320 | 598 | com_err(program_name, retval, |
1d08d9bf | 599 | _("\n\twhile trying to create journal file")); |
63985320 | 600 | exit(1); |
1d08d9bf | 601 | } else |
54434927 | 602 | fputs(_("done\n"), stdout); |
63985320 TT |
603 | /* |
604 | * If the filesystem wasn't mounted, we need to force | |
605 | * the block group descriptors out. | |
606 | */ | |
607 | if ((mount_flags & EXT2_MF_MOUNTED) == 0) | |
608 | fs->flags &= ~EXT2_FLAG_SUPER_ONLY; | |
609 | } | |
faa2dcda LC |
610 | print_check_message(fs->super->s_max_mnt_count, |
611 | fs->super->s_checkinterval); | |
2d15576d AD |
612 | return; |
613 | ||
614 | err: | |
45e338f5 | 615 | free(journal_device); |
2d15576d | 616 | exit(1); |
63985320 TT |
617 | } |
618 | ||
771e8db9 AK |
619 | void handle_quota_options(ext2_filsys fs) |
620 | { | |
621 | quota_ctx_t qctx; | |
622 | errcode_t retval; | |
623 | ext2_ino_t qf_ino; | |
624 | ||
625 | if (!usrquota && !grpquota) | |
626 | /* Nothing to do. */ | |
627 | return; | |
628 | ||
629 | init_quota_context(&qctx, fs, -1); | |
630 | ||
631 | if (usrquota == QOPT_ENABLE && !fs->super->s_usr_quota_inum) { | |
632 | if ((qf_ino = quota_file_exists(fs, USRQUOTA, QFMT_VFS_V1)) > 0) | |
633 | set_sb_quota_inum(fs, qf_ino, USRQUOTA); | |
634 | else | |
635 | write_quota_inode(qctx, USRQUOTA); | |
636 | } else if (usrquota == QOPT_DISABLE) { | |
637 | remove_quota_inode(fs, USRQUOTA); | |
638 | } | |
639 | ||
640 | if (grpquota == QOPT_ENABLE && !fs->super->s_grp_quota_inum) { | |
641 | if ((qf_ino = quota_file_exists(fs, GRPQUOTA, QFMT_VFS_V1)) > 0) | |
642 | set_sb_quota_inum(fs, qf_ino, GRPQUOTA); | |
643 | else | |
644 | write_quota_inode(qctx, GRPQUOTA); | |
645 | } else if (grpquota == QOPT_DISABLE) { | |
646 | remove_quota_inode(fs, GRPQUOTA); | |
647 | } | |
648 | ||
649 | release_quota_context(&qctx); | |
650 | ||
651 | if ((usrquota == QOPT_ENABLE) || (grpquota == QOPT_ENABLE)) { | |
652 | fs->super->s_feature_ro_compat |= EXT4_FEATURE_RO_COMPAT_QUOTA; | |
653 | ext2fs_mark_super_dirty(fs); | |
654 | } else if ((usrquota == QOPT_DISABLE) && (grpquota == QOPT_DISABLE)) { | |
655 | fs->super->s_feature_ro_compat &= ~EXT4_FEATURE_RO_COMPAT_QUOTA; | |
656 | ext2fs_mark_super_dirty(fs); | |
657 | } | |
658 | ||
659 | return; | |
660 | } | |
661 | ||
662 | void parse_quota_opts(const char *opts) | |
663 | { | |
664 | char *buf, *token, *next, *p, *arg; | |
665 | int len; | |
666 | ||
667 | len = strlen(opts); | |
668 | buf = malloc(len+1); | |
669 | if (!buf) { | |
670 | fputs(_("Couldn't allocate memory to parse quota " | |
671 | "options!\n"), stderr); | |
672 | exit(1); | |
673 | } | |
674 | strcpy(buf, opts); | |
675 | for (token = buf; token && *token; token = next) { | |
676 | p = strchr(token, ','); | |
677 | next = 0; | |
678 | if (p) { | |
679 | *p = 0; | |
680 | next = p+1; | |
681 | } | |
682 | ||
683 | if (strcmp(token, "usrquota") == 0) { | |
684 | usrquota = QOPT_ENABLE; | |
685 | } else if (strcmp(token, "^usrquota") == 0) { | |
686 | usrquota = QOPT_DISABLE; | |
687 | } else if (strcmp(token, "grpquota") == 0) { | |
688 | grpquota = QOPT_ENABLE; | |
689 | } else if (strcmp(token, "^grpquota") == 0) { | |
690 | grpquota = QOPT_DISABLE; | |
691 | } else { | |
692 | fputs(_("\nBad quota options specified.\n\n" | |
693 | "Following valid quota options are available " | |
694 | "(pass by separating with comma):\n" | |
695 | "\t[^]usrquota\n" | |
696 | "\t[^]grpquota\n" | |
697 | "\n\n"), stderr); | |
698 | free(buf); | |
699 | exit(1); | |
700 | } | |
701 | } | |
702 | free(buf); | |
703 | } | |
704 | ||
705 | ||
83238153 | 706 | |
c8c071a0 | 707 | static void parse_e2label_options(int argc, char ** argv) |
83238153 TT |
708 | { |
709 | if ((argc < 2) || (argc > 3)) { | |
54434927 | 710 | fputs(_("Usage: e2label device [newlabel]\n"), stderr); |
83238153 TT |
711 | exit(1); |
712 | } | |
2e8ca9a2 TT |
713 | io_options = strchr(argv[1], '?'); |
714 | if (io_options) | |
715 | *io_options++ = 0; | |
332f2c23 | 716 | device_name = blkid_get_devname(NULL, argv[1], NULL); |
817e49e3 | 717 | if (!device_name) { |
efc6f628 | 718 | com_err("e2label", 0, _("Unable to resolve '%s'"), |
817e49e3 TT |
719 | argv[1]); |
720 | exit(1); | |
721 | } | |
2be8fe43 | 722 | open_flag = EXT2_FLAG_JOURNAL_DEV_OK; |
83238153 | 723 | if (argc == 3) { |
0ddfd9a5 | 724 | open_flag |= EXT2_FLAG_RW; |
83238153 TT |
725 | L_flag = 1; |
726 | new_label = argv[2]; | |
efc6f628 | 727 | } else |
83238153 TT |
728 | print_label++; |
729 | } | |
730 | ||
d4de4aa9 TT |
731 | static time_t parse_time(char *str) |
732 | { | |
733 | struct tm ts; | |
734 | ||
735 | if (strcmp(str, "now") == 0) { | |
736 | return (time(0)); | |
737 | } | |
738 | memset(&ts, 0, sizeof(ts)); | |
bc7c14e0 | 739 | #ifdef HAVE_STRPTIME |
690e693c | 740 | strptime(str, "%Y%m%d%H%M%S", &ts); |
bc7c14e0 | 741 | #else |
690e693c | 742 | sscanf(str, "%4d%2d%2d%2d%2d%2d", &ts.tm_year, &ts.tm_mon, |
bc7c14e0 TT |
743 | &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec); |
744 | ts.tm_year -= 1900; | |
745 | ts.tm_mon -= 1; | |
746 | if (ts.tm_year < 0 || ts.tm_mon < 0 || ts.tm_mon > 11 || | |
747 | ts.tm_mday < 0 || ts.tm_mday > 31 || ts.tm_hour > 23 || | |
748 | ts.tm_min > 59 || ts.tm_sec > 61) | |
749 | ts.tm_mday = 0; | |
750 | #endif | |
d4de4aa9 TT |
751 | if (ts.tm_mday == 0) { |
752 | com_err(program_name, 0, | |
753 | _("Couldn't parse date/time specifier: %s"), | |
754 | str); | |
755 | usage(); | |
756 | } | |
a2ff0f31 | 757 | ts.tm_isdst = -1; |
d4de4aa9 TT |
758 | return (mktime(&ts)); |
759 | } | |
83238153 | 760 | |
c8c071a0 | 761 | static void parse_tune2fs_options(int argc, char **argv) |
3839e657 | 762 | { |
519149fb | 763 | int c; |
ec43da2f TT |
764 | char *tmp; |
765 | struct group *gr; | |
766 | struct passwd *pw; | |
3839e657 | 767 | |
2be8fe43 | 768 | open_flag = 0; |
0ddfd9a5 | 769 | |
0f8973fb | 770 | printf("tune2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); |
771e8db9 | 771 | while ((c = getopt(argc, argv, "c:e:fg:i:jlm:o:r:s:u:C:E:I:J:L:M:O:Q:T:U:")) != EOF) |
ec43da2f TT |
772 | switch (c) { |
773 | case 'c': | |
774 | max_mount_count = strtol(optarg, &tmp, 0); | |
775 | if (*tmp || max_mount_count > 16000) { | |
776 | com_err(program_name, 0, | |
777 | _("bad mounts count - %s"), | |
778 | optarg); | |
779 | usage(); | |
780 | } | |
781 | if (max_mount_count == 0) | |
782 | max_mount_count = -1; | |
783 | c_flag = 1; | |
784 | open_flag = EXT2_FLAG_RW; | |
785 | break; | |
786 | case 'C': | |
787 | mount_count = strtoul(optarg, &tmp, 0); | |
788 | if (*tmp || mount_count > 16000) { | |
789 | com_err(program_name, 0, | |
790 | _("bad mounts count - %s"), | |
791 | optarg); | |
792 | usage(); | |
793 | } | |
794 | C_flag = 1; | |
795 | open_flag = EXT2_FLAG_RW; | |
796 | break; | |
797 | case 'e': | |
798 | if (strcmp(optarg, "continue") == 0) | |
799 | errors = EXT2_ERRORS_CONTINUE; | |
800 | else if (strcmp(optarg, "remount-ro") == 0) | |
801 | errors = EXT2_ERRORS_RO; | |
802 | else if (strcmp(optarg, "panic") == 0) | |
803 | errors = EXT2_ERRORS_PANIC; | |
804 | else { | |
805 | com_err(program_name, 0, | |
806 | _("bad error behavior - %s"), | |
807 | optarg); | |
808 | usage(); | |
809 | } | |
810 | e_flag = 1; | |
811 | open_flag = EXT2_FLAG_RW; | |
812 | break; | |
813 | case 'E': | |
814 | extended_cmd = optarg; | |
815 | open_flag |= EXT2_FLAG_RW; | |
816 | break; | |
817 | case 'f': /* Force */ | |
818 | f_flag = 1; | |
819 | break; | |
820 | case 'g': | |
821 | resgid = strtoul(optarg, &tmp, 0); | |
822 | if (*tmp) { | |
823 | gr = getgrnam(optarg); | |
824 | if (gr == NULL) | |
825 | tmp = optarg; | |
818180cd | 826 | else { |
ec43da2f TT |
827 | resgid = gr->gr_gid; |
828 | *tmp = 0; | |
f3db3566 | 829 | } |
ec43da2f TT |
830 | } |
831 | if (*tmp) { | |
832 | com_err(program_name, 0, | |
833 | _("bad gid/group name - %s"), | |
834 | optarg); | |
835 | usage(); | |
836 | } | |
837 | g_flag = 1; | |
838 | open_flag = EXT2_FLAG_RW; | |
839 | break; | |
840 | case 'i': | |
841 | interval = strtoul(optarg, &tmp, 0); | |
842 | switch (*tmp) { | |
843 | case 's': | |
844 | tmp++; | |
f3db3566 | 845 | break; |
ec43da2f TT |
846 | case '\0': |
847 | case 'd': | |
848 | case 'D': /* days */ | |
849 | interval *= 86400; | |
850 | if (*tmp != '\0') | |
1e3472c5 | 851 | tmp++; |
1e3472c5 | 852 | break; |
3839e657 | 853 | case 'm': |
ec43da2f TT |
854 | case 'M': /* months! */ |
855 | interval *= 86400 * 30; | |
856 | tmp++; | |
3839e657 | 857 | break; |
ec43da2f TT |
858 | case 'w': |
859 | case 'W': /* weeks */ | |
860 | interval *= 86400 * 7; | |
861 | tmp++; | |
a0c3fd5e | 862 | break; |
ec43da2f TT |
863 | } |
864 | if (*tmp) { | |
865 | com_err(program_name, 0, | |
866 | _("bad interval - %s"), optarg); | |
867 | usage(); | |
868 | } | |
869 | i_flag = 1; | |
870 | open_flag = EXT2_FLAG_RW; | |
871 | break; | |
872 | case 'j': | |
873 | if (!journal_size) | |
874 | journal_size = -1; | |
875 | open_flag = EXT2_FLAG_RW; | |
876 | break; | |
877 | case 'J': | |
878 | parse_journal_opts(optarg); | |
879 | open_flag = EXT2_FLAG_RW; | |
880 | break; | |
881 | case 'l': | |
882 | l_flag = 1; | |
883 | break; | |
884 | case 'L': | |
885 | new_label = optarg; | |
886 | L_flag = 1; | |
887 | open_flag |= EXT2_FLAG_RW | | |
888 | EXT2_FLAG_JOURNAL_DEV_OK; | |
889 | break; | |
890 | case 'm': | |
891 | reserved_ratio = strtod(optarg, &tmp); | |
8d822455 TT |
892 | if (*tmp || reserved_ratio > 50 || |
893 | reserved_ratio < 0) { | |
ec43da2f TT |
894 | com_err(program_name, 0, |
895 | _("bad reserved block ratio - %s"), | |
896 | optarg); | |
897 | usage(); | |
898 | } | |
899 | m_flag = 1; | |
900 | open_flag = EXT2_FLAG_RW; | |
901 | break; | |
902 | case 'M': | |
903 | new_last_mounted = optarg; | |
904 | M_flag = 1; | |
905 | open_flag = EXT2_FLAG_RW; | |
906 | break; | |
907 | case 'o': | |
908 | if (mntopts_cmd) { | |
909 | com_err(program_name, 0, | |
910 | _("-o may only be specified once")); | |
911 | usage(); | |
912 | } | |
913 | mntopts_cmd = optarg; | |
914 | open_flag = EXT2_FLAG_RW; | |
915 | break; | |
916 | ||
917 | case 'O': | |
918 | if (features_cmd) { | |
919 | com_err(program_name, 0, | |
920 | _("-O may only be specified once")); | |
921 | usage(); | |
922 | } | |
923 | features_cmd = optarg; | |
924 | open_flag = EXT2_FLAG_RW; | |
925 | break; | |
771e8db9 AK |
926 | case 'Q': |
927 | Q_flag = 1; | |
928 | parse_quota_opts(optarg); | |
929 | open_flag = EXT2_FLAG_RW; | |
930 | break; | |
ec43da2f TT |
931 | case 'r': |
932 | reserved_blocks = strtoul(optarg, &tmp, 0); | |
933 | if (*tmp) { | |
934 | com_err(program_name, 0, | |
935 | _("bad reserved blocks count - %s"), | |
936 | optarg); | |
937 | usage(); | |
938 | } | |
939 | r_flag = 1; | |
940 | open_flag = EXT2_FLAG_RW; | |
941 | break; | |
942 | case 's': /* Deprecated */ | |
943 | s_flag = atoi(optarg); | |
944 | open_flag = EXT2_FLAG_RW; | |
945 | break; | |
946 | case 'T': | |
947 | T_flag = 1; | |
948 | last_check_time = parse_time(optarg); | |
949 | open_flag = EXT2_FLAG_RW; | |
950 | break; | |
951 | case 'u': | |
952 | resuid = strtoul(optarg, &tmp, 0); | |
818180cd | 953 | if (*tmp) { |
ec43da2f | 954 | pw = getpwnam(optarg); |
f3db3566 TT |
955 | if (pw == NULL) |
956 | tmp = optarg; | |
a418d3ad | 957 | else { |
f3db3566 | 958 | resuid = pw->pw_uid; |
a418d3ad TT |
959 | *tmp = 0; |
960 | } | |
f3db3566 | 961 | } |
818180cd | 962 | if (*tmp) { |
ec43da2f TT |
963 | com_err(program_name, 0, |
964 | _("bad uid/user name - %s"), | |
965 | optarg); | |
818180cd | 966 | usage(); |
f3db3566 TT |
967 | } |
968 | u_flag = 1; | |
1e3472c5 TT |
969 | open_flag = EXT2_FLAG_RW; |
970 | break; | |
ec43da2f TT |
971 | case 'U': |
972 | new_UUID = optarg; | |
973 | U_flag = 1; | |
974 | open_flag = EXT2_FLAG_RW | | |
975 | EXT2_FLAG_JOURNAL_DEV_OK; | |
976 | break; | |
977 | case 'I': | |
978 | new_inode_size = strtoul(optarg, &tmp, 0); | |
979 | if (*tmp) { | |
980 | com_err(program_name, 0, | |
981 | _("bad inode size - %s"), | |
982 | optarg); | |
818180cd | 983 | usage(); |
ec43da2f TT |
984 | } |
985 | if (!((new_inode_size & | |
986 | (new_inode_size - 1)) == 0)) { | |
987 | com_err(program_name, 0, | |
988 | _("Inode size must be a " | |
989 | "power of two- %s"), | |
990 | optarg); | |
991 | usage(); | |
992 | } | |
993 | open_flag = EXT2_FLAG_RW; | |
994 | I_flag = 1; | |
995 | break; | |
996 | default: | |
997 | usage(); | |
3839e657 TT |
998 | } |
999 | if (optind < argc - 1 || optind == argc) | |
818180cd | 1000 | usage(); |
1e3472c5 TT |
1001 | if (!open_flag && !l_flag) |
1002 | usage(); | |
2e8ca9a2 TT |
1003 | io_options = strchr(argv[optind], '?'); |
1004 | if (io_options) | |
1005 | *io_options++ = 0; | |
332f2c23 | 1006 | device_name = blkid_get_devname(NULL, argv[optind], NULL); |
817e49e3 | 1007 | if (!device_name) { |
efc6f628 | 1008 | com_err("tune2fs", 0, _("Unable to resolve '%s'"), |
817e49e3 TT |
1009 | argv[optind]); |
1010 | exit(1); | |
1011 | } | |
118d7dac TT |
1012 | } |
1013 | ||
14b596d4 | 1014 | #ifdef CONFIG_BUILD_FINDFS |
3e699064 | 1015 | void do_findfs(int argc, char **argv) |
118d7dac TT |
1016 | { |
1017 | char *dev; | |
83238153 | 1018 | |
118d7dac TT |
1019 | if ((argc != 2) || |
1020 | (strncmp(argv[1], "LABEL=", 6) && strncmp(argv[1], "UUID=", 5))) { | |
1021 | fprintf(stderr, "Usage: findfs LABEL=<label>|UUID=<uuid>\n"); | |
1022 | exit(2); | |
1023 | } | |
ed1b33e8 | 1024 | dev = blkid_get_devname(NULL, argv[1], NULL); |
118d7dac | 1025 | if (!dev) { |
efc6f628 | 1026 | com_err("findfs", 0, _("Unable to resolve '%s'"), |
118d7dac TT |
1027 | argv[1]); |
1028 | exit(1); | |
1029 | } | |
1030 | puts(dev); | |
1031 | exit(0); | |
1032 | } | |
14b596d4 | 1033 | #endif |
83238153 | 1034 | |
6cb27404 TT |
1035 | static void parse_extended_opts(ext2_filsys fs, const char *opts) |
1036 | { | |
1037 | char *buf, *token, *next, *p, *arg; | |
10ff68d4 | 1038 | int len, hash_alg; |
6cb27404 TT |
1039 | int r_usage = 0; |
1040 | ||
1041 | len = strlen(opts); | |
1042 | buf = malloc(len+1); | |
1043 | if (!buf) { | |
1044 | fprintf(stderr, | |
1045 | _("Couldn't allocate memory to parse options!\n")); | |
1046 | exit(1); | |
1047 | } | |
1048 | strcpy(buf, opts); | |
1049 | for (token = buf; token && *token; token = next) { | |
1050 | p = strchr(token, ','); | |
1051 | next = 0; | |
1052 | if (p) { | |
1053 | *p = 0; | |
1054 | next = p+1; | |
1055 | } | |
1056 | arg = strchr(token, '='); | |
1057 | if (arg) { | |
1058 | *arg = 0; | |
1059 | arg++; | |
1060 | } | |
1061 | if (!strcmp(token, "test_fs")) { | |
1062 | fs->super->s_flags |= EXT2_FLAGS_TEST_FILESYS; | |
1063 | printf("Setting test filesystem flag\n"); | |
1064 | ext2fs_mark_super_dirty(fs); | |
1065 | } else if (!strcmp(token, "^test_fs")) { | |
1066 | fs->super->s_flags &= ~EXT2_FLAGS_TEST_FILESYS; | |
1067 | printf("Clearing test filesystem flag\n"); | |
1068 | ext2fs_mark_super_dirty(fs); | |
0c17cb25 TT |
1069 | } else if (strcmp(token, "stride") == 0) { |
1070 | if (!arg) { | |
1071 | r_usage++; | |
1072 | continue; | |
1073 | } | |
1074 | stride = strtoul(arg, &p, 0); | |
035f32ab | 1075 | if (*p) { |
0c17cb25 TT |
1076 | fprintf(stderr, |
1077 | _("Invalid RAID stride: %s\n"), | |
1078 | arg); | |
1079 | r_usage++; | |
1080 | continue; | |
1081 | } | |
1082 | stride_set = 1; | |
1083 | } else if (strcmp(token, "stripe-width") == 0 || | |
1084 | strcmp(token, "stripe_width") == 0) { | |
1085 | if (!arg) { | |
1086 | r_usage++; | |
1087 | continue; | |
1088 | } | |
1089 | stripe_width = strtoul(arg, &p, 0); | |
035f32ab | 1090 | if (*p) { |
0c17cb25 TT |
1091 | fprintf(stderr, |
1092 | _("Invalid RAID stripe-width: %s\n"), | |
1093 | arg); | |
1094 | r_usage++; | |
1095 | continue; | |
1096 | } | |
1097 | stripe_width_set = 1; | |
10ff68d4 TT |
1098 | } else if (strcmp(token, "hash_alg") == 0 || |
1099 | strcmp(token, "hash-alg") == 0) { | |
1100 | if (!arg) { | |
1101 | r_usage++; | |
1102 | continue; | |
1103 | } | |
1104 | hash_alg = e2p_string2hash(arg); | |
1105 | if (hash_alg < 0) { | |
ec43da2f | 1106 | fprintf(stderr, |
10ff68d4 TT |
1107 | _("Invalid hash algorithm: %s\n"), |
1108 | arg); | |
1109 | r_usage++; | |
1110 | continue; | |
1111 | } | |
1112 | fs->super->s_def_hash_version = hash_alg; | |
1113 | printf(_("Setting default hash algorithm " | |
ec43da2f | 1114 | "to %s (%d)\n"), |
10ff68d4 TT |
1115 | arg, hash_alg); |
1116 | ext2fs_mark_super_dirty(fs); | |
9a976ac7 | 1117 | } else if (!strcmp(token, "mount_opts")) { |
9345f026 TT |
1118 | if (!arg) { |
1119 | r_usage++; | |
1120 | continue; | |
1121 | } | |
1122 | if (strlen(arg) >= sizeof(fs->super->s_mount_opts)) { | |
1123 | fprintf(stderr, | |
1124 | "Extended mount options too long\n"); | |
1125 | continue; | |
1126 | } | |
9a976ac7 | 1127 | ext_mount_opts = strdup(arg); |
efc6f628 | 1128 | } else |
6cb27404 TT |
1129 | r_usage++; |
1130 | } | |
1131 | if (r_usage) { | |
1132 | fprintf(stderr, _("\nBad options specified.\n\n" | |
1133 | "Extended options are separated by commas, " | |
1134 | "and may take an argument which\n" | |
1135 | "\tis set off by an equals ('=') sign.\n\n" | |
1136 | "Valid extended options are:\n" | |
9a976ac7 TT |
1137 | "\thash_alg=<hash algorithm>\n" |
1138 | "\tmount_opts=<extended default mount options>\n" | |
0c17cb25 | 1139 | "\tstride=<RAID per-disk chunk size in blocks>\n" |
10ff68d4 | 1140 | "\tstripe_width=<RAID stride*data disks in blocks>\n" |
6cb27404 TT |
1141 | "\ttest_fs\n" |
1142 | "\t^test_fs\n")); | |
1143 | free(buf); | |
1144 | exit(1); | |
1145 | } | |
1146 | free(buf); | |
efc6f628 | 1147 | } |
6cb27404 | 1148 | |
31f1815f | 1149 | /* |
a9e5177b AK |
1150 | * Fill in the block bitmap bmap with the information regarding the |
1151 | * blocks to be moved | |
31f1815f TT |
1152 | */ |
1153 | static int get_move_bitmaps(ext2_filsys fs, int new_ino_blks_per_grp, | |
a9e5177b | 1154 | ext2fs_block_bitmap bmap) |
64d588cf AK |
1155 | { |
1156 | dgrp_t i; | |
154a5d75 AK |
1157 | int retval; |
1158 | ext2_badblocks_list bb_list = 0; | |
7117f8d6 VAH |
1159 | blk64_t j, needed_blocks = 0; |
1160 | blk64_t start_blk, end_blk; | |
64d588cf | 1161 | |
154a5d75 AK |
1162 | retval = ext2fs_read_bb_inode(fs, &bb_list); |
1163 | if (retval) | |
1164 | return retval; | |
1165 | ||
64d588cf | 1166 | for (i = 0; i < fs->group_desc_count; i++) { |
d7cca6b0 | 1167 | start_blk = ext2fs_inode_table_loc(fs, i) + |
64d588cf AK |
1168 | fs->inode_blocks_per_group; |
1169 | ||
d7cca6b0 | 1170 | end_blk = ext2fs_inode_table_loc(fs, i) + |
64d588cf AK |
1171 | new_ino_blks_per_grp; |
1172 | ||
1173 | for (j = start_blk; j < end_blk; j++) { | |
3c041a51 | 1174 | if (ext2fs_test_block_bitmap2(fs->block_map, j)) { |
154a5d75 AK |
1175 | /* |
1176 | * IF the block is a bad block we fail | |
64d588cf | 1177 | */ |
154a5d75 AK |
1178 | if (ext2fs_badblocks_list_test(bb_list, j)) { |
1179 | ext2fs_badblocks_list_free(bb_list); | |
1180 | return ENOSPC; | |
1181 | } | |
1182 | ||
3c041a51 | 1183 | ext2fs_mark_block_bitmap2(bmap, j); |
64d588cf AK |
1184 | } else { |
1185 | /* | |
1186 | * We are going to use this block for | |
1187 | * inode table. So mark them used. | |
1188 | */ | |
3c041a51 | 1189 | ext2fs_mark_block_bitmap2(fs->block_map, j); |
64d588cf AK |
1190 | } |
1191 | } | |
a9e5177b | 1192 | needed_blocks += end_blk - start_blk; |
64d588cf AK |
1193 | } |
1194 | ||
154a5d75 | 1195 | ext2fs_badblocks_list_free(bb_list); |
4efbac6f | 1196 | if (needed_blocks > ext2fs_free_blocks_count(fs->super)) |
64d588cf | 1197 | return ENOSPC; |
64d588cf AK |
1198 | |
1199 | return 0; | |
1200 | } | |
1201 | ||
91fac979 AK |
1202 | static int ext2fs_is_meta_block(ext2_filsys fs, blk_t blk) |
1203 | { | |
1204 | dgrp_t group; | |
1205 | group = ext2fs_group_of_blk(fs, blk); | |
d7cca6b0 | 1206 | if (ext2fs_block_bitmap_loc(fs, group) == blk) |
91fac979 | 1207 | return 1; |
d7cca6b0 | 1208 | if (ext2fs_inode_bitmap_loc(fs, group) == blk) |
91fac979 AK |
1209 | return 1; |
1210 | return 0; | |
1211 | } | |
1212 | ||
1213 | static int ext2fs_is_block_in_group(ext2_filsys fs, dgrp_t group, blk_t blk) | |
1214 | { | |
1215 | blk_t start_blk, end_blk; | |
1216 | start_blk = fs->super->s_first_data_block + | |
1217 | EXT2_BLOCKS_PER_GROUP(fs->super) * group; | |
1218 | /* | |
1219 | * We cannot get new block beyond end_blk for for the last block group | |
1220 | * so we can check with EXT2_BLOCKS_PER_GROUP even for last block group | |
1221 | */ | |
1222 | end_blk = start_blk + EXT2_BLOCKS_PER_GROUP(fs->super); | |
1223 | if (blk >= start_blk && blk <= end_blk) | |
1224 | return 1; | |
1225 | return 0; | |
1226 | } | |
1227 | ||
a9e5177b | 1228 | static int move_block(ext2_filsys fs, ext2fs_block_bitmap bmap) |
64d588cf | 1229 | { |
91fac979 | 1230 | |
64d588cf | 1231 | char *buf; |
cf5301d7 | 1232 | dgrp_t group = 0; |
64d588cf | 1233 | errcode_t retval; |
91fac979 | 1234 | int meta_data = 0; |
7117f8d6 | 1235 | blk64_t blk, new_blk, goal; |
64d588cf AK |
1236 | struct blk_move *bmv; |
1237 | ||
64d588cf AK |
1238 | retval = ext2fs_get_mem(fs->blocksize, &buf); |
1239 | if (retval) | |
1240 | return retval; | |
1241 | ||
27c6de45 | 1242 | for (new_blk = blk = fs->super->s_first_data_block; |
4efbac6f | 1243 | blk < ext2fs_blocks_count(fs->super); blk++) { |
3c041a51 | 1244 | if (!ext2fs_test_block_bitmap2(bmap, blk)) |
64d588cf AK |
1245 | continue; |
1246 | ||
91fac979 AK |
1247 | if (ext2fs_is_meta_block(fs, blk)) { |
1248 | /* | |
1249 | * If the block is mapping a fs meta data block | |
1250 | * like group desc/block bitmap/inode bitmap. We | |
1251 | * should find a block in the same group and fix | |
1252 | * the respective fs metadata pointers. Otherwise | |
1253 | * fail | |
1254 | */ | |
1255 | group = ext2fs_group_of_blk(fs, blk); | |
b49f78fe | 1256 | goal = ext2fs_group_first_block2(fs, group); |
91fac979 AK |
1257 | meta_data = 1; |
1258 | ||
1259 | } else { | |
1260 | goal = new_blk; | |
1261 | } | |
7117f8d6 | 1262 | retval = ext2fs_new_block2(fs, goal, NULL, &new_blk); |
64d588cf AK |
1263 | if (retval) |
1264 | goto err_out; | |
1265 | ||
91fac979 AK |
1266 | /* new fs meta data block should be in the same group */ |
1267 | if (meta_data && !ext2fs_is_block_in_group(fs, group, new_blk)) { | |
1268 | retval = ENOSPC; | |
1269 | goto err_out; | |
1270 | } | |
1271 | ||
64d588cf | 1272 | /* Mark this block as allocated */ |
3c041a51 | 1273 | ext2fs_mark_block_bitmap2(fs->block_map, new_blk); |
64d588cf AK |
1274 | |
1275 | /* Add it to block move list */ | |
1276 | retval = ext2fs_get_mem(sizeof(struct blk_move), &bmv); | |
1277 | if (retval) | |
1278 | goto err_out; | |
1279 | ||
1280 | bmv->old_loc = blk; | |
1281 | bmv->new_loc = new_blk; | |
1282 | ||
1283 | list_add(&(bmv->list), &blk_move_list); | |
1284 | ||
24a117ab | 1285 | retval = io_channel_read_blk64(fs->io, blk, 1, buf); |
64d588cf AK |
1286 | if (retval) |
1287 | goto err_out; | |
1288 | ||
24a117ab | 1289 | retval = io_channel_write_blk64(fs->io, new_blk, 1, buf); |
64d588cf AK |
1290 | if (retval) |
1291 | goto err_out; | |
1292 | } | |
1293 | ||
1294 | err_out: | |
1295 | ext2fs_free_mem(&buf); | |
1296 | return retval; | |
1297 | } | |
1298 | ||
7117f8d6 | 1299 | static blk64_t translate_block(blk64_t blk) |
64d588cf AK |
1300 | { |
1301 | struct list_head *entry; | |
1302 | struct blk_move *bmv; | |
1303 | ||
1304 | list_for_each(entry, &blk_move_list) { | |
64d588cf AK |
1305 | bmv = list_entry(entry, struct blk_move, list); |
1306 | if (bmv->old_loc == blk) | |
1307 | return bmv->new_loc; | |
1308 | } | |
1309 | ||
1310 | return 0; | |
1311 | } | |
1312 | ||
721b367a | 1313 | static int process_block(ext2_filsys fs EXT2FS_ATTR((unused)), |
7117f8d6 | 1314 | blk64_t *block_nr, |
721b367a | 1315 | e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), |
7117f8d6 | 1316 | blk64_t ref_block EXT2FS_ATTR((unused)), |
64d588cf | 1317 | int ref_offset EXT2FS_ATTR((unused)), |
27c6de45 | 1318 | void *priv_data) |
64d588cf AK |
1319 | { |
1320 | int ret = 0; | |
7117f8d6 | 1321 | blk64_t new_blk; |
27c6de45 | 1322 | ext2fs_block_bitmap bmap = (ext2fs_block_bitmap) priv_data; |
64d588cf | 1323 | |
3c041a51 | 1324 | if (!ext2fs_test_block_bitmap2(bmap, *block_nr)) |
27c6de45 | 1325 | return 0; |
ec43da2f | 1326 | new_blk = translate_block(*block_nr); |
64d588cf AK |
1327 | if (new_blk) { |
1328 | *block_nr = new_blk; | |
1329 | /* | |
1330 | * This will force the ext2fs_write_inode in the iterator | |
1331 | */ | |
1332 | ret |= BLOCK_CHANGED; | |
1333 | } | |
1334 | ||
1335 | return ret; | |
1336 | } | |
1337 | ||
27c6de45 | 1338 | static int inode_scan_and_fix(ext2_filsys fs, ext2fs_block_bitmap bmap) |
64d588cf AK |
1339 | { |
1340 | errcode_t retval = 0; | |
1341 | ext2_ino_t ino; | |
7117f8d6 | 1342 | blk64_t blk; |
64d588cf AK |
1343 | char *block_buf = 0; |
1344 | struct ext2_inode inode; | |
1345 | ext2_inode_scan scan = NULL; | |
1346 | ||
1347 | retval = ext2fs_get_mem(fs->blocksize * 3, &block_buf); | |
1348 | if (retval) | |
1349 | return retval; | |
1350 | ||
1351 | retval = ext2fs_open_inode_scan(fs, 0, &scan); | |
1352 | if (retval) | |
1353 | goto err_out; | |
1354 | ||
1355 | while (1) { | |
64d588cf AK |
1356 | retval = ext2fs_get_next_inode(scan, &ino, &inode); |
1357 | if (retval) | |
1358 | goto err_out; | |
1359 | ||
1360 | if (!ino) | |
1361 | break; | |
1362 | ||
1363 | if (inode.i_links_count == 0) | |
1364 | continue; /* inode not in use */ | |
1365 | ||
1366 | /* FIXME!! | |
1367 | * If we end up modifying the journal inode | |
1368 | * the sb->s_jnl_blocks will differ. But a | |
1369 | * subsequent e2fsck fixes that. | |
1370 | * Do we need to fix this ?? | |
1371 | */ | |
1372 | ||
a63745e8 VAH |
1373 | if (ext2fs_file_acl_block(&inode) && |
1374 | ext2fs_test_block_bitmap2(bmap, | |
1375 | ext2fs_file_acl_block(&inode))) { | |
1376 | blk = translate_block(ext2fs_file_acl_block(&inode)); | |
64d588cf AK |
1377 | if (!blk) |
1378 | continue; | |
1379 | ||
a63745e8 | 1380 | ext2fs_file_acl_block_set(&inode, blk); |
64d588cf AK |
1381 | |
1382 | /* | |
1383 | * Write the inode to disk so that inode table | |
1384 | * resizing can work | |
1385 | */ | |
1386 | retval = ext2fs_write_inode(fs, ino, &inode); | |
1387 | if (retval) | |
1388 | goto err_out; | |
1389 | } | |
1390 | ||
1391 | if (!ext2fs_inode_has_valid_blocks(&inode)) | |
1392 | continue; | |
1393 | ||
7117f8d6 | 1394 | retval = ext2fs_block_iterate3(fs, ino, 0, block_buf, |
27c6de45 | 1395 | process_block, bmap); |
64d588cf AK |
1396 | if (retval) |
1397 | goto err_out; | |
1398 | ||
1399 | } | |
1400 | ||
1401 | err_out: | |
1402 | ext2fs_free_mem(&block_buf); | |
1403 | ||
1404 | return retval; | |
31f1815f TT |
1405 | } |
1406 | ||
91fac979 AK |
1407 | /* |
1408 | * We need to scan for inode and block bitmaps that may need to be | |
1409 | * moved. This can take place if the filesystem was formatted for | |
1410 | * RAID arrays using the mke2fs's extended option "stride". | |
1411 | */ | |
1412 | static int group_desc_scan_and_fix(ext2_filsys fs, ext2fs_block_bitmap bmap) | |
1413 | { | |
1414 | dgrp_t i; | |
1415 | blk_t blk, new_blk; | |
1416 | ||
1417 | for (i = 0; i < fs->group_desc_count; i++) { | |
d7cca6b0 | 1418 | blk = ext2fs_block_bitmap_loc(fs, i); |
3c041a51 | 1419 | if (ext2fs_test_block_bitmap2(bmap, blk)) { |
91fac979 AK |
1420 | new_blk = translate_block(blk); |
1421 | if (!new_blk) | |
1422 | continue; | |
d7cca6b0 | 1423 | ext2fs_block_bitmap_loc_set(fs, i, new_blk); |
91fac979 AK |
1424 | } |
1425 | ||
d7cca6b0 | 1426 | blk = ext2fs_inode_bitmap_loc(fs, i); |
3c041a51 | 1427 | if (ext2fs_test_block_bitmap2(bmap, blk)) { |
91fac979 AK |
1428 | new_blk = translate_block(blk); |
1429 | if (!new_blk) | |
1430 | continue; | |
d7cca6b0 | 1431 | ext2fs_inode_bitmap_loc_set(fs, i, new_blk); |
91fac979 AK |
1432 | } |
1433 | } | |
1434 | return 0; | |
1435 | } | |
1436 | ||
721b367a | 1437 | static int expand_inode_table(ext2_filsys fs, unsigned long new_ino_size) |
64d588cf AK |
1438 | { |
1439 | dgrp_t i; | |
7117f8d6 | 1440 | blk64_t blk; |
64d588cf | 1441 | errcode_t retval; |
721b367a TT |
1442 | int new_ino_blks_per_grp; |
1443 | unsigned int j; | |
64d588cf AK |
1444 | char *old_itable = NULL, *new_itable = NULL; |
1445 | char *tmp_old_itable = NULL, *tmp_new_itable = NULL; | |
721b367a | 1446 | unsigned long old_ino_size; |
64d588cf AK |
1447 | int old_itable_size, new_itable_size; |
1448 | ||
1449 | old_itable_size = fs->inode_blocks_per_group * fs->blocksize; | |
721b367a | 1450 | old_ino_size = EXT2_INODE_SIZE(fs->super); |
64d588cf AK |
1451 | |
1452 | new_ino_blks_per_grp = ext2fs_div_ceil( | |
1453 | EXT2_INODES_PER_GROUP(fs->super) * | |
721b367a | 1454 | new_ino_size, |
64d588cf AK |
1455 | fs->blocksize); |
1456 | ||
1457 | new_itable_size = new_ino_blks_per_grp * fs->blocksize; | |
1458 | ||
1459 | retval = ext2fs_get_mem(old_itable_size, &old_itable); | |
1460 | if (retval) | |
1461 | return retval; | |
1462 | ||
1463 | retval = ext2fs_get_mem(new_itable_size, &new_itable); | |
1464 | if (retval) | |
1465 | goto err_out; | |
1466 | ||
1467 | tmp_old_itable = old_itable; | |
1468 | tmp_new_itable = new_itable; | |
1469 | ||
1470 | for (i = 0; i < fs->group_desc_count; i++) { | |
d7cca6b0 | 1471 | blk = ext2fs_inode_table_loc(fs, i); |
24a117ab | 1472 | retval = io_channel_read_blk64(fs->io, blk, |
64d588cf AK |
1473 | fs->inode_blocks_per_group, old_itable); |
1474 | if (retval) | |
1475 | goto err_out; | |
1476 | ||
1477 | for (j = 0; j < EXT2_INODES_PER_GROUP(fs->super); j++) { | |
721b367a | 1478 | memcpy(new_itable, old_itable, old_ino_size); |
64d588cf | 1479 | |
721b367a TT |
1480 | memset(new_itable+old_ino_size, 0, |
1481 | new_ino_size - old_ino_size); | |
64d588cf | 1482 | |
721b367a TT |
1483 | new_itable += new_ino_size; |
1484 | old_itable += old_ino_size; | |
64d588cf AK |
1485 | } |
1486 | ||
1487 | /* reset the pointer */ | |
1488 | old_itable = tmp_old_itable; | |
1489 | new_itable = tmp_new_itable; | |
1490 | ||
24a117ab | 1491 | retval = io_channel_write_blk64(fs->io, blk, |
64d588cf AK |
1492 | new_ino_blks_per_grp, new_itable); |
1493 | if (retval) | |
1494 | goto err_out; | |
1495 | } | |
1496 | ||
1497 | /* Update the meta data */ | |
1498 | fs->inode_blocks_per_group = new_ino_blks_per_grp; | |
721b367a | 1499 | fs->super->s_inode_size = new_ino_size; |
64d588cf AK |
1500 | |
1501 | err_out: | |
1502 | if (old_itable) | |
1503 | ext2fs_free_mem(&old_itable); | |
1504 | ||
1505 | if (new_itable) | |
1506 | ext2fs_free_mem(&new_itable); | |
1507 | ||
1508 | return retval; | |
64d588cf AK |
1509 | } |
1510 | ||
1511 | static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs) | |
1512 | { | |
7117f8d6 | 1513 | blk64_t blk; |
64d588cf AK |
1514 | ext2_ino_t ino; |
1515 | unsigned int group = 0; | |
1516 | unsigned int count = 0; | |
1517 | int total_free = 0; | |
1518 | int group_free = 0; | |
1519 | ||
1520 | /* | |
1521 | * First calculate the block statistics | |
1522 | */ | |
1523 | for (blk = fs->super->s_first_data_block; | |
4efbac6f | 1524 | blk < ext2fs_blocks_count(fs->super); blk++) { |
3c041a51 | 1525 | if (!ext2fs_fast_test_block_bitmap2(fs->block_map, blk)) { |
64d588cf AK |
1526 | group_free++; |
1527 | total_free++; | |
1528 | } | |
1529 | count++; | |
1530 | if ((count == fs->super->s_blocks_per_group) || | |
4efbac6f | 1531 | (blk == ext2fs_blocks_count(fs->super)-1)) { |
d7cca6b0 VAH |
1532 | ext2fs_bg_free_blocks_count_set(fs, group++, |
1533 | group_free); | |
64d588cf AK |
1534 | count = 0; |
1535 | group_free = 0; | |
1536 | } | |
1537 | } | |
fe75afbf | 1538 | total_free = EXT2FS_C2B(fs, total_free); |
4efbac6f | 1539 | ext2fs_free_blocks_count_set(fs->super, total_free); |
64d588cf AK |
1540 | |
1541 | /* | |
1542 | * Next, calculate the inode statistics | |
1543 | */ | |
1544 | group_free = 0; | |
1545 | total_free = 0; | |
1546 | count = 0; | |
1547 | group = 0; | |
1548 | ||
1549 | /* Protect loop from wrap-around if s_inodes_count maxed */ | |
1550 | for (ino = 1; ino <= fs->super->s_inodes_count && ino > 0; ino++) { | |
3c041a51 | 1551 | if (!ext2fs_fast_test_inode_bitmap2(fs->inode_map, ino)) { |
64d588cf AK |
1552 | group_free++; |
1553 | total_free++; | |
1554 | } | |
1555 | count++; | |
1556 | if ((count == fs->super->s_inodes_per_group) || | |
1557 | (ino == fs->super->s_inodes_count)) { | |
d7cca6b0 VAH |
1558 | ext2fs_bg_free_inodes_count_set(fs, group++, |
1559 | group_free); | |
64d588cf AK |
1560 | count = 0; |
1561 | group_free = 0; | |
1562 | } | |
1563 | } | |
1564 | fs->super->s_free_inodes_count = total_free; | |
1565 | ext2fs_mark_super_dirty(fs); | |
1566 | return 0; | |
1567 | } | |
1568 | ||
1569 | #define list_for_each_safe(pos, pnext, head) \ | |
1570 | for (pos = (head)->next, pnext = pos->next; pos != (head); \ | |
1571 | pos = pnext, pnext = pos->next) | |
1572 | ||
721b367a | 1573 | static void free_blk_move_list(void) |
64d588cf AK |
1574 | { |
1575 | struct list_head *entry, *tmp; | |
1576 | struct blk_move *bmv; | |
1577 | ||
1578 | list_for_each_safe(entry, tmp, &blk_move_list) { | |
64d588cf AK |
1579 | bmv = list_entry(entry, struct blk_move, list); |
1580 | list_del(entry); | |
1581 | ext2fs_free_mem(&bmv); | |
1582 | } | |
31f1815f | 1583 | return; |
64d588cf | 1584 | } |
721b367a TT |
1585 | |
1586 | static int resize_inode(ext2_filsys fs, unsigned long new_size) | |
64d588cf AK |
1587 | { |
1588 | errcode_t retval; | |
1589 | int new_ino_blks_per_grp; | |
a9e5177b | 1590 | ext2fs_block_bitmap bmap; |
64d588cf | 1591 | |
64d588cf AK |
1592 | ext2fs_read_inode_bitmap(fs); |
1593 | ext2fs_read_block_bitmap(fs); | |
1594 | INIT_LIST_HEAD(&blk_move_list); | |
1595 | ||
1596 | ||
1597 | new_ino_blks_per_grp = ext2fs_div_ceil( | |
1598 | EXT2_INODES_PER_GROUP(fs->super)* | |
721b367a | 1599 | new_size, |
64d588cf AK |
1600 | fs->blocksize); |
1601 | ||
1602 | /* We may change the file system. | |
1603 | * Mark the file system as invalid so that | |
1604 | * the user is prompted to run fsck. | |
1605 | */ | |
1606 | fs->super->s_state &= ~EXT2_VALID_FS; | |
1607 | ||
1608 | retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"), | |
1609 | &bmap); | |
a9e5177b AK |
1610 | if (retval) { |
1611 | fputs(_("Failed to allocate block bitmap when " | |
1612 | "increasing inode size\n"), stderr); | |
31f1815f | 1613 | return retval; |
a9e5177b AK |
1614 | } |
1615 | retval = get_move_bitmaps(fs, new_ino_blks_per_grp, bmap); | |
1616 | if (retval) { | |
1617 | fputs(_("Not enough space to increase inode size \n"), stderr); | |
64d588cf | 1618 | goto err_out; |
a9e5177b AK |
1619 | } |
1620 | retval = move_block(fs, bmap); | |
1621 | if (retval) { | |
1622 | fputs(_("Failed to relocate blocks during inode resize \n"), | |
1623 | stderr); | |
64d588cf | 1624 | goto err_out; |
a9e5177b | 1625 | } |
27c6de45 | 1626 | retval = inode_scan_and_fix(fs, bmap); |
64d588cf | 1627 | if (retval) |
a9e5177b | 1628 | goto err_out_undo; |
31f1815f | 1629 | |
91fac979 AK |
1630 | retval = group_desc_scan_and_fix(fs, bmap); |
1631 | if (retval) | |
1632 | goto err_out_undo; | |
1633 | ||
721b367a | 1634 | retval = expand_inode_table(fs, new_size); |
64d588cf | 1635 | if (retval) |
a9e5177b | 1636 | goto err_out_undo; |
64d588cf AK |
1637 | |
1638 | ext2fs_calculate_summary_stats(fs); | |
1639 | ||
1640 | fs->super->s_state |= EXT2_VALID_FS; | |
1641 | /* mark super block and block bitmap as dirty */ | |
1642 | ext2fs_mark_super_dirty(fs); | |
1643 | ext2fs_mark_bb_dirty(fs); | |
1644 | ||
1645 | err_out: | |
1646 | free_blk_move_list(); | |
1647 | ext2fs_free_block_bitmap(bmap); | |
1648 | ||
1649 | return retval; | |
a9e5177b AK |
1650 | |
1651 | err_out_undo: | |
1652 | free_blk_move_list(); | |
1653 | ext2fs_free_block_bitmap(bmap); | |
1654 | fputs(_("Error in resizing the inode size.\n" | |
1655 | "Run e2undo to undo the " | |
1656 | "file system changes. \n"), stderr); | |
1657 | ||
1658 | return retval; | |
64d588cf AK |
1659 | } |
1660 | ||
1661 | static int tune2fs_setup_tdb(const char *name, io_manager *io_ptr) | |
1662 | { | |
1663 | errcode_t retval = 0; | |
721b367a | 1664 | const char *tdb_dir; |
f203bbdb | 1665 | char *tdb_file; |
721b367a | 1666 | char *dev_name, *tmp_name; |
64d588cf AK |
1667 | |
1668 | #if 0 /* FIXME!! */ | |
1669 | /* | |
1670 | * Configuration via a conf file would be | |
1671 | * nice | |
1672 | */ | |
1673 | profile_get_string(profile, "scratch_files", | |
1674 | "directory", 0, 0, | |
1675 | &tdb_dir); | |
1676 | #endif | |
1677 | tmp_name = strdup(name); | |
f203bbdb TT |
1678 | if (!tmp_name) { |
1679 | alloc_fn_fail: | |
1680 | com_err(program_name, ENOMEM, | |
1681 | _("Couldn't allocate memory for tdb filename\n")); | |
1682 | return ENOMEM; | |
1683 | } | |
721b367a | 1684 | dev_name = basename(tmp_name); |
64d588cf AK |
1685 | |
1686 | tdb_dir = getenv("E2FSPROGS_UNDO_DIR"); | |
1687 | if (!tdb_dir) | |
ec43da2f | 1688 | tdb_dir = "/var/lib/e2fsprogs"; |
64d588cf AK |
1689 | |
1690 | if (!strcmp(tdb_dir, "none") || (tdb_dir[0] == 0) || | |
1691 | access(tdb_dir, W_OK)) | |
1692 | return 0; | |
1693 | ||
f203bbdb TT |
1694 | tdb_file = malloc(strlen(tdb_dir) + 9 + strlen(dev_name) + 7 + 1); |
1695 | if (!tdb_file) | |
1696 | goto alloc_fn_fail; | |
721b367a | 1697 | sprintf(tdb_file, "%s/tune2fs-%s.e2undo", tdb_dir, dev_name); |
64d588cf AK |
1698 | |
1699 | if (!access(tdb_file, F_OK)) { | |
1700 | if (unlink(tdb_file) < 0) { | |
1701 | retval = errno; | |
1702 | com_err(program_name, retval, | |
1703 | _("while trying to delete %s"), | |
1704 | tdb_file); | |
f203bbdb | 1705 | free(tdb_file); |
64d588cf AK |
1706 | return retval; |
1707 | } | |
1708 | } | |
1709 | ||
1710 | set_undo_io_backing_manager(*io_ptr); | |
1711 | *io_ptr = undo_io_manager; | |
1712 | set_undo_io_backup_file(tdb_file); | |
5bf81bae | 1713 | printf(_("To undo the tune2fs operation please run " |
577b5c43 | 1714 | "the command\n e2undo %s %s\n\n"), |
64d588cf | 1715 | tdb_file, name); |
f203bbdb | 1716 | free(tdb_file); |
64d588cf AK |
1717 | free(tmp_name); |
1718 | return retval; | |
1719 | } | |
83238153 | 1720 | |
ec43da2f | 1721 | int main(int argc, char **argv) |
83238153 TT |
1722 | { |
1723 | errcode_t retval; | |
1724 | ext2_filsys fs; | |
1725 | struct ext2_super_block *sb; | |
d887f88d | 1726 | io_manager io_ptr, io_ptr_orig = NULL; |
83238153 TT |
1727 | |
1728 | #ifdef ENABLE_NLS | |
1729 | setlocale(LC_MESSAGES, ""); | |
14308a53 | 1730 | setlocale(LC_CTYPE, ""); |
83238153 TT |
1731 | bindtextdomain(NLS_CAT_NAME, LOCALEDIR); |
1732 | textdomain(NLS_CAT_NAME); | |
1733 | #endif | |
1734 | if (argc && *argv) | |
1735 | program_name = *argv; | |
a6d8302b | 1736 | add_error_table(&et_ext2_error_table); |
83238153 | 1737 | |
14b596d4 | 1738 | #ifdef CONFIG_BUILD_FINDFS |
118d7dac TT |
1739 | if (strcmp(get_progname(argv[0]), "findfs") == 0) |
1740 | do_findfs(argc, argv); | |
14b596d4 | 1741 | #endif |
83238153 TT |
1742 | if (strcmp(get_progname(argv[0]), "e2label") == 0) |
1743 | parse_e2label_options(argc, argv); | |
1744 | else | |
1745 | parse_tune2fs_options(argc, argv); | |
efc6f628 | 1746 | |
2a29f135 | 1747 | #ifdef CONFIG_TESTIO_DEBUG |
f38cf3cb TT |
1748 | if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_DEBUG")) { |
1749 | io_ptr = test_io_manager; | |
1750 | test_io_backing_manager = unix_io_manager; | |
1751 | } else | |
2a29f135 | 1752 | #endif |
f38cf3cb | 1753 | io_ptr = unix_io_manager; |
64d588cf | 1754 | |
d887f88d | 1755 | retry_open: |
efc6f628 | 1756 | retval = ext2fs_open2(device_name, io_options, open_flag, |
2e8ca9a2 | 1757 | 0, 0, io_ptr, &fs); |
ec43da2f TT |
1758 | if (retval) { |
1759 | com_err(program_name, retval, | |
1760 | _("while trying to open %s"), | |
1761 | device_name); | |
7141b54b TT |
1762 | fprintf(stderr, |
1763 | _("Couldn't find valid filesystem superblock.\n")); | |
3839e657 TT |
1764 | exit(1); |
1765 | } | |
d887f88d TT |
1766 | |
1767 | if (I_flag && !io_ptr_orig) { | |
1768 | /* | |
1769 | * Check the inode size is right so we can issue an | |
1770 | * error message and bail before setting up the tdb | |
1771 | * file. | |
1772 | */ | |
1773 | if (new_inode_size == EXT2_INODE_SIZE(fs->super)) { | |
9266fc7a | 1774 | fprintf(stderr, _("The inode size is already %lu\n"), |
d887f88d TT |
1775 | new_inode_size); |
1776 | exit(1); | |
1777 | } | |
1778 | if (new_inode_size < EXT2_INODE_SIZE(fs->super)) { | |
1779 | fprintf(stderr, _("Shrinking the inode size is " | |
1780 | "not supported\n")); | |
1781 | exit(1); | |
1782 | } | |
1783 | ||
1784 | /* | |
1785 | * If inode resize is requested use the | |
1786 | * Undo I/O manager | |
1787 | */ | |
1788 | io_ptr_orig = io_ptr; | |
1789 | retval = tune2fs_setup_tdb(device_name, &io_ptr); | |
1790 | if (retval) | |
1791 | exit(1); | |
1792 | if (io_ptr != io_ptr_orig) { | |
1793 | ext2fs_close(fs); | |
1794 | goto retry_open; | |
1795 | } | |
1796 | } | |
1797 | ||
83238153 | 1798 | sb = fs->super; |
058ad1c7 | 1799 | fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; |
2be8fe43 | 1800 | |
83238153 TT |
1801 | if (print_label) { |
1802 | /* For e2label emulation */ | |
c8c071a0 TT |
1803 | printf("%.*s\n", (int) sizeof(sb->s_volume_name), |
1804 | sb->s_volume_name); | |
a6d8302b | 1805 | remove_error_table(&et_ext2_error_table); |
83238153 TT |
1806 | exit(0); |
1807 | } | |
2be8fe43 | 1808 | |
d06863f0 TT |
1809 | retval = ext2fs_check_if_mounted(device_name, &mount_flags); |
1810 | if (retval) { | |
1811 | com_err("ext2fs_check_if_mount", retval, | |
1812 | _("while determining whether %s is mounted."), | |
1813 | device_name); | |
1814 | exit(1); | |
b21e38a0 | 1815 | } |
63985320 TT |
1816 | /* Normally we only need to write out the superblock */ |
1817 | fs->flags |= EXT2_FLAG_SUPER_ONLY; | |
3839e657 | 1818 | |
1e3472c5 | 1819 | if (c_flag) { |
b21e38a0 | 1820 | sb->s_max_mnt_count = max_mount_count; |
3839e657 | 1821 | ext2fs_mark_super_dirty(fs); |
ec43da2f TT |
1822 | printf(_("Setting maximal mount count to %d\n"), |
1823 | max_mount_count); | |
3839e657 | 1824 | } |
1e3472c5 | 1825 | if (C_flag) { |
b21e38a0 | 1826 | sb->s_mnt_count = mount_count; |
1e3472c5 | 1827 | ext2fs_mark_super_dirty(fs); |
ec43da2f | 1828 | printf(_("Setting current mount count to %d\n"), mount_count); |
1e3472c5 TT |
1829 | } |
1830 | if (e_flag) { | |
b21e38a0 | 1831 | sb->s_errors = errors; |
3839e657 | 1832 | ext2fs_mark_super_dirty(fs); |
ec43da2f | 1833 | printf(_("Setting error behavior to %d\n"), errors); |
3839e657 | 1834 | } |
b21e38a0 TT |
1835 | if (g_flag) { |
1836 | sb->s_def_resgid = resgid; | |
f3db3566 | 1837 | ext2fs_mark_super_dirty(fs); |
ec43da2f | 1838 | printf(_("Setting reserved blocks gid to %lu\n"), resgid); |
f3db3566 | 1839 | } |
818180cd | 1840 | if (i_flag) { |
2972b163 KM |
1841 | if (interval >= (1ULL << 32)) { |
1842 | com_err(program_name, 0, | |
1843 | _("interval between checks is too big (%lu)"), | |
1844 | interval); | |
1845 | exit(1); | |
1846 | } | |
b21e38a0 | 1847 | sb->s_checkinterval = interval; |
3839e657 | 1848 | ext2fs_mark_super_dirty(fs); |
ec43da2f TT |
1849 | printf(_("Setting interval between checks to %lu seconds\n"), |
1850 | interval); | |
3839e657 | 1851 | } |
818180cd | 1852 | if (m_flag) { |
4efbac6f VAH |
1853 | ext2fs_r_blocks_count_set(sb, reserved_ratio * |
1854 | ext2fs_blocks_count(sb) / 100.0); | |
3839e657 | 1855 | ext2fs_mark_super_dirty(fs); |
4efbac6f VAH |
1856 | printf (_("Setting reserved blocks percentage to %g%% (%llu blocks)\n"), |
1857 | reserved_ratio, ext2fs_r_blocks_count(sb)); | |
3839e657 | 1858 | } |
818180cd | 1859 | if (r_flag) { |
3977a4ff | 1860 | if (reserved_blocks > ext2fs_blocks_count(sb)/2) { |
ec43da2f | 1861 | com_err(program_name, 0, |
4efbac6f | 1862 | _("reserved blocks count is too big (%llu)"), |
ec43da2f TT |
1863 | reserved_blocks); |
1864 | exit(1); | |
f3db3566 | 1865 | } |
4efbac6f | 1866 | ext2fs_r_blocks_count_set(sb, reserved_blocks); |
f3db3566 | 1867 | ext2fs_mark_super_dirty(fs); |
4efbac6f | 1868 | printf(_("Setting reserved blocks count to %llu\n"), |
ec43da2f | 1869 | reserved_blocks); |
f3db3566 | 1870 | } |
521e3685 | 1871 | if (s_flag == 1) { |
521e3685 TT |
1872 | if (sb->s_feature_ro_compat & |
1873 | EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) | |
54434927 TT |
1874 | fputs(_("\nThe filesystem already has sparse " |
1875 | "superblocks.\n"), stderr); | |
521e3685 TT |
1876 | else { |
1877 | sb->s_feature_ro_compat |= | |
1878 | EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; | |
b21e38a0 | 1879 | sb->s_state &= ~EXT2_VALID_FS; |
521e3685 | 1880 | ext2fs_mark_super_dirty(fs); |
d9c56d3c | 1881 | printf(_("\nSparse superblock flag set. %s"), |
a4fa100c | 1882 | _(please_fsck)); |
521e3685 | 1883 | } |
521e3685 TT |
1884 | } |
1885 | if (s_flag == 0) { | |
ff662d5d TT |
1886 | fputs(_("\nClearing the sparse superflag not supported.\n"), |
1887 | stderr); | |
1888 | exit(1); | |
521e3685 | 1889 | } |
d4de4aa9 TT |
1890 | if (T_flag) { |
1891 | sb->s_lastcheck = last_check_time; | |
1892 | ext2fs_mark_super_dirty(fs); | |
1893 | printf(_("Setting time filesystem last checked to %s\n"), | |
1894 | ctime(&last_check_time)); | |
1895 | } | |
b21e38a0 TT |
1896 | if (u_flag) { |
1897 | sb->s_def_resuid = resuid; | |
f3db3566 | 1898 | ext2fs_mark_super_dirty(fs); |
ec43da2f | 1899 | printf(_("Setting reserved blocks uid to %lu\n"), resuid); |
f3db3566 | 1900 | } |
1e3472c5 | 1901 | if (L_flag) { |
a789d840 | 1902 | if (strlen(new_label) > sizeof(sb->s_volume_name)) |
efc6f628 | 1903 | fputs(_("Warning: label too long, truncating.\n"), |
54434927 | 1904 | stderr); |
1e3472c5 TT |
1905 | memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name)); |
1906 | strncpy(sb->s_volume_name, new_label, | |
1907 | sizeof(sb->s_volume_name)); | |
1908 | ext2fs_mark_super_dirty(fs); | |
1909 | } | |
1910 | if (M_flag) { | |
1911 | memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted)); | |
1912 | strncpy(sb->s_last_mounted, new_last_mounted, | |
1913 | sizeof(sb->s_last_mounted)); | |
1914 | ext2fs_mark_super_dirty(fs); | |
1915 | } | |
a0c3fd5e TT |
1916 | if (mntopts_cmd) |
1917 | update_mntopts(fs, mntopts_cmd); | |
63985320 TT |
1918 | if (features_cmd) |
1919 | update_feature_set(fs, features_cmd); | |
6cb27404 TT |
1920 | if (extended_cmd) |
1921 | parse_extended_opts(fs, extended_cmd); | |
dc2ec525 | 1922 | if (journal_size || journal_device) |
63985320 | 1923 | add_journal(fs); |
efc6f628 | 1924 | |
771e8db9 AK |
1925 | if (Q_flag) { |
1926 | if (mount_flags & EXT2_MF_MOUNTED) { | |
1927 | fputs(_("The quota feature may only be changed when " | |
1928 | "the filesystem is unmounted.\n"), stderr); | |
1929 | exit(1); | |
1930 | } | |
1931 | handle_quota_options(fs); | |
1932 | } | |
1933 | ||
1e3472c5 | 1934 | if (U_flag) { |
9d4a4dc2 TT |
1935 | int set_csum = 0; |
1936 | dgrp_t i; | |
1937 | ||
1938 | if (sb->s_feature_ro_compat & | |
1939 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM) { | |
ec43da2f | 1940 | /* |
9d4a4dc2 TT |
1941 | * Determine if the block group checksums are |
1942 | * correct so we know whether or not to set | |
1943 | * them later on. | |
1944 | */ | |
1945 | for (i = 0; i < fs->group_desc_count; i++) | |
1946 | if (!ext2fs_group_desc_csum_verify(fs, i)) | |
1947 | break; | |
1948 | if (i >= fs->group_desc_count) | |
1949 | set_csum = 1; | |
1950 | } | |
4d0f2283 TT |
1951 | if ((strcasecmp(new_UUID, "null") == 0) || |
1952 | (strcasecmp(new_UUID, "clear") == 0)) { | |
1e3472c5 | 1953 | uuid_clear(sb->s_uuid); |
63985320 TT |
1954 | } else if (strcasecmp(new_UUID, "time") == 0) { |
1955 | uuid_generate_time(sb->s_uuid); | |
1e3472c5 TT |
1956 | } else if (strcasecmp(new_UUID, "random") == 0) { |
1957 | uuid_generate(sb->s_uuid); | |
1958 | } else if (uuid_parse(new_UUID, sb->s_uuid)) { | |
d9c56d3c | 1959 | com_err(program_name, 0, _("Invalid UUID format\n")); |
1e3472c5 TT |
1960 | exit(1); |
1961 | } | |
9d4a4dc2 TT |
1962 | if (set_csum) { |
1963 | for (i = 0; i < fs->group_desc_count; i++) | |
1964 | ext2fs_group_desc_csum_set(fs, i); | |
1965 | fs->flags &= ~EXT2_FLAG_SUPER_ONLY; | |
1966 | } | |
1e3472c5 TT |
1967 | ext2fs_mark_super_dirty(fs); |
1968 | } | |
64d588cf AK |
1969 | if (I_flag) { |
1970 | if (mount_flags & EXT2_MF_MOUNTED) { | |
1971 | fputs(_("The inode size may only be " | |
1972 | "changed when the filesystem is " | |
1973 | "unmounted.\n"), stderr); | |
1974 | exit(1); | |
1975 | } | |
5bf81bae TT |
1976 | if (fs->super->s_feature_incompat & |
1977 | EXT4_FEATURE_INCOMPAT_FLEX_BG) { | |
ec43da2f TT |
1978 | fputs(_("Changing the inode size not supported for " |
1979 | "filesystems with the flex_bg\n" | |
1980 | "feature enabled.\n"), | |
5bf81bae TT |
1981 | stderr); |
1982 | exit(1); | |
1983 | } | |
64d588cf AK |
1984 | /* |
1985 | * We want to update group descriptor also | |
1986 | * with the new free inode count | |
1987 | */ | |
1988 | fs->flags &= ~EXT2_FLAG_SUPER_ONLY; | |
a9e5177b | 1989 | if (resize_inode(fs, new_inode_size) == 0) { |
ec43da2f | 1990 | printf(_("Setting inode size %lu\n"), |
64d588cf AK |
1991 | new_inode_size); |
1992 | } | |
1993 | } | |
1e3472c5 | 1994 | |
3839e657 | 1995 | if (l_flag) |
ec43da2f | 1996 | list_super(sb); |
0c17cb25 TT |
1997 | if (stride_set) { |
1998 | sb->s_raid_stride = stride; | |
1999 | ext2fs_mark_super_dirty(fs); | |
2000 | printf(_("Setting stride size to %d\n"), stride); | |
2001 | } | |
2002 | if (stripe_width_set) { | |
2003 | sb->s_raid_stripe_width = stripe_width; | |
2004 | ext2fs_mark_super_dirty(fs); | |
2005 | printf(_("Setting stripe width to %d\n"), stripe_width); | |
2006 | } | |
9a976ac7 TT |
2007 | if (ext_mount_opts) { |
2008 | strncpy(fs->super->s_mount_opts, ext_mount_opts, | |
2009 | sizeof(fs->super->s_mount_opts)); | |
2010 | fs->super->s_mount_opts[sizeof(fs->super->s_mount_opts)-1] = 0; | |
2011 | ext2fs_mark_super_dirty(fs); | |
2012 | printf(_("Setting extended default mount options to '%s'\n"), | |
2013 | ext_mount_opts); | |
2014 | free(ext_mount_opts); | |
2015 | } | |
1acde2b2 | 2016 | free(device_name); |
a6d8302b | 2017 | remove_error_table(&et_ext2_error_table); |
ec43da2f | 2018 | return (ext2fs_close(fs) ? 1 : 0); |
3839e657 | 2019 | } |