]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sbin/tunefs/tunefs.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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;
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, 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 = oflag = pflag = sflag = 0;
94         avalue = Jvalue = 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:J: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 '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 = "soft updates";
193                         nvalue = optarg;
194                         if (strcmp(nvalue, "enable") != 0 &&
195                             strcmp(nvalue, "disable") != 0) {
196                                 errx(10, "bad %s (options are %s)",
197                                     name, "`enable' or `disable'");
198                         }
199                         nflag = 1;
200                         break;
201
202                 case 'o':
203                         found_arg = 1;
204                         name = "optimization preference";
205                         if (strcmp(optarg, "space") == 0)
206                                 ovalue = FS_OPTSPACE;
207                         else if (strcmp(optarg, "time") == 0)
208                                 ovalue = FS_OPTTIME;
209                         else
210                                 errx(10,
211                                     "bad %s (options are `space' or `time')",
212                                     name);
213                         oflag = 1;
214                         break;
215
216                 case 'p':
217                         found_arg = 1;
218                         pflag = 1;
219                         break;
220
221                 case 's':
222                         found_arg = 1;
223                         name = "expected number of files per directory";
224                         svalue = atoi(optarg);
225                         if (svalue < 1)
226                                 errx(10, "%s must be >= 1 (was %s)",
227                                     name, optarg);
228                         sflag = 1;
229                         break;
230
231                 default:
232                         usage();
233                 }
234         argc -= optind;
235         argv += optind;
236         if (found_arg == 0 || argc != 1)
237                 usage();
238
239         on = special = argv[0];
240         if (ufs_disk_fillout(&disk, special) == -1)
241                 goto err;
242         if (disk.d_name != special) {
243                 special = disk.d_name;
244                 if (statfs(special, &stfs) == 0 &&
245                     strcmp(special, stfs.f_mntonname) == 0)
246                         active = 1;
247         }
248
249         if (pflag) {
250                 printfs();
251                 exit(0);
252         }
253         if (Lflag) {
254                 name = "volume label";
255                 strlcpy(sblock.fs_volname, Lvalue, MAXVOLLEN);
256         }
257         if (aflag) {
258                 name = "ACLs";
259                 if (strcmp(avalue, "enable") == 0) {
260                         if (sblock.fs_flags & FS_ACLS) {
261                                 warnx("%s remains unchanged as enabled", name);
262                         } else {
263                                 sblock.fs_flags |= FS_ACLS;
264                                 warnx("%s set", name);
265                         }
266                 } else if (strcmp(avalue, "disable") == 0) {
267                         if ((~sblock.fs_flags & FS_ACLS) ==
268                             FS_ACLS) {
269                                 warnx("%s remains unchanged as disabled",
270                                     name);
271                         } else {
272                                 sblock.fs_flags &= ~FS_ACLS;
273                                 warnx("%s cleared", name);
274                         }
275                 }
276         }
277         if (eflag) {
278                 name = "maximum blocks per file in a cylinder group";
279                 if (sblock.fs_maxbpg == evalue)
280                         warnx("%s remains unchanged as %d", name, evalue);
281                 else {
282                         warnx("%s changes from %d to %d",
283                             name, sblock.fs_maxbpg, evalue);
284                         sblock.fs_maxbpg = evalue;
285                 }
286         }
287         if (fflag) {
288                 name = "average file size";
289                 if (sblock.fs_avgfilesize == fvalue) {
290                         warnx("%s remains unchanged as %d", name, fvalue);
291                 }
292                 else {
293                         warnx("%s changes from %d to %d",
294                                         name, sblock.fs_avgfilesize, fvalue);
295                         sblock.fs_avgfilesize = fvalue;
296                 }
297         }
298         if (Jflag) {
299                 name = "gjournal";
300                 if (strcmp(Jvalue, "enable") == 0) {
301                         if (sblock.fs_flags & FS_GJOURNAL) {
302                                 warnx("%s remains unchanged as enabled", name);
303                         } else {
304                                 sblock.fs_flags |= FS_GJOURNAL;
305                                 warnx("%s set", name);
306                         }
307                 } else if (strcmp(Jvalue, "disable") == 0) {
308                         if ((~sblock.fs_flags & FS_GJOURNAL) ==
309                             FS_GJOURNAL) {
310                                 warnx("%s remains unchanged as disabled",
311                                     name);
312                         } else {
313                                 sblock.fs_flags &= ~FS_GJOURNAL;
314                                 warnx("%s cleared", name);
315                         }
316                 }
317         }
318         if (lflag) {
319                 name = "multilabel";
320                 if (strcmp(lvalue, "enable") == 0) {
321                         if (sblock.fs_flags & FS_MULTILABEL) {
322                                 warnx("%s remains unchanged as enabled", name);
323                         } else {
324                                 sblock.fs_flags |= FS_MULTILABEL;
325                                 warnx("%s set", name);
326                         }
327                 } else if (strcmp(lvalue, "disable") == 0) {
328                         if ((~sblock.fs_flags & FS_MULTILABEL) ==
329                             FS_MULTILABEL) {
330                                 warnx("%s remains unchanged as disabled",
331                                     name);
332                         } else {
333                                 sblock.fs_flags &= ~FS_MULTILABEL;
334                                 warnx("%s cleared", name);
335                         }
336                 }
337         }
338         if (mflag) {
339                 name = "minimum percentage of free space";
340                 if (sblock.fs_minfree == mvalue)
341                         warnx("%s remains unchanged as %d%%", name, mvalue);
342                 else {
343                         warnx("%s changes from %d%% to %d%%",
344                                     name, sblock.fs_minfree, mvalue);
345                         sblock.fs_minfree = mvalue;
346                         if (mvalue >= MINFREE && sblock.fs_optim == FS_OPTSPACE)
347                                 warnx(OPTWARN, "time", ">=", MINFREE);
348                         if (mvalue < MINFREE && sblock.fs_optim == FS_OPTTIME)
349                                 warnx(OPTWARN, "space", "<", MINFREE);
350                 }
351         }
352         if (nflag) {
353                 name = "soft updates";
354                 if (strcmp(nvalue, "enable") == 0) {
355                         if (sblock.fs_flags & FS_DOSOFTDEP)
356                                 warnx("%s remains unchanged as enabled", name);
357                         else if (sblock.fs_clean == 0) {
358                                 warnx("%s cannot be enabled until fsck is run",
359                                     name);
360                         } else {
361                                 sblock.fs_flags |= FS_DOSOFTDEP;
362                                 warnx("%s set", name);
363                         }
364                 } else if (strcmp(nvalue, "disable") == 0) {
365                         if ((~sblock.fs_flags & FS_DOSOFTDEP) == FS_DOSOFTDEP)
366                                 warnx("%s remains unchanged as disabled", name);
367                         else {
368                                 sblock.fs_flags &= ~FS_DOSOFTDEP;
369                                 warnx("%s cleared", name);
370                         }
371                 }
372         }
373         if (oflag) {
374                 name = "optimization preference";
375                 chg[FS_OPTSPACE] = "space";
376                 chg[FS_OPTTIME] = "time";
377                 if (sblock.fs_optim == ovalue)
378                         warnx("%s remains unchanged as %s", name, chg[ovalue]);
379                 else {
380                         warnx("%s changes from %s to %s",
381                                     name, chg[sblock.fs_optim], chg[ovalue]);
382                         sblock.fs_optim = ovalue;
383                         if (sblock.fs_minfree >= MINFREE &&
384                             ovalue == FS_OPTSPACE)
385                                 warnx(OPTWARN, "time", ">=", MINFREE);
386                         if (sblock.fs_minfree < MINFREE && ovalue == FS_OPTTIME)
387                                 warnx(OPTWARN, "space", "<", MINFREE);
388                 }
389         }
390         if (sflag) {
391                 name = "expected number of files per directory";
392                 if (sblock.fs_avgfpdir == svalue) {
393                         warnx("%s remains unchanged as %d", name, svalue);
394                 }
395                 else {
396                         warnx("%s changes from %d to %d",
397                                         name, sblock.fs_avgfpdir, svalue);
398                         sblock.fs_avgfpdir = svalue;
399                 }
400         }
401
402         if (sbwrite(&disk, Aflag) == -1)
403                 goto err;
404         ufs_disk_close(&disk);
405         if (active) {
406                 bzero(&args, sizeof(args));
407                 if (mount("ufs", on,
408                     stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0)
409                         err(9, "%s: reload", special);
410                 warnx("file system reloaded");
411         }
412         exit(0);
413 err:
414         if (disk.d_error != NULL)
415                 errx(11, "%s: %s", special, disk.d_error);
416         else
417                 err(12, "%s", special);
418 }
419
420 void
421 usage(void)
422 {
423         fprintf(stderr, "%s\n%s\n%s\n%s\n",
424 "usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]",
425 "              [-J enable | disable ] [-L volname] [-l enable | disable]",
426 "              [-m minfree] [-n enable | disable] [-o space | time] [-p]",
427 "              [-s avgfpdir] special | filesystem");
428         exit(2);
429 }
430
431 void
432 printfs(void)
433 {
434         warnx("ACLs: (-a)                                         %s",
435                 (sblock.fs_flags & FS_ACLS)? "enabled" : "disabled");
436         warnx("MAC multilabel: (-l)                               %s",
437                 (sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled");
438         warnx("soft updates: (-n)                                 %s", 
439                 (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled");
440         warnx("gjournal: (-J)                                     %s",
441                 (sblock.fs_flags & FS_GJOURNAL)? "enabled" : "disabled");
442         warnx("maximum blocks per file in a cylinder group: (-e)  %d",
443               sblock.fs_maxbpg);
444         warnx("average file size: (-f)                            %d",
445               sblock.fs_avgfilesize);
446         warnx("average number of files in a directory: (-s)       %d",
447               sblock.fs_avgfpdir);
448         warnx("minimum percentage of free space: (-m)             %d%%",
449               sblock.fs_minfree);
450         warnx("optimization preference: (-o)                      %s",
451               sblock.fs_optim == FS_OPTSPACE ? "space" : "time");
452         if (sblock.fs_minfree >= MINFREE &&
453             sblock.fs_optim == FS_OPTSPACE)
454                 warnx(OPTWARN, "time", ">=", MINFREE);
455         if (sblock.fs_minfree < MINFREE &&
456             sblock.fs_optim == FS_OPTTIME)
457                 warnx(OPTWARN, "space", "<", MINFREE);
458         warnx("volume label: (-L)                                 %s",
459                 sblock.fs_volname);
460 }