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