]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sbin/tunefs/tunefs.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.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, *Jvalue, *Lvalue, *lvalue, *Nvalue, *nvalue;
80         const char *special, *on;
81         const char *name;
82         int active;
83         int Aflag, aflag, eflag, evalue, fflag, fvalue, Jflag, Lflag, lflag;
84         int mflag, mvalue, Nflag, 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 = Jflag = Lflag = lflag = mflag = 0;
93         Nflag = nflag = oflag = pflag = sflag = 0;
94         avalue = Jvalue = Lvalue = lvalue = Nvalue = 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:J:L:l:m:N: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 = "POSIX.1e 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 'J':
139                         found_arg = 1;
140                         name = "gjournaled file system";
141                         Jvalue = optarg;
142                         if (strcmp(Jvalue, "enable") &&
143                             strcmp(Jvalue, "disable")) {
144                                 errx(10, "bad %s (options are %s)",
145                                     name, "`enable' or `disable'");
146                         }
147                         Jflag = 1;
148                         break;
149
150
151                 case 'L':
152                         found_arg = 1;
153                         name = "volume label";
154                         Lvalue = optarg;
155                         i = -1;
156                         while (isalnum(Lvalue[++i]));
157                         if (Lvalue[i] != '\0') {
158                                 errx(10,
159                                 "bad %s. Valid characters are alphanumerics.",
160                                     name);
161                         }
162                         if (strlen(Lvalue) >= MAXVOLLEN) {
163                                 errx(10, "bad %s. Length is longer than %d.",
164                                     name, MAXVOLLEN - 1);
165                         }
166                         Lflag = 1;
167                         break;
168
169                 case 'l':
170                         found_arg = 1;
171                         name = "multilabel MAC file system";
172                         lvalue = optarg;
173                         if (strcmp(lvalue, "enable") &&
174                             strcmp(lvalue, "disable")) {
175                                 errx(10, "bad %s (options are %s)",
176                                     name, "`enable' or `disable'");
177                         }
178                         lflag = 1;
179                         break;
180
181                 case 'm':
182                         found_arg = 1;
183                         name = "minimum percentage of free space";
184                         mvalue = atoi(optarg);
185                         if (mvalue < 0 || mvalue > 99)
186                                 errx(10, "bad %s (%s)", name, optarg);
187                         mflag = 1;
188                         break;
189
190                 case 'N':
191                         found_arg = 1;
192                         name = "NFSv4 ACLs";
193                         Nvalue = optarg;
194                         if (strcmp(Nvalue, "enable") &&
195                             strcmp(Nvalue, "disable")) {
196                                 errx(10, "bad %s (options are %s)",
197                                     name, "`enable' or `disable'");
198                         }
199                         Nflag = 1;
200                         break;
201
202                 case 'n':
203                         found_arg = 1;
204                         name = "soft updates";
205                         nvalue = optarg;
206                         if (strcmp(nvalue, "enable") != 0 &&
207                             strcmp(nvalue, "disable") != 0) {
208                                 errx(10, "bad %s (options are %s)",
209                                     name, "`enable' or `disable'");
210                         }
211                         nflag = 1;
212                         break;
213
214                 case 'o':
215                         found_arg = 1;
216                         name = "optimization preference";
217                         if (strcmp(optarg, "space") == 0)
218                                 ovalue = FS_OPTSPACE;
219                         else if (strcmp(optarg, "time") == 0)
220                                 ovalue = FS_OPTTIME;
221                         else
222                                 errx(10,
223                                     "bad %s (options are `space' or `time')",
224                                     name);
225                         oflag = 1;
226                         break;
227
228                 case 'p':
229                         found_arg = 1;
230                         pflag = 1;
231                         break;
232
233                 case 's':
234                         found_arg = 1;
235                         name = "expected number of files per directory";
236                         svalue = atoi(optarg);
237                         if (svalue < 1)
238                                 errx(10, "%s must be >= 1 (was %s)",
239                                     name, optarg);
240                         sflag = 1;
241                         break;
242
243                 default:
244                         usage();
245                 }
246         argc -= optind;
247         argv += optind;
248         if (found_arg == 0 || argc != 1)
249                 usage();
250
251         on = special = argv[0];
252         if (ufs_disk_fillout(&disk, special) == -1)
253                 goto err;
254         if (disk.d_name != special) {
255                 special = disk.d_name;
256                 if (statfs(special, &stfs) == 0 &&
257                     strcmp(special, stfs.f_mntonname) == 0)
258                         active = 1;
259         }
260
261         if (pflag) {
262                 printfs();
263                 exit(0);
264         }
265         if (Lflag) {
266                 name = "volume label";
267                 strlcpy(sblock.fs_volname, Lvalue, MAXVOLLEN);
268         }
269         if (aflag) {
270                 name = "POSIX.1e ACLs";
271                 if (strcmp(avalue, "enable") == 0) {
272                         if (sblock.fs_flags & FS_ACLS) {
273                                 warnx("%s remains unchanged as enabled", name);
274                         } else if (sblock.fs_flags & FS_NFS4ACLS) {
275                                 warnx("%s and NFSv4 ACLs are mutually "
276                                     "exclusive", name);
277                         } else {
278                                 sblock.fs_flags |= FS_ACLS;
279                                 warnx("%s set", name);
280                         }
281                 } else if (strcmp(avalue, "disable") == 0) {
282                         if ((~sblock.fs_flags & FS_ACLS) ==
283                             FS_ACLS) {
284                                 warnx("%s remains unchanged as disabled",
285                                     name);
286                         } else {
287                                 sblock.fs_flags &= ~FS_ACLS;
288                                 warnx("%s cleared", name);
289                         }
290                 }
291         }
292         if (eflag) {
293                 name = "maximum blocks per file in a cylinder group";
294                 if (sblock.fs_maxbpg == evalue)
295                         warnx("%s remains unchanged as %d", name, evalue);
296                 else {
297                         warnx("%s changes from %d to %d",
298                             name, sblock.fs_maxbpg, evalue);
299                         sblock.fs_maxbpg = evalue;
300                 }
301         }
302         if (fflag) {
303                 name = "average file size";
304                 if (sblock.fs_avgfilesize == (unsigned)fvalue) {
305                         warnx("%s remains unchanged as %d", name, fvalue);
306                 }
307                 else {
308                         warnx("%s changes from %d to %d",
309                                         name, sblock.fs_avgfilesize, fvalue);
310                         sblock.fs_avgfilesize = fvalue;
311                 }
312         }
313         if (Jflag) {
314                 name = "gjournal";
315                 if (strcmp(Jvalue, "enable") == 0) {
316                         if (sblock.fs_flags & FS_GJOURNAL) {
317                                 warnx("%s remains unchanged as enabled", name);
318                         } else {
319                                 sblock.fs_flags |= FS_GJOURNAL;
320                                 warnx("%s set", name);
321                         }
322                 } else if (strcmp(Jvalue, "disable") == 0) {
323                         if ((~sblock.fs_flags & FS_GJOURNAL) ==
324                             FS_GJOURNAL) {
325                                 warnx("%s remains unchanged as disabled",
326                                     name);
327                         } else {
328                                 sblock.fs_flags &= ~FS_GJOURNAL;
329                                 warnx("%s cleared", name);
330                         }
331                 }
332         }
333         if (lflag) {
334                 name = "multilabel";
335                 if (strcmp(lvalue, "enable") == 0) {
336                         if (sblock.fs_flags & FS_MULTILABEL) {
337                                 warnx("%s remains unchanged as enabled", name);
338                         } else {
339                                 sblock.fs_flags |= FS_MULTILABEL;
340                                 warnx("%s set", name);
341                         }
342                 } else if (strcmp(lvalue, "disable") == 0) {
343                         if ((~sblock.fs_flags & FS_MULTILABEL) ==
344                             FS_MULTILABEL) {
345                                 warnx("%s remains unchanged as disabled",
346                                     name);
347                         } else {
348                                 sblock.fs_flags &= ~FS_MULTILABEL;
349                                 warnx("%s cleared", name);
350                         }
351                 }
352         }
353         if (mflag) {
354                 name = "minimum percentage of free space";
355                 if (sblock.fs_minfree == mvalue)
356                         warnx("%s remains unchanged as %d%%", name, mvalue);
357                 else {
358                         warnx("%s changes from %d%% to %d%%",
359                                     name, sblock.fs_minfree, mvalue);
360                         sblock.fs_minfree = mvalue;
361                         if (mvalue >= MINFREE && sblock.fs_optim == FS_OPTSPACE)
362                                 warnx(OPTWARN, "time", ">=", MINFREE);
363                         if (mvalue < MINFREE && sblock.fs_optim == FS_OPTTIME)
364                                 warnx(OPTWARN, "space", "<", MINFREE);
365                 }
366         }
367         if (Nflag) {
368                 name = "NFSv4 ACLs";
369                 if (strcmp(Nvalue, "enable") == 0) {
370                         if (sblock.fs_flags & FS_NFS4ACLS) {
371                                 warnx("%s remains unchanged as enabled", name);
372                         } else if (sblock.fs_flags & FS_ACLS) {
373                                 warnx("%s and POSIX.1e ACLs are mutually "
374                                     "exclusive", name);
375                         } else {
376                                 sblock.fs_flags |= FS_NFS4ACLS;
377                                 warnx("%s set", name);
378                         }
379                 } else if (strcmp(Nvalue, "disable") == 0) {
380                         if ((~sblock.fs_flags & FS_NFS4ACLS) ==
381                             FS_NFS4ACLS) {
382                                 warnx("%s remains unchanged as disabled",
383                                     name);
384                         } else {
385                                 sblock.fs_flags &= ~FS_NFS4ACLS;
386                                 warnx("%s cleared", name);
387                         }
388                 }
389         }
390         if (nflag) {
391                 name = "soft updates";
392                 if (strcmp(nvalue, "enable") == 0) {
393                         if (sblock.fs_flags & FS_DOSOFTDEP)
394                                 warnx("%s remains unchanged as enabled", name);
395                         else if (sblock.fs_clean == 0) {
396                                 warnx("%s cannot be enabled until fsck is run",
397                                     name);
398                         } else {
399                                 sblock.fs_flags |= FS_DOSOFTDEP;
400                                 warnx("%s set", name);
401                         }
402                 } else if (strcmp(nvalue, "disable") == 0) {
403                         if ((~sblock.fs_flags & FS_DOSOFTDEP) == FS_DOSOFTDEP)
404                                 warnx("%s remains unchanged as disabled", name);
405                         else {
406                                 sblock.fs_flags &= ~FS_DOSOFTDEP;
407                                 warnx("%s cleared", name);
408                         }
409                 }
410         }
411         if (oflag) {
412                 name = "optimization preference";
413                 chg[FS_OPTSPACE] = "space";
414                 chg[FS_OPTTIME] = "time";
415                 if (sblock.fs_optim == ovalue)
416                         warnx("%s remains unchanged as %s", name, chg[ovalue]);
417                 else {
418                         warnx("%s changes from %s to %s",
419                                     name, chg[sblock.fs_optim], chg[ovalue]);
420                         sblock.fs_optim = ovalue;
421                         if (sblock.fs_minfree >= MINFREE &&
422                             ovalue == FS_OPTSPACE)
423                                 warnx(OPTWARN, "time", ">=", MINFREE);
424                         if (sblock.fs_minfree < MINFREE && ovalue == FS_OPTTIME)
425                                 warnx(OPTWARN, "space", "<", MINFREE);
426                 }
427         }
428         if (sflag) {
429                 name = "expected number of files per directory";
430                 if (sblock.fs_avgfpdir == (unsigned)svalue) {
431                         warnx("%s remains unchanged as %d", name, svalue);
432                 }
433                 else {
434                         warnx("%s changes from %d to %d",
435                                         name, sblock.fs_avgfpdir, svalue);
436                         sblock.fs_avgfpdir = svalue;
437                 }
438         }
439
440         if (sbwrite(&disk, Aflag) == -1)
441                 goto err;
442         ufs_disk_close(&disk);
443         if (active) {
444                 bzero(&args, sizeof(args));
445                 if (mount("ufs", on,
446                     stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0)
447                         err(9, "%s: reload", special);
448                 warnx("file system reloaded");
449         }
450         exit(0);
451 err:
452         if (disk.d_error != NULL)
453                 errx(11, "%s: %s", special, disk.d_error);
454         else
455                 err(12, "%s", special);
456 }
457
458 void
459 usage(void)
460 {
461         fprintf(stderr, "%s\n%s\n%s\n%s\n",
462 "usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]",
463 "              [-J enable | disable ] [-L volname] [-l enable | disable]",
464 "              [-m minfree] [-N enable | disable] [-n enable | disable]",
465 "              [-o space | time] [-p] [-s avgfpdir] special | filesystem");
466         exit(2);
467 }
468
469 void
470 printfs(void)
471 {
472         warnx("POSIX.1e ACLs: (-a)                                %s",
473                 (sblock.fs_flags & FS_ACLS)? "enabled" : "disabled");
474         warnx("NFSv4 ACLs: (-N)                                   %s",
475                 (sblock.fs_flags & FS_NFS4ACLS)? "enabled" : "disabled");
476         warnx("MAC multilabel: (-l)                               %s",
477                 (sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled");
478         warnx("soft updates: (-n)                                 %s", 
479                 (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled");
480         warnx("gjournal: (-J)                                     %s",
481                 (sblock.fs_flags & FS_GJOURNAL)? "enabled" : "disabled");
482         warnx("maximum blocks per file in a cylinder group: (-e)  %d",
483               sblock.fs_maxbpg);
484         warnx("average file size: (-f)                            %d",
485               sblock.fs_avgfilesize);
486         warnx("average number of files in a directory: (-s)       %d",
487               sblock.fs_avgfpdir);
488         warnx("minimum percentage of free space: (-m)             %d%%",
489               sblock.fs_minfree);
490         warnx("optimization preference: (-o)                      %s",
491               sblock.fs_optim == FS_OPTSPACE ? "space" : "time");
492         if (sblock.fs_minfree >= MINFREE &&
493             sblock.fs_optim == FS_OPTSPACE)
494                 warnx(OPTWARN, "time", ">=", MINFREE);
495         if (sblock.fs_minfree < MINFREE &&
496             sblock.fs_optim == FS_OPTTIME)
497                 warnx(OPTWARN, "space", "<", MINFREE);
498         warnx("volume label: (-L)                                 %s",
499                 sblock.fs_volname);
500 }