1 /* $NetBSD: newfs_ext2fs.c,v 1.7 2009/03/02 10:16:49 tsutsui Exp $ */
4 * Copyright (c) 1983, 1989, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
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
17 * without specific prior written permission.
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
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
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
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
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1993, 1994\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "@(#)newfs.c 8.13 (Berkeley) 5/1/95";
42 __RCSID("$NetBSD: newfs_ext2fs.c,v 1.7 2009/03/02 10:16:49 tsutsui Exp $");
47 * newfs: friendly front end to mke2fs
49 #include <sys/param.h>
50 #include <sys/ioctl.h>
51 #include <sys/disklabel.h>
54 #include <sys/mount.h>
56 #include <ufs/ext2fs/ext2fs.h>
57 #include <ufs/ext2fs/ext2fs_dinode.h>
74 static int64_t strsuftoi64(const char *, const char *, int64_t, int64_t, int *);
75 static void usage(void) __dead
;
78 * For file systems smaller than SMALL_FSSIZE we use the S_DFL_* defaults,
79 * otherwise if less than MEDIUM_FSSIZE use M_DFL_*, otherwise use
82 #define SMALL_FSSIZE ((4 * 1024 * 1024) / sectorsize) /* 4MB */
83 #define S_DFL_BSIZE 1024
84 #define MEDIUM_FSSIZE ((512 * 1024 * 1024) / sectorsize) /* 512MB */
85 #define M_DFL_BSIZE 1024
86 #define L_DFL_BSIZE 4096
89 * Each file system has a number of inodes statically allocated.
90 * We allocate one inode slot per 2, 4, or 8 blocks, expecting this
91 * to be far more than we will ever need.
93 #define S_DFL_NINODE(blocks) ((blocks) / 8)
94 #define M_DFL_NINODE(blocks) ((blocks) / 4)
95 #define L_DFL_NINODE(blocks) ((blocks) / 2)
98 * Default sector size.
100 #define DFL_SECSIZE 512
102 int Nflag
; /* run without writing file system */
103 int Oflag
= 0; /* format as conservative REV0 by default */
104 int verbosity
; /* amount of printf() output */
105 #define DEFAULT_VERBOSITY 3 /* 4 is traditional behavior of newfs(8) */
106 int64_t fssize
; /* file system size */
107 uint sectorsize
; /* bytes/sector */
108 uint16_t inodesize
= EXT2_REV0_DINODE_SIZE
; /* inode size */
109 uint fsize
= 0; /* fragment size */
110 uint bsize
= 0; /* block size */
111 uint minfree
= MINFREE
; /* free space threshold */
112 uint density
; /* number of bytes per inode */
113 uint num_inodes
; /* number of inodes (overrides density) */
114 char *volname
= NULL
; /* volume name */
116 static char *disktype
= NULL
;
117 static char device
[MAXPATHLEN
];
119 static const char lmsg
[] = "%s: can't read disk label";
122 main(int argc
, char *argv
[])
124 struct disk_geom geo
;
125 struct dkwedge_info dkw
;
128 int ch
, fsi
, fso
, len
, n
, Fflag
, Iflag
, Zflag
;
129 char *cp
, *s1
, *s2
, *special
;
130 const char *opstring
;
132 uint blocks
; /* number of blocks */
136 Fflag
= Iflag
= Zflag
= 0;
138 opstring
= "D:FINO:S:V:Zb:f:i:l:m:n:s:v:";
140 while ((ch
= getopt(argc
, argv
, opstring
)) != -1)
143 inodesize
= (uint16_t)strtol(optarg
, &s1
, 0);
144 if (*s1
|| (inodesize
!= 128 && inodesize
!= 256))
145 errx(1, "Bad inode size %d "
146 "(only 128 and 256 supported)", inodesize
);
157 verbosity
= DEFAULT_VERBOSITY
;
160 Oflag
= strsuftoi64("format", optarg
, 0, 1, NULL
);
165 * non-512 byte sectors almost certainly don't work.
167 sectorsize
= strsuftoi64("sector size",
168 optarg
, 512, 65536, NULL
);
169 if (!powerof2(sectorsize
))
171 "sector size `%s' is not a power of 2.",
175 verbosity
= strsuftoi64("verbose", optarg
, 0, 4, NULL
);
181 bsize
= strsuftoi64("block size",
182 optarg
, MINBSIZE
, EXT2_MAXBSIZE
, NULL
);
185 fsize
= strsuftoi64("fragment size",
186 optarg
, MINBSIZE
, EXT2_MAXBSIZE
, NULL
);
189 density
= strsuftoi64("bytes per inode",
190 optarg
, 1, INT_MAX
, NULL
);
193 minfree
= strsuftoi64("free space %",
194 optarg
, 0, 99, NULL
);
197 num_inodes
= strsuftoi64("number of inodes",
198 optarg
, 1, INT_MAX
, NULL
);
201 fssize
= strsuftoi64("file system size",
202 optarg
, INT64_MIN
, INT64_MAX
, &byte_sized
);
206 if (volname
[0] == '\0')
208 "Volume name cannot be zero length");
218 /* Default to showing cg info */
219 verbosity
= DEFAULT_VERBOSITY
;
224 memset(&sb
, 0, sizeof(sb
));
225 memset(&dkw
, 0, sizeof(dkw
));
230 * It's a file system image
231 * no label, use fixed default for sectorsize.
234 sectorsize
= DFL_SECSIZE
;
236 /* creating image in a regular file */
241 fl
= O_RDWR
| O_CREAT
;
245 fsi
= open(special
, fl
, 0777);
247 err(EXIT_FAILURE
, "can't open file %s", special
);
248 if (fstat(fsi
, &sb
) == -1)
249 err(EXIT_FAILURE
, "can't fstat opened %s", special
);
252 } else { /* !Fflag */
253 fsi
= opendisk(special
, O_RDONLY
, device
, sizeof(device
), 0);
255 if (fsi
< 0 || fstat(fsi
, &sb
) == -1)
256 err(EXIT_FAILURE
, "%s: open for read", special
);
259 fso
= open(special
, O_WRONLY
, 0);
262 "%s: open for write", special
);
264 /* Bail if target special is mounted */
265 n
= getmntinfo(&mp
, MNT_NOWAIT
);
267 err(EXIT_FAILURE
, "%s: getmntinfo", special
);
269 len
= sizeof(_PATH_DEV
) - 1;
271 if (strncmp(_PATH_DEV
, s1
, len
) == 0)
275 s2
= mp
->f_mntfromname
;
276 if (strncmp(_PATH_DEV
, s2
, len
) == 0) {
280 if (strcmp(s1
, s2
) == 0 ||
281 strcmp(s1
, &s2
[1]) == 0)
283 "%s is mounted on %s",
284 special
, mp
->f_mntonname
);
289 if (getdiskinfo(special
, fsi
, disktype
, &geo
, &dkw
) == -1)
290 errx(EXIT_FAILURE
, lmsg
, special
);
292 if (sectorsize
== 0) {
293 sectorsize
= geo
.dg_secsize
;
295 errx(EXIT_FAILURE
, "no default sector size");
298 if (dkw
.dkw_parent
[0]) {
299 if (dkw
.dkw_size
== 0)
301 "%s partition is unavailable", special
);
304 static const char m
[] =
305 "%s partition type is not `%s' (or use -I)";
306 if (strcmp(dkw
.dkw_ptype
, DKW_PTYPE_EXT2FS
))
307 errx(EXIT_FAILURE
, m
,
308 special
, "Linux Ext2");
314 fssize
/= sectorsize
;
317 fssize
+= sb
.st_size
/ sectorsize
;
319 fssize
+= dkw
.dkw_size
;
322 "Unable to determine file system size");
325 if (dkw
.dkw_parent
[0] && fssize
> dkw
.dkw_size
)
327 "size %" PRIu64
" exceeds maximum file system size on "
328 "`%s' of %" PRIu64
" sectors",
329 fssize
, special
, dkw
.dkw_size
);
331 /* XXXLUKEM: only ftruncate() regular files ? (dsl: or at all?) */
332 if (Fflag
&& fso
!= -1
333 && ftruncate(fso
, (off_t
)fssize
* sectorsize
) == -1)
334 err(1, "can't ftruncate %s to %" PRId64
, special
, fssize
);
336 if (Zflag
&& fso
!= -1) { /* pre-zero (and de-sparce) the file */
342 if (fstatvfs(fso
, &sfs
) == -1) {
343 warn("can't fstatvfs `%s'", special
);
346 bufsize
= sfs
.f_iosize
;
348 if ((buf
= calloc(1, bufsize
)) == NULL
)
349 err(1, "can't malloc buffer of %d",
351 bufrem
= fssize
* sectorsize
;
353 printf("Creating file system image in `%s', "
354 "size %" PRId64
" bytes, in %d byte chunks.\n",
355 special
, bufrem
, bufsize
);
357 i
= write(fso
, buf
, MIN(bufsize
, bufrem
));
359 err(1, "writing image");
365 /* Sort out fragment and block sizes */
369 if (fssize
< SMALL_FSSIZE
)
371 else if (fssize
< MEDIUM_FSSIZE
)
380 blocks
= fssize
* sectorsize
/ bsize
;
382 if (num_inodes
== 0) {
384 num_inodes
= fssize
/ density
;
386 if (fssize
< SMALL_FSSIZE
)
387 num_inodes
= S_DFL_NINODE(blocks
);
388 else if (fssize
< MEDIUM_FSSIZE
)
389 num_inodes
= M_DFL_NINODE(blocks
);
391 num_inodes
= L_DFL_NINODE(blocks
);
394 mke2fs(special
, fsi
, fso
);
398 if (fso
!= -1 && fso
!= fsi
)
404 strsuftoi64(const char *desc
, const char *arg
, int64_t min
, int64_t max
,
412 r1
= strtoll(arg
, &ep
, 10);
413 if (ep
[0] != '\0' && ep
[1] != '\0')
415 "%s `%s' is not a valid number.", desc
, arg
);
420 if (num_suffix
!= NULL
)
437 if (num_suffix
!= NULL
)
442 "`%s' is not a valid suffix for %s.", ep
, desc
);
444 result
= r1
<< shift
;
445 if (errno
== ERANGE
|| result
>> shift
!= r1
)
447 "%s `%s' is too large to convert.", desc
, arg
);
450 "%s `%s' (%" PRId64
") is less than the minimum (%"
451 PRId64
").", desc
, arg
, result
, min
);
454 "%s `%s' (%" PRId64
") is greater than the maximum (%"
455 PRId64
").", desc
, arg
, result
, max
);
459 static const char help_strings
[] =
460 "\t-b bsize\tblock size\n"
461 "\t-D inodesize\tsize of an inode in bytes (128 or 256)\n"
462 "\t-F \t\tcreate file system image in regular file\n"
463 "\t-f fsize\tfragment size\n"
464 "\t-I \t\tdo not check that the file system type is `Linux Ext2'\n"
465 "\t-i density\tnumber of bytes per inode\n"
466 "\t-m minfree\tminimum free space %\n"
467 "\t-N \t\tdo not create file system, just print out parameters\n"
468 "\t-n inodes\tnumber of inodes (overrides -i density)\n"
469 "\t-O N\t\tfilesystem revision: 0 ==> REV0, 1 ==> REV1 (default 0)\n"
470 "\t-S secsize\tsector size\n"
471 "\t-s fssize\tfile system size (sectors)\n"
472 "\t-V verbose\toutput verbosity: 0 ==> none, 4 ==> max\n"
473 "\t-v volname\text2fs volume name\n"
474 "\t-Z \t\tpre-zero the image file\n";
481 "usage: %s [ fsoptions ] special-device\n", getprogname());
482 fprintf(stderr
, "where fsoptions are:\n");
483 fprintf(stderr
, "%s", help_strings
);