1 /* $NetBSD: newfs.c,v 1.105 2009/05/07 06:56:56 lukem Exp $ */
4 * Copyright (c) 1983, 1989, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Copyright (c) 2002 Networks Associates Technology, Inc.
34 * All rights reserved.
36 * This software was developed for the FreeBSD Project by Marshall
37 * Kirk McKusick and Network Associates Laboratories, the Security
38 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
39 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement:
52 * This product includes software developed by the University of
53 * California, Berkeley and its contributors.
54 * 4. Neither the name of the University nor the names of its contributors
55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission.
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71 #include <sys/cdefs.h>
73 __COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1993, 1994\
74 The Regents of the University of California. All rights reserved.");
79 static char sccsid
[] = "@(#)newfs.c 8.13 (Berkeley) 5/1/95";
81 __RCSID("$NetBSD: newfs.c,v 1.105 2009/05/07 06:56:56 lukem Exp $");
86 * newfs: friendly front end to mkfs
88 #include <sys/param.h>
89 #include <sys/ioctl.h>
90 #include <sys/disklabel.h>
93 #include <sys/mount.h>
94 #include <sys/sysctl.h>
97 #include <ufs/ufs/dir.h>
98 #include <ufs/ufs/dinode.h>
99 #include <ufs/ufs/ufsmount.h>
100 #include <ufs/ffs/fs.h>
121 #include <mountprog.h>
126 #include "partutil.h"
128 struct mntopt mopts
[] = {
134 { .m_option
= NULL
},
137 static gid_t
mfs_group(const char *);
138 static uid_t
mfs_user(const char *);
139 static int64_t strsuftoi64(const char *, const char *, int64_t, int64_t, int *);
140 static void usage(void) __dead
;
142 #define COMPAT /* allow non-labeled disks */
145 const char lmsg
[] = "%s: can't read disk label; disk type must be specified";
147 const char lmsg
[] = "%s: can't read disk label";
151 * The following two constants set the default block and fragment sizes.
152 * Both constants must be a power of 2 and meet the following constraints:
153 * MINBSIZE <= DESBLKSIZE <= MAXBSIZE
154 * sectorsize <= DESFRAGSIZE <= DESBLKSIZE
155 * DESBLKSIZE / DESFRAGSIZE <= 8
158 * For file systems smaller than SMALL_FSSIZE we use the S_DFL_* defaults,
159 * otherwise if less than MEDIUM_FSSIZE use M_DFL_*, otherwise use
162 #define SMALL_FSSIZE (20*1024*2)
163 #define S_DFL_FRAGSIZE 512
164 #define MEDIUM_FSSIZE (1000*1024*2)
165 #define M_DFL_FRAGSIZE 1024
166 #define L_DFL_FRAGSIZE 2048
167 #define DFL_FRAG_BLK 8
169 /* Apple requires the fragment size to be at least APPLEUFS_DIRBLKSIZ
170 * but the block size cannot be larger than Darwin's PAGE_SIZE. See
171 * the mount check in Darwin's ffs_mountfs for an explanation.
173 #define APPLEUFS_DFL_FRAGSIZE APPLEUFS_DIRBLKSIZ /* 1024 */
174 #define APPLEUFS_DFL_BLKSIZE 4096 /* default Darwin PAGE_SIZE */
177 * Default sector size.
179 #define DFL_SECSIZE 512
182 * Default file system size for "mount_mfs swap /dir" case.
184 #define DFL_FSSIZE (8 * 1024 * 1024)
187 * MAXBLKPG determines the maximum number of data blocks which are
188 * placed in a single cylinder group. The default is one indirect
189 * block worth of data blocks.
191 #define MAXBLKPG_UFS1(bsize) ((bsize) / sizeof(int32_t))
192 #define MAXBLKPG_UFS2(bsize) ((bsize) / sizeof(int64_t))
195 * Each file system has a number of inodes statically allocated.
196 * We allocate one inode slot per NFPI fragments, expecting this
197 * to be far more than we will ever need.
202 int mfs
; /* run as the memory based filesystem */
203 int Nflag
; /* run without writing file system */
204 int Oflag
= 1; /* format as an 4.3BSD file system */
205 int verbosity
; /* amount of printf() output */
206 #define DEFAULT_VERBOSITY 3 /* 4 is traditional behavior */
207 int64_t fssize
; /* file system size */
208 int sectorsize
; /* bytes/sector */
209 int fsize
= 0; /* fragment size */
210 int bsize
= 0; /* block size */
211 int maxbsize
= 0; /* maximum clustering */
212 int minfree
= MINFREE
; /* free space threshold */
213 int opt
= DEFAULTOPT
; /* optimization preference (space or time) */
214 int density
; /* number of bytes per inode */
215 int num_inodes
; /* number of inodes (overrides density) */
216 int maxcontig
= 0; /* max contiguous blocks to allocate */
217 int maxbpg
; /* maximum blocks per file in a cyl group */
218 int avgfilesize
= AVFILESIZ
;/* expected average file size */
219 int avgfpdir
= AFPDIR
; /* expected number of files per directory */
220 int mntflags
= 0; /* flags to be passed to mount */
221 u_long memleft
; /* virtual memory available */
222 caddr_t membase
; /* start address of memory based filesystem */
223 int needswap
; /* Filesystem not in native byte order */
224 char *disktype
= NULL
;
226 char *appleufs_volname
= 0; /* Apple UFS volume name */
229 char device
[MAXPATHLEN
];
232 main(int argc
, char *argv
[])
234 struct disk_geom geo
;
235 struct dkwedge_info dkw
;
238 int ch
, fsi
, fso
, len
, n
, Fflag
, Iflag
, Zflag
;
239 char *cp
, *s1
, *s2
, *special
;
240 const char *opstring
;
243 struct mfs_args args
;
244 char mountfromname
[100];
245 char mounttoname
[MAXPATHLEN
];
250 mode_t mfsmode
= 01777; /* default mode for a /tmp-type directory */
251 uid_t mfsuid
= 0; /* user root */
252 gid_t mfsgid
= 0; /* group wheel */
257 Fflag
= Iflag
= Zflag
= 0;
259 if (strstr(getprogname(), "mfs")) {
262 /* Undocumented, for ease of testing */
263 if (argv
[1] != NULL
&& !strcmp(argv
[1], "-mfs")) {
271 "NT:V:a:b:d:e:f:g:h:i:m:n:o:p:s:u:" :
272 "B:FINO:S:T:V:Za:b:d:e:f:g:h:i:l:m:n:o:r:s:v:";
273 while ((ch
= getopt(argc
, argv
, opstring
)) != -1)
276 if (strcmp(optarg
, "be") == 0) {
277 #if BYTE_ORDER == LITTLE_ENDIAN
280 } else if (strcmp(optarg
, "le") == 0) {
281 #if BYTE_ORDER == BIG_ENDIAN
296 verbosity
= DEFAULT_VERBOSITY
;
299 Oflag
= strsuftoi64("format", optarg
, 0, 2, NULL
);
302 /* XXX: non-512 byte sectors almost certainly don't work. */
303 sectorsize
= strsuftoi64("sector size",
304 optarg
, 512, 65536, NULL
);
305 if (sectorsize
& (sectorsize
- 1))
306 errx(1, "sector size `%s' is not a power of 2.",
315 verbosity
= strsuftoi64("verbose", optarg
, 0, 4, NULL
);
321 maxcontig
= strsuftoi64("maximum contiguous blocks",
322 optarg
, 1, INT_MAX
, NULL
);
325 bsize
= strsuftoi64("block size",
326 optarg
, MINBSIZE
, MAXBSIZE
, NULL
);
329 maxbsize
= strsuftoi64("maximum extent size",
330 optarg
, 0, INT_MAX
, NULL
);
333 maxbpg
= strsuftoi64(
334 "blocks per file in a cylinder group",
335 optarg
, 1, INT_MAX
, NULL
);
338 fsize
= strsuftoi64("fragment size",
339 optarg
, 1, MAXBSIZE
, NULL
);
343 mfsgid
= mfs_group(optarg
);
345 avgfilesize
= strsuftoi64("average file size",
346 optarg
, 1, INT_MAX
, NULL
);
350 avgfpdir
= strsuftoi64("expected files per directory",
351 optarg
, 1, INT_MAX
, NULL
);
354 density
= strsuftoi64("bytes per inode",
355 optarg
, 1, INT_MAX
, NULL
);
358 minfree
= strsuftoi64("free space %",
359 optarg
, 0, 99, NULL
);
362 num_inodes
= strsuftoi64("number of inodes",
363 optarg
, 1, INT_MAX
, NULL
);
367 mo
= getmntopts(optarg
, mopts
, &mntflags
, 0);
369 err(1, "getmntopts");
372 if (strcmp(optarg
, "space") == 0)
374 else if (strcmp(optarg
, "time") == 0)
378 "unknown optimization preference: ",
379 "use `space' or `time'.");
384 if ((mfsmode
= strtol(optarg
, NULL
, 8)) <= 0)
385 errx(1, "bad mode `%s'", optarg
);
388 fssize
= strsuftoi64("file system size",
389 optarg
, INT64_MIN
, INT64_MAX
, &byte_sized
);
393 mfsuid
= mfs_user(optarg
);
396 appleufs_volname
= optarg
;
397 if (strchr(appleufs_volname
, ':') || strchr(appleufs_volname
, '/'))
398 errx(1,"Apple UFS volume name cannot contain ':' or '/'");
399 if (appleufs_volname
[0] == '\0')
400 errx(1,"Apple UFS volume name cannot be zero length");
411 /* Default to not showing CG info if mfs */
412 verbosity
= mfs
? 0 : DEFAULT_VERBOSITY
;
415 /* This is enough to get through the correct kernel code paths */
416 memset(&args
, 0, sizeof args
);
417 args
.fspec
= mountfromname
;
418 if (mntflags
& (MNT_GETARGS
| MNT_UPDATE
)) {
419 if ((mntflags
& MNT_GETARGS
) == 0)
420 mntflags
|= MNT_ASYNC
;
421 if (mount(MOUNT_MFS
, argv
[1], mntflags
,
422 &args
, sizeof args
) == -1)
423 err(1, "mount `%s' failed", argv
[1]);
424 if (mntflags
& MNT_GETARGS
)
425 printf("base=%p, size=%ld\n", args
.base
, args
.size
);
430 if (argc
!= 2 && (mfs
|| argc
!= 1))
433 memset(&sb
, 0, sizeof sb
);
434 memset(&dkw
, 0, sizeof dkw
);
438 * It's a file system image or an MFS,
439 * no label, use fixed default for sectorsize.
442 sectorsize
= DFL_SECSIZE
;
446 * Default filesystem size to that of supplied device,
447 * and fall back to 8M
450 if (stat(special
, &sb
) == -1)
451 fssize
= DFL_FSSIZE
/ sectorsize
;
453 /* creating image in a regular file */
459 fl
= O_RDWR
| O_CREAT
;
463 fsi
= open(special
, fl
, 0777);
465 err(1, "can't open file %s", special
);
466 if (fstat(fsi
, &sb
) == -1)
467 err(1, "can't fstat opened %s", special
);
471 } else { /* !Fflag && !mfs */
472 fsi
= opendisk(special
, O_RDONLY
, device
, sizeof(device
), 0);
474 if (fsi
< 0 || fstat(fsi
, &sb
) == -1)
475 err(1, "%s: open for read", special
);
476 if (S_ISBLK(sb
.st_mode
)) {
477 errx(1, "%s is a block device. use raw device",
482 fso
= open(special
, O_WRONLY
, 0);
484 err(1, "%s: open for write", special
);
486 /* Bail if target special is mounted */
487 n
= getmntinfo(&mp
, MNT_NOWAIT
);
489 err(1, "%s: getmntinfo", special
);
491 len
= sizeof(_PATH_DEV
) - 1;
493 if (strncmp(_PATH_DEV
, s1
, len
) == 0)
497 s2
= mp
->f_mntfromname
;
498 if (strncmp(_PATH_DEV
, s2
, len
) == 0) {
502 if (strcmp(s1
, s2
) == 0 ||
503 strcmp(s1
, &s2
[1]) == 0)
504 errx(1, "%s is mounted on %s",
505 special
, mp
->f_mntonname
);
511 if (disktype
== NULL
)
514 if (getdiskinfo(special
, fsi
, disktype
, &geo
, &dkw
) == -1)
515 errx(1, lmsg
, special
);
516 unlabeled
= disktype
!= NULL
;
518 if (sectorsize
== 0) {
519 sectorsize
= geo
.dg_secsize
;
521 errx(1, "no default sector size");
524 if (dkw
.dkw_parent
[0]) {
525 if (dkw
.dkw_size
== 0)
526 errx(1, "%s partition is unavailable", special
);
528 if (strcmp(dkw
.dkw_ptype
, DKW_PTYPE_APPLEUFS
) == 0)
532 static const char m
[] =
533 "%s partition type is not `%s'";
535 if (strcmp(dkw
.dkw_ptype
,
538 special
, "Apple UFS");
540 if (strcmp(dkw
.dkw_ptype
,
542 errx(1, m
, special
, "4.2BSD");
545 } /* !Fflag && !mfs */
549 fssize
/= sectorsize
;
552 fssize
+= sb
.st_size
/ sectorsize
;
554 fssize
+= dkw
.dkw_size
;
556 errx(1, "Unable to determine file system size");
559 if (dkw
.dkw_parent
[0] && (uint64_t)fssize
> dkw
.dkw_size
)
560 errx(1, "size %" PRIu64
" exceeds maximum file system size on "
561 "`%s' of %" PRIu64
" sectors",
562 fssize
, special
, dkw
.dkw_size
);
564 /* XXXLUKEM: only ftruncate() regular files ? (dsl: or at all?) */
565 if (Fflag
&& fso
!= -1
566 && ftruncate(fso
, (off_t
)fssize
* sectorsize
) == -1)
567 err(1, "can't ftruncate %s to %" PRId64
, special
, fssize
);
569 if (Zflag
&& fso
!= -1) { /* pre-zero (and de-sparce) the file */
575 if (fstatvfs(fso
, &sfs
) == -1) {
576 warn("can't fstatvfs `%s'", special
);
579 bufsize
= sfs
.f_iosize
;
581 if ((buf
= calloc(1, bufsize
)) == NULL
)
582 err(1, "can't malloc buffer of %d",
584 bufrem
= fssize
* sectorsize
;
586 printf( "Creating file system image in `%s', "
587 "size %lld bytes, in %d byte chunks.\n",
588 special
, (long long)bufrem
, bufsize
);
590 i
= write(fso
, buf
, MIN(bufsize
, bufrem
));
592 err(1, "writing image");
598 /* Sort out fragment and block sizes */
600 fsize
= bsize
/ DFL_FRAG_BLK
;
603 fsize
= APPLEUFS_DFL_FRAGSIZE
;
605 if (fssize
< SMALL_FSSIZE
)
606 fsize
= S_DFL_FRAGSIZE
;
607 else if (fssize
< MEDIUM_FSSIZE
)
608 fsize
= M_DFL_FRAGSIZE
;
610 fsize
= L_DFL_FRAGSIZE
;
611 if (fsize
< sectorsize
)
618 bsize
= APPLEUFS_DFL_BLKSIZE
;
620 bsize
= DFL_FRAG_BLK
* fsize
;
623 if (isappleufs
&& (fsize
< APPLEUFS_DFL_FRAGSIZE
)) {
624 warnx("Warning: chosen fsize of %d is less than Apple UFS minimum of %d",
625 fsize
, APPLEUFS_DFL_FRAGSIZE
);
627 if (isappleufs
&& (bsize
> APPLEUFS_DFL_BLKSIZE
)) {
628 warnx("Warning: chosen bsize of %d is greater than Apple UFS maximum of %d",
629 bsize
, APPLEUFS_DFL_BLKSIZE
);
633 * Maxcontig sets the default for the maximum number of blocks
634 * that may be allocated sequentially. With filesystem clustering
635 * it is possible to allocate contiguous blocks up to the maximum
636 * transfer size permitted by the controller or buffering.
639 maxcontig
= MAX(1, MIN(MAXPHYS
, MAXBSIZE
) / bsize
);
641 density
= NFPI
* fsize
;
642 if (minfree
< MINFREE
&& opt
!= FS_OPTSPACE
) {
643 warnx("%s %s %d%%", "Warning: changing optimization to space",
644 "because minfree is less than", MINFREE
);
649 maxbpg
= MAXBLKPG_UFS1(bsize
);
651 maxbpg
= MAXBLKPG_UFS2(bsize
);
653 mkfs(special
, fsi
, fso
, mfsmode
, mfsuid
, mfsgid
);
654 if (fsi
!= -1 && fsi
!= fso
)
661 pathadj(argv
[1], mounttoname
);
662 switch (pid
= fork()) {
667 (void)snprintf(mountfromname
, sizeof(mountfromname
),
671 (void)snprintf(mountfromname
, sizeof(mountfromname
),
675 * spin until the mount succeeds
681 * XXX Here is a race condition: another process
682 * can mount a filesystem which hides our
683 * ramdisk before we see the success.
685 if (statvfs(mounttoname
, &sf
) < 0)
686 err(88, "statvfs %s", mounttoname
);
687 if (!strcmp(sf
.f_mntfromname
, mountfromname
) &&
688 !strncmp(sf
.f_mntonname
, mounttoname
,
690 !strcmp(sf
.f_fstypename
, "mfs"))
693 res
= waitpid(pid
, &status
, WNOHANG
);
698 if (WIFEXITED(status
)) {
699 if (WEXITSTATUS(status
) == 0)
701 errx(1, "%s: mount: %s", mounttoname
,
702 strerror(WEXITSTATUS(status
)));
704 errx(11, "abnormal termination");
716 args
.size
= fssize
* sectorsize
;
717 if (mount(MOUNT_MFS
, mounttoname
, mntflags
| MNT_ASYNC
,
718 &args
, sizeof args
) == -1)
719 exit(errno
); /* parent prints message */
726 mfs_group(const char *gname
)
730 if (!(gp
= getgrnam(gname
)) && !isdigit((unsigned char)*gname
))
731 errx(1, "unknown gname %s", gname
);
732 return gp
? gp
->gr_gid
: (gid_t
)atoi(gname
);
736 mfs_user(const char *uname
)
740 if (!(pp
= getpwnam(uname
)) && !isdigit((unsigned char)*uname
))
741 errx(1, "unknown user %s", uname
);
742 return pp
? pp
->pw_uid
: (uid_t
)atoi(uname
);
746 strsuftoi64(const char *desc
, const char *arg
, int64_t min
, int64_t max
, int *num_suffix
)
753 r1
= strtoll(arg
, &ep
, 10);
754 if (ep
[0] != '\0' && ep
[1] != '\0')
755 errx(1, "%s `%s' is not a valid number.", desc
, arg
);
759 if (num_suffix
!= NULL
)
775 if (num_suffix
!= NULL
)
779 errx(1, "`%s' is not a valid suffix for %s.", ep
, desc
);
781 result
= r1
<< shift
;
782 if (errno
== ERANGE
|| result
>> shift
!= r1
)
783 errx(1, "%s `%s' is too large to convert.", desc
, arg
);
785 errx(1, "%s `%s' (%" PRId64
") is less than the minimum (%" PRId64
").",
786 desc
, arg
, result
, min
);
788 errx(1, "%s `%s' (%" PRId64
") is greater than the maximum (%" PRId64
").",
789 desc
, arg
, result
, max
);
795 #define BOTH NEWFS | MFS_MOUNT
797 struct help_strings
{
800 } const help_strings
[] = {
801 { NEWFS
, "-B byteorder\tbyte order (`be' or `le')" },
802 { NEWFS
, "-F \t\tcreate file system image in regular file" },
803 { NEWFS
, "-I \t\tdo not check that the file system type is '4.2BSD'" },
804 { BOTH
, "-N \t\tdo not create file system, just print out "
806 { NEWFS
, "-O N\t\tfilesystem format: 0 ==> 4.3BSD, 1 ==> FFSv1, 2 ==> FFSv2" },
807 { NEWFS
, "-S secsize\tsector size" },
809 { NEWFS
, "-T disktype\tdisk type" },
811 { BOTH
, "-V verbose\toutput verbosity: 0 ==> none, 4 ==> max" },
812 { NEWFS
, "-Z \t\tpre-zero the image file" },
813 { BOTH
, "-a maxcontig\tmaximum contiguous blocks" },
814 { BOTH
, "-b bsize\tblock size" },
815 { BOTH
, "-d maxbsize\tmaximum extent size" },
816 { BOTH
, "-e maxbpg\tmaximum blocks per file in a cylinder group"
818 { BOTH
, "-f fsize\tfrag size" },
819 { NEWFS
, "-g avgfilesize\taverage file size" },
820 { MFS_MOUNT
, "-g groupname\tgroup name of mount point" },
821 { BOTH
, "-h avgfpdir\taverage files per directory" },
822 { BOTH
, "-i density\tnumber of bytes per inode" },
823 { BOTH
, "-m minfree\tminimum free space %%" },
824 { BOTH
, "-n inodes\tnumber of inodes (overrides -i density)" },
825 { BOTH
, "-o optim\toptimization preference (`space' or `time')"
827 { MFS_MOUNT
, "-p perm\t\tpermissions (in octal)" },
828 { BOTH
, "-s fssize\tfile system size (sectors)" },
829 { MFS_MOUNT
, "-u username\tuser name of mount point" },
830 { NEWFS
, "-v volname\tApple UFS volume name" },
838 const struct help_strings
*hs
;
842 "usage: %s [ fsoptions ] special-device mount-point\n",
846 "usage: %s [ fsoptions ] special-device%s\n",
853 fprintf(stderr
, "where fsoptions are:\n");
855 match
= mfs
? MFS_MOUNT
: NEWFS
;
856 for (hs
= help_strings
; hs
->flags
!= 0; hs
++)
857 if (hs
->flags
& match
)
858 fprintf(stderr
, "\t%s\n", hs
->str
);