tune2fs.c revision f3db3566b5e1342e49dffc5ec3f418a838584194
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 *
9 * This file can be redistributed under the terms of the GNU General
10 * Public License
11 */
12
13/*
14 * History:
15 * 93/06/01	- Creation
16 * 93/10/31	- Added the -c option to change the maximal mount counts
17 * 93/12/14	- Added -l flag to list contents of superblock
18 *                M.J.E. Mol (marcel@duteca.et.tudelft.nl)
19 *                F.W. ten Wolde (franky@duteca.et.tudelft.nl)
20 * 93/12/29	- Added the -e option to change errors behavior
21 * 94/02/27	- Ported to use the ext2fs library
22 * 94/03/06	- Added the checks interval from Uwe Ohse (uwe@tirka.gun.de)
23 */
24
25#include <fcntl.h>
26#include <grp.h>
27#include <getopt.h>
28#include <pwd.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <time.h>
33#include <unistd.h>
34#include <sys/types.h>
35
36#include <linux/ext2_fs.h>
37
38#include "ext2fs/ext2fs.h"
39#include "et/com_err.h"
40#include "e2p/e2p.h"
41
42#include "../version.h"
43
44const char * program_name = "tune2fs";
45char * device_name = NULL;
46int c_flag = 0;
47int e_flag = 0;
48int g_flag = 0;
49int i_flag = 0;
50int l_flag = 0;
51int m_flag = 0;
52int r_flag = 0;
53int u_flag = 0;
54int max_mount_count;
55unsigned long interval;
56unsigned long reserved_ratio = 0;
57unsigned long reserved_blocks = 0;
58unsigned short errors;
59unsigned long resgid = 0;
60unsigned long resuid = 0;
61
62static volatile void usage (void)
63{
64	fprintf (stderr, "Usage: %s [-c max-mounts-count] [-e errors-behavior] "
65		 "[-g group]\n"
66		 "\t[-i interval[d|m|w]] [-l] [-m reserved-blocks-percent]\n"
67		 "\t[-r reserved-blocks-count] [-u user] device\n", program_name);
68	exit (1);
69}
70
71void main (int argc, char ** argv)
72{
73	char c;
74	char * tmp;
75	errcode_t retval;
76	ext2_filsys fs;
77	struct group * gr;
78	struct passwd * pw;
79
80	fprintf (stderr, "tune2fs %s, %s for EXT2 FS %s, %s\n",
81		 E2FSPROGS_VERSION, E2FSPROGS_DATE,
82		 EXT2FS_VERSION, EXT2FS_DATE);
83	if (argc && *argv)
84		program_name = *argv;
85	initialize_ext2_error_table();
86	while ((c = getopt (argc, argv, "c:e:g:i:lm:r:u:")) != EOF)
87		switch (c)
88		{
89			case 'c':
90				max_mount_count = strtoul (optarg, &tmp, 0);
91				if (*tmp || max_mount_count > 16000)
92				{
93					com_err (program_name, 0,
94						 "bad mounts count - %s",
95						 optarg);
96					usage ();
97				}
98				c_flag = 1;
99				break;
100			case 'e':
101				if (strcmp (optarg, "continue") == 0)
102					errors = EXT2_ERRORS_CONTINUE;
103				else if (strcmp (optarg, "remount-ro") == 0)
104					errors = EXT2_ERRORS_RO;
105				else if (strcmp (optarg, "panic") == 0)
106					errors = EXT2_ERRORS_PANIC;
107				else
108				{
109					com_err (program_name, 0,
110						 "bad error behavior - %s",
111						 optarg);
112					usage ();
113				}
114				e_flag = 1;
115				break;
116			case 'g':
117				resgid = strtoul (optarg, &tmp, 0);
118				if (*tmp)
119				{
120					gr = getgrnam (optarg);
121					if (gr == NULL)
122						tmp = optarg;
123					else
124						resgid = gr->gr_gid;
125				}
126				if (*tmp)
127				{
128					com_err (program_name, 0,
129						 "bad gid/group name - %s",
130						 optarg);
131					usage ();
132				}
133				g_flag = 1;
134				break;
135			case 'i':
136				interval = strtoul (optarg, &tmp, 0);
137				switch (*tmp)
138				{
139					case '\0':
140					case 'd':
141					case 'D': /* days */
142						interval *= 86400;
143						if (*tmp != '\0')
144							tmp++;
145						break;
146					case 'm':
147					case 'M': /* months! */
148						interval *= 86400 * 30;
149						tmp++;
150						break;
151					case 'w':
152					case 'W': /* weeks */
153						interval *= 86400 * 7;
154						tmp++;
155						break;
156				}
157				if (*tmp || interval > (365 * 86400))
158				{
159					com_err (program_name, 0,
160						 "bad interval - %s", optarg);
161					usage ();
162				}
163				i_flag = 1;
164				break;
165			case 'l':
166				l_flag = 1;
167				break;
168			case 'm':
169				reserved_ratio = strtoul (optarg, &tmp, 0);
170				if (*tmp || reserved_ratio > 50)
171				{
172					com_err (program_name, 0,
173						 "bad reserved block ratio - %s",
174						 optarg);
175					usage ();
176				}
177				m_flag = 1;
178				break;
179			case 'r':
180				reserved_blocks = strtoul (optarg, &tmp, 0);
181				if (*tmp)
182				{
183					com_err (program_name, 0,
184						 "bad reserved blocks count - %s",
185						 optarg);
186					usage ();
187				}
188				r_flag = 1;
189				break;
190			case 'u':
191				resuid = strtoul (optarg, &tmp, 0);
192				if (*tmp)
193				{
194					pw = getpwnam (optarg);
195					if (pw == NULL)
196						tmp = optarg;
197					else
198						resuid = pw->pw_uid;
199				}
200				if (*tmp)
201				{
202					com_err (program_name, 0,
203						 "bad uid/user name - %s",
204						 optarg);
205					usage ();
206				}
207				u_flag = 1;
208				break;
209			default:
210				usage ();
211		}
212	if (optind < argc - 1 || optind == argc)
213		usage ();
214	if (!c_flag && !e_flag && !g_flag && !i_flag && !l_flag && !m_flag
215	    && !r_flag && !u_flag)
216		usage ();
217	device_name = argv[optind];
218	retval = ext2fs_open (device_name,
219			      (c_flag || e_flag || g_flag || i_flag || m_flag
220			       || r_flag || u_flag) ? EXT2_FLAG_RW : 0,
221			      0, 0, unix_io_manager, &fs);
222        if (retval)
223	{
224		com_err (program_name, retval, "while trying to open %s",
225			 device_name);
226		printf("Couldn't find valid filesystem superblock.\n");
227		exit(1);
228	}
229
230	if (c_flag)
231	{
232		fs->super->s_max_mnt_count = max_mount_count;
233		ext2fs_mark_super_dirty(fs);
234		printf ("Setting maximal mount count to %d\n", max_mount_count);
235	}
236	if (e_flag)
237	{
238		fs->super->s_errors = errors;
239		ext2fs_mark_super_dirty(fs);
240		printf ("Setting error behavior to %d\n", errors);
241	}
242	if (g_flag)
243#ifdef	EXT2_DEF_RESGID
244	{
245		fs->super->s_def_resgid = resgid;
246		ext2fs_mark_super_dirty(fs);
247		printf ("Setting reserved blocks gid to %lu\n", resgid);
248	}
249#else
250		com_err (program_name, 0,
251			 "The -g option is not supported by this version -- "
252			 "Recompile with a newer kernel");
253#endif
254	if (i_flag)
255	{
256		fs->super->s_checkinterval = interval;
257		ext2fs_mark_super_dirty(fs);
258		printf ("Setting interval between check %lu seconds\n", interval);
259	}
260	if (m_flag)
261	{
262		fs->super->s_r_blocks_count = (fs->super->s_blocks_count / 100)
263			* reserved_ratio;
264		ext2fs_mark_super_dirty(fs);
265		printf ("Setting reserved blocks percentage to %lu (%lu blocks)\n",
266			reserved_ratio, fs->super->s_r_blocks_count);
267	}
268	if (r_flag)
269	{
270		if (reserved_blocks >= fs->super->s_blocks_count)
271		{
272			com_err (program_name, 0,
273				 "reserved blocks count is too big (%ul)",
274				 reserved_blocks);
275			exit (1);
276		}
277		fs->super->s_r_blocks_count = reserved_blocks;
278		ext2fs_mark_super_dirty(fs);
279		printf ("Setting reserved blocks count to %lu\n",
280			reserved_blocks);
281	}
282	if (u_flag)
283#ifdef	EXT2_DEF_RESUID
284	{
285		fs->super->s_def_resuid = resuid;
286		ext2fs_mark_super_dirty(fs);
287		printf ("Setting reserved blocks uid to %lu\n", resuid);
288	}
289#else
290		com_err (program_name, 0,
291			 "The -u option is not supported by this version -- "
292			 "Recompile with a newer kernel");
293#endif
294	if (l_flag)
295		list_super (fs->super);
296	ext2fs_close (fs);
297	exit (0);
298}
299