]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/tunefs/tunefs.c
Summer of Code 2005: improve libalias - part 1 of 2
[FreeBSD/FreeBSD.git] / sbin / tunefs / tunefs.c
1 /*
2  * Copyright (c) 1983, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #if 0
31 #ifndef lint
32 static const char copyright[] =
33 "@(#) Copyright (c) 1983, 1993\n\
34         The Regents of the University of California.  All rights reserved.\n";
35 #endif /* not lint */
36
37 #ifndef lint
38 static char sccsid[] = "@(#)tunefs.c    8.2 (Berkeley) 4/19/94";
39 #endif /* not lint */
40 #endif
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
43
44 /*
45  * tunefs: change layout parameters to an existing file system.
46  */
47 #include <sys/param.h>
48 #include <sys/mount.h>
49 #include <sys/disklabel.h>
50 #include <sys/stat.h>
51
52 #include <ufs/ufs/ufsmount.h>
53 #include <ufs/ufs/dinode.h>
54 #include <ufs/ffs/fs.h>
55
56 #include <ctype.h>
57 #include <err.h>
58 #include <fcntl.h>
59 #include <fstab.h>
60 #include <libufs.h>
61 #include <paths.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <unistd.h>
66
67 /* the optimization warning string template */
68 #define OPTWARN "should optimize for %s with minfree %s %d%%"
69
70 struct uufsd disk;
71 #define sblock disk.d_fs
72
73 void usage(void);
74 void printfs(void);
75
76 int
77 main(int argc, char *argv[])
78 {
79         char *avalue, *Lvalue, *lvalue, *nvalue;
80         const char *special, *on;
81         const char *name;
82         int active;
83         int Aflag, aflag, eflag, evalue, fflag, fvalue, Lflag, lflag;
84         int mflag, mvalue, nflag, oflag, ovalue, pflag, sflag, svalue;
85         int ch, found_arg, i;
86         const char *chg[2];
87         struct ufs_args args;
88         struct statfs stfs;
89
90         if (argc < 3)
91                 usage();
92         Aflag = aflag = eflag = fflag = Lflag = lflag = mflag = 0;
93         nflag = oflag = pflag = sflag = 0;
94         avalue = Lvalue = lvalue = nvalue = NULL;
95         evalue = fvalue = mvalue = ovalue = svalue = 0;
96         active = 0;
97         found_arg = 0;          /* At least one arg is required. */
98         while ((ch = getopt(argc, argv, "Aa:e:f:L:l:m:n:o:ps:")) != -1)
99                 switch (ch) {
100
101                 case 'A':
102                         found_arg = 1;
103                         Aflag++;
104                         break;
105
106                 case 'a':
107                         found_arg = 1;
108                         name = "ACLs";
109                         avalue = optarg;
110                         if (strcmp(avalue, "enable") &&
111                             strcmp(avalue, "disable")) {
112                                 errx(10, "bad %s (options are %s)",
113                                     name, "`enable' or `disable'");
114                         }
115                         aflag = 1;
116                         break;
117
118                 case 'e':
119                         found_arg = 1;
120                         name = "maximum blocks per file in a cylinder group";
121                         evalue = atoi(optarg);
122                         if (evalue < 1)
123                                 errx(10, "%s must be >= 1 (was %s)",
124                                     name, optarg);
125                         eflag = 1;
126                         break;
127
128                 case 'f':
129                         found_arg = 1;
130                         name = "average file size";
131                         fvalue = atoi(optarg);
132                         if (fvalue < 1)
133                                 errx(10, "%s must be >= 1 (was %s)",
134                                     name, optarg);
135                         fflag = 1;
136                         break;
137
138                 case 'L':
139                         found_arg = 1;
140                         name = "volume label";
141                         Lvalue = optarg;
142                         i = -1;
143                         while (isalnum(Lvalue[++i]));
144                         if (Lvalue[i] != '\0') {
145                                 errx(10,
146                                 "bad %s. Valid characters are alphanumerics.",
147                                     name);
148                         }
149                         if (strlen(Lvalue) >= MAXVOLLEN) {
150                                 errx(10, "bad %s. Length is longer than %d.",
151                                     name, MAXVOLLEN - 1);
152                         }
153                         Lflag = 1;
154                         break;
155
156                 case 'l':
157                         found_arg = 1;
158                         name = "multilabel MAC file system";
159                         lvalue = optarg;
160                         if (strcmp(lvalue, "enable") &&
161                             strcmp(lvalue, "disable")) {
162                                 errx(10, "bad %s (options are %s)",
163                                     name, "`enable' or `disable'");
164                         }
165                         lflag = 1;
166                         break;
167
168                 case 'm':
169                         found_arg = 1;
170                         name = "minimum percentage of free space";
171                         mvalue = atoi(optarg);
172                         if (mvalue < 0 || mvalue > 99)
173                                 errx(10, "bad %s (%s)", name, optarg);
174                         mflag = 1;
175                         break;
176
177                 case 'n':
178                         found_arg = 1;
179                         name = "soft updates";
180                         nvalue = optarg;
181                         if (strcmp(nvalue, "enable") != 0 &&
182                             strcmp(nvalue, "disable") != 0) {
183                                 errx(10, "bad %s (options are %s)",
184                                     name, "`enable' or `disable'");
185                         }
186                         nflag = 1;
187                         break;
188
189                 case 'o':
190                         found_arg = 1;
191                         name = "optimization preference";
192                         if (strcmp(optarg, "space") == 0)
193                                 ovalue = FS_OPTSPACE;
194                         else if (strcmp(optarg, "time") == 0)
195                                 ovalue = FS_OPTTIME;
196                         else
197                                 errx(10,
198                                     "bad %s (options are `space' or `time')",
199                                     name);
200                         oflag = 1;
201                         break;
202
203                 case 'p':
204                         found_arg = 1;
205                         pflag = 1;
206                         break;
207
208                 case 's':
209                         found_arg = 1;
210                         name = "expected number of files per directory";
211                         svalue = atoi(optarg);
212                         if (svalue < 1)
213                                 errx(10, "%s must be >= 1 (was %s)",
214                                     name, optarg);
215                         sflag = 1;
216                         break;
217
218                 default:
219                         usage();
220                 }
221         argc -= optind;
222         argv += optind;
223         if (found_arg == 0 || argc != 1)
224                 usage();
225
226         on = special = argv[0];
227         if (ufs_disk_fillout(&disk, special) == -1)
228                 goto err;
229         if (disk.d_name != special) {
230                 special = disk.d_name;
231                 if (statfs(special, &stfs) == 0 &&
232                     strcmp(special, stfs.f_mntonname) == 0)
233                         active = 1;
234         }
235
236         if (pflag) {
237                 printfs();
238                 exit(0);
239         }
240         if (Lflag) {
241                 name = "volume label";
242                 strlcpy(sblock.fs_volname, Lvalue, MAXVOLLEN);
243         }
244         if (aflag) {
245                 name = "ACLs";
246                 if (strcmp(avalue, "enable") == 0) {
247                         if (sblock.fs_flags & FS_ACLS) {
248                                 warnx("%s remains unchanged as enabled", name);
249                         } else {
250                                 sblock.fs_flags |= FS_ACLS;
251                                 warnx("%s set", name);
252                         }
253                 } else if (strcmp(avalue, "disable") == 0) {
254                         if ((~sblock.fs_flags & FS_ACLS) ==
255                             FS_ACLS) {
256                                 warnx("%s remains unchanged as disabled",
257                                     name);
258                         } else {
259                                 sblock.fs_flags &= ~FS_ACLS;
260                                 warnx("%s cleared", name);
261                         }
262                 }
263         }
264         if (eflag) {
265                 name = "maximum blocks per file in a cylinder group";
266                 if (sblock.fs_maxbpg == evalue)
267                         warnx("%s remains unchanged as %d", name, evalue);
268                 else {
269                         warnx("%s changes from %d to %d",
270                             name, sblock.fs_maxbpg, evalue);
271                         sblock.fs_maxbpg = evalue;
272                 }
273         }
274         if (fflag) {
275                 name = "average file size";
276                 if (sblock.fs_avgfilesize == fvalue) {
277                         warnx("%s remains unchanged as %d", name, fvalue);
278                 }
279                 else {
280                         warnx("%s changes from %d to %d",
281                                         name, sblock.fs_avgfilesize, fvalue);
282                         sblock.fs_avgfilesize = fvalue;
283                 }
284         }
285         if (lflag) {
286                 name = "multilabel";
287                 if (strcmp(lvalue, "enable") == 0) {
288                         if (sblock.fs_flags & FS_MULTILABEL) {
289                                 warnx("%s remains unchanged as enabled", name);
290                         } else {
291                                 sblock.fs_flags |= FS_MULTILABEL;
292                                 warnx("%s set", name);
293                         }
294                 } else if (strcmp(lvalue, "disable") == 0) {
295                         if ((~sblock.fs_flags & FS_MULTILABEL) ==
296                             FS_MULTILABEL) {
297                                 warnx("%s remains unchanged as disabled",
298                                     name);
299                         } else {
300                                 sblock.fs_flags &= ~FS_MULTILABEL;
301                                 warnx("%s cleared", name);
302                         }
303                 }
304         }
305         if (mflag) {
306                 name = "minimum percentage of free space";
307                 if (sblock.fs_minfree == mvalue)
308                         warnx("%s remains unchanged as %d%%", name, mvalue);
309                 else {
310                         warnx("%s changes from %d%% to %d%%",
311                                     name, sblock.fs_minfree, mvalue);
312                         sblock.fs_minfree = mvalue;
313                         if (mvalue >= MINFREE && sblock.fs_optim == FS_OPTSPACE)
314                                 warnx(OPTWARN, "time", ">=", MINFREE);
315                         if (mvalue < MINFREE && sblock.fs_optim == FS_OPTTIME)
316                                 warnx(OPTWARN, "space", "<", MINFREE);
317                 }
318         }
319         if (nflag) {
320                 name = "soft updates";
321                 if (strcmp(nvalue, "enable") == 0) {
322                         if (sblock.fs_flags & FS_DOSOFTDEP)
323                                 warnx("%s remains unchanged as enabled", name);
324                         else if (sblock.fs_clean == 0) {
325                                 warnx("%s cannot be enabled until fsck is run",
326                                     name);
327                         } else {
328                                 sblock.fs_flags |= FS_DOSOFTDEP;
329                                 warnx("%s set", name);
330                         }
331                 } else if (strcmp(nvalue, "disable") == 0) {
332                         if ((~sblock.fs_flags & FS_DOSOFTDEP) == FS_DOSOFTDEP)
333                                 warnx("%s remains unchanged as disabled", name);
334                         else {
335                                 sblock.fs_flags &= ~FS_DOSOFTDEP;
336                                 warnx("%s cleared", name);
337                         }
338                 }
339         }
340         if (oflag) {
341                 name = "optimization preference";
342                 chg[FS_OPTSPACE] = "space";
343                 chg[FS_OPTTIME] = "time";
344                 if (sblock.fs_optim == ovalue)
345                         warnx("%s remains unchanged as %s", name, chg[ovalue]);
346                 else {
347                         warnx("%s changes from %s to %s",
348                                     name, chg[sblock.fs_optim], chg[ovalue]);
349                         sblock.fs_optim = ovalue;
350                         if (sblock.fs_minfree >= MINFREE &&
351                             ovalue == FS_OPTSPACE)
352                                 warnx(OPTWARN, "time", ">=", MINFREE);
353                         if (sblock.fs_minfree < MINFREE && ovalue == FS_OPTTIME)
354                                 warnx(OPTWARN, "space", "<", MINFREE);
355                 }
356         }
357         if (sflag) {
358                 name = "expected number of files per directory";
359                 if (sblock.fs_avgfpdir == svalue) {
360                         warnx("%s remains unchanged as %d", name, svalue);
361                 }
362                 else {
363                         warnx("%s changes from %d to %d",
364                                         name, sblock.fs_avgfpdir, svalue);
365                         sblock.fs_avgfpdir = svalue;
366                 }
367         }
368
369         if (sbwrite(&disk, Aflag) == -1)
370                 goto err;
371         ufs_disk_close(&disk);
372         if (active) {
373                 bzero(&args, sizeof(args));
374                 if (mount("ufs", on,
375                     stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0)
376                         err(9, "%s: reload", special);
377                 warnx("file system reloaded");
378         }
379         exit(0);
380 err:
381         if (disk.d_error != NULL)
382                 errx(11, "%s: %s", special, disk.d_error);
383         else
384                 err(12, "%s", special);
385 }
386
387 void
388 usage(void)
389 {
390         fprintf(stderr, "%s\n%s\n%s\n%s\n",
391 "usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]",
392 "              [-L volname] [-l enable | disable] [-m minfree]",
393 "              [-n enable | disable] [-o space | time] [-p]",
394 "              [-s avgfpdir] special | filesystem");
395         exit(2);
396 }
397
398 void
399 printfs(void)
400 {
401         warnx("ACLs: (-a)                                         %s",
402                 (sblock.fs_flags & FS_ACLS)? "enabled" : "disabled");
403         warnx("MAC multilabel: (-l)                               %s",
404                 (sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled");
405         warnx("soft updates: (-n)                                 %s", 
406                 (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled");
407         warnx("maximum blocks per file in a cylinder group: (-e)  %d",
408               sblock.fs_maxbpg);
409         warnx("average file size: (-f)                            %d",
410               sblock.fs_avgfilesize);
411         warnx("average number of files in a directory: (-s)       %d",
412               sblock.fs_avgfpdir);
413         warnx("minimum percentage of free space: (-m)             %d%%",
414               sblock.fs_minfree);
415         warnx("optimization preference: (-o)                      %s",
416               sblock.fs_optim == FS_OPTSPACE ? "space" : "time");
417         if (sblock.fs_minfree >= MINFREE &&
418             sblock.fs_optim == FS_OPTSPACE)
419                 warnx(OPTWARN, "time", ">=", MINFREE);
420         if (sblock.fs_minfree < MINFREE &&
421             sblock.fs_optim == FS_OPTTIME)
422                 warnx(OPTWARN, "space", "<", MINFREE);
423         warnx("volume label: (-L)                                 %s",
424                 sblock.fs_volname);
425 }