1 /* $NetBSD: newfs_ext2fs.c,v 1.8 2009/03/02 10:38:13 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.8 2009/03/02 10:38:13 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>
71 #include <minix/partition.h>
76 static int64_t strsuftoi64(const char *, const char *, int64_t, int64_t, int *);
77 static void usage(void) __dead
;
80 * For file systems smaller than SMALL_FSSIZE we use the S_DFL_* defaults,
81 * otherwise if less than MEDIUM_FSSIZE use M_DFL_*, otherwise use
84 #define SMALL_FSSIZE ((4 * 1024 * 1024) / sectorsize) /* 4MB */
85 #define S_DFL_BSIZE 1024
86 #define MEDIUM_FSSIZE ((512 * 1024 * 1024) / sectorsize) /* 512MB */
87 #define M_DFL_BSIZE 1024
88 #define L_DFL_BSIZE 4096
91 * Each file system has a number of inodes statically allocated.
92 * We allocate one inode slot per 2, 4, or 8 blocks, expecting this
93 * to be far more than we will ever need.
95 #define S_DFL_NINODE(blocks) ((blocks) / 8)
96 #define M_DFL_NINODE(blocks) ((blocks) / 4)
97 #define L_DFL_NINODE(blocks) ((blocks) / 2)
100 * Default sector size.
102 #define DFL_SECSIZE 512
104 int Nflag
; /* run without writing file system */
105 int Oflag
= 0; /* format as conservative REV0 by default */
106 int verbosity
; /* amount of printf() output */
107 #define DEFAULT_VERBOSITY 3 /* 4 is traditional behavior of newfs(8) */
108 int64_t fssize
; /* file system size */
109 uint sectorsize
; /* bytes/sector */
110 uint16_t inodesize
= EXT2_REV0_DINODE_SIZE
; /* inode size */
111 uint fsize
= 0; /* fragment size */
112 uint bsize
= 0; /* block size */
113 uint minfree
= MINFREE
; /* free space threshold */
114 uint density
; /* number of bytes per inode */
115 uint num_inodes
; /* number of inodes (overrides density) */
116 char *volname
= NULL
; /* volume name */
119 static char *disktype
= NULL
;
121 static char device
[MAXPATHLEN
];
123 static const char lmsg
[] = "%s: can't read disk label";
126 main(int argc
, char *argv
[])
129 struct disk_geom geo
;
130 struct dkwedge_info dkw
;
138 int ch
, fsi
, fso
, Fflag
, Iflag
, Zflag
;
139 char *cp
, *s1
, *special
;
140 const char *opstring
;
142 uint blocks
; /* number of blocks */
146 Fflag
= Iflag
= Zflag
= 0;
148 opstring
= "D:FINO:S:V:Zb:f:i:l:m:n:s:v:B:";
150 while ((ch
= getopt(argc
, argv
, opstring
)) != -1)
153 inodesize
= (uint16_t)strtol(optarg
, &s1
, 0);
154 if (*s1
|| (inodesize
!= 128 && inodesize
!= 256))
155 errx(1, "Bad inode size %d "
156 "(only 128 and 256 supported)", inodesize
);
169 verbosity
= DEFAULT_VERBOSITY
;
172 Oflag
= strsuftoi64("format", optarg
, 0, 1, NULL
);
177 * non-512 byte sectors almost certainly don't work.
179 sectorsize
= strsuftoi64("sector size",
180 optarg
, 512, 65536, NULL
);
181 if (!powerof2(sectorsize
))
183 "sector size `%s' is not a power of 2.",
187 verbosity
= strsuftoi64("verbose", optarg
, 0, 4, NULL
);
196 bsize
= strsuftoi64("block size",
197 optarg
, MINBSIZE
, EXT2_MAXBSIZE
, NULL
);
200 fsize
= strsuftoi64("fragment size",
201 optarg
, MINBSIZE
, EXT2_MAXBSIZE
, NULL
);
204 density
= strsuftoi64("bytes per inode",
205 optarg
, 1, INT_MAX
, NULL
);
208 minfree
= strsuftoi64("free space %",
209 optarg
, 0, 99, NULL
);
212 num_inodes
= strsuftoi64("number of inodes",
213 optarg
, 1, INT_MAX
, NULL
);
216 fssize
= strsuftoi64("file system size",
217 optarg
, INT64_MIN
, INT64_MAX
, &byte_sized
);
221 if (volname
[0] == '\0')
223 "Volume name cannot be zero length");
233 /* Default to showing cg info */
234 verbosity
= DEFAULT_VERBOSITY
;
239 memset(&sb
, 0, sizeof(sb
));
241 memset(&dkw
, 0, sizeof(dkw
));
247 * It's a file system image
248 * no label, use fixed default for sectorsize.
251 sectorsize
= DFL_SECSIZE
;
253 /* creating image in a regular file */
258 fl
= O_RDWR
| O_CREAT
;
262 fsi
= open(special
, fl
, 0777);
264 err(EXIT_FAILURE
, "can't open file %s", special
);
265 if (fstat(fsi
, &sb
) == -1)
266 err(EXIT_FAILURE
, "can't fstat opened %s", special
);
269 } else { /* !Fflag */
270 fsi
= opendisk(special
, O_RDONLY
, device
, sizeof(device
), 0);
272 if (fsi
< 0 || fstat(fsi
, &sb
) == -1)
273 err(EXIT_FAILURE
, "%s: open for read", special
);
277 fso
= open(special
, O_WRONLY
, 0);
280 "%s: open for write", special
);
282 /* Bail if target special is mounted */
283 n
= getmntinfo(&mp
, MNT_NOWAIT
);
285 err(EXIT_FAILURE
, "%s: getmntinfo", special
);
287 len
= sizeof(_PATH_DEV
) - 1;
289 if (strncmp(_PATH_DEV
, s1
, len
) == 0)
293 s2
= mp
->f_mntfromname
;
294 if (strncmp(_PATH_DEV
, s2
, len
) == 0) {
298 if (strcmp(s1
, s2
) == 0 ||
299 strcmp(s1
, &s2
[1]) == 0)
301 "%s is mounted on %s",
302 special
, mp
->f_mntonname
);
307 if (getdiskinfo(special
, fsi
, disktype
, &geo
, &dkw
) == -1)
308 errx(EXIT_FAILURE
, lmsg
, special
);
310 if (sectorsize
== 0) {
311 sectorsize
= geo
.dg_secsize
;
313 errx(EXIT_FAILURE
, "no default sector size");
316 if (dkw
.dkw_parent
[0]) {
317 if (dkw
.dkw_size
== 0)
319 "%s partition is unavailable", special
);
322 static const char m
[] =
323 "%s partition type is not `%s' (or use -I)";
324 if (strcmp(dkw
.dkw_ptype
, DKW_PTYPE_EXT2FS
))
325 errx(EXIT_FAILURE
, m
,
326 special
, "Linux Ext2");
331 fso
= open(special
, O_WRONLY
, 0);
334 "%s: open for write", special
);
336 if(minix_sizeup(special
, &minix_fssize
) < 0)
337 errx(EXIT_FAILURE
, "minix_sizeup failed");
339 fssize
= minix_fssize
;
349 fssize
/= sectorsize
;
353 fssize
+= sb
.st_size
/ sectorsize
;
355 fssize
+= dkw
.dkw_size
;
358 "Unable to determine file system size");
361 if (dkw
.dkw_parent
[0] && fssize
> dkw
.dkw_size
)
363 "size %" PRIu64
" exceeds maximum file system size on "
364 "`%s' of %" PRIu64
" sectors",
365 fssize
, special
, dkw
.dkw_size
);
368 printf("fssize = %lld %d-byte sectors\n", fssize
, sectorsize
);
370 /* XXXLUKEM: only ftruncate() regular files ? (dsl: or at all?) */
371 if (Fflag
&& fso
!= -1
372 && ftruncate(fso
, (off_t
)fssize
* sectorsize
) == -1)
373 err(1, "can't ftruncate %s to %" PRId64
, special
, fssize
);
376 if (Zflag
&& fso
!= -1) { /* pre-zero (and de-sparce) the file */
382 if (fstatvfs(fso
, &sfs
) == -1) {
383 warn("can't fstatvfs `%s'", special
);
386 bufsize
= sfs
.f_iosize
;
388 if ((buf
= calloc(1, bufsize
)) == NULL
)
389 err(1, "can't malloc buffer of %d",
391 bufrem
= fssize
* sectorsize
;
393 printf("Creating file system image in `%s', "
394 "size %" PRId64
" bytes, in %d byte chunks.\n",
395 special
, (signed long long) bufrem
, bufsize
);
397 i
= write(fso
, buf
, MIN(bufsize
, bufrem
));
399 err(1, "writing image");
406 /* Sort out fragment and block sizes */
410 if (fssize
< SMALL_FSSIZE
)
412 else if (fssize
< MEDIUM_FSSIZE
)
422 blocks
= fssize
* sectorsize
/ bsize
;
424 fssize
= (u64_t
) blocks
* bsize
/ sectorsize
;
426 if (num_inodes
== 0) {
428 num_inodes
= fssize
/ density
;
430 if (fssize
< SMALL_FSSIZE
)
431 num_inodes
= S_DFL_NINODE(blocks
);
432 else if (fssize
< MEDIUM_FSSIZE
)
433 num_inodes
= M_DFL_NINODE(blocks
);
435 num_inodes
= L_DFL_NINODE(blocks
);
438 mke2fs(special
, fsi
, fso
);
442 if (fso
!= -1 && fso
!= fsi
)
448 strsuftoi64(const char *desc
, const char *arg
, int64_t min
, int64_t max
,
456 r1
= strtoll(arg
, &ep
, 10);
457 if (ep
[0] != '\0' && ep
[1] != '\0')
459 "%s `%s' is not a valid number.", desc
, arg
);
464 if (num_suffix
!= NULL
)
481 if (num_suffix
!= NULL
)
486 "`%s' is not a valid suffix for %s.", ep
, desc
);
488 result
= r1
<< shift
;
489 if (errno
== ERANGE
|| result
>> shift
!= r1
)
491 "%s `%s' is too large to convert.", desc
, arg
);
494 "%s `%s' (%" PRId64
") is less than the minimum (%"
495 PRId64
").", desc
, arg
, result
, min
);
498 "%s `%s' (%" PRId64
") is greater than the maximum (%"
499 PRId64
").", desc
, arg
, result
, max
);
503 static const char help_strings
[] =
504 "\t-b bsize\tblock size\n"
505 "\t-D inodesize\tsize of an inode in bytes (128 or 256)\n"
506 "\t-F \t\tcreate file system image in regular file\n"
507 "\t-f fsize\tfragment size\n"
508 "\t-I \t\tdo not check that the file system type is `Linux Ext2'\n"
509 "\t-i density\tnumber of bytes per inode\n"
510 "\t-m minfree\tminimum free space %\n"
511 "\t-N \t\tdo not create file system, just print out parameters\n"
512 "\t-n inodes\tnumber of inodes (overrides -i density)\n"
513 "\t-O N\t\tfilesystem revision: 0 ==> REV0, 1 ==> REV1 (default 0)\n"
514 "\t-S secsize\tsector size\n"
515 "\t-s fssize\tfile system size (sectors)\n"
516 "\t-V verbose\toutput verbosity: 0 ==> none, 4 ==> max\n"
517 "\t-v volname\text2fs volume name\n"
518 "\t-Z \t\tpre-zero the image file\n";
525 "usage: %s [ fsoptions ] special-device\n", getprogname());
526 fprintf(stderr
, "where fsoptions are:\n");
527 fprintf(stderr
, "%s", help_strings
);