]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blame - misc/tune2fs.c
Fix more compiler warnings.
[thirdparty/e2fsprogs.git] / misc / tune2fs.c
CommitLineData
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
b969b1b8
MA
28#define _XOPEN_SOURCE /* for inclusion of strptime() */
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
35extern char *optarg;
36extern int optind;
a418d3ad 37#endif
f3db3566 38#include <pwd.h>
3839e657
TT
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <time.h>
43#include <unistd.h>
f3db3566 44#include <sys/types.h>
3839e657 45
54c637d4 46#include "ext2fs/ext2_fs.h"
3839e657
TT
47#include "ext2fs/ext2fs.h"
48#include "et/com_err.h"
1e3472c5 49#include "uuid/uuid.h"
3839e657 50#include "e2p/e2p.h"
dc2ec525 51#include "jfs_user.h"
63985320 52#include "util.h"
ed1b33e8 53#include "blkid/blkid.h"
3839e657
TT
54
55#include "../version.h"
d9c56d3c 56#include "nls-enable.h"
3839e657
TT
57
58const char * program_name = "tune2fs";
63985320 59char * device_name;
c8c071a0 60char * new_label, *new_last_mounted, *new_UUID;
4d0f2283 61static int c_flag, C_flag, e_flag, f_flag, g_flag, i_flag, l_flag, L_flag;
d4de4aa9
TT
62static int m_flag, M_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag;
63static time_t last_check_time;
83238153 64static int print_label;
63985320
TT
65static int max_mount_count, mount_count, mount_flags;
66static unsigned long interval, reserved_ratio, reserved_blocks;
67static unsigned long resgid, resuid;
68static unsigned short errors;
83238153
TT
69static int open_flag;
70static char *features_cmd;
a0c3fd5e 71static char *mntopts_cmd;
3839e657 72
63985320
TT
73int journal_size, journal_flags;
74char *journal_device;
75
76static const char *please_fsck = N_("Please run e2fsck on the filesystem.\n");
1e3472c5 77
3e699064
TT
78void do_findfs(int argc, char **argv);
79
818180cd 80static void usage(void)
3839e657 81{
b21e38a0
TT
82 fprintf(stderr,
83 _("Usage: %s [-c max-mounts-count] [-e errors-behavior] "
84 "[-g group]\n"
a0c3fd5e
TT
85 "\t[-i interval[d|m|w]] [-j] [-J journal-options]\n"
86 "\t[-l] [-s sparse-flag] [-m reserved-blocks-percent]\n"
87 "\t[-o [^]mount-options[,...]] [-r reserved-blocks-count]\n"
88 "\t[-u user] [-C mount-count] [-L volume-label] "
89 "[-M last-mounted-dir]\n"
d4de4aa9
TT
90 "\t[-O [^]feature[,...]] [-T last-check-time] [-U UUID]"
91 " device\n"), program_name);
3839e657
TT
92 exit (1);
93}
94
896938d5 95static __u32 ok_features[3] = {
843049c4
TT
96 EXT3_FEATURE_COMPAT_HAS_JOURNAL |
97 EXT2_FEATURE_COMPAT_DIR_INDEX, /* Compat */
896938d5
TT
98 EXT2_FEATURE_INCOMPAT_FILETYPE, /* Incompat */
99 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */
100};
101
dc2ec525
TT
102/*
103 * Remove an external journal from the filesystem
104 */
105static void remove_journal_device(ext2_filsys fs)
106{
4ea7bd04 107 char *journal_path;
dc2ec525
TT
108 ext2_filsys jfs;
109 char buf[1024];
110 journal_superblock_t *jsb;
111 int i, nr_users;
112 errcode_t retval;
4d0f2283 113 int commit_remove_journal = 0;
2a29f135 114 io_manager io_ptr;
4d0f2283
TT
115
116 if (f_flag)
117 commit_remove_journal = 1; /* force removal even if error */
dc2ec525 118
2d15576d 119 uuid_unparse(fs->super->s_journal_uuid, buf);
ed1b33e8 120 journal_path = blkid_get_devname(NULL, "UUID", buf);
2d15576d 121
4ea7bd04
TT
122 if (!journal_path) {
123 journal_path =
2d15576d 124 ext2fs_find_block_device(fs->super->s_journal_dev);
4ea7bd04 125 if (!journal_path)
2d15576d
AD
126 return;
127 }
dc2ec525 128
2a29f135
TT
129#ifdef CONFIG_TESTIO_DEBUG
130 io_ptr = test_io_manager;
131 test_io_backing_manager = unix_io_manager;
132#else
133 io_ptr = unix_io_manager;
134#endif
4ea7bd04 135 retval = ext2fs_open(journal_path, EXT2_FLAG_RW|
dc2ec525 136 EXT2_FLAG_JOURNAL_DEV_OK, 0,
2a29f135 137 fs->blocksize, io_ptr, &jfs);
dc2ec525
TT
138 if (retval) {
139 com_err(program_name, retval,
140 _("while trying to open external journal"));
4d0f2283 141 goto no_valid_journal;
dc2ec525
TT
142 }
143 if (!(jfs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
7141b54b 144 fprintf(stderr, _("%s is not a journal device.\n"),
4ea7bd04 145 journal_path);
4d0f2283 146 goto no_valid_journal;
dc2ec525
TT
147 }
148
149 /* Get the journal superblock */
150 if ((retval = io_channel_read_blk(jfs->io, 1, -1024, buf))) {
151 com_err(program_name, retval,
152 _("while reading journal superblock"));
4d0f2283 153 goto no_valid_journal;
dc2ec525
TT
154 }
155
156 jsb = (journal_superblock_t *) buf;
157 if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
158 (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) {
54434927 159 fputs(_("Journal superblock not found!\n"), stderr);
4d0f2283 160 goto no_valid_journal;
dc2ec525
TT
161 }
162
163 /* Find the filesystem UUID */
164 nr_users = ntohl(jsb->s_nr_users);
165 for (i=0; i < nr_users; i++) {
166 if (memcmp(fs->super->s_uuid,
167 &jsb->s_users[i*16], 16) == 0)
168 break;
169 }
170 if (i >= nr_users) {
54434927
TT
171 fputs(_("Filesystem's UUID not found on journal device.\n"),
172 stderr);
4d0f2283
TT
173 commit_remove_journal = 1;
174 goto no_valid_journal;
dc2ec525
TT
175 }
176 nr_users--;
177 for (i=0; i < nr_users; i++)
178 memcpy(&jsb->s_users[i*16], &jsb->s_users[(i+1)*16], 16);
179 jsb->s_nr_users = htonl(nr_users);
180
181 /* Write back the journal superblock */
182 if ((retval = io_channel_write_blk(jfs->io, 1, -1024, buf))) {
183 com_err(program_name, retval,
184 "while writing journal superblock.");
4d0f2283 185 goto no_valid_journal;
dc2ec525
TT
186 }
187
4d0f2283
TT
188 commit_remove_journal = 1;
189
190no_valid_journal:
191 if (commit_remove_journal == 0) {
54434927 192 fputs(_("Journal NOT removed\n"), stderr);
4d0f2283
TT
193 exit(1);
194 }
dc2ec525 195 fs->super->s_journal_dev = 0;
ed1b33e8 196 uuid_clear(fs->super->s_journal_uuid);
dc2ec525 197 ext2fs_mark_super_dirty(fs);
54434927 198 fputs(_("Journal removed\n"), stdout);
4ea7bd04 199 free(journal_path);
dc2ec525
TT
200}
201
194686bb
TT
202/* Helper function for remove_journal_inode */
203static int release_blocks_proc(ext2_filsys fs, blk_t *blocknr,
54434927
TT
204 int blockcnt EXT2FS_ATTR((unused)),
205 void *private EXT2FS_ATTR((unused)))
194686bb
TT
206{
207 blk_t block;
208 int group;
209
210 block = *blocknr;
211 ext2fs_unmark_block_bitmap(fs->block_map,block);
212 group = ext2fs_group_of_blk(fs, block);
213 fs->group_desc[group].bg_free_blocks_count++;
214 fs->super->s_free_blocks_count++;
215 return 0;
216}
217
218/*
219 * Remove the journal inode from the filesystem
220 */
221static void remove_journal_inode(ext2_filsys fs)
222{
223 struct ext2_inode inode;
224 errcode_t retval;
225 ino_t ino = fs->super->s_journal_inum;
194686bb
TT
226
227 retval = ext2fs_read_inode(fs, ino, &inode);
228 if (retval) {
229 com_err(program_name, retval,
230 _("while reading journal inode"));
231 exit(1);
232 }
233 if (ino == EXT2_JOURNAL_INO) {
234 retval = ext2fs_read_bitmaps(fs);
235 if (retval) {
236 com_err(program_name, retval,
237 _("while reading bitmaps"));
238 exit(1);
239 }
240 retval = ext2fs_block_iterate(fs, ino, 0, NULL,
241 release_blocks_proc, NULL);
242 if (retval) {
243 com_err(program_name, retval,
244 _("while clearing journal inode"));
245 exit(1);
246 }
247 memset(&inode, 0, sizeof(inode));
248 ext2fs_mark_bb_dirty(fs);
194686bb
TT
249 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
250 } else
251 inode.i_flags &= ~EXT2_IMMUTABLE_FL;
252 retval = ext2fs_write_inode(fs, ino, &inode);
253 if (retval) {
254 com_err(program_name, retval,
255 _("while writing journal inode"));
256 exit(1);
257 }
258 fs->super->s_journal_inum = 0;
259 ext2fs_mark_super_dirty(fs);
260}
dc2ec525 261
a0c3fd5e
TT
262/*
263 * Update the default mount options
264 */
265static void update_mntopts(ext2_filsys fs, char *mntopts)
266{
267 struct ext2_super_block *sb= fs->super;
268
269 if (e2p_edit_mntopts(mntopts, &sb->s_default_mount_opts, ~0)) {
270 fprintf(stderr, _("Invalid mount option set: %s\n"),
271 mntopts);
272 exit(1);
273 }
274 ext2fs_mark_super_dirty(fs);
275}
276
63985320
TT
277/*
278 * Update the feature set as provided by the user.
279 */
c8c071a0 280static void update_feature_set(ext2_filsys fs, char *features)
63985320
TT
281{
282 int sparse, old_sparse, filetype, old_filetype;
843049c4 283 int journal, old_journal, dxdir, old_dxdir;
63985320 284 struct ext2_super_block *sb= fs->super;
63985320
TT
285
286 old_sparse = sb->s_feature_ro_compat &
287 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
288 old_filetype = sb->s_feature_incompat &
289 EXT2_FEATURE_INCOMPAT_FILETYPE;
290 old_journal = sb->s_feature_compat &
291 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
843049c4
TT
292 old_dxdir = sb->s_feature_compat &
293 EXT2_FEATURE_COMPAT_DIR_INDEX;
c8c071a0 294 if (e2p_edit_feature(features, &sb->s_feature_compat,
63985320
TT
295 ok_features)) {
296 fprintf(stderr, _("Invalid filesystem option set: %s\n"),
c8c071a0 297 features);
63985320
TT
298 exit(1);
299 }
300 sparse = sb->s_feature_ro_compat &
301 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
302 filetype = sb->s_feature_incompat &
303 EXT2_FEATURE_INCOMPAT_FILETYPE;
304 journal = sb->s_feature_compat &
305 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
843049c4
TT
306 dxdir = sb->s_feature_compat &
307 EXT2_FEATURE_COMPAT_DIR_INDEX;
63985320
TT
308 if (old_journal && !journal) {
309 if ((mount_flags & EXT2_MF_MOUNTED) &&
310 !(mount_flags & EXT2_MF_READONLY)) {
54434927
TT
311 fputs(_("The has_journal flag may only be "
312 "cleared when the filesystem is\n"
313 "unmounted or mounted "
314 "read-only.\n"), stderr);
63985320
TT
315 exit(1);
316 }
317 if (sb->s_feature_incompat &
318 EXT3_FEATURE_INCOMPAT_RECOVER) {
54434927
TT
319 fputs(_("The needs_recovery flag is set. "
320 "Please run e2fsck before clearing\n"
321 "the has_journal flag.\n"), stderr);
63985320
TT
322 exit(1);
323 }
63985320 324 if (sb->s_journal_inum) {
194686bb 325 remove_journal_inode(fs);
63985320 326 }
de49f015 327 if (sb->s_journal_dev) {
dc2ec525 328 remove_journal_device(fs);
de49f015 329 }
63985320
TT
330 }
331 if (journal && !old_journal) {
332 /*
333 * If adding a journal flag, let the create journal
334 * code below handle creating setting the flag and
335 * creating the journal. We supply a default size if
336 * necessary.
337 */
dc2ec525
TT
338 if (!journal_size)
339 journal_size = -1;
08dd830d 340 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
63985320 341 }
843049c4
TT
342 if (dxdir && !old_dxdir) {
343 if (!sb->s_def_hash_version)
344 sb->s_def_hash_version = EXT2_HASH_TEA;
345 if (uuid_is_null((unsigned char *) sb->s_hash_seed))
346 uuid_generate((unsigned char *) sb->s_hash_seed);
347 }
dc2ec525 348
63985320
TT
349 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
350 (sb->s_feature_compat || sb->s_feature_ro_compat ||
351 sb->s_feature_incompat))
352 ext2fs_update_dynamic_rev(fs);
353 if ((sparse != old_sparse) ||
194686bb 354 (filetype != old_filetype)) {
63985320
TT
355 sb->s_state &= ~EXT2_VALID_FS;
356 printf("\n%s\n", _(please_fsck));
357 }
358 ext2fs_mark_super_dirty(fs);
359}
360
361/*
362 * Add a journal to the filesystem.
363 */
364static void add_journal(ext2_filsys fs)
365{
366 unsigned long journal_blocks;
367 errcode_t retval;
16ed5b3a 368 ext2_filsys jfs;
2a29f135 369 io_manager io_ptr;
63985320
TT
370
371 if (fs->super->s_feature_compat &
372 EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
54434927 373 fputs(_("The filesystem already has a journal.\n"), stderr);
2d15576d 374 goto err;
63985320 375 }
63985320
TT
376 if (journal_device) {
377 check_plausibility(journal_device);
378 check_mount(journal_device, 0, _("journal"));
2a29f135
TT
379#ifdef CONFIG_TESTIO_DEBUG
380 io_ptr = test_io_manager;
381 test_io_backing_manager = unix_io_manager;
382#else
383 io_ptr = unix_io_manager;
384#endif
16ed5b3a
TT
385 retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
386 EXT2_FLAG_JOURNAL_DEV_OK, 0,
2a29f135 387 fs->blocksize, io_ptr, &jfs);
16ed5b3a
TT
388 if (retval) {
389 com_err(program_name, retval,
1d08d9bf 390 _("\n\twhile trying to open journal on %s\n"),
16ed5b3a 391 journal_device);
2d15576d 392 goto err;
16ed5b3a 393 }
63985320
TT
394 printf(_("Creating journal on device %s: "),
395 journal_device);
4055ef73 396 fflush(stdout);
2d15576d 397
16ed5b3a 398 retval = ext2fs_add_journal_device(fs, jfs);
2d15576d 399 ext2fs_close(jfs);
63985320
TT
400 if (retval) {
401 com_err (program_name, retval,
8d641749 402 _("while adding filesystem to journal on %s"),
63985320 403 journal_device);
2d15576d 404 goto err;
63985320 405 }
54434927 406 fputs(_("done\n"), stdout);
63985320 407 } else if (journal_size) {
54434927 408 fputs(_("Creating journal inode: "), stdout);
63985320 409 fflush(stdout);
2537b6d0
TT
410 journal_blocks = figure_journal_size(journal_size, fs);
411
63985320
TT
412 retval = ext2fs_add_journal_inode(fs, journal_blocks,
413 journal_flags);
414 if (retval) {
7141b54b 415 fprintf(stderr, "\n");
63985320 416 com_err(program_name, retval,
1d08d9bf 417 _("\n\twhile trying to create journal file"));
63985320 418 exit(1);
1d08d9bf 419 } else
54434927 420 fputs(_("done\n"), stdout);
63985320
TT
421 /*
422 * If the filesystem wasn't mounted, we need to force
423 * the block group descriptors out.
424 */
425 if ((mount_flags & EXT2_MF_MOUNTED) == 0)
426 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
427 }
66cf2f60 428 print_check_message(fs);
2d15576d
AD
429 return;
430
431err:
432 if (journal_device)
433 free(journal_device);
434 exit(1);
63985320
TT
435}
436
83238153 437
c8c071a0 438static void parse_e2label_options(int argc, char ** argv)
83238153
TT
439{
440 if ((argc < 2) || (argc > 3)) {
54434927 441 fputs(_("Usage: e2label device [newlabel]\n"), stderr);
83238153
TT
442 exit(1);
443 }
332f2c23 444 device_name = blkid_get_devname(NULL, argv[1], NULL);
817e49e3
TT
445 if (!device_name) {
446 com_err("e2label", 0, _("Unable to resolve '%s'"),
447 argv[1]);
448 exit(1);
449 }
83238153 450 if (argc == 3) {
2d15576d 451 open_flag = EXT2_FLAG_RW | EXT2_FLAG_JOURNAL_DEV_OK;
83238153
TT
452 L_flag = 1;
453 new_label = argv[2];
454 } else
455 print_label++;
456}
457
d4de4aa9
TT
458static time_t parse_time(char *str)
459{
460 struct tm ts;
461
462 if (strcmp(str, "now") == 0) {
463 return (time(0));
464 }
465 memset(&ts, 0, sizeof(ts));
bc7c14e0 466#ifdef HAVE_STRPTIME
d4de4aa9 467 strptime(optarg, "%Y%m%d%H%M%S", &ts);
bc7c14e0
TT
468#else
469 sscanf(optarg, "%4d%2d%2d%2d%2d%2d", &ts.tm_year, &ts.tm_mon,
470 &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec);
471 ts.tm_year -= 1900;
472 ts.tm_mon -= 1;
473 if (ts.tm_year < 0 || ts.tm_mon < 0 || ts.tm_mon > 11 ||
474 ts.tm_mday < 0 || ts.tm_mday > 31 || ts.tm_hour > 23 ||
475 ts.tm_min > 59 || ts.tm_sec > 61)
476 ts.tm_mday = 0;
477#endif
d4de4aa9
TT
478 if (ts.tm_mday == 0) {
479 com_err(program_name, 0,
480 _("Couldn't parse date/time specifier: %s"),
481 str);
482 usage();
483 }
484 return (mktime(&ts));
485}
83238153 486
c8c071a0 487static void parse_tune2fs_options(int argc, char **argv)
3839e657 488{
519149fb 489 int c;
3839e657 490 char * tmp;
f3db3566
TT
491 struct group * gr;
492 struct passwd * pw;
3839e657 493
0f8973fb 494 printf("tune2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
a0c3fd5e 495 while ((c = getopt(argc, argv, "c:e:fg:i:jlm:o:r:s:u:C:J:L:M:O:T:U:")) != EOF)
3839e657
TT
496 switch (c)
497 {
498 case 'c':
45d9e2ff 499 max_mount_count = strtol (optarg, &tmp, 0);
818180cd 500 if (*tmp || max_mount_count > 16000) {
3839e657 501 com_err (program_name, 0,
d9c56d3c 502 _("bad mounts count - %s"),
3839e657 503 optarg);
818180cd 504 usage();
3839e657 505 }
ce57f14f
TT
506 if (max_mount_count == 0)
507 max_mount_count = -1;
3839e657 508 c_flag = 1;
1e3472c5
TT
509 open_flag = EXT2_FLAG_RW;
510 break;
511 case 'C':
512 mount_count = strtoul (optarg, &tmp, 0);
818180cd 513 if (*tmp || mount_count > 16000) {
1e3472c5 514 com_err (program_name, 0,
d9c56d3c 515 _("bad mounts count - %s"),
1e3472c5 516 optarg);
818180cd 517 usage();
1e3472c5
TT
518 }
519 C_flag = 1;
520 open_flag = EXT2_FLAG_RW;
3839e657
TT
521 break;
522 case 'e':
523 if (strcmp (optarg, "continue") == 0)
524 errors = EXT2_ERRORS_CONTINUE;
525 else if (strcmp (optarg, "remount-ro") == 0)
526 errors = EXT2_ERRORS_RO;
527 else if (strcmp (optarg, "panic") == 0)
528 errors = EXT2_ERRORS_PANIC;
818180cd 529 else {
3839e657 530 com_err (program_name, 0,
d9c56d3c 531 _("bad error behavior - %s"),
3839e657 532 optarg);
818180cd 533 usage();
3839e657
TT
534 }
535 e_flag = 1;
1e3472c5 536 open_flag = EXT2_FLAG_RW;
3839e657 537 break;
4d0f2283
TT
538 case 'f': /* Force */
539 f_flag = 1;
540 break;
f3db3566
TT
541 case 'g':
542 resgid = strtoul (optarg, &tmp, 0);
818180cd 543 if (*tmp) {
f3db3566
TT
544 gr = getgrnam (optarg);
545 if (gr == NULL)
546 tmp = optarg;
a418d3ad 547 else {
f3db3566 548 resgid = gr->gr_gid;
a418d3ad
TT
549 *tmp =0;
550 }
f3db3566 551 }
818180cd 552 if (*tmp) {
f3db3566 553 com_err (program_name, 0,
d9c56d3c 554 _("bad gid/group name - %s"),
f3db3566 555 optarg);
818180cd 556 usage();
f3db3566
TT
557 }
558 g_flag = 1;
1e3472c5 559 open_flag = EXT2_FLAG_RW;
f3db3566 560 break;
3839e657
TT
561 case 'i':
562 interval = strtoul (optarg, &tmp, 0);
1e3472c5
TT
563 switch (*tmp) {
564 case 's':
565 tmp++;
566 break;
567 case '\0':
568 case 'd':
569 case 'D': /* days */
570 interval *= 86400;
571 if (*tmp != '\0')
f3db3566 572 tmp++;
1e3472c5
TT
573 break;
574 case 'm':
575 case 'M': /* months! */
576 interval *= 86400 * 30;
577 tmp++;
578 break;
579 case 'w':
580 case 'W': /* weeks */
581 interval *= 86400 * 7;
582 tmp++;
583 break;
3839e657 584 }
818180cd 585 if (*tmp || interval > (365 * 86400)) {
3839e657 586 com_err (program_name, 0,
d9c56d3c 587 _("bad interval - %s"), optarg);
818180cd 588 usage();
3839e657
TT
589 }
590 i_flag = 1;
1e3472c5 591 open_flag = EXT2_FLAG_RW;
3839e657 592 break;
63985320 593 case 'j':
dc2ec525
TT
594 if (!journal_size)
595 journal_size = -1;
4d0f2283 596 open_flag = EXT2_FLAG_RW;
dc2ec525
TT
597 break;
598 case 'J':
599 parse_journal_opts(optarg);
63985320
TT
600 open_flag = EXT2_FLAG_RW;
601 break;
08dd830d
TT
602 case 'l':
603 l_flag = 1;
604 break;
1e3472c5
TT
605 case 'L':
606 new_label = optarg;
607 L_flag = 1;
2d15576d
AD
608 open_flag = EXT2_FLAG_RW |
609 EXT2_FLAG_JOURNAL_DEV_OK;
1e3472c5 610 break;
3839e657
TT
611 case 'm':
612 reserved_ratio = strtoul (optarg, &tmp, 0);
818180cd 613 if (*tmp || reserved_ratio > 50) {
3839e657 614 com_err (program_name, 0,
d9c56d3c 615 _("bad reserved block ratio - %s"),
3839e657 616 optarg);
818180cd 617 usage();
3839e657
TT
618 }
619 m_flag = 1;
1e3472c5
TT
620 open_flag = EXT2_FLAG_RW;
621 break;
622 case 'M':
623 new_last_mounted = optarg;
624 M_flag = 1;
625 open_flag = EXT2_FLAG_RW;
3839e657 626 break;
a0c3fd5e
TT
627 case 'o':
628 if (mntopts_cmd) {
629 com_err (program_name, 0,
630 _("-o may only be specified once"));
631 usage();
632 }
633 mntopts_cmd = optarg;
634 open_flag = EXT2_FLAG_RW;
635 break;
636
896938d5 637 case 'O':
d258668d
TT
638 if (features_cmd) {
639 com_err (program_name, 0,
640 _("-O may only be specified once"));
641 usage();
642 }
896938d5
TT
643 features_cmd = optarg;
644 open_flag = EXT2_FLAG_RW;
645 break;
f3db3566
TT
646 case 'r':
647 reserved_blocks = strtoul (optarg, &tmp, 0);
818180cd 648 if (*tmp) {
f3db3566 649 com_err (program_name, 0,
d9c56d3c 650 _("bad reserved blocks count - %s"),
f3db3566 651 optarg);
818180cd 652 usage();
f3db3566
TT
653 }
654 r_flag = 1;
1e3472c5 655 open_flag = EXT2_FLAG_RW;
f3db3566 656 break;
521e3685
TT
657 case 's':
658 s_flag = atoi(optarg);
659 open_flag = EXT2_FLAG_RW;
660 break;
d4de4aa9
TT
661 case 'T':
662 T_flag = 1;
663 last_check_time = parse_time(optarg);
664 open_flag = EXT2_FLAG_RW;
665 break;
f3db3566
TT
666 case 'u':
667 resuid = strtoul (optarg, &tmp, 0);
818180cd 668 if (*tmp) {
f3db3566
TT
669 pw = getpwnam (optarg);
670 if (pw == NULL)
671 tmp = optarg;
a418d3ad 672 else {
f3db3566 673 resuid = pw->pw_uid;
a418d3ad
TT
674 *tmp = 0;
675 }
f3db3566 676 }
818180cd 677 if (*tmp) {
f3db3566 678 com_err (program_name, 0,
d9c56d3c 679 _("bad uid/user name - %s"),
f3db3566 680 optarg);
818180cd 681 usage();
f3db3566
TT
682 }
683 u_flag = 1;
1e3472c5
TT
684 open_flag = EXT2_FLAG_RW;
685 break;
686 case 'U':
687 new_UUID = optarg;
688 U_flag = 1;
2d15576d
AD
689 open_flag = EXT2_FLAG_RW |
690 EXT2_FLAG_JOURNAL_DEV_OK;
f3db3566 691 break;
3839e657 692 default:
818180cd 693 usage();
3839e657
TT
694 }
695 if (optind < argc - 1 || optind == argc)
818180cd 696 usage();
1e3472c5
TT
697 if (!open_flag && !l_flag)
698 usage();
332f2c23 699 device_name = blkid_get_devname(NULL, argv[optind], NULL);
817e49e3
TT
700 if (!device_name) {
701 com_err("tune2fs", 0, _("Unable to resolve '%s'"),
702 argv[optind]);
703 exit(1);
704 }
118d7dac
TT
705}
706
3e699064 707void do_findfs(int argc, char **argv)
118d7dac
TT
708{
709 char *dev;
83238153 710
118d7dac
TT
711 if ((argc != 2) ||
712 (strncmp(argv[1], "LABEL=", 6) && strncmp(argv[1], "UUID=", 5))) {
713 fprintf(stderr, "Usage: findfs LABEL=<label>|UUID=<uuid>\n");
714 exit(2);
715 }
ed1b33e8 716 dev = blkid_get_devname(NULL, argv[1], NULL);
118d7dac 717 if (!dev) {
817e49e3 718 com_err("findfs", 0, _("Unable to resolve '%s'"),
118d7dac
TT
719 argv[1]);
720 exit(1);
721 }
722 puts(dev);
723 exit(0);
724}
83238153
TT
725
726
727int main (int argc, char ** argv)
728{
729 errcode_t retval;
730 ext2_filsys fs;
731 struct ext2_super_block *sb;
2a29f135 732 io_manager io_ptr;
83238153
TT
733
734#ifdef ENABLE_NLS
735 setlocale(LC_MESSAGES, "");
14308a53 736 setlocale(LC_CTYPE, "");
83238153
TT
737 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
738 textdomain(NLS_CAT_NAME);
739#endif
740 if (argc && *argv)
741 program_name = *argv;
742 initialize_ext2_error_table();
743
118d7dac
TT
744 if (strcmp(get_progname(argv[0]), "findfs") == 0)
745 do_findfs(argc, argv);
83238153
TT
746 if (strcmp(get_progname(argv[0]), "e2label") == 0)
747 parse_e2label_options(argc, argv);
748 else
749 parse_tune2fs_options(argc, argv);
750
2a29f135
TT
751#ifdef CONFIG_TESTIO_DEBUG
752 io_ptr = test_io_manager;
753 test_io_backing_manager = unix_io_manager;
754#else
755 io_ptr = unix_io_manager;
756#endif
757 retval = ext2fs_open (device_name, open_flag, 0, 0, io_ptr, &fs);
818180cd 758 if (retval) {
d9c56d3c 759 com_err (program_name, retval, _("while trying to open %s"),
3839e657 760 device_name);
7141b54b
TT
761 fprintf(stderr,
762 _("Couldn't find valid filesystem superblock.\n"));
3839e657
TT
763 exit(1);
764 }
83238153
TT
765 sb = fs->super;
766 if (print_label) {
767 /* For e2label emulation */
c8c071a0
TT
768 printf("%.*s\n", (int) sizeof(sb->s_volume_name),
769 sb->s_volume_name);
83238153
TT
770 exit(0);
771 }
b21e38a0
TT
772 retval = ext2fs_check_if_mounted(device_name, &mount_flags);
773 if (retval) {
774 com_err("ext2fs_check_if_mount", retval,
775 _("while determining whether %s is mounted."),
776 device_name);
4055ef73 777 exit(1);
b21e38a0 778 }
63985320
TT
779 /* Normally we only need to write out the superblock */
780 fs->flags |= EXT2_FLAG_SUPER_ONLY;
3839e657 781
1e3472c5 782 if (c_flag) {
b21e38a0 783 sb->s_max_mnt_count = max_mount_count;
3839e657 784 ext2fs_mark_super_dirty(fs);
d9c56d3c 785 printf (_("Setting maximal mount count to %d\n"),
1e3472c5 786 max_mount_count);
3839e657 787 }
1e3472c5 788 if (C_flag) {
b21e38a0 789 sb->s_mnt_count = mount_count;
1e3472c5 790 ext2fs_mark_super_dirty(fs);
d9c56d3c 791 printf (_("Setting current mount count to %d\n"), mount_count);
1e3472c5
TT
792 }
793 if (e_flag) {
b21e38a0 794 sb->s_errors = errors;
3839e657 795 ext2fs_mark_super_dirty(fs);
d9c56d3c 796 printf (_("Setting error behavior to %d\n"), errors);
3839e657 797 }
b21e38a0
TT
798 if (g_flag) {
799 sb->s_def_resgid = resgid;
f3db3566 800 ext2fs_mark_super_dirty(fs);
d9c56d3c 801 printf (_("Setting reserved blocks gid to %lu\n"), resgid);
f3db3566 802 }
818180cd 803 if (i_flag) {
b21e38a0 804 sb->s_checkinterval = interval;
3839e657 805 ext2fs_mark_super_dirty(fs);
d9c56d3c 806 printf (_("Setting interval between check %lu seconds\n"), interval);
3839e657 807 }
818180cd 808 if (m_flag) {
b21e38a0 809 sb->s_r_blocks_count = (sb->s_blocks_count / 100)
3839e657
TT
810 * reserved_ratio;
811 ext2fs_mark_super_dirty(fs);
d9c56d3c 812 printf (_("Setting reserved blocks percentage to %lu (%u blocks)\n"),
b21e38a0 813 reserved_ratio, sb->s_r_blocks_count);
3839e657 814 }
818180cd 815 if (r_flag) {
b21e38a0 816 if (reserved_blocks >= sb->s_blocks_count) {
f3db3566 817 com_err (program_name, 0,
54434927 818 _("reserved blocks count is too big (%lu)"),
f3db3566
TT
819 reserved_blocks);
820 exit (1);
821 }
b21e38a0 822 sb->s_r_blocks_count = reserved_blocks;
f3db3566 823 ext2fs_mark_super_dirty(fs);
d9c56d3c 824 printf (_("Setting reserved blocks count to %lu\n"),
f3db3566
TT
825 reserved_blocks);
826 }
521e3685 827 if (s_flag == 1) {
521e3685
TT
828 if (sb->s_feature_ro_compat &
829 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
54434927
TT
830 fputs(_("\nThe filesystem already has sparse "
831 "superblocks.\n"), stderr);
521e3685
TT
832 else {
833 sb->s_feature_ro_compat |=
834 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
b21e38a0 835 sb->s_state &= ~EXT2_VALID_FS;
521e3685 836 ext2fs_mark_super_dirty(fs);
d9c56d3c 837 printf(_("\nSparse superblock flag set. %s"),
a4fa100c 838 _(please_fsck));
521e3685 839 }
521e3685
TT
840 }
841 if (s_flag == 0) {
521e3685
TT
842 if (!(sb->s_feature_ro_compat &
843 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
54434927
TT
844 fputs(_("\nThe filesystem already has sparse "
845 "superblocks disabled.\n"), stderr);
521e3685
TT
846 else {
847 sb->s_feature_ro_compat &=
848 ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
b21e38a0 849 sb->s_state &= ~EXT2_VALID_FS;
521e3685
TT
850 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
851 ext2fs_mark_super_dirty(fs);
d9c56d3c 852 printf(_("\nSparse superblock flag cleared. %s"),
a4fa100c 853 _(please_fsck));
521e3685 854 }
521e3685 855 }
d4de4aa9
TT
856 if (T_flag) {
857 sb->s_lastcheck = last_check_time;
858 ext2fs_mark_super_dirty(fs);
859 printf(_("Setting time filesystem last checked to %s\n"),
860 ctime(&last_check_time));
861 }
b21e38a0
TT
862 if (u_flag) {
863 sb->s_def_resuid = resuid;
f3db3566 864 ext2fs_mark_super_dirty(fs);
d9c56d3c 865 printf (_("Setting reserved blocks uid to %lu\n"), resuid);
f3db3566 866 }
1e3472c5 867 if (L_flag) {
a789d840 868 if (strlen(new_label) > sizeof(sb->s_volume_name))
54434927
TT
869 fputs(_("Warning: label too long, truncating.\n"),
870 stderr);
1e3472c5
TT
871 memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name));
872 strncpy(sb->s_volume_name, new_label,
873 sizeof(sb->s_volume_name));
874 ext2fs_mark_super_dirty(fs);
875 }
876 if (M_flag) {
877 memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted));
878 strncpy(sb->s_last_mounted, new_last_mounted,
879 sizeof(sb->s_last_mounted));
880 ext2fs_mark_super_dirty(fs);
881 }
a0c3fd5e
TT
882 if (mntopts_cmd)
883 update_mntopts(fs, mntopts_cmd);
63985320
TT
884 if (features_cmd)
885 update_feature_set(fs, features_cmd);
dc2ec525 886 if (journal_size || journal_device)
63985320
TT
887 add_journal(fs);
888
1e3472c5 889 if (U_flag) {
4d0f2283
TT
890 if ((strcasecmp(new_UUID, "null") == 0) ||
891 (strcasecmp(new_UUID, "clear") == 0)) {
1e3472c5 892 uuid_clear(sb->s_uuid);
63985320
TT
893 } else if (strcasecmp(new_UUID, "time") == 0) {
894 uuid_generate_time(sb->s_uuid);
1e3472c5
TT
895 } else if (strcasecmp(new_UUID, "random") == 0) {
896 uuid_generate(sb->s_uuid);
897 } else if (uuid_parse(new_UUID, sb->s_uuid)) {
d9c56d3c 898 com_err(program_name, 0, _("Invalid UUID format\n"));
1e3472c5
TT
899 exit(1);
900 }
901 ext2fs_mark_super_dirty(fs);
902 }
903
3839e657 904 if (l_flag)
b21e38a0 905 list_super (sb);
c007bc06 906 return (ext2fs_close (fs) ? 1 : 0);
3839e657 907}