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