1 1.120 riastrad /* $NetBSD: newfs.c,v 1.120 2023/07/05 10:58:58 riastradh Exp $ */ 2 1.67 agc 3 1.67 agc /* 4 1.67 agc * Copyright (c) 1983, 1989, 1993, 1994 5 1.67 agc * The Regents of the University of California. All rights reserved. 6 1.67 agc * 7 1.67 agc * Redistribution and use in source and binary forms, with or without 8 1.67 agc * modification, are permitted provided that the following conditions 9 1.67 agc * are met: 10 1.67 agc * 1. Redistributions of source code must retain the above copyright 11 1.67 agc * notice, this list of conditions and the following disclaimer. 12 1.67 agc * 2. Redistributions in binary form must reproduce the above copyright 13 1.67 agc * notice, this list of conditions and the following disclaimer in the 14 1.67 agc * documentation and/or other materials provided with the distribution. 15 1.67 agc * 3. Neither the name of the University nor the names of its contributors 16 1.67 agc * may be used to endorse or promote products derived from this software 17 1.67 agc * without specific prior written permission. 18 1.67 agc * 19 1.67 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.67 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.67 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.67 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.67 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.67 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.67 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.67 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.67 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.67 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.67 agc * SUCH DAMAGE. 30 1.67 agc */ 31 1.18 cgd 32 1.1 cgd /* 33 1.64 fvdl * Copyright (c) 2002 Networks Associates Technology, Inc. 34 1.64 fvdl * All rights reserved. 35 1.64 fvdl * 36 1.64 fvdl * This software was developed for the FreeBSD Project by Marshall 37 1.64 fvdl * Kirk McKusick and Network Associates Laboratories, the Security 38 1.64 fvdl * Research Division of Network Associates, Inc. under DARPA/SPAWAR 39 1.64 fvdl * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS 40 1.64 fvdl * research program 41 1.64 fvdl * 42 1.1 cgd * Redistribution and use in source and binary forms, with or without 43 1.1 cgd * modification, are permitted provided that the following conditions 44 1.1 cgd * are met: 45 1.1 cgd * 1. Redistributions of source code must retain the above copyright 46 1.1 cgd * notice, this list of conditions and the following disclaimer. 47 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 48 1.1 cgd * notice, this list of conditions and the following disclaimer in the 49 1.1 cgd * documentation and/or other materials provided with the distribution. 50 1.1 cgd * 3. All advertising materials mentioning features or use of this software 51 1.1 cgd * must display the following acknowledgement: 52 1.1 cgd * This product includes software developed by the University of 53 1.1 cgd * California, Berkeley and its contributors. 54 1.1 cgd * 4. Neither the name of the University nor the names of its contributors 55 1.1 cgd * may be used to endorse or promote products derived from this software 56 1.1 cgd * without specific prior written permission. 57 1.1 cgd * 58 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 1.1 cgd * SUCH DAMAGE. 69 1.1 cgd */ 70 1.1 cgd 71 1.25 christos #include <sys/cdefs.h> 72 1.1 cgd #ifndef lint 73 1.101 lukem __COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1993, 1994\ 74 1.101 lukem The Regents of the University of California. All rights reserved."); 75 1.1 cgd #endif /* not lint */ 76 1.1 cgd 77 1.1 cgd #ifndef lint 78 1.18 cgd #if 0 79 1.27 lukem static char sccsid[] = "@(#)newfs.c 8.13 (Berkeley) 5/1/95"; 80 1.18 cgd #else 81 1.120 riastrad __RCSID("$NetBSD: newfs.c,v 1.120 2023/07/05 10:58:58 riastradh Exp $"); 82 1.18 cgd #endif 83 1.1 cgd #endif /* not lint */ 84 1.1 cgd 85 1.1 cgd /* 86 1.1 cgd * newfs: friendly front end to mkfs 87 1.1 cgd */ 88 1.1 cgd #include <sys/param.h> 89 1.1 cgd #include <sys/ioctl.h> 90 1.1 cgd #include <sys/disklabel.h> 91 1.92 christos #include <sys/disk.h> 92 1.1 cgd #include <sys/file.h> 93 1.1 cgd #include <sys/mount.h> 94 1.19 thorpej #include <sys/sysctl.h> 95 1.30 drochner #include <sys/wait.h> 96 1.1 cgd 97 1.10 mycroft #include <ufs/ufs/dir.h> 98 1.27 lukem #include <ufs/ufs/dinode.h> 99 1.32 fvdl #include <ufs/ufs/ufsmount.h> 100 1.109 bouyer #include <ufs/ufs/quota2.h> 101 1.10 mycroft #include <ufs/ffs/fs.h> 102 1.10 mycroft 103 1.10 mycroft #include <ctype.h> 104 1.37 tron #include <disktab.h> 105 1.54 simonb #include <err.h> 106 1.1 cgd #include <errno.h> 107 1.54 simonb #include <grp.h> 108 1.76 wiz #include <limits.h> 109 1.10 mycroft #include <paths.h> 110 1.54 simonb #include <pwd.h> 111 1.54 simonb #include <signal.h> 112 1.76 wiz #include <stdint.h> 113 1.1 cgd #include <stdio.h> 114 1.10 mycroft #include <stdlib.h> 115 1.1 cgd #include <string.h> 116 1.10 mycroft #include <syslog.h> 117 1.10 mycroft #include <unistd.h> 118 1.20 thorpej #include <util.h> 119 1.95 christos #include <mntopts.h> 120 1.10 mycroft 121 1.106 dsl #ifdef MFS 122 1.106 dsl #include <mountprog.h> 123 1.106 dsl #endif 124 1.106 dsl 125 1.25 christos #include "dkcksum.h" 126 1.25 christos #include "extern.h" 127 1.92 christos #include "partutil.h" 128 1.10 mycroft 129 1.10 mycroft struct mntopt mopts[] = { 130 1.10 mycroft MOPT_STDOPTS, 131 1.10 mycroft MOPT_ASYNC, 132 1.22 cgd MOPT_UPDATE, 133 1.60 christos MOPT_GETARGS, 134 1.23 tls MOPT_NOATIME, 135 1.95 christos { .m_option = NULL }, 136 1.10 mycroft }; 137 1.10 mycroft 138 1.54 simonb static gid_t mfs_group(const char *); 139 1.54 simonb static uid_t mfs_user(const char *); 140 1.75 dsl static int64_t strsuftoi64(const char *, const char *, int64_t, int64_t, int *); 141 1.100 perry static void usage(void) __dead; 142 1.1 cgd 143 1.1 cgd #define COMPAT /* allow non-labeled disks */ 144 1.1 cgd 145 1.92 christos #ifdef COMPAT 146 1.92 christos const char lmsg[] = "%s: can't read disk label; disk type must be specified"; 147 1.92 christos #else 148 1.92 christos const char lmsg[] = "%s: can't read disk label"; 149 1.92 christos #endif 150 1.92 christos 151 1.1 cgd /* 152 1.1 cgd * The following two constants set the default block and fragment sizes. 153 1.1 cgd * Both constants must be a power of 2 and meet the following constraints: 154 1.1 cgd * MINBSIZE <= DESBLKSIZE <= MAXBSIZE 155 1.1 cgd * sectorsize <= DESFRAGSIZE <= DESBLKSIZE 156 1.1 cgd * DESBLKSIZE / DESFRAGSIZE <= 8 157 1.1 cgd */ 158 1.53 augustss /* 159 1.53 augustss * For file systems smaller than SMALL_FSSIZE we use the S_DFL_* defaults, 160 1.111 tsutsui * otherwise if less than MEDIUM_FSSIZE use M_DFL_*, 161 1.111 tsutsui * otherwise if less than LARGE_FSSIZE use L_DFL_*, 162 1.111 tsutsui * otherwise use LL_DFL_* especially for modern AFT disks. 163 1.53 augustss */ 164 1.54 simonb #define SMALL_FSSIZE (20*1024*2) 165 1.53 augustss #define S_DFL_FRAGSIZE 512 166 1.54 simonb #define MEDIUM_FSSIZE (1000*1024*2) 167 1.53 augustss #define M_DFL_FRAGSIZE 1024 168 1.111 tsutsui #define LARGE_FSSIZE (128*1024*1024*2) 169 1.53 augustss #define L_DFL_FRAGSIZE 2048 170 1.111 tsutsui #define LL_DFL_FRAGSIZE 4096 171 1.75 dsl #define DFL_FRAG_BLK 8 172 1.1 cgd 173 1.65 dbj /* Apple requires the fragment size to be at least APPLEUFS_DIRBLKSIZ 174 1.65 dbj * but the block size cannot be larger than Darwin's PAGE_SIZE. See 175 1.65 dbj * the mount check in Darwin's ffs_mountfs for an explanation. 176 1.65 dbj */ 177 1.65 dbj #define APPLEUFS_DFL_FRAGSIZE APPLEUFS_DIRBLKSIZ /* 1024 */ 178 1.65 dbj #define APPLEUFS_DFL_BLKSIZE 4096 /* default Darwin PAGE_SIZE */ 179 1.65 dbj 180 1.1 cgd /* 181 1.43 lukem * Default sector size. 182 1.43 lukem */ 183 1.54 simonb #define DFL_SECSIZE 512 184 1.43 lukem 185 1.43 lukem /* 186 1.96 christos * Default file system size for "mount_mfs swap /dir" case. 187 1.96 christos */ 188 1.96 christos #define DFL_FSSIZE (8 * 1024 * 1024) 189 1.96 christos 190 1.96 christos /* 191 1.1 cgd * MAXBLKPG determines the maximum number of data blocks which are 192 1.1 cgd * placed in a single cylinder group. The default is one indirect 193 1.1 cgd * block worth of data blocks. 194 1.1 cgd */ 195 1.64 fvdl #define MAXBLKPG_UFS1(bsize) ((bsize) / sizeof(int32_t)) 196 1.64 fvdl #define MAXBLKPG_UFS2(bsize) ((bsize) / sizeof(int64_t)) 197 1.1 cgd 198 1.1 cgd /* 199 1.1 cgd * Each file system has a number of inodes statically allocated. 200 1.1 cgd * We allocate one inode slot per NFPI fragments, expecting this 201 1.1 cgd * to be far more than we will ever need. 202 1.1 cgd */ 203 1.1 cgd #define NFPI 4 204 1.1 cgd 205 1.1 cgd 206 1.1 cgd int mfs; /* run as the memory based filesystem */ 207 1.107 pooka int Gflag; /* allow garbage parameters (for testing) */ 208 1.1 cgd int Nflag; /* run without writing file system */ 209 1.64 fvdl int Oflag = 1; /* format as an 4.3BSD file system */ 210 1.118 chs int eaflag; /* use UFS2ea fs_magic */ 211 1.88 dsl int verbosity; /* amount of printf() output */ 212 1.94 christos #define DEFAULT_VERBOSITY 3 /* 4 is traditional behavior */ 213 1.64 fvdl int64_t fssize; /* file system size */ 214 1.1 cgd int sectorsize; /* bytes/sector */ 215 1.1 cgd int fsize = 0; /* fragment size */ 216 1.1 cgd int bsize = 0; /* block size */ 217 1.64 fvdl int maxbsize = 0; /* maximum clustering */ 218 1.1 cgd int minfree = MINFREE; /* free space threshold */ 219 1.1 cgd int opt = DEFAULTOPT; /* optimization preference (space or time) */ 220 1.1 cgd int density; /* number of bytes per inode */ 221 1.84 lukem int num_inodes; /* number of inodes (overrides density) */ 222 1.36 mycroft int maxcontig = 0; /* max contiguous blocks to allocate */ 223 1.1 cgd int maxbpg; /* maximum blocks per file in a cyl group */ 224 1.47 lukem int avgfilesize = AVFILESIZ;/* expected average file size */ 225 1.47 lukem int avgfpdir = AFPDIR; /* expected number of files per directory */ 226 1.91 christos int mntflags = 0; /* flags to be passed to mount */ 227 1.1 cgd u_long memleft; /* virtual memory available */ 228 1.1 cgd caddr_t membase; /* start address of memory based filesystem */ 229 1.115 rin #ifndef NO_FFS_EI 230 1.43 lukem int needswap; /* Filesystem not in native byte order */ 231 1.115 rin #endif 232 1.92 christos char *disktype = NULL; 233 1.1 cgd int unlabeled; 234 1.115 rin #ifndef NO_APPLE_UFS 235 1.61 dbj char *appleufs_volname = 0; /* Apple UFS volume name */ 236 1.61 dbj int isappleufs = 0; 237 1.115 rin #endif 238 1.109 bouyer int quotas = 0; 239 1.1 cgd 240 1.1 cgd char device[MAXPATHLEN]; 241 1.1 cgd 242 1.10 mycroft int 243 1.40 simonb main(int argc, char *argv[]) 244 1.1 cgd { 245 1.92 christos struct disk_geom geo; 246 1.92 christos struct dkwedge_info dkw; 247 1.82 christos struct statvfs *mp; 248 1.75 dsl struct stat sb; 249 1.75 dsl int ch, fsi, fso, len, n, Fflag, Iflag, Zflag; 250 1.112 mlelstv const char *s1, *special, *raw; 251 1.112 mlelstv char *s2; 252 1.112 mlelstv char specname[MAXPATHLEN]; 253 1.112 mlelstv char rawname[MAXPATHLEN]; 254 1.43 lukem const char *opstring; 255 1.75 dsl int byte_sized = 0; 256 1.30 drochner #ifdef MFS 257 1.79 dsl struct mfs_args args; 258 1.30 drochner char mountfromname[100]; 259 1.106 dsl char mounttoname[MAXPATHLEN]; 260 1.30 drochner pid_t pid, res; 261 1.82 christos struct statvfs sf; 262 1.56 lukem int status; 263 1.56 lukem #endif 264 1.75 dsl mode_t mfsmode = 01777; /* default mode for a /tmp-type directory */ 265 1.75 dsl uid_t mfsuid = 0; /* user root */ 266 1.75 dsl gid_t mfsgid = 0; /* group wheel */ 267 1.90 christos mntoptparse_t mo; 268 1.1 cgd 269 1.43 lukem fsi = fso = -1; 270 1.58 lukem Fflag = Iflag = Zflag = 0; 271 1.88 dsl verbosity = -1; 272 1.42 cgd if (strstr(getprogname(), "mfs")) { 273 1.1 cgd mfs = 1; 274 1.80 dsl } else { 275 1.80 dsl /* Undocumented, for ease of testing */ 276 1.81 dsl if (argv[1] != NULL && !strcmp(argv[1], "-mfs")) { 277 1.80 dsl argv++; 278 1.80 dsl argc--; 279 1.80 dsl mfs = 1; 280 1.80 dsl } 281 1.1 cgd } 282 1.1 cgd 283 1.10 mycroft opstring = mfs ? 284 1.109 bouyer "NT:V:a:b:d:e:f:g:h:i:m:n:o:p:q:s:u:" : 285 1.109 bouyer "B:FGINO:S:T:V:Za:b:d:e:f:g:h:i:l:m:n:o:q:r:s:v:"; 286 1.26 lukem while ((ch = getopt(argc, argv, opstring)) != -1) 287 1.10 mycroft switch (ch) { 288 1.115 rin #ifndef NO_FFS_EI 289 1.33 bouyer case 'B': 290 1.33 bouyer if (strcmp(optarg, "be") == 0) { 291 1.115 rin # if BYTE_ORDER == LITTLE_ENDIAN 292 1.33 bouyer needswap = 1; 293 1.115 rin # endif 294 1.33 bouyer } else if (strcmp(optarg, "le") == 0) { 295 1.115 rin # if BYTE_ORDER == BIG_ENDIAN 296 1.33 bouyer needswap = 1; 297 1.115 rin # endif 298 1.33 bouyer } else 299 1.33 bouyer usage(); 300 1.33 bouyer break; 301 1.115 rin #endif 302 1.43 lukem case 'F': 303 1.43 lukem Fflag = 1; 304 1.43 lukem break; 305 1.107 pooka case 'G': 306 1.107 pooka fprintf(stderr, "WARNING: -G may create file systems " 307 1.107 pooka "which cause kernel panics\n"); 308 1.107 pooka Gflag = 1; 309 1.107 pooka break; 310 1.58 lukem case 'I': 311 1.58 lukem Iflag = 1; 312 1.58 lukem break; 313 1.10 mycroft case 'N': 314 1.10 mycroft Nflag = 1; 315 1.88 dsl if (verbosity == -1) 316 1.93 christos verbosity = DEFAULT_VERBOSITY; 317 1.1 cgd break; 318 1.10 mycroft case 'O': 319 1.118 chs if (strcmp(optarg, "2ea") == 0) { 320 1.118 chs eaflag = 1; 321 1.118 chs optarg[1] = 0; 322 1.118 chs } 323 1.75 dsl Oflag = strsuftoi64("format", optarg, 0, 2, NULL); 324 1.1 cgd break; 325 1.1 cgd case 'S': 326 1.89 dsl /* XXX: non-512 byte sectors almost certainly don't work. */ 327 1.75 dsl sectorsize = strsuftoi64("sector size", 328 1.88 dsl optarg, 512, 65536, NULL); 329 1.88 dsl if (sectorsize & (sectorsize - 1)) 330 1.88 dsl errx(1, "sector size `%s' is not a power of 2.", 331 1.88 dsl optarg); 332 1.1 cgd break; 333 1.1 cgd #ifdef COMPAT 334 1.1 cgd case 'T': 335 1.1 cgd disktype = optarg; 336 1.1 cgd break; 337 1.1 cgd #endif 338 1.88 dsl case 'V': 339 1.88 dsl verbosity = strsuftoi64("verbose", optarg, 0, 4, NULL); 340 1.88 dsl break; 341 1.43 lukem case 'Z': 342 1.43 lukem Zflag = 1; 343 1.43 lukem break; 344 1.1 cgd case 'a': 345 1.75 dsl maxcontig = strsuftoi64("maximum contiguous blocks", 346 1.75 dsl optarg, 1, INT_MAX, NULL); 347 1.1 cgd break; 348 1.1 cgd case 'b': 349 1.75 dsl bsize = strsuftoi64("block size", 350 1.75 dsl optarg, MINBSIZE, MAXBSIZE, NULL); 351 1.1 cgd break; 352 1.1 cgd case 'd': 353 1.75 dsl maxbsize = strsuftoi64("maximum extent size", 354 1.75 dsl optarg, 0, INT_MAX, NULL); 355 1.1 cgd break; 356 1.1 cgd case 'e': 357 1.75 dsl maxbpg = strsuftoi64( 358 1.43 lukem "blocks per file in a cylinder group", 359 1.75 dsl optarg, 1, INT_MAX, NULL); 360 1.1 cgd break; 361 1.1 cgd case 'f': 362 1.75 dsl fsize = strsuftoi64("fragment size", 363 1.75 dsl optarg, 1, MAXBSIZE, NULL); 364 1.1 cgd break; 365 1.47 lukem case 'g': 366 1.54 simonb if (mfs) 367 1.54 simonb mfsgid = mfs_group(optarg); 368 1.54 simonb else { 369 1.75 dsl avgfilesize = strsuftoi64("average file size", 370 1.75 dsl optarg, 1, INT_MAX, NULL); 371 1.54 simonb } 372 1.47 lukem break; 373 1.47 lukem case 'h': 374 1.75 dsl avgfpdir = strsuftoi64("expected files per directory", 375 1.75 dsl optarg, 1, INT_MAX, NULL); 376 1.47 lukem break; 377 1.1 cgd case 'i': 378 1.75 dsl density = strsuftoi64("bytes per inode", 379 1.75 dsl optarg, 1, INT_MAX, NULL); 380 1.1 cgd break; 381 1.1 cgd case 'm': 382 1.75 dsl minfree = strsuftoi64("free space %", 383 1.75 dsl optarg, 0, 99, NULL); 384 1.1 cgd break; 385 1.70 dsl case 'n': 386 1.75 dsl num_inodes = strsuftoi64("number of inodes", 387 1.75 dsl optarg, 1, INT_MAX, NULL); 388 1.70 dsl break; 389 1.1 cgd case 'o': 390 1.90 christos if (mfs) { 391 1.90 christos mo = getmntopts(optarg, mopts, &mntflags, 0); 392 1.90 christos if (mo == NULL) 393 1.90 christos err(1, "getmntopts"); 394 1.90 christos freemntopts(mo); 395 1.90 christos } else { 396 1.10 mycroft if (strcmp(optarg, "space") == 0) 397 1.10 mycroft opt = FS_OPTSPACE; 398 1.10 mycroft else if (strcmp(optarg, "time") == 0) 399 1.10 mycroft opt = FS_OPTTIME; 400 1.10 mycroft else 401 1.25 christos errx(1, "%s %s", 402 1.25 christos "unknown optimization preference: ", 403 1.25 christos "use `space' or `time'."); 404 1.10 mycroft } 405 1.1 cgd break; 406 1.109 bouyer case 'q': 407 1.109 bouyer if (strcmp(optarg, "user") == 0) 408 1.109 bouyer quotas |= FS_Q2_DO_TYPE(USRQUOTA); 409 1.109 bouyer else if (strcmp(optarg, "group") == 0) 410 1.109 bouyer quotas |= FS_Q2_DO_TYPE(GRPQUOTA); 411 1.109 bouyer else 412 1.109 bouyer errx(1, "invalid quota type %s", optarg); 413 1.109 bouyer break; 414 1.1 cgd case 'p': 415 1.88 dsl /* mfs only */ 416 1.88 dsl if ((mfsmode = strtol(optarg, NULL, 8)) <= 0) 417 1.88 dsl errx(1, "bad mode `%s'", optarg); 418 1.1 cgd break; 419 1.1 cgd case 's': 420 1.75 dsl fssize = strsuftoi64("file system size", 421 1.75 dsl optarg, INT64_MIN, INT64_MAX, &byte_sized); 422 1.1 cgd break; 423 1.1 cgd case 'u': 424 1.88 dsl /* mfs only */ 425 1.88 dsl mfsuid = mfs_user(optarg); 426 1.1 cgd break; 427 1.115 rin #ifndef NO_APPLE_UFS 428 1.61 dbj case 'v': 429 1.61 dbj appleufs_volname = optarg; 430 1.61 dbj if (strchr(appleufs_volname, ':') || strchr(appleufs_volname, '/')) 431 1.61 dbj errx(1,"Apple UFS volume name cannot contain ':' or '/'"); 432 1.61 dbj if (appleufs_volname[0] == '\0') 433 1.61 dbj errx(1,"Apple UFS volume name cannot be zero length"); 434 1.61 dbj isappleufs = 1; 435 1.61 dbj break; 436 1.115 rin #endif 437 1.1 cgd case '?': 438 1.1 cgd default: 439 1.1 cgd usage(); 440 1.1 cgd } 441 1.1 cgd argc -= optind; 442 1.1 cgd argv += optind; 443 1.79 dsl 444 1.109 bouyer if (Oflag < 1 && quotas != 0) 445 1.109 bouyer errx(1, "in-filesystem quota is incompatible with -O0"); 446 1.109 bouyer 447 1.88 dsl if (verbosity == -1) 448 1.88 dsl /* Default to not showing CG info if mfs */ 449 1.93 christos verbosity = mfs ? 0 : DEFAULT_VERBOSITY; 450 1.88 dsl 451 1.79 dsl #ifdef MFS 452 1.79 dsl /* This is enough to get through the correct kernel code paths */ 453 1.79 dsl memset(&args, 0, sizeof args); 454 1.79 dsl args.fspec = mountfromname; 455 1.81 dsl if (mntflags & (MNT_GETARGS | MNT_UPDATE)) { 456 1.91 christos if ((mntflags & MNT_GETARGS) == 0) 457 1.91 christos mntflags |= MNT_ASYNC; 458 1.99 pooka if (mount(MOUNT_MFS, argv[1], mntflags, 459 1.99 pooka &args, sizeof args) == -1) 460 1.81 dsl err(1, "mount `%s' failed", argv[1]); 461 1.81 dsl if (mntflags & MNT_GETARGS) 462 1.81 dsl printf("base=%p, size=%ld\n", args.base, args.size); 463 1.81 dsl exit(0); 464 1.81 dsl } 465 1.79 dsl #endif 466 1.1 cgd 467 1.1 cgd if (argc != 2 && (mfs || argc != 1)) 468 1.1 cgd usage(); 469 1.1 cgd 470 1.75 dsl memset(&sb, 0, sizeof sb); 471 1.97 christos memset(&dkw, 0, sizeof dkw); 472 1.1 cgd special = argv[0]; 473 1.49 lukem if (Fflag || mfs) { 474 1.14 cgd /* 475 1.75 dsl * It's a file system image or an MFS, 476 1.75 dsl * no label, use fixed default for sectorsize. 477 1.14 cgd */ 478 1.75 dsl if (sectorsize == 0) 479 1.43 lukem sectorsize = DFL_SECSIZE; 480 1.43 lukem 481 1.80 dsl if (mfs) { 482 1.96 christos /* 483 1.96 christos * Default filesystem size to that of supplied device, 484 1.96 christos * and fall back to 8M 485 1.96 christos */ 486 1.80 dsl if (fssize == 0) 487 1.96 christos if (stat(special, &sb) == -1) 488 1.96 christos fssize = DFL_FSSIZE / sectorsize; 489 1.80 dsl } else { 490 1.80 dsl /* creating image in a regular file */ 491 1.75 dsl int fl; 492 1.75 dsl if (Nflag) 493 1.75 dsl fl = O_RDONLY; 494 1.75 dsl else { 495 1.75 dsl if (fssize > 0) 496 1.75 dsl fl = O_RDWR | O_CREAT; 497 1.75 dsl else 498 1.75 dsl fl = O_RDWR; 499 1.75 dsl } 500 1.75 dsl fsi = open(special, fl, 0777); 501 1.75 dsl if (fsi == -1) 502 1.43 lukem err(1, "can't open file %s", special); 503 1.75 dsl if (fstat(fsi, &sb) == -1) 504 1.75 dsl err(1, "can't fstat opened %s", special); 505 1.75 dsl if (!Nflag) 506 1.75 dsl fso = fsi; 507 1.43 lukem } 508 1.49 lukem } else { /* !Fflag && !mfs */ 509 1.113 mlelstv raw = getfsspecname(specname, sizeof(specname), special); 510 1.113 mlelstv if (raw == NULL) 511 1.113 mlelstv err(1, "%s: %s", special, specname); 512 1.113 mlelstv special = getdiskrawname(rawname, sizeof(rawname), raw); 513 1.113 mlelstv if (special == NULL) 514 1.112 mlelstv special = raw; 515 1.112 mlelstv 516 1.49 lukem fsi = opendisk(special, O_RDONLY, device, sizeof(device), 0); 517 1.49 lukem special = device; 518 1.75 dsl if (fsi < 0 || fstat(fsi, &sb) == -1) 519 1.49 lukem err(1, "%s: open for read", special); 520 1.103 pooka if (S_ISBLK(sb.st_mode)) { 521 1.103 pooka errx(1, "%s is a block device. use raw device", 522 1.103 pooka special); 523 1.103 pooka } 524 1.49 lukem 525 1.75 dsl if (!Nflag) { 526 1.75 dsl fso = open(special, O_WRONLY, 0); 527 1.49 lukem if (fso < 0) 528 1.49 lukem err(1, "%s: open for write", special); 529 1.49 lukem 530 1.49 lukem /* Bail if target special is mounted */ 531 1.49 lukem n = getmntinfo(&mp, MNT_NOWAIT); 532 1.49 lukem if (n == 0) 533 1.49 lukem err(1, "%s: getmntinfo", special); 534 1.49 lukem 535 1.49 lukem len = sizeof(_PATH_DEV) - 1; 536 1.49 lukem s1 = special; 537 1.49 lukem if (strncmp(_PATH_DEV, s1, len) == 0) 538 1.49 lukem s1 += len; 539 1.49 lukem 540 1.49 lukem while (--n >= 0) { 541 1.49 lukem s2 = mp->f_mntfromname; 542 1.49 lukem if (strncmp(_PATH_DEV, s2, len) == 0) { 543 1.49 lukem s2 += len - 1; 544 1.49 lukem *s2 = 'r'; 545 1.49 lukem } 546 1.49 lukem if (strcmp(s1, s2) == 0 || 547 1.49 lukem strcmp(s1, &s2[1]) == 0) 548 1.49 lukem errx(1, "%s is mounted on %s", 549 1.49 lukem special, mp->f_mntonname); 550 1.49 lukem ++mp; 551 1.10 mycroft } 552 1.10 mycroft } 553 1.75 dsl 554 1.1 cgd #ifdef COMPAT 555 1.49 lukem if (disktype == NULL) 556 1.10 mycroft disktype = argv[1]; 557 1.1 cgd #endif 558 1.92 christos if (getdiskinfo(special, fsi, disktype, &geo, &dkw) == -1) 559 1.92 christos errx(1, lmsg, special); 560 1.92 christos unlabeled = disktype != NULL; 561 1.92 christos 562 1.75 dsl if (sectorsize == 0) { 563 1.92 christos sectorsize = geo.dg_secsize; 564 1.75 dsl if (sectorsize <= 0) 565 1.75 dsl errx(1, "no default sector size"); 566 1.75 dsl } 567 1.75 dsl 568 1.92 christos if (dkw.dkw_parent[0]) { 569 1.92 christos if (dkw.dkw_size == 0) 570 1.92 christos errx(1, "%s partition is unavailable", special); 571 1.92 christos 572 1.115 rin #ifndef NO_APPLE_UFS 573 1.92 christos if (strcmp(dkw.dkw_ptype, DKW_PTYPE_APPLEUFS) == 0) 574 1.75 dsl isappleufs = 1; 575 1.115 rin #endif 576 1.92 christos 577 1.75 dsl if (!Iflag) { 578 1.92 christos static const char m[] = 579 1.92 christos "%s partition type is not `%s'"; 580 1.75 dsl if (isappleufs) { 581 1.92 christos if (strcmp(dkw.dkw_ptype, 582 1.92 christos DKW_PTYPE_APPLEUFS)) 583 1.92 christos errx(1, m, 584 1.92 christos special, "Apple UFS"); 585 1.75 dsl } else { 586 1.92 christos if (strcmp(dkw.dkw_ptype, 587 1.92 christos DKW_PTYPE_FFS)) 588 1.92 christos errx(1, m, special, "4.2BSD"); 589 1.75 dsl } 590 1.75 dsl } 591 1.92 christos } /* !Fflag && !mfs */ 592 1.92 christos } 593 1.43 lukem 594 1.75 dsl if (byte_sized) 595 1.75 dsl fssize /= sectorsize; 596 1.75 dsl if (fssize <= 0) { 597 1.75 dsl if (sb.st_size != 0) 598 1.75 dsl fssize += sb.st_size / sectorsize; 599 1.75 dsl else 600 1.92 christos fssize += dkw.dkw_size; 601 1.75 dsl if (fssize <= 0) 602 1.75 dsl errx(1, "Unable to determine file system size"); 603 1.75 dsl } 604 1.75 dsl 605 1.104 lukem if (dkw.dkw_parent[0] && (uint64_t)fssize > dkw.dkw_size) 606 1.87 dsl errx(1, "size %" PRIu64 " exceeds maximum file system size on " 607 1.92 christos "`%s' of %" PRIu64 " sectors", 608 1.92 christos fssize, special, dkw.dkw_size); 609 1.75 dsl 610 1.75 dsl /* XXXLUKEM: only ftruncate() regular files ? (dsl: or at all?) */ 611 1.75 dsl if (Fflag && fso != -1 612 1.75 dsl && ftruncate(fso, (off_t)fssize * sectorsize) == -1) 613 1.75 dsl err(1, "can't ftruncate %s to %" PRId64, special, fssize); 614 1.75 dsl 615 1.117 andvar if (Zflag && fso != -1) { /* pre-zero (and de-sparse) the file */ 616 1.75 dsl char *buf; 617 1.75 dsl int bufsize, i; 618 1.75 dsl off_t bufrem; 619 1.82 christos struct statvfs sfs; 620 1.75 dsl 621 1.82 christos if (fstatvfs(fso, &sfs) == -1) { 622 1.82 christos warn("can't fstatvfs `%s'", special); 623 1.75 dsl bufsize = 8192; 624 1.75 dsl } else 625 1.75 dsl bufsize = sfs.f_iosize; 626 1.75 dsl 627 1.120 riastrad if ((buf = aligned_alloc(DEV_BSIZE, bufsize)) == NULL) 628 1.75 dsl err(1, "can't malloc buffer of %d", 629 1.75 dsl bufsize); 630 1.116 jdolecek memset(buf, 0, bufsize); 631 1.75 dsl bufrem = fssize * sectorsize; 632 1.88 dsl if (verbosity > 0) 633 1.88 dsl printf( "Creating file system image in `%s', " 634 1.88 dsl "size %lld bytes, in %d byte chunks.\n", 635 1.88 dsl special, (long long)bufrem, bufsize); 636 1.75 dsl while (bufrem > 0) { 637 1.75 dsl i = write(fso, buf, MIN(bufsize, bufrem)); 638 1.75 dsl if (i == -1) 639 1.75 dsl err(1, "writing image"); 640 1.75 dsl bufrem -= i; 641 1.75 dsl } 642 1.75 dsl free(buf); 643 1.53 augustss } 644 1.53 augustss 645 1.75 dsl /* Sort out fragment and block sizes */ 646 1.1 cgd if (fsize == 0) { 647 1.75 dsl fsize = bsize / DFL_FRAG_BLK; 648 1.75 dsl if (fsize <= 0) { 649 1.75 dsl if (isappleufs) { 650 1.75 dsl fsize = APPLEUFS_DFL_FRAGSIZE; 651 1.75 dsl } else { 652 1.75 dsl if (fssize < SMALL_FSSIZE) 653 1.75 dsl fsize = S_DFL_FRAGSIZE; 654 1.75 dsl else if (fssize < MEDIUM_FSSIZE) 655 1.75 dsl fsize = M_DFL_FRAGSIZE; 656 1.111 tsutsui else if (fssize < LARGE_FSSIZE) 657 1.111 tsutsui fsize = L_DFL_FRAGSIZE; 658 1.75 dsl else 659 1.111 tsutsui fsize = LL_DFL_FRAGSIZE; 660 1.75 dsl if (fsize < sectorsize) 661 1.75 dsl fsize = sectorsize; 662 1.75 dsl } 663 1.75 dsl } 664 1.1 cgd } 665 1.92 christos if (bsize <= 0) { 666 1.92 christos if (isappleufs) 667 1.92 christos bsize = APPLEUFS_DFL_BLKSIZE; 668 1.92 christos else 669 1.92 christos bsize = DFL_FRAG_BLK * fsize; 670 1.1 cgd } 671 1.65 dbj 672 1.65 dbj if (isappleufs && (fsize < APPLEUFS_DFL_FRAGSIZE)) { 673 1.65 dbj warnx("Warning: chosen fsize of %d is less than Apple UFS minimum of %d", 674 1.75 dsl fsize, APPLEUFS_DFL_FRAGSIZE); 675 1.65 dbj } 676 1.65 dbj if (isappleufs && (bsize > APPLEUFS_DFL_BLKSIZE)) { 677 1.65 dbj warnx("Warning: chosen bsize of %d is greater than Apple UFS maximum of %d", 678 1.75 dsl bsize, APPLEUFS_DFL_BLKSIZE); 679 1.65 dbj } 680 1.65 dbj 681 1.10 mycroft /* 682 1.10 mycroft * Maxcontig sets the default for the maximum number of blocks 683 1.10 mycroft * that may be allocated sequentially. With filesystem clustering 684 1.10 mycroft * it is possible to allocate contiguous blocks up to the maximum 685 1.10 mycroft * transfer size permitted by the controller or buffering. 686 1.10 mycroft */ 687 1.10 mycroft if (maxcontig == 0) 688 1.27 lukem maxcontig = MAX(1, MIN(MAXPHYS, MAXBSIZE) / bsize); 689 1.1 cgd if (density == 0) 690 1.1 cgd density = NFPI * fsize; 691 1.8 cgd if (minfree < MINFREE && opt != FS_OPTSPACE) { 692 1.25 christos warnx("%s %s %d%%", "Warning: changing optimization to space", 693 1.25 christos "because minfree is less than", MINFREE); 694 1.1 cgd opt = FS_OPTSPACE; 695 1.1 cgd } 696 1.64 fvdl if (maxbpg == 0) { 697 1.64 fvdl if (Oflag <= 1) 698 1.64 fvdl maxbpg = MAXBLKPG_UFS1(bsize); 699 1.64 fvdl else 700 1.64 fvdl maxbpg = MAXBLKPG_UFS2(bsize); 701 1.64 fvdl } 702 1.92 christos mkfs(special, fsi, fso, mfsmode, mfsuid, mfsgid); 703 1.75 dsl if (fsi != -1 && fsi != fso) 704 1.75 dsl close(fsi); 705 1.75 dsl if (fso != -1) 706 1.1 cgd close(fso); 707 1.1 cgd #ifdef MFS 708 1.1 cgd if (mfs) { 709 1.1 cgd 710 1.106 dsl pathadj(argv[1], mounttoname); 711 1.30 drochner switch (pid = fork()) { 712 1.30 drochner case -1: 713 1.30 drochner perror("mfs"); 714 1.30 drochner exit(10); 715 1.30 drochner case 0: 716 1.34 mycroft (void)snprintf(mountfromname, sizeof(mountfromname), 717 1.34 mycroft "mfs:%d", getpid()); 718 1.30 drochner break; 719 1.30 drochner default: 720 1.34 mycroft (void)snprintf(mountfromname, sizeof(mountfromname), 721 1.34 mycroft "mfs:%d", pid); 722 1.30 drochner for (;;) { 723 1.30 drochner /* 724 1.30 drochner * spin until the mount succeeds 725 1.30 drochner * or the child exits 726 1.30 drochner */ 727 1.30 drochner usleep(1); 728 1.30 drochner 729 1.30 drochner /* 730 1.30 drochner * XXX Here is a race condition: another process 731 1.30 drochner * can mount a filesystem which hides our 732 1.30 drochner * ramdisk before we see the success. 733 1.30 drochner */ 734 1.106 dsl if (statvfs(mounttoname, &sf) < 0) 735 1.106 dsl err(88, "statvfs %s", mounttoname); 736 1.30 drochner if (!strcmp(sf.f_mntfromname, mountfromname) && 737 1.106 dsl !strncmp(sf.f_mntonname, mounttoname, 738 1.30 drochner MNAMELEN) && 739 1.30 drochner !strcmp(sf.f_fstypename, "mfs")) 740 1.30 drochner exit(0); 741 1.30 drochner 742 1.30 drochner res = waitpid(pid, &status, WNOHANG); 743 1.30 drochner if (res == -1) 744 1.30 drochner err(11, "waitpid"); 745 1.30 drochner if (res != pid) 746 1.30 drochner continue; 747 1.31 drochner if (WIFEXITED(status)) { 748 1.31 drochner if (WEXITSTATUS(status) == 0) 749 1.31 drochner exit(0); 750 1.106 dsl errx(1, "%s: mount: %s", mounttoname, 751 1.30 drochner strerror(WEXITSTATUS(status))); 752 1.31 drochner } else 753 1.30 drochner errx(11, "abnormal termination"); 754 1.30 drochner } 755 1.30 drochner /* NOTREACHED */ 756 1.30 drochner } 757 1.30 drochner 758 1.30 drochner (void) setsid(); 759 1.30 drochner (void) close(0); 760 1.30 drochner (void) close(1); 761 1.30 drochner (void) close(2); 762 1.30 drochner (void) chdir("/"); 763 1.30 drochner 764 1.1 cgd args.base = membase; 765 1.1 cgd args.size = fssize * sectorsize; 766 1.106 dsl if (mount(MOUNT_MFS, mounttoname, mntflags | MNT_ASYNC, 767 1.99 pooka &args, sizeof args) == -1) 768 1.30 drochner exit(errno); /* parent prints message */ 769 1.1 cgd } 770 1.1 cgd #endif 771 1.1 cgd exit(0); 772 1.1 cgd } 773 1.1 cgd 774 1.54 simonb static gid_t 775 1.54 simonb mfs_group(const char *gname) 776 1.54 simonb { 777 1.54 simonb struct group *gp; 778 1.54 simonb 779 1.54 simonb if (!(gp = getgrnam(gname)) && !isdigit((unsigned char)*gname)) 780 1.54 simonb errx(1, "unknown gname %s", gname); 781 1.104 lukem return gp ? gp->gr_gid : (gid_t)atoi(gname); 782 1.54 simonb } 783 1.54 simonb 784 1.54 simonb static uid_t 785 1.54 simonb mfs_user(const char *uname) 786 1.54 simonb { 787 1.54 simonb struct passwd *pp; 788 1.54 simonb 789 1.54 simonb if (!(pp = getpwnam(uname)) && !isdigit((unsigned char)*uname)) 790 1.54 simonb errx(1, "unknown user %s", uname); 791 1.104 lukem return pp ? pp->pw_uid : (uid_t)atoi(uname); 792 1.54 simonb } 793 1.54 simonb 794 1.75 dsl static int64_t 795 1.75 dsl strsuftoi64(const char *desc, const char *arg, int64_t min, int64_t max, int *num_suffix) 796 1.43 lukem { 797 1.75 dsl int64_t result, r1; 798 1.75 dsl int shift = 0; 799 1.43 lukem char *ep; 800 1.43 lukem 801 1.43 lukem errno = 0; 802 1.75 dsl r1 = strtoll(arg, &ep, 10); 803 1.43 lukem if (ep[0] != '\0' && ep[1] != '\0') 804 1.43 lukem errx(1, "%s `%s' is not a valid number.", desc, arg); 805 1.75 dsl switch (ep[0]) { 806 1.43 lukem case '\0': 807 1.75 dsl case 's': case 'S': 808 1.75 dsl if (num_suffix != NULL) 809 1.75 dsl *num_suffix = 0; 810 1.43 lukem break; 811 1.102 simonb case 't': case 'T': 812 1.102 simonb shift += 10; 813 1.102 simonb /* FALLTHROUGH */ 814 1.75 dsl case 'g': case 'G': 815 1.75 dsl shift += 10; 816 1.75 dsl /* FALLTHROUGH */ 817 1.75 dsl case 'm': case 'M': 818 1.75 dsl shift += 10; 819 1.75 dsl /* FALLTHROUGH */ 820 1.75 dsl case 'k': case 'K': 821 1.75 dsl shift += 10; 822 1.75 dsl /* FALLTHROUGH */ 823 1.75 dsl case 'b': case 'B': 824 1.75 dsl if (num_suffix != NULL) 825 1.75 dsl *num_suffix = 1; 826 1.43 lukem break; 827 1.43 lukem default: 828 1.43 lukem errx(1, "`%s' is not a valid suffix for %s.", ep, desc); 829 1.43 lukem } 830 1.75 dsl result = r1 << shift; 831 1.75 dsl if (errno == ERANGE || result >> shift != r1) 832 1.75 dsl errx(1, "%s `%s' is too large to convert.", desc, arg); 833 1.107 pooka if (result < min) { 834 1.107 pooka if (Gflag) { 835 1.107 pooka warnx("%s `%s' (%" PRId64 ") is less than the " 836 1.107 pooka "minimum (%" PRId64 ").", desc, arg, result, min); 837 1.107 pooka } else { 838 1.107 pooka errx(1, "%s `%s' (%" PRId64 ") is less than the " 839 1.107 pooka "minimum (%" PRId64 ").", desc, arg, result, min); 840 1.107 pooka } 841 1.107 pooka } 842 1.107 pooka if (result > max) { 843 1.107 pooka if (Gflag) { 844 1.107 pooka warnx("%s `%s' (%" PRId64 ") is greater than the " 845 1.107 pooka "maximum (%" PRId64 ").", desc, arg, result, max); 846 1.107 pooka } else { 847 1.107 pooka errx(1, "%s `%s' (%" PRId64 ") is greater than the " 848 1.107 pooka "maximum (%" PRId64 ").", desc, arg, result, max); 849 1.107 pooka } 850 1.107 pooka } 851 1.75 dsl return result; 852 1.43 lukem } 853 1.43 lukem 854 1.54 simonb #define NEWFS 1 855 1.54 simonb #define MFS_MOUNT 2 856 1.54 simonb #define BOTH NEWFS | MFS_MOUNT 857 1.54 simonb 858 1.54 simonb struct help_strings { 859 1.54 simonb int flags; 860 1.54 simonb const char *str; 861 1.54 simonb } const help_strings[] = { 862 1.115 rin #ifndef NO_FFS_EI 863 1.54 simonb { NEWFS, "-B byteorder\tbyte order (`be' or `le')" }, 864 1.115 rin #endif 865 1.54 simonb { NEWFS, "-F \t\tcreate file system image in regular file" }, 866 1.108 pooka { NEWFS, "-G \t\tmake sanity calculations non-fatal (testing only!)" }, 867 1.58 lukem { NEWFS, "-I \t\tdo not check that the file system type is '4.2BSD'" }, 868 1.54 simonb { BOTH, "-N \t\tdo not create file system, just print out " 869 1.54 simonb "parameters" }, 870 1.118 chs { NEWFS, "-O N\t\tfilesystem format: 0 => 4.3BSD, 1 => FFSv1, 2 => FFSv2, 2ea => FFSv2 with extattrs" }, 871 1.54 simonb { NEWFS, "-S secsize\tsector size" }, 872 1.54 simonb #ifdef COMPAT 873 1.54 simonb { NEWFS, "-T disktype\tdisk type" }, 874 1.54 simonb #endif 875 1.89 dsl { BOTH, "-V verbose\toutput verbosity: 0 ==> none, 4 ==> max" }, 876 1.75 dsl { NEWFS, "-Z \t\tpre-zero the image file" }, 877 1.54 simonb { BOTH, "-a maxcontig\tmaximum contiguous blocks" }, 878 1.54 simonb { BOTH, "-b bsize\tblock size" }, 879 1.75 dsl { BOTH, "-d maxbsize\tmaximum extent size" }, 880 1.54 simonb { BOTH, "-e maxbpg\tmaximum blocks per file in a cylinder group" 881 1.54 simonb }, 882 1.54 simonb { BOTH, "-f fsize\tfrag size" }, 883 1.54 simonb { NEWFS, "-g avgfilesize\taverage file size" }, 884 1.54 simonb { MFS_MOUNT, "-g groupname\tgroup name of mount point" }, 885 1.54 simonb { BOTH, "-h avgfpdir\taverage files per directory" }, 886 1.54 simonb { BOTH, "-i density\tnumber of bytes per inode" }, 887 1.114 ryo { BOTH, "-m minfree\tminimum free space %" }, 888 1.78 jmmv { BOTH, "-n inodes\tnumber of inodes (overrides -i density)" }, 889 1.54 simonb { BOTH, "-o optim\toptimization preference (`space' or `time')" 890 1.54 simonb }, 891 1.109 bouyer { BOTH, "-q (user|group) enable specified quota" }, 892 1.54 simonb { MFS_MOUNT, "-p perm\t\tpermissions (in octal)" }, 893 1.54 simonb { BOTH, "-s fssize\tfile system size (sectors)" }, 894 1.54 simonb { MFS_MOUNT, "-u username\tuser name of mount point" }, 895 1.115 rin #ifndef NO_APPLE_UFS 896 1.61 dbj { NEWFS, "-v volname\tApple UFS volume name" }, 897 1.115 rin #endif 898 1.54 simonb { 0, NULL } 899 1.54 simonb }; 900 1.54 simonb 901 1.25 christos static void 902 1.40 simonb usage(void) 903 1.1 cgd { 904 1.54 simonb int match; 905 1.54 simonb const struct help_strings *hs; 906 1.43 lukem 907 1.1 cgd if (mfs) { 908 1.1 cgd fprintf(stderr, 909 1.43 lukem "usage: %s [ fsoptions ] special-device mount-point\n", 910 1.42 cgd getprogname()); 911 1.1 cgd } else 912 1.1 cgd fprintf(stderr, 913 1.43 lukem "usage: %s [ fsoptions ] special-device%s\n", 914 1.42 cgd getprogname(), 915 1.1 cgd #ifdef COMPAT 916 1.75 dsl " [disk-type]"); 917 1.1 cgd #else 918 1.1 cgd ""); 919 1.1 cgd #endif 920 1.1 cgd fprintf(stderr, "where fsoptions are:\n"); 921 1.54 simonb 922 1.54 simonb match = mfs ? MFS_MOUNT : NEWFS; 923 1.54 simonb for (hs = help_strings; hs->flags != 0; hs++) 924 1.54 simonb if (hs->flags & match) 925 1.54 simonb fprintf(stderr, "\t%s\n", hs->str); 926 1.1 cgd exit(1); 927 1.1 cgd } 928