Sat Jul 25 10:37:22 2015 UTC ()
Handle getfsspecname errors.


(mlelstv)
diff -r1.112 -r1.113 src/sbin/newfs/newfs.c
diff -r1.38 -r1.39 src/usr.sbin/installboot/installboot.c

cvs diff -r1.112 -r1.113 src/sbin/newfs/newfs.c (switch to unified diff)

--- src/sbin/newfs/newfs.c 2014/10/25 16:47:23 1.112
+++ src/sbin/newfs/newfs.c 2015/07/25 10:37:22 1.113
@@ -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
79static char sccsid[] = "@(#)newfs.c 8.13 (Berkeley) 5/1/95"; 79static 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
129struct mntopt mopts[] = { 129struct 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
138static gid_t mfs_group(const char *); 138static gid_t mfs_group(const char *);
139static uid_t mfs_user(const char *); 139static uid_t mfs_user(const char *);
140static int64_t strsuftoi64(const char *, const char *, int64_t, int64_t, int *); 140static int64_t strsuftoi64(const char *, const char *, int64_t, int64_t, int *);
141static void usage(void) __dead; 141static 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
146const char lmsg[] = "%s: can't read disk label; disk type must be specified"; 146const char lmsg[] = "%s: can't read disk label; disk type must be specified";
147#else 147#else
148const char lmsg[] = "%s: can't read disk label"; 148const 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
206int mfs; /* run as the memory based filesystem */ 206int mfs; /* run as the memory based filesystem */
207int Gflag; /* allow garbage parameters (for testing) */ 207int Gflag; /* allow garbage parameters (for testing) */
208int Nflag; /* run without writing file system */ 208int Nflag; /* run without writing file system */
209int Oflag = 1; /* format as an 4.3BSD file system */ 209int Oflag = 1; /* format as an 4.3BSD file system */
210int verbosity; /* amount of printf() output */ 210int verbosity; /* amount of printf() output */
211#define DEFAULT_VERBOSITY 3 /* 4 is traditional behavior */ 211#define DEFAULT_VERBOSITY 3 /* 4 is traditional behavior */
212int64_t fssize; /* file system size */ 212int64_t fssize; /* file system size */
213int sectorsize; /* bytes/sector */ 213int sectorsize; /* bytes/sector */
214int fsize = 0; /* fragment size */ 214int fsize = 0; /* fragment size */
215int bsize = 0; /* block size */ 215int bsize = 0; /* block size */
216int maxbsize = 0; /* maximum clustering */ 216int maxbsize = 0; /* maximum clustering */
217int minfree = MINFREE; /* free space threshold */ 217int minfree = MINFREE; /* free space threshold */
218int opt = DEFAULTOPT; /* optimization preference (space or time) */ 218int opt = DEFAULTOPT; /* optimization preference (space or time) */
219int density; /* number of bytes per inode */ 219int density; /* number of bytes per inode */
220int num_inodes; /* number of inodes (overrides density) */ 220int num_inodes; /* number of inodes (overrides density) */
221int maxcontig = 0; /* max contiguous blocks to allocate */ 221int maxcontig = 0; /* max contiguous blocks to allocate */
222int maxbpg; /* maximum blocks per file in a cyl group */ 222int maxbpg; /* maximum blocks per file in a cyl group */
223int avgfilesize = AVFILESIZ;/* expected average file size */ 223int avgfilesize = AVFILESIZ;/* expected average file size */
224int avgfpdir = AFPDIR; /* expected number of files per directory */ 224int avgfpdir = AFPDIR; /* expected number of files per directory */
225int mntflags = 0; /* flags to be passed to mount */ 225int mntflags = 0; /* flags to be passed to mount */
226u_long memleft; /* virtual memory available */ 226u_long memleft; /* virtual memory available */
227caddr_t membase; /* start address of memory based filesystem */ 227caddr_t membase; /* start address of memory based filesystem */
228int needswap; /* Filesystem not in native byte order */ 228int needswap; /* Filesystem not in native byte order */
229char *disktype = NULL; 229char *disktype = NULL;
230int unlabeled; 230int unlabeled;
231char *appleufs_volname = 0; /* Apple UFS volume name */ 231char *appleufs_volname = 0; /* Apple UFS volume name */
232int isappleufs = 0; 232int isappleufs = 0;
233int quotas = 0; 233int quotas = 0;
234 234
235char device[MAXPATHLEN]; 235char device[MAXPATHLEN];
236 236
237int 237int
238main(int argc, char *argv[]) 238main(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
756static gid_t 758static gid_t
757mfs_group(const char *gname) 759mfs_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
766static uid_t 768static uid_t
767mfs_user(const char *uname) 769mfs_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
776static int64_t 778static int64_t
777strsuftoi64(const char *desc, const char *arg, int64_t min, int64_t max, int *num_suffix) 779strsuftoi64(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
840struct help_strings { 842struct 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
879static void 881static void
880usage(void) 882usage(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}

cvs diff -r1.38 -r1.39 src/usr.sbin/installboot/installboot.c (switch to unified diff)

--- src/usr.sbin/installboot/installboot.c 2015/06/05 07:44:39 1.38
+++ src/usr.sbin/installboot/installboot.c 2015/07/25 10:37:22 1.39
@@ -1,587 +1,589 @@ @@ -1,587 +1,589 @@
1/* $NetBSD: installboot.c,v 1.38 2015/06/05 07:44:39 mlelstv Exp $ */ 1/* $NetBSD: installboot.c,v 1.39 2015/07/25 10:37:22 mlelstv Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Luke Mewburn of Wasabi Systems. 8 * by Luke Mewburn of Wasabi Systems.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#if HAVE_NBTOOL_CONFIG_H 32#if HAVE_NBTOOL_CONFIG_H
33#include "nbtool_config.h" 33#include "nbtool_config.h"
34#endif 34#endif
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37#if !defined(__lint) 37#if !defined(__lint)
38__RCSID("$NetBSD: installboot.c,v 1.38 2015/06/05 07:44:39 mlelstv Exp $"); 38__RCSID("$NetBSD: installboot.c,v 1.39 2015/07/25 10:37:22 mlelstv Exp $");
39#endif /* !__lint */ 39#endif /* !__lint */
40 40
41#include <sys/param.h> 41#include <sys/param.h>
42#include <sys/ioctl.h> 42#include <sys/ioctl.h>
43#include <sys/utsname.h> 43#include <sys/utsname.h>
44 44
45#include <assert.h> 45#include <assert.h>
46#include <err.h> 46#include <err.h>
47#include <fcntl.h> 47#include <fcntl.h>
48#include <limits.h> 48#include <limits.h>
49#include <stdio.h> 49#include <stdio.h>
50#include <stdlib.h> 50#include <stdlib.h>
51#include <stddef.h> 51#include <stddef.h>
52#include <string.h> 52#include <string.h>
53#include <unistd.h> 53#include <unistd.h>
54#if !HAVE_NBTOOL_CONFIG_H 54#if !HAVE_NBTOOL_CONFIG_H
55#include <util.h> 55#include <util.h>
56#endif 56#endif
57 57
58#include "installboot.h" 58#include "installboot.h"
59 59
60static void getmachine(ib_params *, const char *, const char *); 60static void getmachine(ib_params *, const char *, const char *);
61static void getfstype(ib_params *, const char *, const char *); 61static void getfstype(ib_params *, const char *, const char *);
62static void parseoptions(ib_params *, const char *); 62static void parseoptions(ib_params *, const char *);
63__dead static void usage(void); 63__dead static void usage(void);
64static void options_usage(void); 64static void options_usage(void);
65static void machine_usage(void); 65static void machine_usage(void);
66static void fstype_usage(void); 66static void fstype_usage(void);
67 67
68static ib_params installboot_params; 68static ib_params installboot_params;
69 69
70#define OFFSET(field) offsetof(ib_params, field) 70#define OFFSET(field) offsetof(ib_params, field)
71const struct option { 71const struct option {
72 const char *name; /* Name of option */ 72 const char *name; /* Name of option */
73 ib_flags flag; /* Corresponding IB_xxx flag */ 73 ib_flags flag; /* Corresponding IB_xxx flag */
74 enum { /* Type of option value... */ 74 enum { /* Type of option value... */
75 OPT_BOOL, /* no value */ 75 OPT_BOOL, /* no value */
76 OPT_INT, /* numeric value */ 76 OPT_INT, /* numeric value */
77 OPT_WORD, /* space/tab/, terminated */ 77 OPT_WORD, /* space/tab/, terminated */
78 OPT_STRING /* null terminated */ 78 OPT_STRING /* null terminated */
79 } type; 79 } type;
80 int offset; /* of field in ib_params */ 80 int offset; /* of field in ib_params */
81} options[] = { 81} options[] = {
82 { "alphasum", IB_ALPHASUM, OPT_BOOL, 0 }, 82 { "alphasum", IB_ALPHASUM, OPT_BOOL, 0 },
83 { "append", IB_APPEND, OPT_BOOL, 0 }, 83 { "append", IB_APPEND, OPT_BOOL, 0 },
84 { "command", IB_COMMAND, OPT_STRING, OFFSET(command) }, 84 { "command", IB_COMMAND, OPT_STRING, OFFSET(command) },
85 { "console", IB_CONSOLE, OPT_WORD, OFFSET(console) }, 85 { "console", IB_CONSOLE, OPT_WORD, OFFSET(console) },
86 { "ioaddr", IB_CONSADDR, OPT_INT, OFFSET(consaddr) }, 86 { "ioaddr", IB_CONSADDR, OPT_INT, OFFSET(consaddr) },
87 { "keymap", IB_KEYMAP, OPT_WORD, OFFSET(keymap) }, 87 { "keymap", IB_KEYMAP, OPT_WORD, OFFSET(keymap) },
88 { "password", IB_PASSWORD, OPT_WORD, OFFSET(password) }, 88 { "password", IB_PASSWORD, OPT_WORD, OFFSET(password) },
89 { "resetvideo", IB_RESETVIDEO, OPT_BOOL, 0 }, 89 { "resetvideo", IB_RESETVIDEO, OPT_BOOL, 0 },
90 { "speed", IB_CONSPEED, OPT_INT, OFFSET(conspeed) }, 90 { "speed", IB_CONSPEED, OPT_INT, OFFSET(conspeed) },
91 { "sunsum", IB_SUNSUM, OPT_BOOL, 0 }, 91 { "sunsum", IB_SUNSUM, OPT_BOOL, 0 },
92 { "timeout", IB_TIMEOUT, OPT_INT, OFFSET(timeout) }, 92 { "timeout", IB_TIMEOUT, OPT_INT, OFFSET(timeout) },
93 { "modules", IB_MODULES, OPT_BOOL, 0 }, 93 { "modules", IB_MODULES, OPT_BOOL, 0 },
94 { "bootconf", IB_BOOTCONF, OPT_BOOL, 0 }, 94 { "bootconf", IB_BOOTCONF, OPT_BOOL, 0 },
95 { .name = NULL }, 95 { .name = NULL },
96}; 96};
97#undef OFFSET 97#undef OFFSET
98#define OPTION(params, type, opt) (*(type *)((char *)(params) + (opt)->offset)) 98#define OPTION(params, type, opt) (*(type *)((char *)(params) + (opt)->offset))
99 99
100#define DFL_SECSIZE 512 /* Don't use DEV_BSIZE. It's host's value. */ 100#define DFL_SECSIZE 512 /* Don't use DEV_BSIZE. It's host's value. */
101 101
102int 102int
103main(int argc, char *argv[]) 103main(int argc, char *argv[])
104{ 104{
105 struct utsname utsname; 105 struct utsname utsname;
106 ib_params *params; 106 ib_params *params;
107 unsigned long lval; 107 unsigned long lval;
108 int ch, rv, mode; 108 int ch, rv, mode;
109 char *p; 109 char *p;
110 const char *op; 110 const char *op;
111 ib_flags unsupported_flags; 111 ib_flags unsupported_flags;
112#if !HAVE_NBTOOL_CONFIG_H 112#if !HAVE_NBTOOL_CONFIG_H
113 char specname[MAXPATHLEN]; 113 char specname[MAXPATHLEN];
114 char rawname[MAXPATHLEN]; 114 char rawname[MAXPATHLEN];
115 const char *special, *raw; 115 const char *special, *raw;
116#endif 116#endif
117 117
118 setprogname(argv[0]); 118 setprogname(argv[0]);
119 params = &installboot_params; 119 params = &installboot_params;
120 memset(params, 0, sizeof(*params)); 120 memset(params, 0, sizeof(*params));
121 params->fsfd = -1; 121 params->fsfd = -1;
122 params->s1fd = -1; 122 params->s1fd = -1;
123 if ((p = getenv("MACHINE")) != NULL) 123 if ((p = getenv("MACHINE")) != NULL)
124 getmachine(params, p, "$MACHINE"); 124 getmachine(params, p, "$MACHINE");
125 125
126 while ((ch = getopt(argc, argv, "b:B:cefm:no:t:v")) != -1) { 126 while ((ch = getopt(argc, argv, "b:B:cefm:no:t:v")) != -1) {
127 switch (ch) { 127 switch (ch) {
128 128
129 case 'b': 129 case 'b':
130 case 'B': 130 case 'B':
131 if (*optarg == '\0') 131 if (*optarg == '\0')
132 goto badblock; 132 goto badblock;
133 lval = strtoul(optarg, &p, 0); 133 lval = strtoul(optarg, &p, 0);
134 if (lval > UINT32_MAX || *p != '\0') { 134 if (lval > UINT32_MAX || *p != '\0') {
135 badblock: 135 badblock:
136 errx(1, "Invalid block number `%s'", optarg); 136 errx(1, "Invalid block number `%s'", optarg);
137 } 137 }
138 if (ch == 'b') { 138 if (ch == 'b') {
139 params->s1start = (uint32_t)lval; 139 params->s1start = (uint32_t)lval;
140 params->flags |= IB_STAGE1START; 140 params->flags |= IB_STAGE1START;
141 } else { 141 } else {
142 params->s2start = (uint32_t)lval; 142 params->s2start = (uint32_t)lval;
143 params->flags |= IB_STAGE2START; 143 params->flags |= IB_STAGE2START;
144 } 144 }
145 break; 145 break;
146 146
147 case 'c': 147 case 'c':
148 params->flags |= IB_CLEAR; 148 params->flags |= IB_CLEAR;
149 break; 149 break;
150 150
151 case 'e': 151 case 'e':
152 params->flags |= IB_EDIT; 152 params->flags |= IB_EDIT;
153 break; 153 break;
154 154
155 case 'f': 155 case 'f':
156 params->flags |= IB_FORCE; 156 params->flags |= IB_FORCE;
157 break; 157 break;
158 158
159 case 'm': 159 case 'm':
160 getmachine(params, optarg, "-m"); 160 getmachine(params, optarg, "-m");
161 break; 161 break;
162 162
163 case 'n': 163 case 'n':
164 params->flags |= IB_NOWRITE; 164 params->flags |= IB_NOWRITE;
165 break; 165 break;
166 166
167 case 'o': 167 case 'o':
168 parseoptions(params, optarg); 168 parseoptions(params, optarg);
169 break; 169 break;
170 170
171 case 't': 171 case 't':
172 getfstype(params, optarg, "-t"); 172 getfstype(params, optarg, "-t");
173 break; 173 break;
174 174
175 case 'v': 175 case 'v':
176 params->flags |= IB_VERBOSE; 176 params->flags |= IB_VERBOSE;
177 break; 177 break;
178 178
179 case '?': 179 case '?':
180 default: 180 default:
181 usage(); 181 usage();
182 /* NOTREACHED */ 182 /* NOTREACHED */
183 183
184 } 184 }
185 } 185 }
186 argc -= optind; 186 argc -= optind;
187 argv += optind; 187 argv += optind;
188 188
189 if (params->flags & IB_CLEAR && params->flags & IB_EDIT) 189 if (params->flags & IB_CLEAR && params->flags & IB_EDIT)
190 usage(); 190 usage();
191 if (argc < 1 || argc + 2 * !!(params->flags & (IB_CLEAR | IB_EDIT)) > 3) 191 if (argc < 1 || argc + 2 * !!(params->flags & (IB_CLEAR | IB_EDIT)) > 3)
192 usage(); 192 usage();
193 193
194 /* set missing defaults */ 194 /* set missing defaults */
195 if (params->machine == NULL) { 195 if (params->machine == NULL) {
196 if (uname(&utsname) == -1) 196 if (uname(&utsname) == -1)
197 err(1, "Determine uname"); 197 err(1, "Determine uname");
198 getmachine(params, utsname.machine, "uname()"); 198 getmachine(params, utsname.machine, "uname()");
199 } 199 }
200 200
201 /* Check that options are supported by this system */ 201 /* Check that options are supported by this system */
202 unsupported_flags = params->flags & ~params->machine->valid_flags; 202 unsupported_flags = params->flags & ~params->machine->valid_flags;
203 unsupported_flags &= ~(IB_VERBOSE | IB_NOWRITE | IB_CLEAR | IB_EDIT 203 unsupported_flags &= ~(IB_VERBOSE | IB_NOWRITE | IB_CLEAR | IB_EDIT
204 | IB_FORCE); 204 | IB_FORCE);
205 if (unsupported_flags != 0) { 205 if (unsupported_flags != 0) {
206 int ndx; 206 int ndx;
207 for (ndx = 0; options[ndx].name != NULL; ndx++) { 207 for (ndx = 0; options[ndx].name != NULL; ndx++) {
208 if (unsupported_flags & options[ndx].flag) { 208 if (unsupported_flags & options[ndx].flag) {
209 unsupported_flags &= ~options[ndx].flag; 209 unsupported_flags &= ~options[ndx].flag;
210 warnx("`-o %s' is not supported for %s", 210 warnx("`-o %s' is not supported for %s",
211 options[ndx].name, params->machine->name); 211 options[ndx].name, params->machine->name);
212 } 212 }
213 } 213 }
214 if (unsupported_flags & IB_STAGE1START) 214 if (unsupported_flags & IB_STAGE1START)
215 warnx("`-b bno' is not supported for %s", 215 warnx("`-b bno' is not supported for %s",
216 params->machine->name); 216 params->machine->name);
217 if (unsupported_flags & IB_STAGE2START) 217 if (unsupported_flags & IB_STAGE2START)
218 warnx("`-B bno' is not supported for %s", 218 warnx("`-B bno' is not supported for %s",
219 params->machine->name); 219 params->machine->name);
220 unsupported_flags &= ~(IB_STAGE1START | IB_STAGE2START); 220 unsupported_flags &= ~(IB_STAGE1START | IB_STAGE2START);
221 if (unsupported_flags != 0) 221 if (unsupported_flags != 0)
222 warnx("Unknown unsupported flag %#x (coding error!)", 222 warnx("Unknown unsupported flag %#x (coding error!)",
223 unsupported_flags); 223 unsupported_flags);
224 exit(1); 224 exit(1);
225 } 225 }
226 /* and some illegal combinations */ 226 /* and some illegal combinations */
227 if (params->flags & IB_STAGE1START && params->flags & IB_APPEND) { 227 if (params->flags & IB_STAGE1START && params->flags & IB_APPEND) {
228 warnx("Can't use `-b bno' with `-o append'"); 228 warnx("Can't use `-b bno' with `-o append'");
229 exit(1); 229 exit(1);
230 } 230 }
231 if (params->flags & IB_CLEAR && 231 if (params->flags & IB_CLEAR &&
232 params->flags & (IB_STAGE1START | IB_STAGE2START | IB_APPEND)) { 232 params->flags & (IB_STAGE1START | IB_STAGE2START | IB_APPEND)) {
233 warnx("Can't use `-b bno', `-B bno' or `-o append' with `-c'"); 233 warnx("Can't use `-b bno', `-B bno' or `-o append' with `-c'");
234 exit(1); 234 exit(1);
235 } 235 }
236 236
237 if (argc >= 3) { 237 if (argc >= 3) {
238 params->stage2 = argv[2]; 238 params->stage2 = argv[2];
239 } 239 }
240 240
241#if !HAVE_NBTOOL_CONFIG_H 241#if !HAVE_NBTOOL_CONFIG_H
242 special = getfsspecname(specname, sizeof(specname), argv[0]); 242 special = getfsspecname(specname, sizeof(specname), argv[0]);
 243 if (special == NULL)
 244 err(1, "%s: %s", argv[0], specname);
243 raw = getdiskrawname(rawname, sizeof(rawname), special); 245 raw = getdiskrawname(rawname, sizeof(rawname), special);
244 if (raw != NULL) 246 if (raw != NULL)
245 special = raw; 247 special = raw;
246 params->filesystem = special; 248 params->filesystem = special;
247#else 249#else
248 params->filesystem = argv[0]; 250 params->filesystem = argv[0];
249#endif 251#endif
250 252
251 if (params->flags & IB_NOWRITE) { 253 if (params->flags & IB_NOWRITE) {
252 op = "only"; 254 op = "only";
253 mode = O_RDONLY; 255 mode = O_RDONLY;
254 } else { 256 } else {
255 op = "write"; 257 op = "write";
256 mode = O_RDWR; 258 mode = O_RDWR;
257 } 259 }
258 /* XXX should be specified via option */ 260 /* XXX should be specified via option */
259 params->sectorsize = DFL_SECSIZE; 261 params->sectorsize = DFL_SECSIZE;
260 if ((params->fsfd = open(params->filesystem, mode, 0600)) == -1) 262 if ((params->fsfd = open(params->filesystem, mode, 0600)) == -1)
261 err(1, "Opening file system `%s' read-%s", 263 err(1, "Opening file system `%s' read-%s",
262 params->filesystem, op); 264 params->filesystem, op);
263 if (fstat(params->fsfd, &params->fsstat) == -1) 265 if (fstat(params->fsfd, &params->fsstat) == -1)
264 err(1, "Examining file system `%s'", params->filesystem); 266 err(1, "Examining file system `%s'", params->filesystem);
265 if (params->fstype != NULL) { 267 if (params->fstype != NULL) {
266 if (! params->fstype->match(params)) 268 if (! params->fstype->match(params))
267 errx(1, "File system `%s' is not of type %s", 269 errx(1, "File system `%s' is not of type %s",
268 params->filesystem, params->fstype->name); 270 params->filesystem, params->fstype->name);
269 } else { 271 } else {
270 if (params->stage2 != NULL) { 272 if (params->stage2 != NULL) {
271 params->fstype = &fstypes[0]; 273 params->fstype = &fstypes[0];
272 while (params->fstype->name != NULL && 274 while (params->fstype->name != NULL &&
273 !params->fstype->match(params)) 275 !params->fstype->match(params))
274 params->fstype++; 276 params->fstype++;
275 if (params->fstype->name == NULL) 277 if (params->fstype->name == NULL)
276 errx(1, "File system `%s' is of an unknown type", 278 errx(1, "File system `%s' is of an unknown type",
277 params->filesystem); 279 params->filesystem);
278 } 280 }
279 } 281 }
280 282
281 if (argc >= 2) { 283 if (argc >= 2) {
282 if ((params->s1fd = open(argv[1], O_RDONLY, 0600)) == -1) 284 if ((params->s1fd = open(argv[1], O_RDONLY, 0600)) == -1)
283 err(1, "Opening primary bootstrap `%s'", argv[1]); 285 err(1, "Opening primary bootstrap `%s'", argv[1]);
284 if (fstat(params->s1fd, &params->s1stat) == -1) 286 if (fstat(params->s1fd, &params->s1stat) == -1)
285 err(1, "Examining primary bootstrap `%s'", argv[1]); 287 err(1, "Examining primary bootstrap `%s'", argv[1]);
286 if (!S_ISREG(params->s1stat.st_mode)) 288 if (!S_ISREG(params->s1stat.st_mode))
287 errx(1, "`%s' must be a regular file", argv[1]); 289 errx(1, "`%s' must be a regular file", argv[1]);
288 params->stage1 = argv[1]; 290 params->stage1 = argv[1];
289 } 291 }
290 assert(params->machine != NULL); 292 assert(params->machine != NULL);
291 293
292 if (params->flags & IB_VERBOSE) { 294 if (params->flags & IB_VERBOSE) {
293 printf("File system: %s\n", params->filesystem); 295 printf("File system: %s\n", params->filesystem);
294 if (params->fstype)  296 if (params->fstype)
295 printf("File system type: %s (blocksize %u, " 297 printf("File system type: %s (blocksize %u, "
296 "needswap %d)\n", 298 "needswap %d)\n",
297 params->fstype->name, params->fstype->blocksize, 299 params->fstype->name, params->fstype->blocksize,
298 params->fstype->needswap); 300 params->fstype->needswap);
299 if (!(params->flags & IB_EDIT)) 301 if (!(params->flags & IB_EDIT))
300 printf("Primary bootstrap: %s\n", 302 printf("Primary bootstrap: %s\n",
301 (params->flags & IB_CLEAR) ? "(to be cleared)" 303 (params->flags & IB_CLEAR) ? "(to be cleared)"
302 : params->stage1 ? params->stage1 : "(none)" ); 304 : params->stage1 ? params->stage1 : "(none)" );
303 if (params->stage2 != NULL) 305 if (params->stage2 != NULL)
304 printf("Secondary bootstrap: %s\n", params->stage2); 306 printf("Secondary bootstrap: %s\n", params->stage2);
305 } 307 }
306 308
307 if (params->flags & IB_EDIT) { 309 if (params->flags & IB_EDIT) {
308 op = "Edit"; 310 op = "Edit";
309 rv = params->machine->editboot(params); 311 rv = params->machine->editboot(params);
310 } else if (params->flags & IB_CLEAR) { 312 } else if (params->flags & IB_CLEAR) {
311 op = "Clear"; 313 op = "Clear";
312 rv = params->machine->clearboot(params); 314 rv = params->machine->clearboot(params);
313 } else { 315 } else {
314 if (argc < 2) 316 if (argc < 2)
315 errx(EXIT_FAILURE, "Please specify the primary " 317 errx(EXIT_FAILURE, "Please specify the primary "
316 "bootstrap file"); 318 "bootstrap file");
317 op = "Set"; 319 op = "Set";
318 rv = params->machine->setboot(params); 320 rv = params->machine->setboot(params);
319 } 321 }
320 if (rv == 0) 322 if (rv == 0)
321 errx(1, "%s bootstrap operation failed", op); 323 errx(1, "%s bootstrap operation failed", op);
322 324
323 if (S_ISREG(params->fsstat.st_mode)) { 325 if (S_ISREG(params->fsstat.st_mode)) {
324 if (fsync(params->fsfd) == -1) 326 if (fsync(params->fsfd) == -1)
325 err(1, "Synchronising file system `%s'", 327 err(1, "Synchronising file system `%s'",
326 params->filesystem); 328 params->filesystem);
327 } else { 329 } else {
328 /* Sync filesystems (to clean in-memory superblock?) */ 330 /* Sync filesystems (to clean in-memory superblock?) */
329 sync(); 331 sync();
330 } 332 }
331 if (close(params->fsfd) == -1) 333 if (close(params->fsfd) == -1)
332 err(1, "Closing file system `%s'", params->filesystem); 334 err(1, "Closing file system `%s'", params->filesystem);
333 if (argc == 2) 335 if (argc == 2)
334 if (close(params->s1fd) == -1) 336 if (close(params->s1fd) == -1)
335 err(1, "Closing primary bootstrap `%s'", 337 err(1, "Closing primary bootstrap `%s'",
336 params->stage1); 338 params->stage1);
337 339
338 exit(0); 340 exit(0);
339 /* NOTREACHED */ 341 /* NOTREACHED */
340} 342}
341 343
342static void 344static void
343parseoptions(ib_params *params, const char *option) 345parseoptions(ib_params *params, const char *option)
344{ 346{
345 char *cp; 347 char *cp;
346 const struct option *opt; 348 const struct option *opt;
347 int len; 349 int len;
348 unsigned long val; 350 unsigned long val;
349 351
350 assert(params != NULL); 352 assert(params != NULL);
351 assert(option != NULL); 353 assert(option != NULL);
352 354
353 for (;; option += len) { 355 for (;; option += len) {
354 option += strspn(option, ", \t"); 356 option += strspn(option, ", \t");
355 if (*option == 0) 357 if (*option == 0)
356 return; 358 return;
357 len = strcspn(option, "=,"); 359 len = strcspn(option, "=,");
358 for (opt = options; opt->name != NULL; opt++) { 360 for (opt = options; opt->name != NULL; opt++) {
359 if (memcmp(option, opt->name, len) == 0 361 if (memcmp(option, opt->name, len) == 0
360 && opt->name[len] == 0) 362 && opt->name[len] == 0)
361 break; 363 break;
362 } 364 }
363 if (opt->name == NULL) { 365 if (opt->name == NULL) {
364 len = strcspn(option, ","); 366 len = strcspn(option, ",");
365 warnx("Unknown option `-o %.*s'", len, option); 367 warnx("Unknown option `-o %.*s'", len, option);
366 break; 368 break;
367 } 369 }
368 params->flags |= opt->flag; 370 params->flags |= opt->flag;
369 if (opt->type == OPT_BOOL) { 371 if (opt->type == OPT_BOOL) {
370 if (option[len] != '=') 372 if (option[len] != '=')
371 continue; 373 continue;
372 warnx("Option `%s' must not have a value", opt->name); 374 warnx("Option `%s' must not have a value", opt->name);
373 break; 375 break;
374 } 376 }
375 if (option[len] != '=') { 377 if (option[len] != '=') {
376 warnx("Option `%s' must have a value", opt->name); 378 warnx("Option `%s' must have a value", opt->name);
377 break; 379 break;
378 } 380 }
379 option += len + 1; 381 option += len + 1;
380 len = strcspn(option, ","); 382 len = strcspn(option, ",");
381 switch (opt->type) { 383 switch (opt->type) {
382 case OPT_STRING: 384 case OPT_STRING:
383 len = strlen(option); 385 len = strlen(option);
384 /* FALLTHROUGH */ 386 /* FALLTHROUGH */
385 case OPT_WORD: 387 case OPT_WORD:
386 cp = strdup(option); 388 cp = strdup(option);
387 if (cp == NULL) 389 if (cp == NULL)
388 err(1, "strdup"); 390 err(1, "strdup");
389 cp[len] = 0; 391 cp[len] = 0;
390 OPTION(params, char *, opt) = cp; 392 OPTION(params, char *, opt) = cp;
391 continue; 393 continue;
392 case OPT_INT: 394 case OPT_INT:
393 val = strtoul(option, &cp, 0); 395 val = strtoul(option, &cp, 0);
394 if (cp > option + len || (*cp != 0 && *cp != ',')) 396 if (cp > option + len || (*cp != 0 && *cp != ','))
395 break; 397 break;
396 if (val > INT_MAX) 398 if (val > INT_MAX)
397 break; 399 break;
398 OPTION(params, int, opt) = (int)val; 400 OPTION(params, int, opt) = (int)val;
399 continue; 401 continue;
400 default: 402 default:
401 errx(1, "Internal error: option `%s' has invalid type %d", 403 errx(1, "Internal error: option `%s' has invalid type %d",
402 opt->name, opt->type); 404 opt->name, opt->type);
403 } 405 }
404 warnx("Invalid option value `%s=%.*s'", opt->name, len, option); 406 warnx("Invalid option value `%s=%.*s'", opt->name, len, option);
405 break; 407 break;
406 } 408 }
407 options_usage(); 409 options_usage();
408 exit(1); 410 exit(1);
409} 411}
410 412
411static void 413static void
412options_usage(void) 414options_usage(void)
413{ 415{
414 int ndx; 416 int ndx;
415 const char *pfx; 417 const char *pfx;
416 418
417 warnx("Valid options are:"); 419 warnx("Valid options are:");
418 pfx = "\t"; 420 pfx = "\t";
419 for (ndx = 0; options[ndx].name != 0; ndx++) { 421 for (ndx = 0; options[ndx].name != 0; ndx++) {
420 fprintf(stderr, "%s%s", pfx, options[ndx].name); 422 fprintf(stderr, "%s%s", pfx, options[ndx].name);
421 switch (options[ndx].type) { 423 switch (options[ndx].type) {
422 case OPT_INT: 424 case OPT_INT:
423 fprintf(stderr, "=number"); 425 fprintf(stderr, "=number");
424 break; 426 break;
425 case OPT_WORD: 427 case OPT_WORD:
426 fprintf(stderr, "=word"); 428 fprintf(stderr, "=word");
427 break; 429 break;
428 case OPT_STRING: 430 case OPT_STRING:
429 fprintf(stderr, "=string"); 431 fprintf(stderr, "=string");
430 break; 432 break;
431 default: 433 default:
432 break; 434 break;
433 } 435 }
434 if ((ndx % 5) == 4) 436 if ((ndx % 5) == 4)
435 pfx = ",\n\t"; 437 pfx = ",\n\t";
436 else 438 else
437 pfx = ", "; 439 pfx = ", ";
438 } 440 }
439 fprintf(stderr, "\n"); 441 fprintf(stderr, "\n");
440} 442}
441 443
442int 444int
443no_setboot(ib_params *params) 445no_setboot(ib_params *params)
444{ 446{
445 447
446 assert(params != NULL); 448 assert(params != NULL);
447 449
448 warnx("%s: bootstrap installation is not supported", 450 warnx("%s: bootstrap installation is not supported",
449 params->machine->name); 451 params->machine->name);
450 return (0); 452 return (0);
451} 453}
452 454
453int 455int
454no_clearboot(ib_params *params) 456no_clearboot(ib_params *params)
455{ 457{
456 458
457 assert(params != NULL); 459 assert(params != NULL);
458 460
459 warnx("%s: bootstrap removal is not supported", 461 warnx("%s: bootstrap removal is not supported",
460 params->machine->name); 462 params->machine->name);
461 return (0); 463 return (0);
462} 464}
463 465
464int 466int
465no_editboot(ib_params *params) 467no_editboot(ib_params *params)
466{ 468{
467 469
468 assert(params != NULL); 470 assert(params != NULL);
469 471
470 warnx("%s: bootstrap editing is not supported", 472 warnx("%s: bootstrap editing is not supported",
471 params->machine->name); 473 params->machine->name);
472 return (0); 474 return (0);
473} 475}
474 476
475 477
476static void 478static void
477getmachine(ib_params *param, const char *mach, const char *provider) 479getmachine(ib_params *param, const char *mach, const char *provider)
478{ 480{
479 int i; 481 int i;
480 482
481 assert(param != NULL); 483 assert(param != NULL);
482 assert(mach != NULL); 484 assert(mach != NULL);
483 assert(provider != NULL); 485 assert(provider != NULL);
484 486
485 for (i = 0; machines[i] != NULL; i++) { 487 for (i = 0; machines[i] != NULL; i++) {
486 if (machines[i]->name == NULL) 488 if (machines[i]->name == NULL)
487 continue; 489 continue;
488 if (strcmp(machines[i]->name, mach) == 0) { 490 if (strcmp(machines[i]->name, mach) == 0) {
489 param->machine = machines[i]; 491 param->machine = machines[i];
490 return; 492 return;
491 } 493 }
492 } 494 }
493 warnx("Invalid machine `%s' from %s", mach, provider); 495 warnx("Invalid machine `%s' from %s", mach, provider);
494 machine_usage(); 496 machine_usage();
495 exit(1); 497 exit(1);
496} 498}
497 499
498static void 500static void
499machine_usage(void) 501machine_usage(void)
500{ 502{
501 const char *prefix; 503 const char *prefix;
502 int i; 504 int i;
503 int col, len; 505 int col, len;
504 const char *name; 506 const char *name;
505 int wincol=80; 507 int wincol=80;
506#ifdef TIOCGWINSZ 508#ifdef TIOCGWINSZ
507 struct winsize win; 509 struct winsize win;
508 510
509 if (ioctl(fileno(stderr), TIOCGWINSZ, &win) == 0 && win.ws_col > 0) 511 if (ioctl(fileno(stderr), TIOCGWINSZ, &win) == 0 && win.ws_col > 0)
510 wincol = win.ws_col; 512 wincol = win.ws_col;
511#endif 513#endif
512 514
513 warnx("Supported machines are:"); 515 warnx("Supported machines are:");
514 prefix="\t"; 516 prefix="\t";
515 col = 8 + 3; 517 col = 8 + 3;
516 for (i = 0; machines[i] != NULL; i++) { 518 for (i = 0; machines[i] != NULL; i++) {
517 name = machines[i]->name; 519 name = machines[i]->name;
518 if (name == NULL) 520 if (name == NULL)
519 continue; 521 continue;
520 len = strlen(name); 522 len = strlen(name);
521 if (col + len > wincol) { 523 if (col + len > wincol) {
522 prefix=",\n\t"; 524 prefix=",\n\t";
523 col = -2 + 8 + 3; 525 col = -2 + 8 + 3;
524 } 526 }
525 col += fprintf(stderr, "%s%s", prefix, name); 527 col += fprintf(stderr, "%s%s", prefix, name);
526 prefix=", "; 528 prefix=", ";
527 } 529 }
528 fputs("\n", stderr); 530 fputs("\n", stderr);
529} 531}
530 532
531static void 533static void
532getfstype(ib_params *param, const char *fstype, const char *provider) 534getfstype(ib_params *param, const char *fstype, const char *provider)
533{ 535{
534 int i; 536 int i;
535 537
536 assert(param != NULL); 538 assert(param != NULL);
537 assert(fstype != NULL); 539 assert(fstype != NULL);
538 assert(provider != NULL); 540 assert(provider != NULL);
539 541
540 for (i = 0; fstypes[i].name != NULL; i++) { 542 for (i = 0; fstypes[i].name != NULL; i++) {
541 if (strcmp(fstypes[i].name, fstype) == 0) { 543 if (strcmp(fstypes[i].name, fstype) == 0) {
542 param->fstype = &fstypes[i]; 544 param->fstype = &fstypes[i];
543 return; 545 return;
544 } 546 }
545 } 547 }
546 warnx("Invalid file system type `%s' from %s", fstype, provider); 548 warnx("Invalid file system type `%s' from %s", fstype, provider);
547 fstype_usage(); 549 fstype_usage();
548 exit(1); 550 exit(1);
549} 551}
550 552
551static void 553static void
552fstype_usage(void) 554fstype_usage(void)
553{ 555{
554#ifndef NO_STAGE2 556#ifndef NO_STAGE2
555 const char *prefix; 557 const char *prefix;
556 int i; 558 int i;
557 559
558 warnx("Supported file system types are:"); 560 warnx("Supported file system types are:");
559#define FSTYPES_PER_LINE 9 561#define FSTYPES_PER_LINE 9
560 prefix="\t"; 562 prefix="\t";
561 for (i = 0; fstypes[i].name != NULL; i++) { 563 for (i = 0; fstypes[i].name != NULL; i++) {
562 if (i && (i % FSTYPES_PER_LINE) == 0) 564 if (i && (i % FSTYPES_PER_LINE) == 0)
563 prefix=",\n\t"; 565 prefix=",\n\t";
564 fprintf(stderr, "%s%s", prefix, fstypes[i].name); 566 fprintf(stderr, "%s%s", prefix, fstypes[i].name);
565 prefix=", "; 567 prefix=", ";
566 } 568 }
567 fputs("\n", stderr); 569 fputs("\n", stderr);
568#endif 570#endif
569} 571}
570 572
571static void 573static void
572usage(void) 574usage(void)
573{ 575{
574 const char *prog; 576 const char *prog;
575 577
576 prog = getprogname(); 578 prog = getprogname();
577 fprintf(stderr, 579 fprintf(stderr,
578"usage: %s [-fnv] [-B s2bno] [-b s1bno] [-m machine] [-o options]\n" 580"usage: %s [-fnv] [-B s2bno] [-b s1bno] [-m machine] [-o options]\n"
579"\t\t [-t fstype] filesystem primary [secondary]\n" 581"\t\t [-t fstype] filesystem primary [secondary]\n"
580"usage: %s -c [-fnv] [-m machine] [-o options] [-t fstype] filesystem\n" 582"usage: %s -c [-fnv] [-m machine] [-o options] [-t fstype] filesystem\n"
581"usage: %s -e [-fnv] [-m machine] [-o options] bootstrap\n", 583"usage: %s -e [-fnv] [-m machine] [-o options] bootstrap\n",
582 prog, prog, prog); 584 prog, prog, prog);
583 machine_usage(); 585 machine_usage();
584 fstype_usage(); 586 fstype_usage();
585 options_usage(); 587 options_usage();
586 exit(1); 588 exit(1);
587} 589}