]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blame - misc/tune2fs.c
ChangeLog, fsck.c:
[thirdparty/e2fsprogs.git] / misc / tune2fs.c
CommitLineData
3839e657
TT
1/*
2 * tune2fs.c - Change the file system parameters on
3 * an unmounted second extended file system
4 *
5 * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
6 * Laboratoire MASI, Institut Blaise Pascal
7 * Universite Pierre et Marie Curie (Paris VI)
8 *
19c78dc0
TT
9 * Copyright 1995, 1996, 1997 by Theodore Ts'o.
10 *
11 * %Begin-Header%
12 * This file may be redistributed under the terms of the GNU Public
13 * License.
14 * %End-Header%
3839e657
TT
15 */
16
17/*
18 * History:
19 * 93/06/01 - Creation
20 * 93/10/31 - Added the -c option to change the maximal mount counts
21 * 93/12/14 - Added -l flag to list contents of superblock
22 * M.J.E. Mol (marcel@duteca.et.tudelft.nl)
23 * F.W. ten Wolde (franky@duteca.et.tudelft.nl)
24 * 93/12/29 - Added the -e option to change errors behavior
25 * 94/02/27 - Ported to use the ext2fs library
26 * 94/03/06 - Added the checks interval from Uwe Ohse (uwe@tirka.gun.de)
27 */
28
29#include <fcntl.h>
f3db3566 30#include <grp.h>
a418d3ad 31#ifdef HAVE_GETOPT_H
3839e657 32#include <getopt.h>
373b8337
TT
33#else
34extern char *optarg;
35extern int optind;
a418d3ad 36#endif
f3db3566 37#include <pwd.h>
3839e657
TT
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <time.h>
42#include <unistd.h>
f3db3566 43#include <sys/types.h>
3839e657
TT
44
45#include <linux/ext2_fs.h>
46
47#include "ext2fs/ext2fs.h"
48#include "et/com_err.h"
1e3472c5 49#include "uuid/uuid.h"
3839e657
TT
50#include "e2p/e2p.h"
51
52#include "../version.h"
d9c56d3c 53#include "nls-enable.h"
3839e657
TT
54
55const char * program_name = "tune2fs";
56char * device_name = NULL;
1e3472c5
TT
57char * new_label = NULL;
58char * new_last_mounted = NULL;
59char * new_UUID = NULL;
3839e657 60int c_flag = 0;
1e3472c5 61int C_flag = 0;
3839e657 62int e_flag = 0;
f3db3566 63int g_flag = 0;
3839e657
TT
64int i_flag = 0;
65int l_flag = 0;
1e3472c5 66int L_flag = 0;
3839e657 67int m_flag = 0;
1e3472c5 68int M_flag = 0;
f3db3566 69int r_flag = 0;
521e3685 70int s_flag = -1;
f3db3566 71int u_flag = 0;
1e3472c5
TT
72int U_flag = 0;
73int max_mount_count, mount_count;
3839e657
TT
74unsigned long interval;
75unsigned long reserved_ratio = 0;
f3db3566 76unsigned long reserved_blocks = 0;
3839e657 77unsigned short errors;
f3db3566
TT
78unsigned long resgid = 0;
79unsigned long resuid = 0;
3839e657 80
1e3472c5
TT
81#ifndef HAVE_STRCASECMP
82static int strcasecmp (char *s1, char *s2)
83{
84 while (*s1 && *s2) {
85 int ch1 = *s1++, ch2 = *s2++;
86 if (isupper (ch1))
87 ch1 = tolower (ch1);
88 if (isupper (ch2))
89 ch2 = tolower (ch2);
90 if (ch1 != ch2)
91 return ch1 - ch2;
92 }
93 return *s1 ? 1 : *s2 ? -1 : 0;
94}
95#endif
96
818180cd 97static void usage(void)
3839e657 98{
d9c56d3c 99 fprintf(stderr, _("Usage: %s [-c max-mounts-count] [-e errors-behavior] "
f3db3566 100 "[-g group]\n"
582134cc
TT
101 "\t[-i interval[d|m|w]] [-l] [-s sparse-flag] "
102 "[-m reserved-blocks-percent]\n"
1e3472c5 103 "\t[-r reserved-blocks-count] [-u user] [-C mount-count]\n"
896938d5 104 "\t[-L volume-label] [-M last-mounted-dir] [-U UUID]\n"
d9c56d3c 105 "\t[-O [^]feature[,...]] device\n"), program_name);
3839e657
TT
106 exit (1);
107}
108
896938d5
TT
109static __u32 ok_features[3] = {
110 0, /* Compat */
111 EXT2_FEATURE_INCOMPAT_FILETYPE, /* Incompat */
112 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */
113};
114
a4fa100c 115static const char *please_fsck = N_("Please run e2fsck on the filesystem.\n");
896938d5 116
00e5433e 117int main (int argc, char ** argv)
3839e657 118{
519149fb 119 int c;
3839e657
TT
120 char * tmp;
121 errcode_t retval;
122 ext2_filsys fs;
1e3472c5 123 struct ext2fs_sb *sb;
f3db3566
TT
124 struct group * gr;
125 struct passwd * pw;
1e3472c5 126 int open_flag = 0;
896938d5 127 char *features_cmd = 0;
3839e657 128
d9c56d3c
TT
129#ifdef ENABLE_NLS
130 setlocale(LC_MESSAGES, "");
131 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
132 textdomain(NLS_CAT_NAME);
133#endif
134 fprintf (stderr, _("tune2fs %s, %s for EXT2 FS %s, %s\n"),
3839e657
TT
135 E2FSPROGS_VERSION, E2FSPROGS_DATE,
136 EXT2FS_VERSION, EXT2FS_DATE);
137 if (argc && *argv)
138 program_name = *argv;
139 initialize_ext2_error_table();
896938d5 140 while ((c = getopt (argc, argv, "c:e:g:i:lm:r:s:u:C:L:M:O:U:")) != EOF)
3839e657
TT
141 switch (c)
142 {
143 case 'c':
144 max_mount_count = strtoul (optarg, &tmp, 0);
818180cd 145 if (*tmp || max_mount_count > 16000) {
3839e657 146 com_err (program_name, 0,
d9c56d3c 147 _("bad mounts count - %s"),
3839e657 148 optarg);
818180cd 149 usage();
3839e657
TT
150 }
151 c_flag = 1;
1e3472c5
TT
152 open_flag = EXT2_FLAG_RW;
153 break;
154 case 'C':
155 mount_count = strtoul (optarg, &tmp, 0);
818180cd 156 if (*tmp || mount_count > 16000) {
1e3472c5 157 com_err (program_name, 0,
d9c56d3c 158 _("bad mounts count - %s"),
1e3472c5 159 optarg);
818180cd 160 usage();
1e3472c5
TT
161 }
162 C_flag = 1;
163 open_flag = EXT2_FLAG_RW;
3839e657
TT
164 break;
165 case 'e':
166 if (strcmp (optarg, "continue") == 0)
167 errors = EXT2_ERRORS_CONTINUE;
168 else if (strcmp (optarg, "remount-ro") == 0)
169 errors = EXT2_ERRORS_RO;
170 else if (strcmp (optarg, "panic") == 0)
171 errors = EXT2_ERRORS_PANIC;
818180cd 172 else {
3839e657 173 com_err (program_name, 0,
d9c56d3c 174 _("bad error behavior - %s"),
3839e657 175 optarg);
818180cd 176 usage();
3839e657
TT
177 }
178 e_flag = 1;
1e3472c5 179 open_flag = EXT2_FLAG_RW;
3839e657 180 break;
f3db3566
TT
181 case 'g':
182 resgid = strtoul (optarg, &tmp, 0);
818180cd 183 if (*tmp) {
f3db3566
TT
184 gr = getgrnam (optarg);
185 if (gr == NULL)
186 tmp = optarg;
a418d3ad 187 else {
f3db3566 188 resgid = gr->gr_gid;
a418d3ad
TT
189 *tmp =0;
190 }
f3db3566 191 }
818180cd 192 if (*tmp) {
f3db3566 193 com_err (program_name, 0,
d9c56d3c 194 _("bad gid/group name - %s"),
f3db3566 195 optarg);
818180cd 196 usage();
f3db3566
TT
197 }
198 g_flag = 1;
1e3472c5 199 open_flag = EXT2_FLAG_RW;
f3db3566 200 break;
3839e657
TT
201 case 'i':
202 interval = strtoul (optarg, &tmp, 0);
1e3472c5
TT
203 switch (*tmp) {
204 case 's':
205 tmp++;
206 break;
207 case '\0':
208 case 'd':
209 case 'D': /* days */
210 interval *= 86400;
211 if (*tmp != '\0')
f3db3566 212 tmp++;
1e3472c5
TT
213 break;
214 case 'm':
215 case 'M': /* months! */
216 interval *= 86400 * 30;
217 tmp++;
218 break;
219 case 'w':
220 case 'W': /* weeks */
221 interval *= 86400 * 7;
222 tmp++;
223 break;
3839e657 224 }
818180cd 225 if (*tmp || interval > (365 * 86400)) {
3839e657 226 com_err (program_name, 0,
d9c56d3c 227 _("bad interval - %s"), optarg);
818180cd 228 usage();
3839e657
TT
229 }
230 i_flag = 1;
1e3472c5 231 open_flag = EXT2_FLAG_RW;
3839e657
TT
232 break;
233 case 'l':
234 l_flag = 1;
235 break;
1e3472c5
TT
236 case 'L':
237 new_label = optarg;
238 L_flag = 1;
239 open_flag = EXT2_FLAG_RW;
240 break;
3839e657
TT
241 case 'm':
242 reserved_ratio = strtoul (optarg, &tmp, 0);
818180cd 243 if (*tmp || reserved_ratio > 50) {
3839e657 244 com_err (program_name, 0,
d9c56d3c 245 _("bad reserved block ratio - %s"),
3839e657 246 optarg);
818180cd 247 usage();
3839e657
TT
248 }
249 m_flag = 1;
1e3472c5
TT
250 open_flag = EXT2_FLAG_RW;
251 break;
252 case 'M':
253 new_last_mounted = optarg;
254 M_flag = 1;
255 open_flag = EXT2_FLAG_RW;
3839e657 256 break;
896938d5
TT
257 case 'O':
258 features_cmd = optarg;
259 open_flag = EXT2_FLAG_RW;
260 break;
f3db3566
TT
261 case 'r':
262 reserved_blocks = strtoul (optarg, &tmp, 0);
818180cd 263 if (*tmp) {
f3db3566 264 com_err (program_name, 0,
d9c56d3c 265 _("bad reserved blocks count - %s"),
f3db3566 266 optarg);
818180cd 267 usage();
f3db3566
TT
268 }
269 r_flag = 1;
1e3472c5 270 open_flag = EXT2_FLAG_RW;
f3db3566 271 break;
521e3685
TT
272 case 's':
273 s_flag = atoi(optarg);
274 open_flag = EXT2_FLAG_RW;
275 break;
f3db3566
TT
276 case 'u':
277 resuid = strtoul (optarg, &tmp, 0);
818180cd 278 if (*tmp) {
f3db3566
TT
279 pw = getpwnam (optarg);
280 if (pw == NULL)
281 tmp = optarg;
a418d3ad 282 else {
f3db3566 283 resuid = pw->pw_uid;
a418d3ad
TT
284 *tmp = 0;
285 }
f3db3566 286 }
818180cd 287 if (*tmp) {
f3db3566 288 com_err (program_name, 0,
d9c56d3c 289 _("bad uid/user name - %s"),
f3db3566 290 optarg);
818180cd 291 usage();
f3db3566
TT
292 }
293 u_flag = 1;
1e3472c5
TT
294 open_flag = EXT2_FLAG_RW;
295 break;
296 case 'U':
297 new_UUID = optarg;
298 U_flag = 1;
299 open_flag = EXT2_FLAG_RW;
f3db3566 300 break;
3839e657 301 default:
818180cd 302 usage();
3839e657
TT
303 }
304 if (optind < argc - 1 || optind == argc)
818180cd 305 usage();
1e3472c5
TT
306 if (!open_flag && !l_flag)
307 usage();
3839e657 308 device_name = argv[optind];
1e3472c5
TT
309 retval = ext2fs_open (device_name, open_flag, 0, 0,
310 unix_io_manager, &fs);
818180cd 311 if (retval) {
d9c56d3c 312 com_err (program_name, retval, _("while trying to open %s"),
3839e657 313 device_name);
d9c56d3c 314 printf(_("Couldn't find valid filesystem superblock.\n"));
3839e657
TT
315 exit(1);
316 }
1e3472c5 317 sb = (struct ext2fs_sb *) fs->super;
3839e657 318
1e3472c5 319 if (c_flag) {
3839e657
TT
320 fs->super->s_max_mnt_count = max_mount_count;
321 ext2fs_mark_super_dirty(fs);
d9c56d3c 322 printf (_("Setting maximal mount count to %d\n"),
1e3472c5 323 max_mount_count);
3839e657 324 }
1e3472c5
TT
325 if (C_flag) {
326 fs->super->s_mnt_count = mount_count;
327 ext2fs_mark_super_dirty(fs);
d9c56d3c 328 printf (_("Setting current mount count to %d\n"), mount_count);
1e3472c5
TT
329 }
330 if (e_flag) {
3839e657
TT
331 fs->super->s_errors = errors;
332 ext2fs_mark_super_dirty(fs);
d9c56d3c 333 printf (_("Setting error behavior to %d\n"), errors);
3839e657 334 }
f3db3566
TT
335 if (g_flag)
336#ifdef EXT2_DEF_RESGID
337 {
338 fs->super->s_def_resgid = resgid;
339 ext2fs_mark_super_dirty(fs);
d9c56d3c 340 printf (_("Setting reserved blocks gid to %lu\n"), resgid);
f3db3566
TT
341 }
342#else
343 com_err (program_name, 0,
d9c56d3c
TT
344 _("The -g option is not supported by this version -- "
345 "Recompile with a newer kernel"));
f3db3566 346#endif
818180cd 347 if (i_flag) {
3839e657
TT
348 fs->super->s_checkinterval = interval;
349 ext2fs_mark_super_dirty(fs);
d9c56d3c 350 printf (_("Setting interval between check %lu seconds\n"), interval);
3839e657 351 }
818180cd 352 if (m_flag) {
3839e657
TT
353 fs->super->s_r_blocks_count = (fs->super->s_blocks_count / 100)
354 * reserved_ratio;
355 ext2fs_mark_super_dirty(fs);
d9c56d3c 356 printf (_("Setting reserved blocks percentage to %lu (%u blocks)\n"),
3839e657
TT
357 reserved_ratio, fs->super->s_r_blocks_count);
358 }
818180cd
TT
359 if (r_flag) {
360 if (reserved_blocks >= fs->super->s_blocks_count) {
f3db3566 361 com_err (program_name, 0,
d9c56d3c 362 _("reserved blocks count is too big (%ul)"),
f3db3566
TT
363 reserved_blocks);
364 exit (1);
365 }
366 fs->super->s_r_blocks_count = reserved_blocks;
367 ext2fs_mark_super_dirty(fs);
d9c56d3c 368 printf (_("Setting reserved blocks count to %lu\n"),
f3db3566
TT
369 reserved_blocks);
370 }
521e3685
TT
371 if (s_flag == 1) {
372#ifdef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
373 if (sb->s_feature_ro_compat &
374 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
d9c56d3c 375 fprintf(stderr, _("\nThe filesystem already"
e1a0a3e3 376 " has sparse superblocks.\n"));
521e3685
TT
377 else {
378 sb->s_feature_ro_compat |=
379 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
380 fs->super->s_state &= ~EXT2_VALID_FS;
381 ext2fs_mark_super_dirty(fs);
d9c56d3c 382 printf(_("\nSparse superblock flag set. %s"),
a4fa100c 383 _(please_fsck));
521e3685
TT
384 }
385#else /* !EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER */
386 com_err (program_name, 0,
d9c56d3c
TT
387 _("The -s option is not supported by this version -- "
388 "Recompile with a newer kernel"));
521e3685
TT
389#endif /* EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER */
390 }
391 if (s_flag == 0) {
392#ifdef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
393 if (!(sb->s_feature_ro_compat &
394 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
d9c56d3c 395 fprintf(stderr, _("\nThe filesystem already"
e1a0a3e3 396 " has sparse superblocks disabled.\n"));
521e3685
TT
397 else {
398 sb->s_feature_ro_compat &=
399 ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
400 fs->super->s_state &= ~EXT2_VALID_FS;
401 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
402 ext2fs_mark_super_dirty(fs);
d9c56d3c 403 printf(_("\nSparse superblock flag cleared. %s"),
a4fa100c 404 _(please_fsck));
521e3685
TT
405 }
406#else /* !EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER */
407 com_err (program_name, 0,
d9c56d3c
TT
408 _("The -s option is not supported by this version -- "
409 "Recompile with a newer kernel"));
521e3685
TT
410#endif /* EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER */
411 }
412
f3db3566
TT
413 if (u_flag)
414#ifdef EXT2_DEF_RESUID
415 {
416 fs->super->s_def_resuid = resuid;
417 ext2fs_mark_super_dirty(fs);
d9c56d3c 418 printf (_("Setting reserved blocks uid to %lu\n"), resuid);
f3db3566
TT
419 }
420#else
421 com_err (program_name, 0,
d9c56d3c
TT
422 _("The -u option is not supported by this version -- "
423 "Recompile with a newer kernel"));
f3db3566 424#endif
1e3472c5 425 if (L_flag) {
a789d840 426 if (strlen(new_label) > sizeof(sb->s_volume_name))
d9c56d3c
TT
427 fprintf(stderr, _("Warning: label too "
428 "long, truncating.\n"));
1e3472c5
TT
429 memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name));
430 strncpy(sb->s_volume_name, new_label,
431 sizeof(sb->s_volume_name));
432 ext2fs_mark_super_dirty(fs);
433 }
434 if (M_flag) {
435 memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted));
436 strncpy(sb->s_last_mounted, new_last_mounted,
437 sizeof(sb->s_last_mounted));
438 ext2fs_mark_super_dirty(fs);
439 }
896938d5
TT
440 if (features_cmd) {
441 int sparse, old_sparse, filetype, old_filetype;
442
443 old_sparse = sb->s_feature_ro_compat &
444 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
445 old_filetype = sb->s_feature_incompat &
446 EXT2_FEATURE_INCOMPAT_FILETYPE;
447 if (e2p_edit_feature(features_cmd,
448 &sb->s_feature_compat,
449 ok_features)) {
d9c56d3c 450 fprintf(stderr, _("Invalid filesystem option set: %s\n"),
896938d5
TT
451 features_cmd);
452 exit(1);
453 }
454 sparse = sb->s_feature_ro_compat &
455 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
456 filetype = sb->s_feature_incompat &
457 EXT2_FEATURE_INCOMPAT_FILETYPE;
458 if ((sparse != old_sparse) ||
459 (filetype != old_filetype)) {
460 fs->super->s_state &= ~EXT2_VALID_FS;
a4fa100c 461 printf("\n%s\n", _(please_fsck));
896938d5
TT
462 }
463 ext2fs_mark_super_dirty(fs);
464 }
1e3472c5
TT
465 if (U_flag) {
466 if (strcasecmp(new_UUID, "null") == 0) {
467 uuid_clear(sb->s_uuid);
468 } else if (strcasecmp(new_UUID, "random") == 0) {
469 uuid_generate(sb->s_uuid);
470 } else if (uuid_parse(new_UUID, sb->s_uuid)) {
d9c56d3c 471 com_err(program_name, 0, _("Invalid UUID format\n"));
1e3472c5
TT
472 exit(1);
473 }
474 ext2fs_mark_super_dirty(fs);
475 }
476
3839e657
TT
477 if (l_flag)
478 list_super (fs->super);
479 ext2fs_close (fs);
480 exit (0);
481}