1*d7259957Scheloha /* $OpenBSD: newfs_ext2fs.c,v 1.29 2022/12/04 23:50:47 cheloha Exp $ */
2b2753aa5Sotto /* $NetBSD: newfs_ext2fs.c,v 1.8 2009/03/02 10:38:13 tsutsui Exp $ */
3b2753aa5Sotto
4b2753aa5Sotto /*
5b2753aa5Sotto * Copyright (c) 1983, 1989, 1993, 1994
6b2753aa5Sotto * The Regents of the University of California. All rights reserved.
7b2753aa5Sotto *
8b2753aa5Sotto * Redistribution and use in source and binary forms, with or without
9b2753aa5Sotto * modification, are permitted provided that the following conditions
10b2753aa5Sotto * are met:
11b2753aa5Sotto * 1. Redistributions of source code must retain the above copyright
12b2753aa5Sotto * notice, this list of conditions and the following disclaimer.
13b2753aa5Sotto * 2. Redistributions in binary form must reproduce the above copyright
14b2753aa5Sotto * notice, this list of conditions and the following disclaimer in the
15b2753aa5Sotto * documentation and/or other materials provided with the distribution.
16b2753aa5Sotto * 3. Neither the name of the University nor the names of its contributors
17b2753aa5Sotto * may be used to endorse or promote products derived from this software
18b2753aa5Sotto * without specific prior written permission.
19b2753aa5Sotto *
20b2753aa5Sotto * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21b2753aa5Sotto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22b2753aa5Sotto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23b2753aa5Sotto * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24b2753aa5Sotto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25b2753aa5Sotto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26b2753aa5Sotto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27b2753aa5Sotto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28b2753aa5Sotto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29b2753aa5Sotto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30b2753aa5Sotto * SUCH DAMAGE.
31b2753aa5Sotto */
32b2753aa5Sotto
33b2753aa5Sotto /*
34b2753aa5Sotto * newfs: friendly front end to mke2fs
35b2753aa5Sotto */
36b9fc9a72Sderaadt #include <sys/param.h> /* powerof2 */
37b9fc9a72Sderaadt #include <sys/types.h>
38b2753aa5Sotto #include <sys/ioctl.h>
3991f4f7d8Sdlg #include <sys/dkio.h>
40b2753aa5Sotto #include <sys/disklabel.h>
41b2753aa5Sotto #include <sys/mount.h>
42b2753aa5Sotto
43b2753aa5Sotto #include <ufs/ext2fs/ext2fs.h>
44b2753aa5Sotto #include <ufs/ext2fs/ext2fs_dinode.h>
45b2753aa5Sotto
46b2753aa5Sotto #include <ctype.h>
47b2753aa5Sotto #include <err.h>
48b2753aa5Sotto #include <errno.h>
498e1dad3fStedu #include <fcntl.h>
50b2753aa5Sotto #include <inttypes.h>
51b2753aa5Sotto #include <limits.h>
52b2753aa5Sotto #include <paths.h>
53b2753aa5Sotto #include <stdint.h>
54b2753aa5Sotto #include <stdio.h>
55b2753aa5Sotto #include <stdlib.h>
56b2753aa5Sotto #include <string.h>
57b2753aa5Sotto #include <unistd.h>
58b2753aa5Sotto #include <util.h>
59b2753aa5Sotto
60b9fc9a72Sderaadt #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
61b9fc9a72Sderaadt
62b2753aa5Sotto #include "extern.h"
63b2753aa5Sotto
64b2753aa5Sotto static int64_t strsuftoi64(const char *, const char *, int64_t, int64_t, int *);
65b2753aa5Sotto static void usage(void) __dead;
66b2753aa5Sotto
67b2753aa5Sotto /*
68b2753aa5Sotto * For file systems smaller than SMALL_FSSIZE we use the S_DFL_* defaults,
69b2753aa5Sotto * otherwise if less than MEDIUM_FSSIZE use M_DFL_*, otherwise use
70b2753aa5Sotto * L_DFL_*.
71b2753aa5Sotto */
72b2753aa5Sotto #define SMALL_FSSIZE ((4 * 1024 * 1024) / sectorsize) /* 4MB */
73b2753aa5Sotto #define S_DFL_BSIZE 1024
74b2753aa5Sotto #define MEDIUM_FSSIZE ((512 * 1024 * 1024) / sectorsize) /* 512MB */
75b2753aa5Sotto #define M_DFL_BSIZE 1024
76b2753aa5Sotto #define L_DFL_BSIZE 4096
77b2753aa5Sotto
78b2753aa5Sotto /*
79b2753aa5Sotto * Each file system has a number of inodes statically allocated.
80b2753aa5Sotto * We allocate one inode slot per 2, 4, or 8 blocks, expecting this
81b2753aa5Sotto * to be far more than we will ever need.
82b2753aa5Sotto */
83b2753aa5Sotto #define S_DFL_NINODE(blocks) ((blocks) / 8)
84b2753aa5Sotto #define M_DFL_NINODE(blocks) ((blocks) / 4)
85b2753aa5Sotto #define L_DFL_NINODE(blocks) ((blocks) / 2)
86b2753aa5Sotto
87b2753aa5Sotto /*
88b2753aa5Sotto * Default sector size.
89b2753aa5Sotto */
90b2753aa5Sotto #define DFL_SECSIZE 512
91b2753aa5Sotto
92b2753aa5Sotto int Nflag; /* run without writing file system */
93b2753aa5Sotto int Oflag = 0; /* format as conservative REV0 by default */
94b2753aa5Sotto int verbosity; /* amount of printf() output */
9514f7dd5fSotto #define DEFAULT_VERBOSITY 4 /* 4 is traditional behavior of newfs(8) */
96b2753aa5Sotto int64_t fssize; /* file system size */
97b2753aa5Sotto uint sectorsize; /* bytes/sector */
98b2753aa5Sotto uint16_t inodesize = EXT2_REV0_DINODE_SIZE; /* inode size */
99b2753aa5Sotto uint fsize = 0; /* fragment size */
100b2753aa5Sotto uint bsize = 0; /* block size */
101b2753aa5Sotto uint minfree = MINFREE; /* free space threshold */
102b2753aa5Sotto uint density; /* number of bytes per inode */
103b2753aa5Sotto uint num_inodes; /* number of inodes (overrides density) */
1044a93462bSderaadt int max_cols;
105b2753aa5Sotto char *volname = NULL; /* volume name */
106b2753aa5Sotto
107b2753aa5Sotto static char *disktype = NULL;
108b2753aa5Sotto
109b2753aa5Sotto struct disklabel *getdisklabel(const char *, int);
110b2753aa5Sotto struct partition *getpartition(int, const char *, char *[], struct disklabel **);
111b2753aa5Sotto
112b2753aa5Sotto int
main(int argc,char * argv[])113b2753aa5Sotto main(int argc, char *argv[])
114b2753aa5Sotto {
115b2753aa5Sotto struct statfs *mp;
116b2753aa5Sotto struct stat sb;
117bed75cd5Snatano int ch, fd, len, n, Fflag, Iflag, Zflag;
118bed75cd5Snatano char *s1, *s2, *special;
119b2753aa5Sotto const char *opstring;
120bed75cd5Snatano int byte_sized, fl;
121b2753aa5Sotto uint blocks; /* number of blocks */
122b2753aa5Sotto struct partition *pp = NULL;
123b2753aa5Sotto struct disklabel *lp;
1244a93462bSderaadt struct winsize winsize;
1254a93462bSderaadt
1264a93462bSderaadt /* Get terminal width */
1274a93462bSderaadt if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0)
1284a93462bSderaadt max_cols = winsize.ws_col;
1294a93462bSderaadt else
1304a93462bSderaadt max_cols = 80;
131b2753aa5Sotto
13225ae8cb0Snatano if (pledge("stdio rpath wpath cpath disklabel", NULL) == -1)
133e384f6efSderaadt err(1, "pledge");
134e384f6efSderaadt
135b2753aa5Sotto Fflag = Iflag = Zflag = 0;
136b2753aa5Sotto verbosity = -1;
137ddd3dd00Sotto opstring = "D:FINO:S:V:Zb:f:i:l:m:n:qs:t:v:";
138b2753aa5Sotto byte_sized = 0;
139b2753aa5Sotto while ((ch = getopt(argc, argv, opstring)) != -1)
140b2753aa5Sotto switch (ch) {
141b2753aa5Sotto case 'D':
142b2753aa5Sotto inodesize = (uint16_t)strtol(optarg, &s1, 0);
143b2753aa5Sotto if (*s1 || (inodesize != 128 && inodesize != 256))
144b2753aa5Sotto errx(1, "Bad inode size %d "
145b2753aa5Sotto "(only 128 and 256 supported)", inodesize);
146b2753aa5Sotto break;
147b2753aa5Sotto case 'F':
148b2753aa5Sotto Fflag = 1;
149b2753aa5Sotto break;
150b2753aa5Sotto case 'I':
151b2753aa5Sotto Iflag = 1;
152b2753aa5Sotto break;
153b2753aa5Sotto case 'N':
154b2753aa5Sotto Nflag = 1;
155b2753aa5Sotto if (verbosity == -1)
156b2753aa5Sotto verbosity = DEFAULT_VERBOSITY;
157b2753aa5Sotto break;
158b2753aa5Sotto case 'O':
159b2753aa5Sotto Oflag = strsuftoi64("format", optarg, 0, 1, NULL);
160b2753aa5Sotto break;
161b2753aa5Sotto case 'S':
162b2753aa5Sotto /*
163b2753aa5Sotto * XXX:
164b2753aa5Sotto * non-512 byte sectors almost certainly don't work.
165b2753aa5Sotto */
166b2753aa5Sotto sectorsize = strsuftoi64("sector size",
167b2753aa5Sotto optarg, 512, 65536, NULL);
168b2753aa5Sotto if (!powerof2(sectorsize))
169b2753aa5Sotto errx(EXIT_FAILURE,
170b2753aa5Sotto "sector size `%s' is not a power of 2.",
171b2753aa5Sotto optarg);
172b2753aa5Sotto break;
173b2753aa5Sotto case 'V':
174b2753aa5Sotto verbosity = strsuftoi64("verbose", optarg, 0, 4, NULL);
175b2753aa5Sotto break;
176b2753aa5Sotto case 'Z':
177b2753aa5Sotto Zflag = 1;
178b2753aa5Sotto break;
179b2753aa5Sotto case 'b':
180b2753aa5Sotto bsize = strsuftoi64("block size",
181b2753aa5Sotto optarg, MINBSIZE, EXT2_MAXBSIZE, NULL);
182b2753aa5Sotto break;
183b2753aa5Sotto case 'f':
184b2753aa5Sotto fsize = strsuftoi64("fragment size",
185b2753aa5Sotto optarg, MINBSIZE, EXT2_MAXBSIZE, NULL);
186b2753aa5Sotto break;
187b2753aa5Sotto case 'i':
188b2753aa5Sotto density = strsuftoi64("bytes per inode",
189b2753aa5Sotto optarg, 1, INT_MAX, NULL);
190b2753aa5Sotto break;
191b2753aa5Sotto case 'm':
192b2753aa5Sotto minfree = strsuftoi64("free space %",
193b2753aa5Sotto optarg, 0, 99, NULL);
194b2753aa5Sotto break;
195b2753aa5Sotto case 'n':
196b2753aa5Sotto num_inodes = strsuftoi64("number of inodes",
197b2753aa5Sotto optarg, 1, INT_MAX, NULL);
198b2753aa5Sotto break;
199ddd3dd00Sotto case 'q':
200ddd3dd00Sotto verbosity = 1;
201ddd3dd00Sotto break;
202b2753aa5Sotto case 's':
203b2753aa5Sotto fssize = strsuftoi64("file system size",
204b2753aa5Sotto optarg, INT64_MIN, INT64_MAX, &byte_sized);
205b2753aa5Sotto break;
2065aed88f7Sotto case 't':
2075aed88f7Sotto /* compat with newfs -t */
2085aed88f7Sotto break;
209b2753aa5Sotto case 'v':
210b2753aa5Sotto volname = optarg;
211b2753aa5Sotto if (volname[0] == '\0')
212b2753aa5Sotto errx(EXIT_FAILURE,
213b2753aa5Sotto "Volume name cannot be zero length");
214b2753aa5Sotto break;
215b2753aa5Sotto default:
216b2753aa5Sotto usage();
217b2753aa5Sotto }
218b2753aa5Sotto argc -= optind;
219b2753aa5Sotto argv += optind;
220b2753aa5Sotto
221b2753aa5Sotto if (verbosity == -1)
222b2753aa5Sotto /* Default to showing cg info */
223b2753aa5Sotto verbosity = DEFAULT_VERBOSITY;
224b2753aa5Sotto
225b2753aa5Sotto if (argc != 1)
226b2753aa5Sotto usage();
227b2753aa5Sotto
228b2753aa5Sotto memset(&sb, 0, sizeof(sb));
229b2753aa5Sotto special = argv[0];
230bed75cd5Snatano fl = Nflag ? O_RDONLY : O_RDWR;
231bed75cd5Snatano
232b2753aa5Sotto if (Fflag) {
233b2753aa5Sotto /*
234b2753aa5Sotto * It's a file system image
235b2753aa5Sotto * no label, use fixed default for sectorsize.
236b2753aa5Sotto */
237b2753aa5Sotto if (sectorsize == 0)
238b2753aa5Sotto sectorsize = DFL_SECSIZE;
239b2753aa5Sotto
240b2753aa5Sotto /* creating image in a regular file */
241bed75cd5Snatano if (!Nflag && fssize > 0)
242bed75cd5Snatano fl |= O_CREAT;
2437ed4ab4bSnatano fd = open(special, fl, 0666);
244bed75cd5Snatano if (fd == -1)
245b2753aa5Sotto err(EXIT_FAILURE, "can't open file %s", special);
246bed75cd5Snatano if (fstat(fd, &sb) == -1)
247b2753aa5Sotto err(EXIT_FAILURE, "can't fstat opened %s", special);
248b2753aa5Sotto } else { /* !Fflag */
249bed75cd5Snatano fd = opendev(special, fl, 0, &special);
250df69c215Sderaadt if (fd == -1 || fstat(fd, &sb) == -1)
251bed75cd5Snatano err(EXIT_FAILURE, "%s: open", special);
252b2753aa5Sotto
253b2753aa5Sotto if (!Nflag) {
254b2753aa5Sotto /* Bail if target special is mounted */
255b2753aa5Sotto n = getmntinfo(&mp, MNT_NOWAIT);
256b2753aa5Sotto if (n == 0)
257b2753aa5Sotto err(EXIT_FAILURE, "%s: getmntinfo", special);
258b2753aa5Sotto
259b2753aa5Sotto len = sizeof(_PATH_DEV) - 1;
260b2753aa5Sotto s1 = special;
261b2753aa5Sotto if (strncmp(_PATH_DEV, s1, len) == 0)
262b2753aa5Sotto s1 += len;
263b2753aa5Sotto
264b2753aa5Sotto while (--n >= 0) {
265b2753aa5Sotto s2 = mp->f_mntfromname;
266b2753aa5Sotto if (strncmp(_PATH_DEV, s2, len) == 0) {
267b2753aa5Sotto s2 += len - 1;
268b2753aa5Sotto *s2 = 'r';
269b2753aa5Sotto }
270b2753aa5Sotto if (strcmp(s1, s2) == 0 ||
271b2753aa5Sotto strcmp(s1, &s2[1]) == 0)
272b2753aa5Sotto errx(EXIT_FAILURE,
273b2753aa5Sotto "%s is mounted on %s",
274b2753aa5Sotto special, mp->f_mntonname);
275b2753aa5Sotto ++mp;
276b2753aa5Sotto }
277b2753aa5Sotto }
278b2753aa5Sotto
279bed75cd5Snatano pp = getpartition(fd, special, argv, &lp);
280b2753aa5Sotto if (!Iflag) {
281b2753aa5Sotto static const char m[] =
282b2753aa5Sotto "%s partition type is not `%s' (or use -I)";
283b2753aa5Sotto if (pp->p_fstype != FS_EXT2FS)
2848602cba2Sguenther errx(EXIT_FAILURE, m, special, "ext2fs");
285b2753aa5Sotto }
286b2753aa5Sotto if (sectorsize == 0) {
287b2753aa5Sotto sectorsize = lp->d_secsize;
288b2753aa5Sotto if (sectorsize <= 0)
289b2753aa5Sotto errx(EXIT_FAILURE, "no default sector size");
290b2753aa5Sotto }
291b2753aa5Sotto }
292b2753aa5Sotto
293b2753aa5Sotto if (byte_sized)
294b2753aa5Sotto fssize /= sectorsize;
295b2753aa5Sotto if (fssize <= 0) {
296b2753aa5Sotto if (sb.st_size != 0)
297b2753aa5Sotto fssize += sb.st_size / sectorsize;
298b2753aa5Sotto else if (pp)
299b2753aa5Sotto fssize += DL_GETPSIZE(pp);
300b2753aa5Sotto if (fssize <= 0)
301b2753aa5Sotto errx(EXIT_FAILURE,
302b2753aa5Sotto "Unable to determine file system size");
303b2753aa5Sotto }
304b2753aa5Sotto
305b2753aa5Sotto /* XXXLUKEM: only ftruncate() regular files ? (dsl: or at all?) */
306bed75cd5Snatano if (Fflag && !Nflag
307bed75cd5Snatano && ftruncate(fd, (off_t)fssize * sectorsize) == -1)
308b2753aa5Sotto err(1, "can't ftruncate %s to %" PRId64, special, fssize);
309b2753aa5Sotto
310bed75cd5Snatano if (Zflag && !Nflag) { /* pre-zero (and de-sparce) the file */
311b2753aa5Sotto char *buf;
312b2753aa5Sotto int bufsize, i;
313b2753aa5Sotto off_t bufrem;
314b2753aa5Sotto struct statfs sfs;
315b2753aa5Sotto
316bed75cd5Snatano if (fstatfs(fd, &sfs) == -1) {
317b2753aa5Sotto warn("can't fstatvfs `%s'", special);
318b2753aa5Sotto bufsize = 8192;
319b2753aa5Sotto } else
320b2753aa5Sotto bufsize = sfs.f_iosize;
321b2753aa5Sotto
322b2753aa5Sotto if ((buf = calloc(1, bufsize)) == NULL)
323c85a3368Sguenther err(1, "can't allocate buffer of %d",
324b2753aa5Sotto bufsize);
325b2753aa5Sotto bufrem = fssize * sectorsize;
326b2753aa5Sotto if (verbosity > 0)
327b2753aa5Sotto printf("Creating file system image in `%s', "
328b2753aa5Sotto "size %" PRId64 " bytes, in %d byte chunks.\n",
329b2753aa5Sotto special, bufrem, bufsize);
330b2753aa5Sotto while (bufrem > 0) {
331bed75cd5Snatano i = write(fd, buf, MINIMUM(bufsize, bufrem));
332b2753aa5Sotto if (i == -1)
333b2753aa5Sotto err(1, "writing image");
334b2753aa5Sotto bufrem -= i;
335b2753aa5Sotto }
336b2753aa5Sotto free(buf);
337b2753aa5Sotto }
338b2753aa5Sotto
339b2753aa5Sotto /* Sort out fragment and block sizes */
340b2753aa5Sotto if (bsize == 0) {
341b2753aa5Sotto bsize = fsize;
342b2753aa5Sotto if (bsize == 0) {
343b2753aa5Sotto if (fssize < SMALL_FSSIZE)
344b2753aa5Sotto bsize = S_DFL_BSIZE;
345b2753aa5Sotto else if (fssize < MEDIUM_FSSIZE)
346b2753aa5Sotto bsize = M_DFL_BSIZE;
347b2753aa5Sotto else
348b2753aa5Sotto bsize = L_DFL_BSIZE;
349b2753aa5Sotto }
350b2753aa5Sotto }
351b2753aa5Sotto if (fsize == 0)
352b2753aa5Sotto fsize = bsize;
353b2753aa5Sotto
354b2753aa5Sotto blocks = fssize * sectorsize / bsize;
355b2753aa5Sotto
356b2753aa5Sotto if (num_inodes == 0) {
357b2753aa5Sotto if (density != 0)
358b2753aa5Sotto num_inodes = fssize / density;
359b2753aa5Sotto else {
360b2753aa5Sotto if (fssize < SMALL_FSSIZE)
361b2753aa5Sotto num_inodes = S_DFL_NINODE(blocks);
362b2753aa5Sotto else if (fssize < MEDIUM_FSSIZE)
363b2753aa5Sotto num_inodes = M_DFL_NINODE(blocks);
364b2753aa5Sotto else
365b2753aa5Sotto num_inodes = L_DFL_NINODE(blocks);
366b2753aa5Sotto }
367b2753aa5Sotto }
368bed75cd5Snatano mke2fs(special, fd);
369b2753aa5Sotto
370bed75cd5Snatano close(fd);
371b2753aa5Sotto exit(EXIT_SUCCESS);
372b2753aa5Sotto }
373b2753aa5Sotto
374b2753aa5Sotto static int64_t
strsuftoi64(const char * desc,const char * arg,int64_t min,int64_t max,int * num_suffix)375b2753aa5Sotto strsuftoi64(const char *desc, const char *arg, int64_t min, int64_t max,
376b2753aa5Sotto int *num_suffix)
377b2753aa5Sotto {
378b2753aa5Sotto int64_t result, r1;
379b2753aa5Sotto int shift = 0;
380b2753aa5Sotto char *ep;
381b2753aa5Sotto
382b2753aa5Sotto errno = 0;
383b2753aa5Sotto r1 = strtoll(arg, &ep, 10);
384b2753aa5Sotto if (ep[0] != '\0' && ep[1] != '\0')
385b2753aa5Sotto errx(EXIT_FAILURE,
386b2753aa5Sotto "%s `%s' is not a valid number.", desc, arg);
387b2753aa5Sotto switch (ep[0]) {
388b2753aa5Sotto case '\0':
389b2753aa5Sotto case 's':
390b2753aa5Sotto case 'S':
391b2753aa5Sotto if (num_suffix != NULL)
392b2753aa5Sotto *num_suffix = 0;
393b2753aa5Sotto break;
394b2753aa5Sotto case 'g':
395b2753aa5Sotto case 'G':
396b2753aa5Sotto shift += 10;
397b2753aa5Sotto /* FALLTHROUGH */
398b2753aa5Sotto case 'm':
399b2753aa5Sotto case 'M':
400b2753aa5Sotto shift += 10;
401b2753aa5Sotto /* FALLTHROUGH */
402b2753aa5Sotto case 'k':
403b2753aa5Sotto case 'K':
404b2753aa5Sotto shift += 10;
405b2753aa5Sotto /* FALLTHROUGH */
406b2753aa5Sotto case 'b':
407b2753aa5Sotto case 'B':
408b2753aa5Sotto if (num_suffix != NULL)
409b2753aa5Sotto *num_suffix = 1;
410b2753aa5Sotto break;
411b2753aa5Sotto default:
412b2753aa5Sotto errx(EXIT_FAILURE,
413b2753aa5Sotto "`%s' is not a valid suffix for %s.", ep, desc);
414b2753aa5Sotto }
415b2753aa5Sotto result = r1 << shift;
416b2753aa5Sotto if (errno == ERANGE || result >> shift != r1)
417b2753aa5Sotto errx(EXIT_FAILURE,
418b2753aa5Sotto "%s `%s' is too large to convert.", desc, arg);
419b2753aa5Sotto if (result < min)
420b2753aa5Sotto errx(EXIT_FAILURE,
421b2753aa5Sotto "%s `%s' (%" PRId64 ") is less than the minimum (%"
422b2753aa5Sotto PRId64 ").", desc, arg, result, min);
423b2753aa5Sotto if (result > max)
424b2753aa5Sotto errx(EXIT_FAILURE,
425b2753aa5Sotto "%s `%s' (%" PRId64 ") is greater than the maximum (%"
426b2753aa5Sotto PRId64 ").", desc, arg, result, max);
427b2753aa5Sotto return result;
428b2753aa5Sotto }
429b2753aa5Sotto
430b2753aa5Sotto static void
usage(void)431b2753aa5Sotto usage(void)
432b2753aa5Sotto {
433b2753aa5Sotto extern char *__progname;
434b2753aa5Sotto
435b2753aa5Sotto fprintf(stderr,
436b2753aa5Sotto "usage: %s [ fsoptions ] special-device\n", __progname);
437b2753aa5Sotto exit(EXIT_FAILURE);
438b2753aa5Sotto }
439b2753aa5Sotto
440b2753aa5Sotto struct disklabel *
getdisklabel(const char * s,int fd)441b2753aa5Sotto getdisklabel(const char *s, int fd)
442b2753aa5Sotto {
443b2753aa5Sotto static struct disklabel lab;
444b2753aa5Sotto
445df69c215Sderaadt if (ioctl(fd, DIOCGDINFO, (char *)&lab) == -1) {
446b2753aa5Sotto if (disktype != NULL) {
447b2753aa5Sotto struct disklabel *lp;
448b2753aa5Sotto
449b2753aa5Sotto //unlabeled++;
450b2753aa5Sotto lp = getdiskbyname(disktype);
451b2753aa5Sotto if (lp == NULL)
452b2753aa5Sotto errx(EXIT_FAILURE, "%s: unknown disk type",
453b2753aa5Sotto disktype);
454b2753aa5Sotto return (lp);
455b2753aa5Sotto }
456b2753aa5Sotto warn("ioctl (GDINFO)");
457390b7edbSguenther errx(EXIT_FAILURE,
458390b7edbSguenther "%s: can't read disk label; disk type must be specified",
459390b7edbSguenther s);
460b2753aa5Sotto }
461b2753aa5Sotto return (&lab);
462b2753aa5Sotto }
463b2753aa5Sotto
464b2753aa5Sotto struct partition *
getpartition(int fsi,const char * special,char * argv[],struct disklabel ** dl)465b2753aa5Sotto getpartition(int fsi, const char *special, char *argv[], struct disklabel **dl)
466b2753aa5Sotto {
467b2753aa5Sotto struct stat st;
468b2753aa5Sotto const char *cp;
469b2753aa5Sotto struct disklabel *lp;
470b2753aa5Sotto struct partition *pp;
471b2753aa5Sotto
472df69c215Sderaadt if (fstat(fsi, &st) == -1)
473cd5cfea9Sguenther err(EXIT_FAILURE, "%s", special);
474b2753aa5Sotto if (S_ISBLK(st.st_mode))
475b2753aa5Sotto errx(EXIT_FAILURE, "%s: block device", special);
476b2753aa5Sotto if (!S_ISCHR(st.st_mode))
477b2753aa5Sotto warnx("%s: not a character-special device", special);
4784d4ccfdfStobias if (*argv[0] == '\0')
4794d4ccfdfStobias errx(EXIT_FAILURE, "empty partition name supplied");
4804d4ccfdfStobias cp = argv[0] + strlen(argv[0]) - 1;
4814d4ccfdfStobias if ((*cp < 'a' || *cp > ('a' + getmaxpartitions() - 1))
4824d4ccfdfStobias && !isdigit((unsigned char)*cp))
483b2753aa5Sotto errx(EXIT_FAILURE, "%s: can't figure out file system partition", argv[0]);
484b2753aa5Sotto lp = getdisklabel(special, fsi);
485025f5691Sderaadt if (isdigit((unsigned char)*cp))
486b2753aa5Sotto pp = &lp->d_partitions[0];
487b2753aa5Sotto else
488b2753aa5Sotto pp = &lp->d_partitions[*cp - 'a'];
489b2753aa5Sotto if (DL_GETPSIZE(pp) == 0)
490b2753aa5Sotto errx(EXIT_FAILURE, "%s: `%c' partition is unavailable", argv[0], *cp);
491b2753aa5Sotto *dl = lp;
492b2753aa5Sotto return pp;
493b2753aa5Sotto }
494b2753aa5Sotto
495