~ubuntu-branches/ubuntu/edgy/e2fsprogs/edgy

« back to all changes in this revision

Viewing changes to misc/tune2fs.c

  • Committer: Bazaar Package Importer
  • Author(s): Yann Dirson
  • Date: 2002-03-21 23:58:48 UTC
  • Revision ID: james.westby@ubuntu.com-20020321235848-cmmy98hy0nihp922
Tags: upstream-1.27
ImportĀ upstreamĀ versionĀ 1.27

Show diffs side-by-side

added added

removed removed

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