File: | src/sbin/newfs/newfs.c |
Warning: | line 460, column 11 Access to field 'p_sizeh' results in a dereference of a null pointer (loaded from variable 'pp') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: newfs.c,v 1.115 2021/06/03 06:42:03 otto Exp $ */ | |||
2 | /* $NetBSD: newfs.c,v 1.20 1996/05/16 07:13:03 thorpej Exp $ */ | |||
3 | ||||
4 | /* | |||
5 | * Copyright (c) 2002 Networks Associates Technology, Inc. | |||
6 | * All rights reserved. | |||
7 | * | |||
8 | * This software was developed for the FreeBSD Project by Marshall | |||
9 | * Kirk McKusick and Network Associates Laboratories, the Security | |||
10 | * Research Division of Network Associates, Inc. under DARPA/SPAWAR | |||
11 | * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS | |||
12 | * research program. | |||
13 | * | |||
14 | * Copyright (c) 1983, 1989, 1993, 1994 | |||
15 | * The Regents of the University of California. All rights reserved. | |||
16 | * | |||
17 | * Redistribution and use in source and binary forms, with or without | |||
18 | * modification, are permitted provided that the following conditions | |||
19 | * are met: | |||
20 | * 1. Redistributions of source code must retain the above copyright | |||
21 | * notice, this list of conditions and the following disclaimer. | |||
22 | * 2. Redistributions in binary form must reproduce the above copyright | |||
23 | * notice, this list of conditions and the following disclaimer in the | |||
24 | * documentation and/or other materials provided with the distribution. | |||
25 | * 3. Neither the name of the University nor the names of its contributors | |||
26 | * may be used to endorse or promote products derived from this software | |||
27 | * without specific prior written permission. | |||
28 | * | |||
29 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |||
30 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
31 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
32 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |||
33 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
34 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
35 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
36 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
37 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
38 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
39 | * SUCH DAMAGE. | |||
40 | */ | |||
41 | ||||
42 | #include <sys/param.h> /* DEV_BSIZE MAXBSIZE */ | |||
43 | #include <sys/types.h> | |||
44 | #include <sys/stat.h> | |||
45 | #include <sys/ioctl.h> | |||
46 | #include <sys/dkio.h> | |||
47 | #include <sys/disklabel.h> | |||
48 | #include <sys/mount.h> | |||
49 | #include <sys/resource.h> | |||
50 | #include <sys/sysctl.h> | |||
51 | #include <sys/wait.h> | |||
52 | ||||
53 | #include <ufs/ufs/dinode.h> | |||
54 | #include <ufs/ufs/dir.h> | |||
55 | #include <ufs/ffs/fs.h> | |||
56 | ||||
57 | #include <ctype.h> | |||
58 | #include <err.h> | |||
59 | #include <errno(*__errno()).h> | |||
60 | #include <fcntl.h> | |||
61 | #include <paths.h> | |||
62 | #include <stdarg.h> | |||
63 | #include <stdio.h> | |||
64 | #include <stdlib.h> | |||
65 | #include <string.h> | |||
66 | #include <syslog.h> | |||
67 | #include <unistd.h> | |||
68 | #include <limits.h> | |||
69 | #include <signal.h> | |||
70 | #include <util.h> | |||
71 | ||||
72 | #include "mntopts.h" | |||
73 | #include "pathnames.h" | |||
74 | ||||
75 | #define MINIMUM(a, b)(((a) < (b)) ? (a) : (b)) (((a) < (b)) ? (a) : (b)) | |||
76 | #define MAXIMUM(a, b)(((a) > (b)) ? (a) : (b)) (((a) > (b)) ? (a) : (b)) | |||
77 | ||||
78 | struct mntopt mopts[] = { | |||
79 | MOPT_STDOPTS{ "userquota", 0, 0x02 | 0x04 | 0x10 }, { "groupquota", 0, 0x02 | 0x04 | 0x10 }, { "ro", 0x00000001, 0x02 }, { "rw", 0x00000001 , 0x01 | 0x02 }, { "net", 0, 0x02 }, { "auto", 0, 0x02 }, { "accesstime" , 0x00008000, 0x01 | 0x02 }, { "atime", 0x00008000, 0x01 | 0x02 }, { "dev", 0x00000010, 0x01 | 0x02 }, { "exec", 0x00000004, 0x01 | 0x02 }, { "suid", 0x00000008, 0x01 | 0x02 }, { "rdonly" , 0x00000001, 0x02 }, | |||
80 | MOPT_WXALLOWED{ "wxallowed", 0x00000800, 0x02 }, | |||
81 | MOPT_NOPERM{ "perm", 0x00000020, 0x01 | 0x02 }, | |||
82 | MOPT_ASYNC{ "async", 0x00000040, 0x02 }, | |||
83 | MOPT_UPDATE{ "update", 0x00010000, 0x02 }, | |||
84 | MOPT_FORCE{ "force", 0x00080000, 0x02 }, | |||
85 | { NULL((void *)0) }, | |||
86 | }; | |||
87 | ||||
88 | void fatal(const char *fmt, ...) | |||
89 | __attribute__((__format__ (printf, 1, 2))) | |||
90 | __attribute__((__nonnull__ (1))); | |||
91 | __dead__attribute__((__noreturn__)) void usage(void); | |||
92 | void mkfs(struct partition *, char *, int, int, mode_t, uid_t, gid_t); | |||
93 | void getphysmem(void); | |||
94 | void rewritelabel(char *, int, struct disklabel *); | |||
95 | u_short dkcksum(struct disklabel *); | |||
96 | ||||
97 | /* | |||
98 | * The following two constants set the default block and fragment sizes. | |||
99 | * Both constants must be a power of 2 and meet the following constraints: | |||
100 | * MINBSIZE <= DESBLKSIZE <= MAXBSIZE | |||
101 | * sectorsize <= DESFRAGSIZE <= DESBLKSIZE | |||
102 | * DESBLKSIZE / DESFRAGSIZE <= 8 | |||
103 | */ | |||
104 | #define DFL_FRAGSIZE2048 2048 | |||
105 | #define DFL_BLKSIZE16384 16384 | |||
106 | ||||
107 | /* | |||
108 | * MAXBLKPG determines the maximum number of data blocks which are | |||
109 | * placed in a single cylinder group. The default is one indirect | |||
110 | * block worth of data blocks. | |||
111 | */ | |||
112 | #define MAXBLKPG_FFS1(bsize)((bsize) / sizeof(int32_t)) ((bsize) / sizeof(int32_t)) | |||
113 | #define MAXBLKPG_FFS2(bsize)((bsize) / sizeof(int64_t)) ((bsize) / sizeof(int64_t)) | |||
114 | ||||
115 | /* | |||
116 | * Each file system has a number of inodes statically allocated. | |||
117 | * We allocate one inode slot per NFPI fragments, expecting this | |||
118 | * to be far more than we will ever need. | |||
119 | */ | |||
120 | #define NFPI4 4 | |||
121 | ||||
122 | int mfs; /* run as the memory based filesystem */ | |||
123 | int Nflag; /* run without writing file system */ | |||
124 | int Oflag = 2; /* 0 = 4.3BSD ffs, 1 = 4.4BSD ffs, 2 = ffs2 */ | |||
125 | daddr_t fssize; /* file system size in 512-byte blocks */ | |||
126 | long long sectorsize; /* bytes/sector */ | |||
127 | int fsize = 0; /* fragment size */ | |||
128 | int bsize = 0; /* block size */ | |||
129 | int maxfrgspercg = INT_MAX2147483647; /* maximum fragments per cylinder group */ | |||
130 | int minfree = MINFREE5; /* free space threshold */ | |||
131 | int opt = DEFAULTOPT0; /* optimization preference (space or time) */ | |||
132 | int reqopt = -1; /* opt preference has not been specified */ | |||
133 | int density; /* number of bytes per inode */ | |||
134 | int maxbpg; /* maximum blocks per file in a cyl group */ | |||
135 | int avgfilesize = AVFILESIZ16384;/* expected average file size */ | |||
136 | int avgfilesperdir = AFPDIR64;/* expected number of files per directory */ | |||
137 | int mntflags = MNT_ASYNC0x00000040; /* flags to be passed to mount */ | |||
138 | int quiet = 0; /* quiet flag */ | |||
139 | caddr_t membase; /* start address of memory based filesystem */ | |||
140 | char *disktype; | |||
141 | int unlabeled; | |||
142 | ||||
143 | extern char *__progname; | |||
144 | struct disklabel *getdisklabel(char *, int); | |||
145 | ||||
146 | #ifdef MFS1 | |||
147 | static void waitformount(char *, pid_t); | |||
148 | static int do_exec(const char *, const char *, char *const[]); | |||
149 | static int isdir(const char *); | |||
150 | static void copy(char *, char *); | |||
151 | static int gettmpmnt(char *, size_t); | |||
152 | #endif | |||
153 | ||||
154 | int64_t physmem; | |||
155 | ||||
156 | void | |||
157 | getphysmem(void) | |||
158 | { | |||
159 | int mib[] = { CTL_HW6, HW_PHYSMEM6419 }; | |||
160 | size_t len = sizeof(physmem); | |||
161 | ||||
162 | if (sysctl(mib, 2, &physmem, &len, NULL((void *)0), 0) != 0) | |||
163 | err(1, "can't get physmem"); | |||
164 | } | |||
165 | ||||
166 | int | |||
167 | main(int argc, char *argv[]) | |||
168 | { | |||
169 | int ch; | |||
170 | struct partition *pp; | |||
171 | struct disklabel *lp; | |||
172 | struct disklabel mfsfakelabel; | |||
173 | struct partition oldpartition; | |||
174 | struct stat st; | |||
175 | struct statfs *mp; | |||
176 | struct rlimit rl; | |||
177 | int fsi = -1, oflagset = 0, fso, len, n, maxpartitions; | |||
178 | char *cp = NULL((void *)0), *s1, *s2, *special, *opstring, *realdev; | |||
179 | #ifdef MFS1 | |||
180 | char mountfromname[BUFSIZ1024]; | |||
181 | char *pop = NULL((void *)0), node[PATH_MAX1024]; | |||
182 | pid_t pid; | |||
183 | struct stat mountpoint; | |||
184 | #endif | |||
185 | uid_t mfsuid = 0; | |||
186 | gid_t mfsgid = 0; | |||
187 | mode_t mfsmode = 0; | |||
188 | char *fstype = NULL((void *)0); | |||
189 | char **saveargv = argv; | |||
190 | int ffsflag = 1; | |||
191 | const char *errstr; | |||
192 | long long fssize_input = 0; | |||
193 | int fssize_usebytes = 0; | |||
194 | int defaultfsize; | |||
195 | u_int64_t nsecs; | |||
196 | ||||
197 | if (strstr(__progname, "mfs")) | |||
| ||||
198 | mfs = Nflag = quiet = Oflag = 1; | |||
199 | ||||
200 | getphysmem(); | |||
201 | maxpartitions = getmaxpartitions(); | |||
202 | if (maxpartitions > 26) | |||
203 | fatal("insane maxpartitions value %d", maxpartitions); | |||
204 | ||||
205 | opstring = mfs ? | |||
206 | "P:T:b:c:e:f:i:m:o:s:" : | |||
207 | "NO:S:T:b:c:e:f:g:h:i:m:o:qs:t:"; | |||
208 | while ((ch = getopt(argc, argv, opstring)) != -1) { | |||
209 | switch (ch) { | |||
210 | case 'N': | |||
211 | Nflag = 1; | |||
212 | break; | |||
213 | case 'O': | |||
214 | Oflag = strtonum(optarg, 0, 2, &errstr); | |||
215 | if (errstr) | |||
216 | fatal("%s: invalid ffs version", optarg); | |||
217 | oflagset = 1; | |||
218 | break; | |||
219 | case 'S': | |||
220 | if (scan_scaled(optarg, §orsize) == -1 || | |||
221 | sectorsize <= 0 || (sectorsize % DEV_BSIZE(1 << 9))) | |||
222 | fatal("sector size invalid: %s", optarg); | |||
223 | break; | |||
224 | case 'T': | |||
225 | disktype = optarg; | |||
226 | break; | |||
227 | case 'b': | |||
228 | bsize = strtonum(optarg, MINBSIZE4096, MAXBSIZE(64 * 1024), &errstr); | |||
229 | if (errstr) | |||
230 | fatal("block size is %s: %s", errstr, optarg); | |||
231 | break; | |||
232 | case 'c': | |||
233 | maxfrgspercg = strtonum(optarg, 1, INT_MAX2147483647, &errstr); | |||
234 | if (errstr) | |||
235 | fatal("fragments per cylinder group is %s: %s", | |||
236 | errstr, optarg); | |||
237 | break; | |||
238 | case 'e': | |||
239 | maxbpg = strtonum(optarg, 1, INT_MAX2147483647, &errstr); | |||
240 | if (errstr) | |||
241 | fatal("blocks per file in a cylinder group is" | |||
242 | " %s: %s", errstr, optarg); | |||
243 | break; | |||
244 | case 'f': | |||
245 | fsize = strtonum(optarg, MINBSIZE4096 / MAXFRAG8, MAXBSIZE(64 * 1024), | |||
246 | &errstr); | |||
247 | if (errstr) | |||
248 | fatal("fragment size is %s: %s", | |||
249 | errstr, optarg); | |||
250 | break; | |||
251 | case 'g': | |||
252 | avgfilesize = strtonum(optarg, 1, INT_MAX2147483647, &errstr); | |||
253 | if (errstr) | |||
254 | fatal("average file size is %s: %s", | |||
255 | errstr, optarg); | |||
256 | break; | |||
257 | case 'h': | |||
258 | avgfilesperdir = strtonum(optarg, 1, INT_MAX2147483647, &errstr); | |||
259 | if (errstr) | |||
260 | fatal("average files per dir is %s: %s", | |||
261 | errstr, optarg); | |||
262 | break; | |||
263 | case 'i': | |||
264 | density = strtonum(optarg, 1, INT_MAX2147483647, &errstr); | |||
265 | if (errstr) | |||
266 | fatal("bytes per inode is %s: %s", | |||
267 | errstr, optarg); | |||
268 | break; | |||
269 | case 'm': | |||
270 | minfree = strtonum(optarg, 0, 99, &errstr); | |||
271 | if (errstr) | |||
272 | fatal("free space %% is %s: %s", | |||
273 | errstr, optarg); | |||
274 | break; | |||
275 | case 'o': | |||
276 | if (mfs) | |||
277 | getmntopts(optarg, mopts, &mntflags); | |||
278 | else { | |||
279 | if (strcmp(optarg, "space") == 0) | |||
280 | reqopt = opt = FS_OPTSPACE1; | |||
281 | else if (strcmp(optarg, "time") == 0) | |||
282 | reqopt = opt = FS_OPTTIME0; | |||
283 | else | |||
284 | fatal("%s: unknown optimization " | |||
285 | "preference: use `space' or `time'.", | |||
286 | optarg); | |||
287 | } | |||
288 | break; | |||
289 | case 'q': | |||
290 | quiet = 1; | |||
291 | break; | |||
292 | case 's': | |||
293 | if (scan_scaled(optarg, &fssize_input) == -1 || | |||
294 | fssize_input <= 0) | |||
295 | fatal("file system size invalid: %s", optarg); | |||
296 | fssize_usebytes = 0; /* in case of multiple -s */ | |||
297 | for (s1 = optarg; *s1 != '\0'; s1++) | |||
298 | if (isalpha((unsigned char)*s1)) { | |||
299 | fssize_usebytes = 1; | |||
300 | break; | |||
301 | } | |||
302 | break; | |||
303 | case 't': | |||
304 | fstype = optarg; | |||
305 | if (strcmp(fstype, "ffs")) | |||
306 | ffsflag = 0; | |||
307 | break; | |||
308 | #ifdef MFS1 | |||
309 | case 'P': | |||
310 | pop = optarg; | |||
311 | break; | |||
312 | #endif | |||
313 | case '?': | |||
314 | default: | |||
315 | usage(); | |||
316 | } | |||
317 | if (!ffsflag) | |||
318 | break; | |||
319 | } | |||
320 | argc -= optind; | |||
321 | argv += optind; | |||
322 | ||||
323 | if (ffsflag
| |||
324 | usage(); | |||
325 | ||||
326 | if (mfs
| |||
327 | /* Increase our data size to the max */ | |||
328 | if (getrlimit(RLIMIT_DATA2, &rl) == 0) { | |||
329 | rl.rlim_cur = rl.rlim_max; | |||
330 | (void)setrlimit(RLIMIT_DATA2, &rl); | |||
331 | } | |||
332 | } | |||
333 | ||||
334 | special = argv[0]; | |||
335 | ||||
336 | if (!mfs
| |||
337 | char execname[PATH_MAX1024], name[PATH_MAX1024]; | |||
338 | ||||
339 | if (fstype == NULL((void *)0)) | |||
340 | fstype = readlabelfs(special, 0); | |||
341 | if (fstype != NULL((void *)0) && strcmp(fstype, "ffs")) { | |||
342 | snprintf(name, sizeof name, "newfs_%s", fstype); | |||
343 | saveargv[0] = name; | |||
344 | snprintf(execname, sizeof execname, "%s/newfs_%s", | |||
345 | _PATH_SBIN"/sbin", fstype); | |||
346 | (void)execv(execname, saveargv); | |||
347 | snprintf(execname, sizeof execname, "%s/newfs_%s", | |||
348 | _PATH_USRSBIN"/usr/sbin", fstype); | |||
349 | (void)execv(execname, saveargv); | |||
350 | err(1, "%s not found", name); | |||
351 | } | |||
352 | } | |||
353 | ||||
354 | if (mfs
| |||
355 | /* | |||
356 | * it's an MFS, mounted on "swap." fake up a label. | |||
357 | * XXX XXX XXX | |||
358 | */ | |||
359 | fso = -1; /* XXX; normally done below. */ | |||
360 | ||||
361 | memset(&mfsfakelabel, 0, sizeof(mfsfakelabel)); | |||
362 | mfsfakelabel.d_secsize = 512; | |||
363 | mfsfakelabel.d_nsectors = 64; | |||
364 | mfsfakelabel.d_ntracks = 16; | |||
365 | mfsfakelabel.d_ncylinders = 16; | |||
366 | mfsfakelabel.d_secpercyl = 1024; | |||
367 | DL_SETDSIZE(&mfsfakelabel, 16384)do { u_int64_t __x = (16384); (&mfsfakelabel)->d_secperunith = __x >> 32; (&mfsfakelabel)->d_secperunit = __x ; } while (0); | |||
368 | mfsfakelabel.d_npartitions = 1; | |||
369 | mfsfakelabel.d_version = 1; | |||
370 | DL_SETPSIZE(&mfsfakelabel.d_partitions[0], 16384)do { u_int64_t __x = (16384); (&mfsfakelabel.d_partitions [0])->p_sizeh = __x >> 32; (&mfsfakelabel.d_partitions [0])->p_size = __x; } while (0); | |||
371 | mfsfakelabel.d_partitions[0].p_fragblock = | |||
372 | DISKLABELV1_FFS_FRAGBLOCK(1024, 8)((1024) * (8) == 0 ? 0 : (((ffs((1024) * (8)) - 13) << 3 ) | (ffs(8)))); | |||
373 | mfsfakelabel.d_partitions[0].p_cpg = 16; | |||
374 | ||||
375 | lp = &mfsfakelabel; | |||
376 | pp = &mfsfakelabel.d_partitions[0]; | |||
377 | ||||
378 | goto havelabel; | |||
379 | } | |||
380 | if (Nflag) { | |||
381 | fso = -1; | |||
382 | } else { | |||
383 | fso = opendev(special, O_WRONLY0x0001, 0, &realdev); | |||
384 | if (fso == -1) | |||
385 | fatal("%s: %s", special, strerror(errno(*__errno()))); | |||
386 | special = realdev; | |||
387 | ||||
388 | /* Bail if target special is mounted */ | |||
389 | n = getmntinfo(&mp, MNT_NOWAIT2); | |||
390 | if (n == 0) | |||
391 | fatal("%s: getmntinfo: %s", special, strerror(errno(*__errno()))); | |||
392 | ||||
393 | len = sizeof(_PATH_DEV"/dev/") - 1; | |||
394 | s1 = special; | |||
395 | if (strncmp(_PATH_DEV"/dev/", s1, len) == 0) | |||
396 | s1 += len; | |||
397 | ||||
398 | while (--n >= 0) { | |||
399 | s2 = mp->f_mntfromname; | |||
400 | if (strncmp(_PATH_DEV"/dev/", s2, len) == 0) { | |||
401 | s2 += len - 1; | |||
402 | *s2 = 'r'; | |||
403 | } | |||
404 | if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) | |||
405 | fatal("%s is mounted on %s", | |||
406 | special, mp->f_mntonname); | |||
407 | ++mp; | |||
408 | } | |||
409 | } | |||
410 | if (mfs
| |||
411 | lp = (struct disklabel *)getdiskbyname(disktype); | |||
412 | if (lp == NULL((void *)0)) | |||
413 | fatal("%s: unknown disk type", disktype); | |||
414 | pp = &lp->d_partitions[1]; | |||
415 | } else { | |||
416 | fsi = opendev(special, O_RDONLY0x0000, 0, NULL((void *)0)); | |||
417 | if (fsi == -1) | |||
418 | fatal("%s: %s", special, strerror(errno(*__errno()))); | |||
419 | if (fstat(fsi, &st) == -1) | |||
420 | fatal("%s: %s", special, strerror(errno(*__errno()))); | |||
421 | if (!mfs) { | |||
422 | if (S_ISBLK(st.st_mode)((st.st_mode & 0170000) == 0060000)) | |||
423 | fatal("%s: block device", special); | |||
424 | if (!S_ISCHR(st.st_mode)((st.st_mode & 0170000) == 0020000)) | |||
425 | warnx("%s: not a character-special device", | |||
426 | special); | |||
427 | } | |||
428 | if (*argv[0] == '\0') | |||
429 | fatal("empty partition name supplied"); | |||
430 | cp = argv[0] + strlen(argv[0]) - 1; | |||
431 | if ((*cp < 'a' || *cp > ('a' + maxpartitions - 1)) | |||
432 | && !isdigit((unsigned char)*cp)) | |||
433 | fatal("%s: can't figure out file system partition", | |||
434 | argv[0]); | |||
435 | lp = getdisklabel(special, fsi); | |||
436 | if (!mfs) { | |||
437 | if (pledge("stdio disklabel tty", NULL((void *)0)) == -1) | |||
438 | err(1, "pledge"); | |||
439 | } | |||
440 | if (isdigit((unsigned char)*cp)) | |||
441 | pp = &lp->d_partitions[0]; | |||
442 | else | |||
443 | pp = &lp->d_partitions[*cp - 'a']; | |||
444 | if (DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size) == 0) | |||
445 | fatal("%s: `%c' partition is unavailable", | |||
446 | argv[0], *cp); | |||
447 | } | |||
448 | havelabel: | |||
449 | if (sectorsize == 0) { | |||
450 | sectorsize = lp->d_secsize; | |||
451 | if (sectorsize <= 0) | |||
452 | fatal("%s: no default sector size", argv[0]); | |||
453 | } | |||
454 | ||||
455 | if (fssize_usebytes
| |||
456 | nsecs = fssize_input / sectorsize; | |||
457 | if (fssize_input % sectorsize != 0) | |||
458 | nsecs++; | |||
459 | } else if (fssize_input
| |||
460 | nsecs = DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size); | |||
| ||||
461 | else | |||
462 | nsecs = fssize_input; | |||
463 | ||||
464 | if (nsecs > DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size) && !mfs) | |||
465 | fatal("%s: maximum file system size on the `%c' partition is " | |||
466 | "%llu sectors", argv[0], *cp, DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size)); | |||
467 | ||||
468 | /* Can't use DL_SECTOBLK() because sectorsize may not be from label! */ | |||
469 | fssize = nsecs * (sectorsize / DEV_BSIZE(1 << 9)); | |||
470 | if (oflagset == 0 && fssize >= INT_MAX2147483647) | |||
471 | Oflag = 2; /* FFS2 */ | |||
472 | defaultfsize = fsize == 0; | |||
473 | if (fsize == 0) { | |||
474 | fsize = DISKLABELV1_FFS_FSIZE(pp->p_fragblock)(((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock ) & 0x07) - 1))) == 0 ? 0 : (((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock) >> 3) + 12))) / ((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock ) & 0x07) - 1))))); | |||
475 | if (fsize <= 0) | |||
476 | fsize = MAXIMUM(DFL_FRAGSIZE, lp->d_secsize)(((2048) > (lp->d_secsize)) ? (2048) : (lp->d_secsize )); | |||
477 | } | |||
478 | if (bsize == 0) { | |||
479 | bsize = DISKLABELV1_FFS_BSIZE(pp->p_fragblock)((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock ) >> 3) + 12))); | |||
480 | if (bsize <= 0) | |||
481 | bsize = MINIMUM(DFL_BLKSIZE, 8 * fsize)(((16384) < (8 * fsize)) ? (16384) : (8 * fsize)); | |||
482 | } | |||
483 | if (density == 0) { | |||
484 | density = NFPI4 * fsize; | |||
485 | /* large sectors lead to fewer inodes due to large fsize, | |||
486 | compensate */ | |||
487 | if (defaultfsize && sectorsize > DEV_BSIZE(1 << 9)) | |||
488 | density /= 2; | |||
489 | } | |||
490 | if (minfree < MINFREE5 && opt != FS_OPTSPACE1 && reqopt == -1) { | |||
491 | warnx("warning: changing optimization to space " | |||
492 | "because minfree is less than %d%%\n", MINFREE5); | |||
493 | opt = FS_OPTSPACE1; | |||
494 | } | |||
495 | if (maxbpg == 0) { | |||
496 | if (Oflag <= 1) | |||
497 | maxbpg = MAXBLKPG_FFS1(bsize)((bsize) / sizeof(int32_t)); | |||
498 | else | |||
499 | maxbpg = MAXBLKPG_FFS2(bsize)((bsize) / sizeof(int64_t)); | |||
500 | } | |||
501 | oldpartition = *pp; | |||
502 | #ifdef MFS1 | |||
503 | if (mfs) { | |||
504 | if (realpath(argv[1], node) == NULL((void *)0)) | |||
505 | err(1, "realpath %s", argv[1]); | |||
506 | if (stat(node, &mountpoint) == -1) | |||
507 | err(ECANCELED88, "stat %s", node); | |||
508 | mfsuid = mountpoint.st_uid; | |||
509 | mfsgid = mountpoint.st_gid; | |||
510 | mfsmode = mountpoint.st_mode & ALLPERMS(0004000|0002000|0001000|0000700|0000070|0000007); | |||
511 | } | |||
512 | #endif | |||
513 | ||||
514 | mkfs(pp, special, fsi, fso, mfsmode, mfsuid, mfsgid); | |||
515 | if (!Nflag && memcmp(pp, &oldpartition, sizeof(oldpartition))) | |||
516 | rewritelabel(special, fso, lp); | |||
517 | if (!Nflag) | |||
518 | close(fso); | |||
519 | if (fsi != -1) | |||
520 | close(fsi); | |||
521 | #ifdef MFS1 | |||
522 | if (mfs) { | |||
523 | struct mfs_args args; | |||
524 | char tmpnode[PATH_MAX1024]; | |||
525 | ||||
526 | if (pop != NULL((void *)0) && gettmpmnt(tmpnode, sizeof(tmpnode)) == 0) | |||
527 | errx(1, "Cannot create tmp mountpoint for -P"); | |||
528 | memset(&args, 0, sizeof(args)); | |||
529 | args.base = membase; | |||
530 | args.size = fssize * DEV_BSIZE(1 << 9); | |||
531 | args.export_info.ex_root = -2; | |||
532 | if (mntflags & MNT_RDONLY0x00000001) | |||
533 | args.export_info.ex_flags = MNT_EXRDONLY0x00000080; | |||
534 | if (mntflags & MNT_NOPERM0x00000020) | |||
535 | mntflags |= MNT_NODEV0x00000010 | MNT_NOEXEC0x00000004; | |||
536 | ||||
537 | switch (pid = fork()) { | |||
538 | case -1: | |||
539 | err(10, "mfs"); | |||
540 | case 0: | |||
541 | snprintf(mountfromname, sizeof(mountfromname), | |||
542 | "mfs:%d", getpid()); | |||
543 | break; | |||
544 | default: | |||
545 | if (pop != NULL((void *)0)) { | |||
546 | waitformount(tmpnode, pid); | |||
547 | copy(pop, tmpnode); | |||
548 | unmount(tmpnode, 0); | |||
549 | rmdir(tmpnode); | |||
550 | } | |||
551 | waitformount(node, pid); | |||
552 | exit(0); | |||
553 | /* NOTREACHED */ | |||
554 | } | |||
555 | ||||
556 | (void) setsid(); | |||
557 | (void) close(0); | |||
558 | (void) close(1); | |||
559 | (void) close(2); | |||
560 | (void) chdir("/"); | |||
561 | ||||
562 | args.fspec = mountfromname; | |||
563 | if (pop != NULL((void *)0)) { | |||
564 | int tmpflags = mntflags & ~MNT_RDONLY0x00000001; | |||
565 | if (mount(MOUNT_MFS"mfs", tmpnode, tmpflags, &args) == -1) | |||
566 | exit(errno(*__errno())); /* parent prints message */ | |||
567 | } | |||
568 | if (mount(MOUNT_MFS"mfs", node, mntflags, &args) == -1) | |||
569 | exit(errno(*__errno())); /* parent prints message */ | |||
570 | } | |||
571 | #endif | |||
572 | exit(0); | |||
573 | } | |||
574 | ||||
575 | struct disklabel * | |||
576 | getdisklabel(char *s, int fd) | |||
577 | { | |||
578 | static struct disklabel lab; | |||
579 | ||||
580 | if (ioctl(fd, DIOCGDINFO((unsigned long)0x40000000 | ((sizeof(struct disklabel) & 0x1fff) << 16) | ((('d')) << 8) | ((101))), (char *)&lab) == -1) { | |||
581 | if (disktype != NULL((void *)0)) { | |||
582 | struct disklabel *lp; | |||
583 | ||||
584 | unlabeled++; | |||
585 | lp = getdiskbyname(disktype); | |||
586 | if (lp == NULL((void *)0)) | |||
587 | fatal("%s: unknown disk type", disktype); | |||
588 | return (lp); | |||
589 | } | |||
590 | warn("ioctl (GDINFO)"); | |||
591 | fatal("%s: can't read disk label; disk type must be specified", | |||
592 | s); | |||
593 | } | |||
594 | return (&lab); | |||
595 | } | |||
596 | ||||
597 | void | |||
598 | rewritelabel(char *s, int fd, struct disklabel *lp) | |||
599 | { | |||
600 | if (unlabeled) | |||
601 | return; | |||
602 | ||||
603 | lp->d_checksum = 0; | |||
604 | lp->d_checksum = dkcksum(lp); | |||
605 | if (ioctl(fd, DIOCWDINFO((unsigned long)0x80000000 | ((sizeof(struct disklabel) & 0x1fff) << 16) | ((('d')) << 8) | ((103))), (char *)lp) == -1) { | |||
606 | warn("ioctl (WDINFO)"); | |||
607 | fatal("%s: can't rewrite disk label", s); | |||
608 | } | |||
609 | } | |||
610 | ||||
611 | void | |||
612 | fatal(const char *fmt, ...) | |||
613 | { | |||
614 | va_list ap; | |||
615 | ||||
616 | va_start(ap, fmt)__builtin_va_start(ap, fmt); | |||
617 | if (fcntl(STDERR_FILENO2, F_GETFL3) == -1) { | |||
618 | openlog(__progname, LOG_CONS0x02, LOG_DAEMON(3<<3)); | |||
619 | vsyslog(LOG_ERR3, fmt, ap); | |||
620 | closelog(); | |||
621 | } else { | |||
622 | vwarnx(fmt, ap); | |||
623 | } | |||
624 | va_end(ap)__builtin_va_end(ap); | |||
625 | exit(1); | |||
626 | /*NOTREACHED*/ | |||
627 | } | |||
628 | ||||
629 | __dead__attribute__((__noreturn__)) void | |||
630 | usage(void) | |||
631 | { | |||
632 | extern char *__progname; | |||
633 | ||||
634 | if (mfs) { | |||
635 | fprintf(stderr(&__sF[2]), | |||
636 | "usage: %s [-b block-size] [-c fragments-per-cylinder-group] " | |||
637 | "[-e maxbpg]\n" | |||
638 | "\t[-f frag-size] [-i bytes] [-m free-space] [-o options] " | |||
639 | "[-P file]\n" | |||
640 | "\t[-s size] special node\n", | |||
641 | __progname); | |||
642 | } else { | |||
643 | fprintf(stderr(&__sF[2]), | |||
644 | "usage: %s [-Nq] [-b block-size] " | |||
645 | "[-c fragments-per-cylinder-group] [-e maxbpg]\n" | |||
646 | "\t[-f frag-size] [-g avgfilesize] [-h avgfpdir] [-i bytes]\n" | |||
647 | "\t[-m free-space] [-O filesystem-format] [-o optimization]\n" | |||
648 | "\t[-S sector-size] [-s size] [-T disktype] [-t fstype] " | |||
649 | "special\n", | |||
650 | __progname); | |||
651 | } | |||
652 | ||||
653 | exit(1); | |||
654 | } | |||
655 | ||||
656 | #ifdef MFS1 | |||
657 | ||||
658 | static void | |||
659 | waitformount(char *node, pid_t pid) | |||
660 | { | |||
661 | char mountfromname[BUFSIZ1024]; | |||
662 | struct statfs sf; | |||
663 | int status; | |||
664 | pid_t res; | |||
665 | ||||
666 | snprintf(mountfromname, sizeof(mountfromname), "mfs:%d", pid); | |||
667 | for (;;) { | |||
668 | /* | |||
669 | * spin until the mount succeeds | |||
670 | * or the child exits | |||
671 | */ | |||
672 | usleep(1); | |||
673 | ||||
674 | /* | |||
675 | * XXX Here is a race condition: another process | |||
676 | * can mount a filesystem which hides our | |||
677 | * ramdisk before we see the success. | |||
678 | */ | |||
679 | if (statfs(node, &sf) == -1) | |||
680 | err(ECANCELED88, "statfs %s", node); | |||
681 | if (!strcmp(sf.f_mntfromname, mountfromname) && | |||
682 | !strncmp(sf.f_mntonname, node, | |||
683 | MNAMELEN90) && | |||
684 | !strcmp(sf.f_fstypename, "mfs")) { | |||
685 | return; | |||
686 | } | |||
687 | res = waitpid(pid, &status, WNOHANG1); | |||
688 | if (res == -1) | |||
689 | err(EDEADLK11, "waitpid"); | |||
690 | if (res != pid) | |||
691 | continue; | |||
692 | if (WIFEXITED(status)(((status) & 0177) == 0)) { | |||
693 | if (WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff) == 0) | |||
694 | exit(0); | |||
695 | errx(1, "%s: mount: %s", node, | |||
696 | strerror(WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff))); | |||
697 | } else | |||
698 | errx(EDEADLK11, "abnormal termination"); | |||
699 | } | |||
700 | } | |||
701 | ||||
702 | static int | |||
703 | do_exec(const char *dir, const char *cmd, char *const argv[]) | |||
704 | { | |||
705 | pid_t pid; | |||
706 | int ret, status; | |||
707 | sig_t intsave, quitsave; | |||
708 | ||||
709 | switch (pid = fork()) { | |||
710 | case -1: | |||
711 | err(1, "fork"); | |||
712 | case 0: | |||
713 | if (dir != NULL((void *)0) && chdir(dir) != 0) | |||
714 | err(1, "chdir"); | |||
715 | if (execv(cmd, argv) != 0) | |||
716 | err(1, "%s", cmd); | |||
717 | break; | |||
718 | default: | |||
719 | intsave = signal(SIGINT2, SIG_IGN(void (*)(int))1); | |||
720 | quitsave = signal(SIGQUIT3, SIG_IGN(void (*)(int))1); | |||
721 | for (;;) { | |||
722 | ret = waitpid(pid, &status, 0); | |||
723 | if (ret == -1) | |||
724 | err(11, "waitpid"); | |||
725 | if (WIFEXITED(status)(((status) & 0177) == 0)) { | |||
726 | status = WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff); | |||
727 | if (status != 0) | |||
728 | warnx("%s: exited", cmd); | |||
729 | break; | |||
730 | } else if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177 ) != 0)) { | |||
731 | warnx("%s: %s", cmd, | |||
732 | strsignal(WTERMSIG(status)(((status) & 0177)))); | |||
733 | status = 1; | |||
734 | break; | |||
735 | } | |||
736 | } | |||
737 | signal(SIGINT2, intsave); | |||
738 | signal(SIGQUIT3, quitsave); | |||
739 | return (status); | |||
740 | } | |||
741 | /* NOTREACHED */ | |||
742 | return (-1); | |||
743 | } | |||
744 | ||||
745 | static int | |||
746 | isdir(const char *path) | |||
747 | { | |||
748 | struct stat st; | |||
749 | ||||
750 | if (stat(path, &st) != 0) | |||
751 | err(1, "cannot stat %s", path); | |||
752 | if (!S_ISDIR(st.st_mode)((st.st_mode & 0170000) == 0040000) && !S_ISBLK(st.st_mode)((st.st_mode & 0170000) == 0060000)) | |||
753 | errx(1, "%s: not a dir or a block device", path); | |||
754 | return (S_ISDIR(st.st_mode)((st.st_mode & 0170000) == 0040000)); | |||
755 | } | |||
756 | ||||
757 | static void | |||
758 | copy(char *src, char *dst) | |||
759 | { | |||
760 | int ret, dir, created = 0; | |||
761 | struct ufs_args mount_args; | |||
762 | char mountpoint[MNAMELEN90]; | |||
763 | char *const argv[] = { "pax", "-rw", "-pe", ".", dst, NULL((void *)0) } ; | |||
764 | ||||
765 | dir = isdir(src); | |||
766 | if (dir) | |||
767 | strlcpy(mountpoint, src, sizeof(mountpoint)); | |||
768 | else { | |||
769 | created = gettmpmnt(mountpoint, sizeof(mountpoint)); | |||
770 | memset(&mount_args, 0, sizeof(mount_args)); | |||
771 | mount_args.fspec = src; | |||
772 | ret = mount(MOUNT_FFS"ffs", mountpoint, MNT_RDONLY0x00000001, &mount_args); | |||
773 | if (ret != 0) { | |||
774 | int saved_errno = errno(*__errno()); | |||
775 | if (created && rmdir(mountpoint) != 0) | |||
776 | warn("rmdir %s", mountpoint); | |||
777 | if (unmount(dst, 0) != 0) | |||
778 | warn("unmount %s", dst); | |||
779 | errc(1, saved_errno, "mount %s %s", src, mountpoint); | |||
780 | } | |||
781 | } | |||
782 | ret = do_exec(mountpoint, "/bin/pax", argv); | |||
783 | if (!dir && unmount(mountpoint, 0) != 0) | |||
784 | warn("unmount %s", mountpoint); | |||
785 | if (created && rmdir(mountpoint) != 0) | |||
786 | warn("rmdir %s", mountpoint); | |||
787 | if (ret != 0) { | |||
788 | if (unmount(dst, 0) != 0) | |||
789 | warn("unmount %s", dst); | |||
790 | errx(1, "copy %s to %s failed", mountpoint, dst); | |||
791 | } | |||
792 | } | |||
793 | ||||
794 | static int | |||
795 | gettmpmnt(char *mountpoint, size_t len) | |||
796 | { | |||
797 | const char *tmp = _PATH_TMP"/tmp/"; | |||
798 | const char *mnt = _PATH_MNT"/mnt"; | |||
799 | struct statfs fs; | |||
800 | size_t n; | |||
801 | ||||
802 | if (statfs(tmp, &fs) != 0) | |||
803 | err(1, "statfs %s", tmp); | |||
804 | if (fs.f_flags & MNT_RDONLY0x00000001) { | |||
805 | if (statfs(mnt, &fs) != 0) | |||
806 | err(1, "statfs %s", mnt); | |||
807 | if (strcmp(fs.f_mntonname, "/") != 0) | |||
808 | errx(1, "tmp mountpoint %s busy", mnt); | |||
809 | if (strlcpy(mountpoint, mnt, len) >= len) | |||
810 | errx(1, "tmp mountpoint %s too long", mnt); | |||
811 | return (0); | |||
812 | } | |||
813 | n = strlcpy(mountpoint, tmp, len); | |||
814 | if (n >= len) | |||
815 | errx(1, "tmp mount point too long"); | |||
816 | if (mountpoint[n - 1] != '/') | |||
817 | strlcat(mountpoint, "/", len); | |||
818 | n = strlcat(mountpoint, "mntXXXXXXXXXX", len); | |||
819 | if (n >= len) | |||
820 | errx(1, "tmp mount point too long"); | |||
821 | if (mkdtemp(mountpoint) == NULL((void *)0)) | |||
822 | err(1, "mkdtemp %s", mountpoint); | |||
823 | return (1); | |||
824 | } | |||
825 | ||||
826 | #endif /* MFS */ |