Deleted Added
full compact
newfs.c (204615) newfs.c (204654)
1/*
2 * Copyright (c) 2002 Networks Associates Technology, Inc.
3 * All rights reserved.
4 *
5 * This software was developed for the FreeBSD Project by Marshall
6 * Kirk McKusick and Network Associates Laboratories, the Security
7 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
8 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
9 * research program.
10 *
11 * Copyright (c) 1983, 1989, 1993, 1994
12 * The Regents of the University of California. All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39#if 0
40#ifndef lint
41static const char copyright[] =
42"@(#) Copyright (c) 1983, 1989, 1993, 1994\n\
43 The Regents of the University of California. All rights reserved.\n";
44#endif /* not lint */
45
46#ifndef lint
47static char sccsid[] = "@(#)newfs.c 8.13 (Berkeley) 5/1/95";
48#endif /* not lint */
49#endif
50#include <sys/cdefs.h>
1/*
2 * Copyright (c) 2002 Networks Associates Technology, Inc.
3 * All rights reserved.
4 *
5 * This software was developed for the FreeBSD Project by Marshall
6 * Kirk McKusick and Network Associates Laboratories, the Security
7 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
8 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
9 * research program.
10 *
11 * Copyright (c) 1983, 1989, 1993, 1994
12 * The Regents of the University of California. All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39#if 0
40#ifndef lint
41static const char copyright[] =
42"@(#) Copyright (c) 1983, 1989, 1993, 1994\n\
43 The Regents of the University of California. All rights reserved.\n";
44#endif /* not lint */
45
46#ifndef lint
47static char sccsid[] = "@(#)newfs.c 8.13 (Berkeley) 5/1/95";
48#endif /* not lint */
49#endif
50#include <sys/cdefs.h>
51__FBSDID("$FreeBSD: head/sbin/newfs/newfs.c 204615 2010-03-03 02:05:09Z sobomax $");
51__FBSDID("$FreeBSD: head/sbin/newfs/newfs.c 204654 2010-03-03 19:25:28Z sobomax $");
52
53/*
54 * newfs: friendly front end to mkfs
55 */
56#include <sys/param.h>
57#include <sys/stat.h>
58#include <sys/disk.h>
59#include <sys/disklabel.h>
60#include <sys/file.h>
61#include <sys/mount.h>
62
63#include <ufs/ufs/dir.h>
64#include <ufs/ufs/dinode.h>
65#include <ufs/ffs/fs.h>
66#include <ufs/ufs/ufsmount.h>
67
68#include <ctype.h>
69#include <err.h>
70#include <errno.h>
71#include <inttypes.h>
72#include <paths.h>
73#include <stdarg.h>
74#include <stdio.h>
75#include <stdlib.h>
76#include <string.h>
77#include <syslog.h>
78#include <unistd.h>
79
52
53/*
54 * newfs: friendly front end to mkfs
55 */
56#include <sys/param.h>
57#include <sys/stat.h>
58#include <sys/disk.h>
59#include <sys/disklabel.h>
60#include <sys/file.h>
61#include <sys/mount.h>
62
63#include <ufs/ufs/dir.h>
64#include <ufs/ufs/dinode.h>
65#include <ufs/ffs/fs.h>
66#include <ufs/ufs/ufsmount.h>
67
68#include <ctype.h>
69#include <err.h>
70#include <errno.h>
71#include <inttypes.h>
72#include <paths.h>
73#include <stdarg.h>
74#include <stdio.h>
75#include <stdlib.h>
76#include <string.h>
77#include <syslog.h>
78#include <unistd.h>
79
80#include <libutil.h>
81
80#include "newfs.h"
81
82int Eflag; /* Erase previous disk contents */
83int Lflag; /* add a volume label */
84int Nflag; /* run without writing file system */
85int Oflag = 2; /* file system format (1 => UFS1, 2 => UFS2) */
86int Rflag; /* regression test */
87int Uflag; /* enable soft updates for file system */
88int Xflag = 0; /* exit in middle of newfs for testing */
89int Jflag; /* enable gjournal for file system */
90int lflag; /* enable multilabel for file system */
91int nflag; /* do not create .snap directory */
92intmax_t fssize; /* file system size */
82#include "newfs.h"
83
84int Eflag; /* Erase previous disk contents */
85int Lflag; /* add a volume label */
86int Nflag; /* run without writing file system */
87int Oflag = 2; /* file system format (1 => UFS1, 2 => UFS2) */
88int Rflag; /* regression test */
89int Uflag; /* enable soft updates for file system */
90int Xflag = 0; /* exit in middle of newfs for testing */
91int Jflag; /* enable gjournal for file system */
92int lflag; /* enable multilabel for file system */
93int nflag; /* do not create .snap directory */
94intmax_t fssize; /* file system size */
93int sectorsize; /* bytes/sector */
95int64_t sectorsize; /* bytes/sector */
94int realsectorsize; /* bytes/sector in hardware */
96int realsectorsize; /* bytes/sector in hardware */
95int fsize = 0; /* fragment size */
96int bsize = 0; /* block size */
97int maxbsize = 0; /* maximum clustering */
98int maxblkspercg = MAXBLKSPERCG; /* maximum blocks per cylinder group */
97int64_t fsize = 0; /* fragment size */
98int64_t bsize = 0; /* block size */
99int64_t maxbsize = 0; /* maximum clustering */
100int64_t maxblkspercg = MAXBLKSPERCG; /* maximum blocks per cylinder group */
99int minfree = MINFREE; /* free space threshold */
100int opt = DEFAULTOPT; /* optimization preference (space or time) */
101int minfree = MINFREE; /* free space threshold */
102int opt = DEFAULTOPT; /* optimization preference (space or time) */
101int density; /* number of bytes per inode */
102int maxcontig = 0; /* max contiguous blocks to allocate */
103int maxbpg; /* maximum blocks per file in a cyl group */
104int avgfilesize = AVFILESIZ;/* expected average file size */
105int avgfilesperdir = AFPDIR;/* expected number of files per directory */
103int64_t density; /* number of bytes per inode */
104int64_t maxcontig = 0; /* max contiguous blocks to allocate */
105int64_t maxbpg; /* maximum blocks per file in a cyl group */
106int64_t avgfilesize = AVFILESIZ;/* expected average file size */
107int64_t avgfilesperdir = AFPDIR;/* expected number of files per directory */
106u_char *volumelabel = NULL; /* volume label for filesystem */
107struct uufsd disk; /* libufs disk structure */
108
109static char device[MAXPATHLEN];
110static u_char bootarea[BBSIZE];
111static int is_file; /* work on a file, not a device */
112static char *dkname;
113static char *disktype;
114static int unlabeled;
115
116static void getfssize(intmax_t *, const char *p, intmax_t, intmax_t);
117static struct disklabel *getdisklabel(char *s);
118static void rewritelabel(char *s, struct disklabel *lp);
119static void usage(void);
108u_char *volumelabel = NULL; /* volume label for filesystem */
109struct uufsd disk; /* libufs disk structure */
110
111static char device[MAXPATHLEN];
112static u_char bootarea[BBSIZE];
113static int is_file; /* work on a file, not a device */
114static char *dkname;
115static char *disktype;
116static int unlabeled;
117
118static void getfssize(intmax_t *, const char *p, intmax_t, intmax_t);
119static struct disklabel *getdisklabel(char *s);
120static void rewritelabel(char *s, struct disklabel *lp);
121static void usage(void);
120static int parselength(const char *ls, int *sz);
121
122ufs2_daddr_t part_ofs; /* partition offset in blocks, used with files */
123
124int
125main(int argc, char *argv[])
126{
127 struct partition *pp;
128 struct disklabel *lp;
129 struct partition oldpartition;
130 struct stat st;
131 char *cp, *special;
132 intmax_t reserved;
133 int ch, i, rval;
134 off_t mediasize;
135 char part_name; /* partition name, default to full disk */
136
137 part_name = 'c';
138 reserved = 0;
139 while ((ch = getopt(argc, argv,
140 "EJL:NO:RS:T:UXa:b:c:d:e:f:g:h:i:lm:no:r:s:")) != -1)
141 switch (ch) {
142 case 'E':
143 Eflag = 1;
144 break;
145 case 'J':
146 Jflag = 1;
147 break;
148 case 'L':
149 volumelabel = optarg;
150 i = -1;
151 while (isalnum(volumelabel[++i]));
152 if (volumelabel[i] != '\0') {
153 errx(1, "bad volume label. Valid characters are alphanumerics.");
154 }
155 if (strlen(volumelabel) >= MAXVOLLEN) {
156 errx(1, "bad volume label. Length is longer than %d.",
157 MAXVOLLEN);
158 }
159 Lflag = 1;
160 break;
161 case 'N':
162 Nflag = 1;
163 break;
164 case 'O':
165 if ((Oflag = atoi(optarg)) < 1 || Oflag > 2)
166 errx(1, "%s: bad file system format value",
167 optarg);
168 break;
169 case 'R':
170 Rflag = 1;
171 break;
172 case 'S':
122
123ufs2_daddr_t part_ofs; /* partition offset in blocks, used with files */
124
125int
126main(int argc, char *argv[])
127{
128 struct partition *pp;
129 struct disklabel *lp;
130 struct partition oldpartition;
131 struct stat st;
132 char *cp, *special;
133 intmax_t reserved;
134 int ch, i, rval;
135 off_t mediasize;
136 char part_name; /* partition name, default to full disk */
137
138 part_name = 'c';
139 reserved = 0;
140 while ((ch = getopt(argc, argv,
141 "EJL:NO:RS:T:UXa:b:c:d:e:f:g:h:i:lm:no:r:s:")) != -1)
142 switch (ch) {
143 case 'E':
144 Eflag = 1;
145 break;
146 case 'J':
147 Jflag = 1;
148 break;
149 case 'L':
150 volumelabel = optarg;
151 i = -1;
152 while (isalnum(volumelabel[++i]));
153 if (volumelabel[i] != '\0') {
154 errx(1, "bad volume label. Valid characters are alphanumerics.");
155 }
156 if (strlen(volumelabel) >= MAXVOLLEN) {
157 errx(1, "bad volume label. Length is longer than %d.",
158 MAXVOLLEN);
159 }
160 Lflag = 1;
161 break;
162 case 'N':
163 Nflag = 1;
164 break;
165 case 'O':
166 if ((Oflag = atoi(optarg)) < 1 || Oflag > 2)
167 errx(1, "%s: bad file system format value",
168 optarg);
169 break;
170 case 'R':
171 Rflag = 1;
172 break;
173 case 'S':
173 rval = parselength(optarg, &sectorsize);
174 rval = expand_number(optarg, &sectorsize);
174 if (rval < 0 || sectorsize <= 0)
175 errx(1, "%s: bad sector size", optarg);
176 break;
177 case 'T':
178 disktype = optarg;
179 break;
180 case 'U':
181 Uflag = 1;
182 break;
183 case 'X':
184 Xflag++;
185 break;
186 case 'a':
175 if (rval < 0 || sectorsize <= 0)
176 errx(1, "%s: bad sector size", optarg);
177 break;
178 case 'T':
179 disktype = optarg;
180 break;
181 case 'U':
182 Uflag = 1;
183 break;
184 case 'X':
185 Xflag++;
186 break;
187 case 'a':
187 rval = parselength(optarg, &maxcontig);
188 rval = expand_number(optarg, &maxcontig);
188 if (rval < 0 || maxcontig <= 0)
189 errx(1, "%s: bad maximum contiguous blocks",
190 optarg);
191 break;
192 case 'b':
189 if (rval < 0 || maxcontig <= 0)
190 errx(1, "%s: bad maximum contiguous blocks",
191 optarg);
192 break;
193 case 'b':
193 rval = parselength(optarg, &bsize);
194 rval = expand_number(optarg, &bsize);
194 if (rval < 0)
195 errx(1, "%s: bad block size",
196 optarg);
197 if (bsize < MINBSIZE)
198 errx(1, "%s: block size too small, min is %d",
199 optarg, MINBSIZE);
200 if (bsize > MAXBSIZE)
201 errx(1, "%s: block size too large, max is %d",
202 optarg, MAXBSIZE);
203 break;
204 case 'c':
195 if (rval < 0)
196 errx(1, "%s: bad block size",
197 optarg);
198 if (bsize < MINBSIZE)
199 errx(1, "%s: block size too small, min is %d",
200 optarg, MINBSIZE);
201 if (bsize > MAXBSIZE)
202 errx(1, "%s: block size too large, max is %d",
203 optarg, MAXBSIZE);
204 break;
205 case 'c':
205 rval = parselength(optarg, &maxblkspercg);
206 rval = expand_number(optarg, &maxblkspercg);
206 if (rval < 0 || maxblkspercg <= 0)
207 errx(1, "%s: bad blocks per cylinder group",
208 optarg);
209 break;
210 case 'd':
207 if (rval < 0 || maxblkspercg <= 0)
208 errx(1, "%s: bad blocks per cylinder group",
209 optarg);
210 break;
211 case 'd':
211 rval = parselength(optarg, &maxbsize);
212 rval = expand_number(optarg, &maxbsize);
212 if (rval < 0 || maxbsize < MINBSIZE)
213 errx(1, "%s: bad extent block size", optarg);
214 break;
215 case 'e':
213 if (rval < 0 || maxbsize < MINBSIZE)
214 errx(1, "%s: bad extent block size", optarg);
215 break;
216 case 'e':
216 rval = parselength(optarg, &maxbpg);
217 rval = expand_number(optarg, &maxbpg);
217 if (rval < 0 || maxbpg <= 0)
218 errx(1, "%s: bad blocks per file in a cylinder group",
219 optarg);
220 break;
221 case 'f':
218 if (rval < 0 || maxbpg <= 0)
219 errx(1, "%s: bad blocks per file in a cylinder group",
220 optarg);
221 break;
222 case 'f':
222 rval = parselength(optarg, &fsize);
223 rval = expand_number(optarg, &fsize);
223 if (rval < 0 || fsize <= 0)
224 errx(1, "%s: bad fragment size", optarg);
225 break;
226 case 'g':
224 if (rval < 0 || fsize <= 0)
225 errx(1, "%s: bad fragment size", optarg);
226 break;
227 case 'g':
227 rval = parselength(optarg, &avgfilesize);
228 rval = expand_number(optarg, &avgfilesize);
228 if (rval < 0 || avgfilesize <= 0)
229 errx(1, "%s: bad average file size", optarg);
230 break;
231 case 'h':
229 if (rval < 0 || avgfilesize <= 0)
230 errx(1, "%s: bad average file size", optarg);
231 break;
232 case 'h':
232 rval = parselength(optarg, &avgfilesperdir);
233 rval = expand_number(optarg, &avgfilesperdir);
233 if (rval < 0 || avgfilesperdir <= 0)
234 errx(1, "%s: bad average files per dir", optarg);
235 break;
236 case 'i':
234 if (rval < 0 || avgfilesperdir <= 0)
235 errx(1, "%s: bad average files per dir", optarg);
236 break;
237 case 'i':
237 rval = parselength(optarg, &density);
238 rval = expand_number(optarg, &density);
238 if (rval < 0 || density <= 0)
239 errx(1, "%s: bad bytes per inode", optarg);
240 break;
241 case 'l':
242 lflag = 1;
243 break;
244 case 'm':
245 if ((minfree = atoi(optarg)) < 0 || minfree > 99)
246 errx(1, "%s: bad free space %%", optarg);
247 break;
248 case 'n':
249 nflag = 1;
250 break;
251 case 'o':
252 if (strcmp(optarg, "space") == 0)
253 opt = FS_OPTSPACE;
254 else if (strcmp(optarg, "time") == 0)
255 opt = FS_OPTTIME;
256 else
257 errx(1,
258 "%s: unknown optimization preference: use `space' or `time'",
259 optarg);
260 break;
261 case 'r':
262 errno = 0;
263 reserved = strtoimax(optarg, &cp, 0);
264 if (errno != 0 || cp == optarg ||
265 *cp != '\0' || reserved < 0)
266 errx(1, "%s: bad reserved size", optarg);
267 break;
268 case 'p':
269 is_file = 1;
270 part_name = optarg[0];
271 break;
272
273 case 's':
274 errno = 0;
275 fssize = strtoimax(optarg, &cp, 0);
276 if (errno != 0 || cp == optarg ||
277 *cp != '\0' || fssize < 0)
278 errx(1, "%s: bad file system size", optarg);
279 break;
280 case '?':
281 default:
282 usage();
283 }
284 argc -= optind;
285 argv += optind;
286
287 if (argc != 1)
288 usage();
289
290 special = argv[0];
291 if (!special[0])
292 err(1, "empty file/special name");
293 cp = strrchr(special, '/');
294 if (cp == 0) {
295 /*
296 * No path prefix; try prefixing _PATH_DEV.
297 */
298 snprintf(device, sizeof(device), "%s%s", _PATH_DEV, special);
299 special = device;
300 }
301
302 if (is_file) {
303 /* bypass ufs_disk_fillout_blank */
304 bzero( &disk, sizeof(disk));
305 disk.d_bsize = 1;
306 disk.d_name = special;
307 disk.d_fd = open(special, O_RDONLY);
308 if (disk.d_fd < 0 ||
309 (!Nflag && ufs_disk_write(&disk) == -1))
310 errx(1, "%s: ", special);
311 } else if (ufs_disk_fillout_blank(&disk, special) == -1 ||
312 (!Nflag && ufs_disk_write(&disk) == -1)) {
313 if (disk.d_error != NULL)
314 errx(1, "%s: %s", special, disk.d_error);
315 else
316 err(1, "%s", special);
317 }
318 if (fstat(disk.d_fd, &st) < 0)
319 err(1, "%s", special);
320 if ((st.st_mode & S_IFMT) != S_IFCHR) {
321 warn("%s: not a character-special device", special);
322 is_file = 1; /* assume it is a file */
323 dkname = special;
324 if (sectorsize == 0)
325 sectorsize = 512;
326 mediasize = st.st_size;
327 /* set fssize from the partition */
328 } else {
329 if (sectorsize == 0)
330 if (ioctl(disk.d_fd, DIOCGSECTORSIZE, &sectorsize) == -1)
331 sectorsize = 0; /* back out on error for safety */
332 if (sectorsize && ioctl(disk.d_fd, DIOCGMEDIASIZE, &mediasize) != -1)
333 getfssize(&fssize, special, mediasize / sectorsize, reserved);
334 }
335 pp = NULL;
336 lp = getdisklabel(special);
337 if (lp != NULL) {
338 if (!is_file) /* already set for files */
339 part_name = special[strlen(special) - 1];
340 if ((part_name < 'a' || part_name - 'a' >= MAXPARTITIONS) &&
341 !isdigit(part_name))
342 errx(1, "%s: can't figure out file system partition",
343 special);
344 cp = &part_name;
345 if (isdigit(*cp))
346 pp = &lp->d_partitions[RAW_PART];
347 else
348 pp = &lp->d_partitions[*cp - 'a'];
349 oldpartition = *pp;
350 if (pp->p_size == 0)
351 errx(1, "%s: `%c' partition is unavailable",
352 special, *cp);
353 if (pp->p_fstype == FS_BOOT)
354 errx(1, "%s: `%c' partition overlaps boot program",
355 special, *cp);
356 getfssize(&fssize, special, pp->p_size, reserved);
357 if (sectorsize == 0)
358 sectorsize = lp->d_secsize;
359 if (fsize == 0)
360 fsize = pp->p_fsize;
361 if (bsize == 0)
362 bsize = pp->p_frag * pp->p_fsize;
363 if (is_file)
364 part_ofs = pp->p_offset;
365 }
366 if (sectorsize <= 0)
367 errx(1, "%s: no default sector size", special);
368 if (fsize <= 0)
369 fsize = MAX(DFL_FRAGSIZE, sectorsize);
370 if (bsize <= 0)
371 bsize = MIN(DFL_BLKSIZE, 8 * fsize);
372 if (minfree < MINFREE && opt != FS_OPTSPACE) {
373 fprintf(stderr, "Warning: changing optimization to space ");
374 fprintf(stderr, "because minfree is less than %d%%\n", MINFREE);
375 opt = FS_OPTSPACE;
376 }
377 realsectorsize = sectorsize;
378 if (sectorsize != DEV_BSIZE) { /* XXX */
379 int secperblk = sectorsize / DEV_BSIZE;
380
381 sectorsize = DEV_BSIZE;
382 fssize *= secperblk;
383 if (pp != NULL)
384 pp->p_size *= secperblk;
385 }
386 mkfs(pp, special);
387 if (!unlabeled) {
388 if (realsectorsize != DEV_BSIZE)
389 pp->p_size /= realsectorsize / DEV_BSIZE;
390 if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
391 rewritelabel(special, lp);
392 }
393 ufs_disk_close(&disk);
394 exit(0);
395}
396
397void
398getfssize(intmax_t *fsz, const char *s, intmax_t disksize, intmax_t reserved)
399{
400 intmax_t available;
401
402 available = disksize - reserved;
403 if (available <= 0)
404 errx(1, "%s: reserved not less than device size %jd",
405 s, disksize);
406 if (*fsz == 0)
407 *fsz = available;
408 else if (*fsz > available)
409 errx(1, "%s: maximum file system size is %jd",
410 s, available);
411}
412
413struct disklabel *
414getdisklabel(char *s)
415{
416 static struct disklabel lab;
417 struct disklabel *lp;
418
419 if (is_file) {
420 if (read(disk.d_fd, bootarea, BBSIZE) != BBSIZE)
421 err(4, "cannot read bootarea");
422 if (bsd_disklabel_le_dec(
423 bootarea + (0 /* labeloffset */ +
424 1 /* labelsoffset */ * sectorsize),
425 &lab, MAXPARTITIONS))
426 errx(1, "no valid label found");
427
428 lp = &lab;
429 return &lab;
430 }
431
432 if (ioctl(disk.d_fd, DIOCGDINFO, (char *)&lab) != -1)
433 return (&lab);
434 unlabeled++;
435 if (disktype) {
436 lp = getdiskbyname(disktype);
437 if (lp != NULL)
438 return (lp);
439 }
440 return (NULL);
441}
442
443void
444rewritelabel(char *s, struct disklabel *lp)
445{
446 if (unlabeled)
447 return;
448 lp->d_checksum = 0;
449 lp->d_checksum = dkcksum(lp);
450 if (is_file) {
451 bsd_disklabel_le_enc(bootarea + 0 /* labeloffset */ +
452 1 /* labelsoffset */ * sectorsize, lp);
453 lseek(disk.d_fd, 0, SEEK_SET);
454 if (write(disk.d_fd, bootarea, BBSIZE) != BBSIZE)
455 errx(1, "cannot write label");
456 return;
457 }
458 if (ioctl(disk.d_fd, DIOCWDINFO, (char *)lp) == -1)
459 warn("ioctl (WDINFO): %s: can't rewrite disk label", s);
460}
461
462static void
463usage()
464{
465 fprintf(stderr,
466 "usage: %s [ -fsoptions ] special-device%s\n",
467 getprogname(),
468 " [device-type]");
469 fprintf(stderr, "where fsoptions are:\n");
470 fprintf(stderr, "\t-E Erase previous disk content\n");
471 fprintf(stderr, "\t-J Enable journaling via gjournal\n");
472 fprintf(stderr, "\t-L volume label to add to superblock\n");
473 fprintf(stderr,
474 "\t-N do not create file system, just print out parameters\n");
475 fprintf(stderr, "\t-O file system format: 1 => UFS1, 2 => UFS2\n");
476 fprintf(stderr, "\t-R regression test, suppress random factors\n");
477 fprintf(stderr, "\t-S sector size\n");
478 fprintf(stderr, "\t-T disktype\n");
479 fprintf(stderr, "\t-U enable soft updates\n");
480 fprintf(stderr, "\t-a maximum contiguous blocks\n");
481 fprintf(stderr, "\t-b block size\n");
482 fprintf(stderr, "\t-c blocks per cylinders group\n");
483 fprintf(stderr, "\t-d maximum extent size\n");
484 fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
485 fprintf(stderr, "\t-f frag size\n");
486 fprintf(stderr, "\t-g average file size\n");
487 fprintf(stderr, "\t-h average files per directory\n");
488 fprintf(stderr, "\t-i number of bytes per inode\n");
489 fprintf(stderr, "\t-l enable multilabel MAC\n");
490 fprintf(stderr, "\t-n do not create .snap directory\n");
491 fprintf(stderr, "\t-m minimum free space %%\n");
492 fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
493 fprintf(stderr, "\t-p partition name (a..h)\n");
494 fprintf(stderr, "\t-r reserved sectors at the end of device\n");
495 fprintf(stderr, "\t-s file system size (sectors)\n");
496 exit(1);
497}
239 if (rval < 0 || density <= 0)
240 errx(1, "%s: bad bytes per inode", optarg);
241 break;
242 case 'l':
243 lflag = 1;
244 break;
245 case 'm':
246 if ((minfree = atoi(optarg)) < 0 || minfree > 99)
247 errx(1, "%s: bad free space %%", optarg);
248 break;
249 case 'n':
250 nflag = 1;
251 break;
252 case 'o':
253 if (strcmp(optarg, "space") == 0)
254 opt = FS_OPTSPACE;
255 else if (strcmp(optarg, "time") == 0)
256 opt = FS_OPTTIME;
257 else
258 errx(1,
259 "%s: unknown optimization preference: use `space' or `time'",
260 optarg);
261 break;
262 case 'r':
263 errno = 0;
264 reserved = strtoimax(optarg, &cp, 0);
265 if (errno != 0 || cp == optarg ||
266 *cp != '\0' || reserved < 0)
267 errx(1, "%s: bad reserved size", optarg);
268 break;
269 case 'p':
270 is_file = 1;
271 part_name = optarg[0];
272 break;
273
274 case 's':
275 errno = 0;
276 fssize = strtoimax(optarg, &cp, 0);
277 if (errno != 0 || cp == optarg ||
278 *cp != '\0' || fssize < 0)
279 errx(1, "%s: bad file system size", optarg);
280 break;
281 case '?':
282 default:
283 usage();
284 }
285 argc -= optind;
286 argv += optind;
287
288 if (argc != 1)
289 usage();
290
291 special = argv[0];
292 if (!special[0])
293 err(1, "empty file/special name");
294 cp = strrchr(special, '/');
295 if (cp == 0) {
296 /*
297 * No path prefix; try prefixing _PATH_DEV.
298 */
299 snprintf(device, sizeof(device), "%s%s", _PATH_DEV, special);
300 special = device;
301 }
302
303 if (is_file) {
304 /* bypass ufs_disk_fillout_blank */
305 bzero( &disk, sizeof(disk));
306 disk.d_bsize = 1;
307 disk.d_name = special;
308 disk.d_fd = open(special, O_RDONLY);
309 if (disk.d_fd < 0 ||
310 (!Nflag && ufs_disk_write(&disk) == -1))
311 errx(1, "%s: ", special);
312 } else if (ufs_disk_fillout_blank(&disk, special) == -1 ||
313 (!Nflag && ufs_disk_write(&disk) == -1)) {
314 if (disk.d_error != NULL)
315 errx(1, "%s: %s", special, disk.d_error);
316 else
317 err(1, "%s", special);
318 }
319 if (fstat(disk.d_fd, &st) < 0)
320 err(1, "%s", special);
321 if ((st.st_mode & S_IFMT) != S_IFCHR) {
322 warn("%s: not a character-special device", special);
323 is_file = 1; /* assume it is a file */
324 dkname = special;
325 if (sectorsize == 0)
326 sectorsize = 512;
327 mediasize = st.st_size;
328 /* set fssize from the partition */
329 } else {
330 if (sectorsize == 0)
331 if (ioctl(disk.d_fd, DIOCGSECTORSIZE, &sectorsize) == -1)
332 sectorsize = 0; /* back out on error for safety */
333 if (sectorsize && ioctl(disk.d_fd, DIOCGMEDIASIZE, &mediasize) != -1)
334 getfssize(&fssize, special, mediasize / sectorsize, reserved);
335 }
336 pp = NULL;
337 lp = getdisklabel(special);
338 if (lp != NULL) {
339 if (!is_file) /* already set for files */
340 part_name = special[strlen(special) - 1];
341 if ((part_name < 'a' || part_name - 'a' >= MAXPARTITIONS) &&
342 !isdigit(part_name))
343 errx(1, "%s: can't figure out file system partition",
344 special);
345 cp = &part_name;
346 if (isdigit(*cp))
347 pp = &lp->d_partitions[RAW_PART];
348 else
349 pp = &lp->d_partitions[*cp - 'a'];
350 oldpartition = *pp;
351 if (pp->p_size == 0)
352 errx(1, "%s: `%c' partition is unavailable",
353 special, *cp);
354 if (pp->p_fstype == FS_BOOT)
355 errx(1, "%s: `%c' partition overlaps boot program",
356 special, *cp);
357 getfssize(&fssize, special, pp->p_size, reserved);
358 if (sectorsize == 0)
359 sectorsize = lp->d_secsize;
360 if (fsize == 0)
361 fsize = pp->p_fsize;
362 if (bsize == 0)
363 bsize = pp->p_frag * pp->p_fsize;
364 if (is_file)
365 part_ofs = pp->p_offset;
366 }
367 if (sectorsize <= 0)
368 errx(1, "%s: no default sector size", special);
369 if (fsize <= 0)
370 fsize = MAX(DFL_FRAGSIZE, sectorsize);
371 if (bsize <= 0)
372 bsize = MIN(DFL_BLKSIZE, 8 * fsize);
373 if (minfree < MINFREE && opt != FS_OPTSPACE) {
374 fprintf(stderr, "Warning: changing optimization to space ");
375 fprintf(stderr, "because minfree is less than %d%%\n", MINFREE);
376 opt = FS_OPTSPACE;
377 }
378 realsectorsize = sectorsize;
379 if (sectorsize != DEV_BSIZE) { /* XXX */
380 int secperblk = sectorsize / DEV_BSIZE;
381
382 sectorsize = DEV_BSIZE;
383 fssize *= secperblk;
384 if (pp != NULL)
385 pp->p_size *= secperblk;
386 }
387 mkfs(pp, special);
388 if (!unlabeled) {
389 if (realsectorsize != DEV_BSIZE)
390 pp->p_size /= realsectorsize / DEV_BSIZE;
391 if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
392 rewritelabel(special, lp);
393 }
394 ufs_disk_close(&disk);
395 exit(0);
396}
397
398void
399getfssize(intmax_t *fsz, const char *s, intmax_t disksize, intmax_t reserved)
400{
401 intmax_t available;
402
403 available = disksize - reserved;
404 if (available <= 0)
405 errx(1, "%s: reserved not less than device size %jd",
406 s, disksize);
407 if (*fsz == 0)
408 *fsz = available;
409 else if (*fsz > available)
410 errx(1, "%s: maximum file system size is %jd",
411 s, available);
412}
413
414struct disklabel *
415getdisklabel(char *s)
416{
417 static struct disklabel lab;
418 struct disklabel *lp;
419
420 if (is_file) {
421 if (read(disk.d_fd, bootarea, BBSIZE) != BBSIZE)
422 err(4, "cannot read bootarea");
423 if (bsd_disklabel_le_dec(
424 bootarea + (0 /* labeloffset */ +
425 1 /* labelsoffset */ * sectorsize),
426 &lab, MAXPARTITIONS))
427 errx(1, "no valid label found");
428
429 lp = &lab;
430 return &lab;
431 }
432
433 if (ioctl(disk.d_fd, DIOCGDINFO, (char *)&lab) != -1)
434 return (&lab);
435 unlabeled++;
436 if (disktype) {
437 lp = getdiskbyname(disktype);
438 if (lp != NULL)
439 return (lp);
440 }
441 return (NULL);
442}
443
444void
445rewritelabel(char *s, struct disklabel *lp)
446{
447 if (unlabeled)
448 return;
449 lp->d_checksum = 0;
450 lp->d_checksum = dkcksum(lp);
451 if (is_file) {
452 bsd_disklabel_le_enc(bootarea + 0 /* labeloffset */ +
453 1 /* labelsoffset */ * sectorsize, lp);
454 lseek(disk.d_fd, 0, SEEK_SET);
455 if (write(disk.d_fd, bootarea, BBSIZE) != BBSIZE)
456 errx(1, "cannot write label");
457 return;
458 }
459 if (ioctl(disk.d_fd, DIOCWDINFO, (char *)lp) == -1)
460 warn("ioctl (WDINFO): %s: can't rewrite disk label", s);
461}
462
463static void
464usage()
465{
466 fprintf(stderr,
467 "usage: %s [ -fsoptions ] special-device%s\n",
468 getprogname(),
469 " [device-type]");
470 fprintf(stderr, "where fsoptions are:\n");
471 fprintf(stderr, "\t-E Erase previous disk content\n");
472 fprintf(stderr, "\t-J Enable journaling via gjournal\n");
473 fprintf(stderr, "\t-L volume label to add to superblock\n");
474 fprintf(stderr,
475 "\t-N do not create file system, just print out parameters\n");
476 fprintf(stderr, "\t-O file system format: 1 => UFS1, 2 => UFS2\n");
477 fprintf(stderr, "\t-R regression test, suppress random factors\n");
478 fprintf(stderr, "\t-S sector size\n");
479 fprintf(stderr, "\t-T disktype\n");
480 fprintf(stderr, "\t-U enable soft updates\n");
481 fprintf(stderr, "\t-a maximum contiguous blocks\n");
482 fprintf(stderr, "\t-b block size\n");
483 fprintf(stderr, "\t-c blocks per cylinders group\n");
484 fprintf(stderr, "\t-d maximum extent size\n");
485 fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
486 fprintf(stderr, "\t-f frag size\n");
487 fprintf(stderr, "\t-g average file size\n");
488 fprintf(stderr, "\t-h average files per directory\n");
489 fprintf(stderr, "\t-i number of bytes per inode\n");
490 fprintf(stderr, "\t-l enable multilabel MAC\n");
491 fprintf(stderr, "\t-n do not create .snap directory\n");
492 fprintf(stderr, "\t-m minimum free space %%\n");
493 fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
494 fprintf(stderr, "\t-p partition name (a..h)\n");
495 fprintf(stderr, "\t-r reserved sectors at the end of device\n");
496 fprintf(stderr, "\t-s file system size (sectors)\n");
497 exit(1);
498}
498
499/*
500 * Return the numeric value of a string given in the form [+-][0-9]+[GMKT]
501 * or -1 on format error or overflow.
502 */
503static int
504parselength(const char *ls, int *sz)
505{
506 off_t length, oflow;
507 int lsign;
508
509 length = 0;
510 lsign = 1;
511
512 switch (*ls) {
513 case '-':
514 lsign = -1;
515 case '+':
516 ls++;
517 }
518
519#define ASSIGN_CHK_OFLOW(x, y) if (x < y) return -1; y = x
520 /*
521 * Calculate the value of the decimal digit string, failing
522 * on overflow.
523 */
524 while (isdigit(*ls)) {
525 oflow = length * 10 + *ls++ - '0';
526 ASSIGN_CHK_OFLOW(oflow, length);
527 }
528
529 switch (*ls) {
530 case 'T':
531 case 't':
532 oflow = length * 1024;
533 ASSIGN_CHK_OFLOW(oflow, length);
534 case 'G':
535 case 'g':
536 oflow = length * 1024;
537 ASSIGN_CHK_OFLOW(oflow, length);
538 case 'M':
539 case 'm':
540 oflow = length * 1024;
541 ASSIGN_CHK_OFLOW(oflow, length);
542 case 'K':
543 case 'k':
544 if (ls[1] != '\0')
545 return -1;
546 oflow = length * 1024;
547 ASSIGN_CHK_OFLOW(oflow, length);
548 case '\0':
549 break;
550 default:
551 return -1;
552 }
553
554 *sz = length * lsign;
555 return 0;
556}