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