blob: 5150780e74ef50e4329082874a59a5a80efba430 [file] [log] [blame]
Theodore Ts'o3839e651997-04-26 13:21:57 +00001/*
Theodore Ts'o4d0f2282001-04-23 20:58:03 +00002 * tune2fs.c - Change the file system parameters on an ext2 file system
Theodore Ts'o3839e651997-04-26 13:21:57 +00003 *
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 *
Theodore Ts'o4d0f2282001-04-23 20:58:03 +00008 * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
Theodore Ts'o19c78dc1997-04-29 16:17:09 +00009 *
10 * %Begin-Header%
11 * This file may be redistributed under the terms of the GNU Public
12 * License.
13 * %End-Header%
Theodore Ts'o3839e651997-04-26 13:21:57 +000014 */
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>
Theodore Ts'of3db3561997-04-26 13:34:30 +000029#include <grp.h>
Theodore Ts'oa418d3a1997-04-26 14:00:26 +000030#ifdef HAVE_GETOPT_H
Theodore Ts'o3839e651997-04-26 13:21:57 +000031#include <getopt.h>
Theodore Ts'o373b8332000-04-03 16:22:35 +000032#else
33extern char *optarg;
34extern int optind;
Theodore Ts'oa418d3a1997-04-26 14:00:26 +000035#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000036#include <pwd.h>
Theodore Ts'o3839e651997-04-26 13:21:57 +000037#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <time.h>
41#include <unistd.h>
Theodore Ts'of3db3561997-04-26 13:34:30 +000042#include <sys/types.h>
Theodore Ts'o3839e651997-04-26 13:21:57 +000043
Theodore Ts'o54c637d2001-05-14 11:45:38 +000044#include "ext2fs/ext2_fs.h"
Theodore Ts'o3839e651997-04-26 13:21:57 +000045#include "ext2fs/ext2fs.h"
46#include "et/com_err.h"
Theodore Ts'o1e3472c1997-04-29 14:53:37 +000047#include "uuid/uuid.h"
Theodore Ts'o3839e651997-04-26 13:21:57 +000048#include "e2p/e2p.h"
Theodore Ts'odc2ec522001-01-18 01:51:15 +000049#include "jfs_user.h"
Theodore Ts'o63985322001-01-03 17:02:13 +000050#include "util.h"
Theodore Ts'o3839e651997-04-26 13:21:57 +000051
52#include "../version.h"
Theodore Ts'od9c56d32000-02-08 00:47:55 +000053#include "nls-enable.h"
Theodore Ts'o3839e651997-04-26 13:21:57 +000054
55const char * program_name = "tune2fs";
Theodore Ts'o63985322001-01-03 17:02:13 +000056char * device_name;
Theodore Ts'oc8c071a2001-01-11 16:08:23 +000057char * new_label, *new_last_mounted, *new_UUID;
Theodore Ts'o4d0f2282001-04-23 20:58:03 +000058static int c_flag, C_flag, e_flag, f_flag, g_flag, i_flag, l_flag, L_flag;
Theodore Ts'o63985322001-01-03 17:02:13 +000059static int m_flag, M_flag, r_flag, s_flag = -1, u_flag, U_flag;
Theodore Ts'o83238152001-01-09 00:16:26 +000060static int print_label;
Theodore Ts'o63985322001-01-03 17:02:13 +000061static int max_mount_count, mount_count, mount_flags;
62static unsigned long interval, reserved_ratio, reserved_blocks;
63static unsigned long resgid, resuid;
64static unsigned short errors;
Theodore Ts'o83238152001-01-09 00:16:26 +000065static int open_flag;
66static char *features_cmd;
Theodore Ts'o3839e651997-04-26 13:21:57 +000067
Theodore Ts'o63985322001-01-03 17:02:13 +000068int journal_size, journal_flags;
69char *journal_device;
70
71static const char *please_fsck = N_("Please run e2fsck on the filesystem.\n");
Theodore Ts'o1e3472c1997-04-29 14:53:37 +000072
Theodore Ts'o818180c1998-06-27 05:11:14 +000073static void usage(void)
Theodore Ts'o3839e651997-04-26 13:21:57 +000074{
Theodore Ts'ob21e38a2001-01-01 15:26:58 +000075 fprintf(stderr,
76 _("Usage: %s [-c max-mounts-count] [-e errors-behavior] "
77 "[-g group]\n"
Theodore Ts'odc2ec522001-01-18 01:51:15 +000078 "\t[-i interval[d|m|w]] [-j] [-J journal-options]\n"
Theodore Ts'o63985322001-01-03 17:02:13 +000079 "\t[-l] [-s sparse-flag] [-m reserved-blocks-percent]\n"
Theodore Ts'ob21e38a2001-01-01 15:26:58 +000080 "\t[-r reserved-blocks-count] [-u user] [-C mount-count]\n"
81 "\t[-L volume-label] [-M last-mounted-dir] [-U UUID]\n"
82 "\t[-O [^]feature[,...]] device\n"), program_name);
Theodore Ts'o3839e651997-04-26 13:21:57 +000083 exit (1);
84}
85
Theodore Ts'o896938d1999-10-23 01:04:50 +000086static __u32 ok_features[3] = {
Theodore Ts'ob21e38a2001-01-01 15:26:58 +000087 EXT3_FEATURE_COMPAT_HAS_JOURNAL, /* Compat */
Theodore Ts'o896938d1999-10-23 01:04:50 +000088 EXT2_FEATURE_INCOMPAT_FILETYPE, /* Incompat */
89 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */
90};
91
Theodore Ts'o63985322001-01-03 17:02:13 +000092/*
Theodore Ts'odc2ec522001-01-18 01:51:15 +000093 * Remove an external journal from the filesystem
94 */
95static void remove_journal_device(ext2_filsys fs)
96{
97 char *journal_device;
98 ext2_filsys jfs;
99 char buf[1024];
100 journal_superblock_t *jsb;
101 int i, nr_users;
102 errcode_t retval;
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000103 int commit_remove_journal = 0;
104
105 if (f_flag)
106 commit_remove_journal = 1; /* force removal even if error */
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000107
108 journal_device = ext2fs_find_block_device(fs->super->s_journal_dev);
109 if (!journal_device)
110 return;
111
112 retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
113 EXT2_FLAG_JOURNAL_DEV_OK, 0,
114 fs->blocksize, unix_io_manager, &jfs);
115 if (retval) {
116 com_err(program_name, retval,
117 _("while trying to open external journal"));
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000118 goto no_valid_journal;
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000119 }
120 if (!(jfs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
121 fprintf(stderr, "%s is not a journal device.\n",
122 journal_device);
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000123 goto no_valid_journal;
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000124 }
125
126 /* Get the journal superblock */
127 if ((retval = io_channel_read_blk(jfs->io, 1, -1024, buf))) {
128 com_err(program_name, retval,
129 _("while reading journal superblock"));
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000130 goto no_valid_journal;
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000131 }
132
133 jsb = (journal_superblock_t *) buf;
134 if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
135 (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) {
136 fprintf(stderr, _("Journal superblock not found!\n"));
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000137 goto no_valid_journal;
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000138 }
139
140 /* Find the filesystem UUID */
141 nr_users = ntohl(jsb->s_nr_users);
142 for (i=0; i < nr_users; i++) {
143 if (memcmp(fs->super->s_uuid,
144 &jsb->s_users[i*16], 16) == 0)
145 break;
146 }
147 if (i >= nr_users) {
148 fprintf(stderr, "Filesystem's UUID not found on journal device.\n");
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000149 commit_remove_journal = 1;
150 goto no_valid_journal;
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000151 }
152 nr_users--;
153 for (i=0; i < nr_users; i++)
154 memcpy(&jsb->s_users[i*16], &jsb->s_users[(i+1)*16], 16);
155 jsb->s_nr_users = htonl(nr_users);
156
157 /* Write back the journal superblock */
158 if ((retval = io_channel_write_blk(jfs->io, 1, -1024, buf))) {
159 com_err(program_name, retval,
160 "while writing journal superblock.");
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000161 goto no_valid_journal;
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000162 }
163
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000164 commit_remove_journal = 1;
165
166no_valid_journal:
167 if (commit_remove_journal == 0) {
168 printf(_("Journal NOT removed\n"));
169 exit(1);
170 }
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000171 fs->super->s_journal_dev = 0;
172 memset(fs->super->s_journal_uuid, 0,
173 sizeof(fs->super->s_journal_uuid));
174 ext2fs_mark_super_dirty(fs);
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000175 printf(_("Journal removed\n"));
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000176}
177
178
179/*
Theodore Ts'o63985322001-01-03 17:02:13 +0000180 * Update the feature set as provided by the user.
181 */
Theodore Ts'oc8c071a2001-01-11 16:08:23 +0000182static void update_feature_set(ext2_filsys fs, char *features)
Theodore Ts'o63985322001-01-03 17:02:13 +0000183{
184 int sparse, old_sparse, filetype, old_filetype;
185 int journal, old_journal;
186 struct ext2_inode inode;
187 struct ext2_super_block *sb= fs->super;
188 errcode_t retval;
189
190 old_sparse = sb->s_feature_ro_compat &
191 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
192 old_filetype = sb->s_feature_incompat &
193 EXT2_FEATURE_INCOMPAT_FILETYPE;
194 old_journal = sb->s_feature_compat &
195 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
Theodore Ts'oc8c071a2001-01-11 16:08:23 +0000196 if (e2p_edit_feature(features, &sb->s_feature_compat,
Theodore Ts'o63985322001-01-03 17:02:13 +0000197 ok_features)) {
198 fprintf(stderr, _("Invalid filesystem option set: %s\n"),
Theodore Ts'oc8c071a2001-01-11 16:08:23 +0000199 features);
Theodore Ts'o63985322001-01-03 17:02:13 +0000200 exit(1);
201 }
202 sparse = sb->s_feature_ro_compat &
203 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
204 filetype = sb->s_feature_incompat &
205 EXT2_FEATURE_INCOMPAT_FILETYPE;
206 journal = sb->s_feature_compat &
207 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
208 if (old_journal && !journal) {
209 if ((mount_flags & EXT2_MF_MOUNTED) &&
210 !(mount_flags & EXT2_MF_READONLY)) {
211 fprintf(stderr,
Theodore Ts'o8d641742001-05-14 04:12:27 +0000212 _("The has_journal flag may only be "
Theodore Ts'o63985322001-01-03 17:02:13 +0000213 "cleared when the filesystem is\n"
214 "unmounted or mounted "
215 "read-only.\n"));
216 exit(1);
217 }
218 if (sb->s_feature_incompat &
219 EXT3_FEATURE_INCOMPAT_RECOVER) {
220 fprintf(stderr,
Theodore Ts'o8d641742001-05-14 04:12:27 +0000221 _("The needs_recovery flag is set. "
Theodore Ts'o63985322001-01-03 17:02:13 +0000222 "Please run e2fsck before clearing\n"
Theodore Ts'oe549d0a2001-05-25 16:38:48 +0000223 "the has_journal flag.\n"));
Theodore Ts'o63985322001-01-03 17:02:13 +0000224 exit(1);
225 }
226 /*
227 * Remove the immutable flag on the journal inode
228 */
229 if (sb->s_journal_inum) {
230 retval = ext2fs_read_inode(fs, sb->s_journal_inum,
231 &inode);
232 if (retval) {
233 com_err(program_name, retval,
234 "while reading journal inode");
235 exit(1);
236 }
237 inode.i_flags &= ~EXT2_IMMUTABLE_FL;
238 retval = ext2fs_write_inode(fs, sb->s_journal_inum,
239 &inode);
240 if (retval) {
241 com_err(program_name, retval,
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000242 "while writing journal inode");
Theodore Ts'o63985322001-01-03 17:02:13 +0000243 exit(1);
244 }
245 }
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000246 if (sb->s_journal_dev)
247 remove_journal_device(fs);
Theodore Ts'o63985322001-01-03 17:02:13 +0000248 }
249 if (journal && !old_journal) {
250 /*
251 * If adding a journal flag, let the create journal
252 * code below handle creating setting the flag and
253 * creating the journal. We supply a default size if
254 * necessary.
255 */
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000256 if (!journal_size)
257 journal_size = -1;
Theodore Ts'o08dd8302001-01-14 16:25:58 +0000258 sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
Theodore Ts'o63985322001-01-03 17:02:13 +0000259 journal = old_journal;
260 }
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000261
Theodore Ts'o63985322001-01-03 17:02:13 +0000262 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
263 (sb->s_feature_compat || sb->s_feature_ro_compat ||
264 sb->s_feature_incompat))
265 ext2fs_update_dynamic_rev(fs);
266 if ((sparse != old_sparse) ||
267 (filetype != old_filetype) ||
268 (journal != old_journal)) {
269 sb->s_state &= ~EXT2_VALID_FS;
270 printf("\n%s\n", _(please_fsck));
271 }
272 ext2fs_mark_super_dirty(fs);
273}
274
275/*
276 * Add a journal to the filesystem.
277 */
278static void add_journal(ext2_filsys fs)
279{
280 unsigned long journal_blocks;
281 errcode_t retval;
Theodore Ts'o16ed5b32001-01-16 07:47:31 +0000282 ext2_filsys jfs;
Theodore Ts'o63985322001-01-03 17:02:13 +0000283
284 if (fs->super->s_feature_compat &
285 EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
286 fprintf(stderr, _("The filesystem already has a journal.\n"));
287 exit(1);
288 }
Theodore Ts'o63985322001-01-03 17:02:13 +0000289 if (journal_device) {
290 check_plausibility(journal_device);
291 check_mount(journal_device, 0, _("journal"));
Theodore Ts'o16ed5b32001-01-16 07:47:31 +0000292 retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
293 EXT2_FLAG_JOURNAL_DEV_OK, 0,
294 fs->blocksize, unix_io_manager, &jfs);
295 if (retval) {
296 com_err(program_name, retval,
Theodore Ts'o1d08d9b2001-04-17 01:01:49 +0000297 _("\n\twhile trying to open journal on %s\n"),
Theodore Ts'o16ed5b32001-01-16 07:47:31 +0000298 journal_device);
299 exit(1);
300 }
Theodore Ts'o63985322001-01-03 17:02:13 +0000301 printf(_("Creating journal on device %s: "),
302 journal_device);
Theodore Ts'o4055ef72001-01-14 16:11:14 +0000303 fflush(stdout);
Theodore Ts'o16ed5b32001-01-16 07:47:31 +0000304
305 retval = ext2fs_add_journal_device(fs, jfs);
Theodore Ts'o63985322001-01-03 17:02:13 +0000306 if (retval) {
307 com_err (program_name, retval,
Theodore Ts'o8d641742001-05-14 04:12:27 +0000308 _("while adding filesystem to journal on %s"),
Theodore Ts'o63985322001-01-03 17:02:13 +0000309 journal_device);
310 exit(1);
311 }
312 printf(_("done\n"));
Theodore Ts'o16ed5b32001-01-16 07:47:31 +0000313 ext2fs_close(jfs);
Theodore Ts'o63985322001-01-03 17:02:13 +0000314 } else if (journal_size) {
Theodore Ts'o63985322001-01-03 17:02:13 +0000315 printf(_("Creating journal inode: "));
316 fflush(stdout);
Theodore Ts'o2537b6d2001-03-26 20:07:13 +0000317 journal_blocks = figure_journal_size(journal_size, fs);
318
Theodore Ts'o63985322001-01-03 17:02:13 +0000319 retval = ext2fs_add_journal_inode(fs, journal_blocks,
320 journal_flags);
321 if (retval) {
322 printf("\n");
323 com_err(program_name, retval,
Theodore Ts'o1d08d9b2001-04-17 01:01:49 +0000324 _("\n\twhile trying to create journal file"));
Theodore Ts'o63985322001-01-03 17:02:13 +0000325 exit(1);
Theodore Ts'o1d08d9b2001-04-17 01:01:49 +0000326 } else
327 printf(_("done\n"));
Theodore Ts'o63985322001-01-03 17:02:13 +0000328 /*
329 * If the filesystem wasn't mounted, we need to force
330 * the block group descriptors out.
331 */
332 if ((mount_flags & EXT2_MF_MOUNTED) == 0)
333 fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
334 }
Theodore Ts'o66cf2f62001-06-14 06:42:44 +0000335 print_check_message(fs);
Theodore Ts'o63985322001-01-03 17:02:13 +0000336}
337
Theodore Ts'o83238152001-01-09 00:16:26 +0000338/*
339 * Given argv[0], return the program name.
340 */
Theodore Ts'oc8c071a2001-01-11 16:08:23 +0000341static char *get_progname(char *argv_zero)
Theodore Ts'o83238152001-01-09 00:16:26 +0000342{
343 char *cp;
344
345 cp = strrchr(argv_zero, '/');
346 if (!cp )
347 return argv_zero;
348 else
349 return cp+1;
350}
Theodore Ts'o63985322001-01-03 17:02:13 +0000351
Theodore Ts'o896938d1999-10-23 01:04:50 +0000352
Theodore Ts'oc8c071a2001-01-11 16:08:23 +0000353static void parse_e2label_options(int argc, char ** argv)
Theodore Ts'o83238152001-01-09 00:16:26 +0000354{
355 if ((argc < 2) || (argc > 3)) {
356 fprintf(stderr, _("Usage: e2label device [newlabel]\n"));
357 exit(1);
358 }
359 device_name = argv[1];
360 if (argc == 3) {
361 open_flag = EXT2_FLAG_RW;
362 L_flag = 1;
363 new_label = argv[2];
364 } else
365 print_label++;
366}
367
368
Theodore Ts'oc8c071a2001-01-11 16:08:23 +0000369static void parse_tune2fs_options(int argc, char **argv)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000370{
Theodore Ts'o519149f1997-10-25 03:49:49 +0000371 int c;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000372 char * tmp;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000373 struct group * gr;
374 struct passwd * pw;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000375
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000376 fprintf (stderr, _("tune2fs %s, %s for EXT2 FS %s, %s\n"),
Theodore Ts'o3839e651997-04-26 13:21:57 +0000377 E2FSPROGS_VERSION, E2FSPROGS_DATE,
378 EXT2FS_VERSION, EXT2FS_DATE);
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000379 while ((c = getopt (argc, argv, "c:e:fg:i:jlm:r:s:u:C:J:L:M:O:U:")) != EOF)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000380 switch (c)
381 {
382 case 'c':
Theodore Ts'o45d9e2f2000-07-07 03:12:54 +0000383 max_mount_count = strtol (optarg, &tmp, 0);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000384 if (*tmp || max_mount_count > 16000) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000385 com_err (program_name, 0,
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000386 _("bad mounts count - %s"),
Theodore Ts'o3839e651997-04-26 13:21:57 +0000387 optarg);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000388 usage();
Theodore Ts'o3839e651997-04-26 13:21:57 +0000389 }
Theodore Ts'oce57f142001-04-26 04:25:39 +0000390 if (max_mount_count == 0)
391 max_mount_count = -1;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000392 c_flag = 1;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000393 open_flag = EXT2_FLAG_RW;
394 break;
395 case 'C':
396 mount_count = strtoul (optarg, &tmp, 0);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000397 if (*tmp || mount_count > 16000) {
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000398 com_err (program_name, 0,
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000399 _("bad mounts count - %s"),
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000400 optarg);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000401 usage();
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000402 }
403 C_flag = 1;
404 open_flag = EXT2_FLAG_RW;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000405 break;
406 case 'e':
407 if (strcmp (optarg, "continue") == 0)
408 errors = EXT2_ERRORS_CONTINUE;
409 else if (strcmp (optarg, "remount-ro") == 0)
410 errors = EXT2_ERRORS_RO;
411 else if (strcmp (optarg, "panic") == 0)
412 errors = EXT2_ERRORS_PANIC;
Theodore Ts'o818180c1998-06-27 05:11:14 +0000413 else {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000414 com_err (program_name, 0,
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000415 _("bad error behavior - %s"),
Theodore Ts'o3839e651997-04-26 13:21:57 +0000416 optarg);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000417 usage();
Theodore Ts'o3839e651997-04-26 13:21:57 +0000418 }
419 e_flag = 1;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000420 open_flag = EXT2_FLAG_RW;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000421 break;
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000422 case 'f': /* Force */
423 f_flag = 1;
424 break;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000425 case 'g':
426 resgid = strtoul (optarg, &tmp, 0);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000427 if (*tmp) {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000428 gr = getgrnam (optarg);
429 if (gr == NULL)
430 tmp = optarg;
Theodore Ts'oa418d3a1997-04-26 14:00:26 +0000431 else {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000432 resgid = gr->gr_gid;
Theodore Ts'oa418d3a1997-04-26 14:00:26 +0000433 *tmp =0;
434 }
Theodore Ts'of3db3561997-04-26 13:34:30 +0000435 }
Theodore Ts'o818180c1998-06-27 05:11:14 +0000436 if (*tmp) {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000437 com_err (program_name, 0,
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000438 _("bad gid/group name - %s"),
Theodore Ts'of3db3561997-04-26 13:34:30 +0000439 optarg);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000440 usage();
Theodore Ts'of3db3561997-04-26 13:34:30 +0000441 }
442 g_flag = 1;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000443 open_flag = EXT2_FLAG_RW;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000444 break;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000445 case 'i':
446 interval = strtoul (optarg, &tmp, 0);
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000447 switch (*tmp) {
448 case 's':
449 tmp++;
450 break;
451 case '\0':
452 case 'd':
453 case 'D': /* days */
454 interval *= 86400;
455 if (*tmp != '\0')
Theodore Ts'o3839e651997-04-26 13:21:57 +0000456 tmp++;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000457 break;
458 case 'm':
459 case 'M': /* months! */
460 interval *= 86400 * 30;
461 tmp++;
462 break;
463 case 'w':
464 case 'W': /* weeks */
465 interval *= 86400 * 7;
466 tmp++;
467 break;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000468 }
Theodore Ts'o818180c1998-06-27 05:11:14 +0000469 if (*tmp || interval > (365 * 86400)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000470 com_err (program_name, 0,
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000471 _("bad interval - %s"), optarg);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000472 usage();
Theodore Ts'o3839e651997-04-26 13:21:57 +0000473 }
474 i_flag = 1;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000475 open_flag = EXT2_FLAG_RW;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000476 break;
Theodore Ts'o63985322001-01-03 17:02:13 +0000477 case 'j':
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000478 if (!journal_size)
479 journal_size = -1;
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000480 open_flag = EXT2_FLAG_RW;
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000481 break;
482 case 'J':
483 parse_journal_opts(optarg);
Theodore Ts'o63985322001-01-03 17:02:13 +0000484 open_flag = EXT2_FLAG_RW;
485 break;
Theodore Ts'o08dd8302001-01-14 16:25:58 +0000486 case 'l':
487 l_flag = 1;
488 break;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000489 case 'L':
490 new_label = optarg;
491 L_flag = 1;
492 open_flag = EXT2_FLAG_RW;
493 break;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000494 case 'm':
495 reserved_ratio = strtoul (optarg, &tmp, 0);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000496 if (*tmp || reserved_ratio > 50) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000497 com_err (program_name, 0,
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000498 _("bad reserved block ratio - %s"),
Theodore Ts'o3839e651997-04-26 13:21:57 +0000499 optarg);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000500 usage();
Theodore Ts'o3839e651997-04-26 13:21:57 +0000501 }
502 m_flag = 1;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000503 open_flag = EXT2_FLAG_RW;
504 break;
505 case 'M':
506 new_last_mounted = optarg;
507 M_flag = 1;
508 open_flag = EXT2_FLAG_RW;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000509 break;
Theodore Ts'o896938d1999-10-23 01:04:50 +0000510 case 'O':
511 features_cmd = optarg;
512 open_flag = EXT2_FLAG_RW;
513 break;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000514 case 'r':
515 reserved_blocks = strtoul (optarg, &tmp, 0);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000516 if (*tmp) {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000517 com_err (program_name, 0,
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000518 _("bad reserved blocks count - %s"),
Theodore Ts'of3db3561997-04-26 13:34:30 +0000519 optarg);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000520 usage();
Theodore Ts'of3db3561997-04-26 13:34:30 +0000521 }
522 r_flag = 1;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000523 open_flag = EXT2_FLAG_RW;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000524 break;
Theodore Ts'o521e3681997-04-29 17:48:10 +0000525 case 's':
526 s_flag = atoi(optarg);
527 open_flag = EXT2_FLAG_RW;
528 break;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000529 case 'u':
530 resuid = strtoul (optarg, &tmp, 0);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000531 if (*tmp) {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000532 pw = getpwnam (optarg);
533 if (pw == NULL)
534 tmp = optarg;
Theodore Ts'oa418d3a1997-04-26 14:00:26 +0000535 else {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000536 resuid = pw->pw_uid;
Theodore Ts'oa418d3a1997-04-26 14:00:26 +0000537 *tmp = 0;
538 }
Theodore Ts'of3db3561997-04-26 13:34:30 +0000539 }
Theodore Ts'o818180c1998-06-27 05:11:14 +0000540 if (*tmp) {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000541 com_err (program_name, 0,
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000542 _("bad uid/user name - %s"),
Theodore Ts'of3db3561997-04-26 13:34:30 +0000543 optarg);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000544 usage();
Theodore Ts'of3db3561997-04-26 13:34:30 +0000545 }
546 u_flag = 1;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000547 open_flag = EXT2_FLAG_RW;
548 break;
549 case 'U':
550 new_UUID = optarg;
551 U_flag = 1;
552 open_flag = EXT2_FLAG_RW;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000553 break;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000554 default:
Theodore Ts'o818180c1998-06-27 05:11:14 +0000555 usage();
Theodore Ts'o3839e651997-04-26 13:21:57 +0000556 }
557 if (optind < argc - 1 || optind == argc)
Theodore Ts'o818180c1998-06-27 05:11:14 +0000558 usage();
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000559 if (!open_flag && !l_flag)
560 usage();
Theodore Ts'o3839e651997-04-26 13:21:57 +0000561 device_name = argv[optind];
Theodore Ts'o83238152001-01-09 00:16:26 +0000562}
563
564
565
566int main (int argc, char ** argv)
567{
568 errcode_t retval;
569 ext2_filsys fs;
570 struct ext2_super_block *sb;
571
572#ifdef ENABLE_NLS
573 setlocale(LC_MESSAGES, "");
574 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
575 textdomain(NLS_CAT_NAME);
576#endif
577 if (argc && *argv)
578 program_name = *argv;
579 initialize_ext2_error_table();
580
581 if (strcmp(get_progname(argv[0]), "e2label") == 0)
582 parse_e2label_options(argc, argv);
583 else
584 parse_tune2fs_options(argc, argv);
585
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000586 retval = ext2fs_open (device_name, open_flag, 0, 0,
587 unix_io_manager, &fs);
Theodore Ts'o818180c1998-06-27 05:11:14 +0000588 if (retval) {
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000589 com_err (program_name, retval, _("while trying to open %s"),
Theodore Ts'o3839e651997-04-26 13:21:57 +0000590 device_name);
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000591 printf(_("Couldn't find valid filesystem superblock.\n"));
Theodore Ts'o3839e651997-04-26 13:21:57 +0000592 exit(1);
593 }
Theodore Ts'o83238152001-01-09 00:16:26 +0000594 sb = fs->super;
595 if (print_label) {
596 /* For e2label emulation */
Theodore Ts'oc8c071a2001-01-11 16:08:23 +0000597 printf("%.*s\n", (int) sizeof(sb->s_volume_name),
598 sb->s_volume_name);
Theodore Ts'o83238152001-01-09 00:16:26 +0000599 exit(0);
600 }
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000601 retval = ext2fs_check_if_mounted(device_name, &mount_flags);
602 if (retval) {
603 com_err("ext2fs_check_if_mount", retval,
604 _("while determining whether %s is mounted."),
605 device_name);
Theodore Ts'o4055ef72001-01-14 16:11:14 +0000606 exit(1);
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000607 }
Theodore Ts'o63985322001-01-03 17:02:13 +0000608 /* Normally we only need to write out the superblock */
609 fs->flags |= EXT2_FLAG_SUPER_ONLY;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000610
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000611 if (c_flag) {
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000612 sb->s_max_mnt_count = max_mount_count;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000613 ext2fs_mark_super_dirty(fs);
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000614 printf (_("Setting maximal mount count to %d\n"),
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000615 max_mount_count);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000616 }
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000617 if (C_flag) {
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000618 sb->s_mnt_count = mount_count;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000619 ext2fs_mark_super_dirty(fs);
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000620 printf (_("Setting current mount count to %d\n"), mount_count);
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000621 }
622 if (e_flag) {
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000623 sb->s_errors = errors;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000624 ext2fs_mark_super_dirty(fs);
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000625 printf (_("Setting error behavior to %d\n"), errors);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000626 }
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000627 if (g_flag) {
628 sb->s_def_resgid = resgid;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000629 ext2fs_mark_super_dirty(fs);
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000630 printf (_("Setting reserved blocks gid to %lu\n"), resgid);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000631 }
Theodore Ts'o818180c1998-06-27 05:11:14 +0000632 if (i_flag) {
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000633 sb->s_checkinterval = interval;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000634 ext2fs_mark_super_dirty(fs);
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000635 printf (_("Setting interval between check %lu seconds\n"), interval);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000636 }
Theodore Ts'o818180c1998-06-27 05:11:14 +0000637 if (m_flag) {
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000638 sb->s_r_blocks_count = (sb->s_blocks_count / 100)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000639 * reserved_ratio;
640 ext2fs_mark_super_dirty(fs);
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000641 printf (_("Setting reserved blocks percentage to %lu (%u blocks)\n"),
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000642 reserved_ratio, sb->s_r_blocks_count);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000643 }
Theodore Ts'o818180c1998-06-27 05:11:14 +0000644 if (r_flag) {
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000645 if (reserved_blocks >= sb->s_blocks_count) {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000646 com_err (program_name, 0,
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000647 _("reserved blocks count is too big (%ul)"),
Theodore Ts'of3db3561997-04-26 13:34:30 +0000648 reserved_blocks);
649 exit (1);
650 }
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000651 sb->s_r_blocks_count = reserved_blocks;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000652 ext2fs_mark_super_dirty(fs);
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000653 printf (_("Setting reserved blocks count to %lu\n"),
Theodore Ts'of3db3561997-04-26 13:34:30 +0000654 reserved_blocks);
655 }
Theodore Ts'o521e3681997-04-29 17:48:10 +0000656 if (s_flag == 1) {
Theodore Ts'o521e3681997-04-29 17:48:10 +0000657 if (sb->s_feature_ro_compat &
658 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000659 fprintf(stderr, _("\nThe filesystem already"
Theodore Ts'oe1a0a3e2000-02-11 05:00:19 +0000660 " has sparse superblocks.\n"));
Theodore Ts'o521e3681997-04-29 17:48:10 +0000661 else {
662 sb->s_feature_ro_compat |=
663 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000664 sb->s_state &= ~EXT2_VALID_FS;
Theodore Ts'o521e3681997-04-29 17:48:10 +0000665 ext2fs_mark_super_dirty(fs);
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000666 printf(_("\nSparse superblock flag set. %s"),
Theodore Ts'oa4fa1002000-02-08 21:35:41 +0000667 _(please_fsck));
Theodore Ts'o521e3681997-04-29 17:48:10 +0000668 }
Theodore Ts'o521e3681997-04-29 17:48:10 +0000669 }
670 if (s_flag == 0) {
Theodore Ts'o521e3681997-04-29 17:48:10 +0000671 if (!(sb->s_feature_ro_compat &
672 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000673 fprintf(stderr, _("\nThe filesystem already"
Theodore Ts'oe1a0a3e2000-02-11 05:00:19 +0000674 " has sparse superblocks disabled.\n"));
Theodore Ts'o521e3681997-04-29 17:48:10 +0000675 else {
676 sb->s_feature_ro_compat &=
677 ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000678 sb->s_state &= ~EXT2_VALID_FS;
Theodore Ts'o521e3681997-04-29 17:48:10 +0000679 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
680 ext2fs_mark_super_dirty(fs);
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000681 printf(_("\nSparse superblock flag cleared. %s"),
Theodore Ts'oa4fa1002000-02-08 21:35:41 +0000682 _(please_fsck));
Theodore Ts'o521e3681997-04-29 17:48:10 +0000683 }
Theodore Ts'o521e3681997-04-29 17:48:10 +0000684 }
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000685 if (u_flag) {
686 sb->s_def_resuid = resuid;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000687 ext2fs_mark_super_dirty(fs);
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000688 printf (_("Setting reserved blocks uid to %lu\n"), resuid);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000689 }
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000690 if (L_flag) {
Theodore Ts'oa789d841998-03-30 01:20:55 +0000691 if (strlen(new_label) > sizeof(sb->s_volume_name))
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000692 fprintf(stderr, _("Warning: label too "
693 "long, truncating.\n"));
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000694 memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name));
695 strncpy(sb->s_volume_name, new_label,
696 sizeof(sb->s_volume_name));
697 ext2fs_mark_super_dirty(fs);
698 }
699 if (M_flag) {
700 memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted));
701 strncpy(sb->s_last_mounted, new_last_mounted,
702 sizeof(sb->s_last_mounted));
703 ext2fs_mark_super_dirty(fs);
704 }
Theodore Ts'o63985322001-01-03 17:02:13 +0000705 if (features_cmd)
706 update_feature_set(fs, features_cmd);
Theodore Ts'odc2ec522001-01-18 01:51:15 +0000707 if (journal_size || journal_device)
Theodore Ts'o63985322001-01-03 17:02:13 +0000708 add_journal(fs);
709
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000710 if (U_flag) {
Theodore Ts'o4d0f2282001-04-23 20:58:03 +0000711 if ((strcasecmp(new_UUID, "null") == 0) ||
712 (strcasecmp(new_UUID, "clear") == 0)) {
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000713 uuid_clear(sb->s_uuid);
Theodore Ts'o63985322001-01-03 17:02:13 +0000714 } else if (strcasecmp(new_UUID, "time") == 0) {
715 uuid_generate_time(sb->s_uuid);
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000716 } else if (strcasecmp(new_UUID, "random") == 0) {
717 uuid_generate(sb->s_uuid);
718 } else if (uuid_parse(new_UUID, sb->s_uuid)) {
Theodore Ts'od9c56d32000-02-08 00:47:55 +0000719 com_err(program_name, 0, _("Invalid UUID format\n"));
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000720 exit(1);
721 }
722 ext2fs_mark_super_dirty(fs);
723 }
724
Theodore Ts'o3839e651997-04-26 13:21:57 +0000725 if (l_flag)
Theodore Ts'ob21e38a2001-01-01 15:26:58 +0000726 list_super (sb);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000727 ext2fs_close (fs);
728 exit (0);
729}