1 /* $NetBSD: newfs_ext2fs.c,v 1.9 2013/10/19 01:09:59 christos 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.9 2013/10/19 01:09:59 christos 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>
72 #include <minix/partition.h>
73 #endif /* !defined(__minix) */
78 static int64_t strsuftoi64(const char *, const char *, int64_t, int64_t, int *);
79 static void usage(void) __dead
;
82 * For file systems smaller than SMALL_FSSIZE we use the S_DFL_* defaults,
83 * otherwise if less than MEDIUM_FSSIZE use M_DFL_*, otherwise use
86 #define SMALL_FSSIZE ((4 * 1024 * 1024) / sectorsize) /* 4MB */
88 #define S_DFL_BSIZE 1024
90 #define S_DFL_BSIZE 4096
91 #endif /* !defined(__minix) */
92 #define MEDIUM_FSSIZE ((512 * 1024 * 1024) / sectorsize) /* 512MB */
94 #define M_DFL_BSIZE 1024
96 #define M_DFL_BSIZE 4096
97 #endif /* !defined(__minix) */
98 #define L_DFL_BSIZE 4096
101 * Each file system has a number of inodes statically allocated.
102 * We allocate one inode slot per 2, 4, or 8 blocks, expecting this
103 * to be far more than we will ever need.
105 #define S_DFL_NINODE(blocks) ((blocks) / 8)
106 #define M_DFL_NINODE(blocks) ((blocks) / 4)
107 #define L_DFL_NINODE(blocks) ((blocks) / 2)
110 * Default sector size.
112 #define DFL_SECSIZE 512
114 int Nflag
; /* run without writing file system */
115 int Oflag
= 0; /* format as conservative REV0 by default */
116 int verbosity
; /* amount of printf() output */
117 #define DEFAULT_VERBOSITY 3 /* 4 is traditional behavior of newfs(8) */
118 int64_t fssize
; /* file system size */
119 uint sectorsize
; /* bytes/sector */
120 uint16_t inodesize
= EXT2_REV0_DINODE_SIZE
; /* inode size */
121 uint fsize
= 0; /* fragment size */
122 uint bsize
= 0; /* block size */
123 uint minfree
= MINFREE
; /* free space threshold */
124 uint density
; /* number of bytes per inode */
125 uint num_inodes
; /* number of inodes (overrides density) */
126 char *volname
= NULL
; /* volume name */
128 #if !defined(__minix)
129 static char *disktype
= NULL
;
130 #endif /* !defined(__minix) */
131 static char device
[MAXPATHLEN
];
133 #if !defined(__minix)
134 static const char lmsg
[] = "%s: can't read disk label";
135 #endif /* !defined(__minix) */
138 main(int argc
, char *argv
[])
140 #if !defined(__minix)
141 struct disk_geom geo
;
142 struct dkwedge_info dkw
;
145 #endif /* !defined(__minix) */
148 int ch
, fsi
, fso
, len
, n
, Fflag
, Iflag
, Zflag
;
149 char *s1
, *s2
, *special
;
150 const char *opstring
;
152 uint blocks
; /* number of blocks */
155 Fflag
= Iflag
= Zflag
= 0;
157 #if !defined(__minix)
158 opstring
= "D:FINO:S:V:Zb:f:i:l:m:n:s:v:";
160 opstring
= "D:FINO:S:V:Zb:f:i:l:m:n:s:v:B:";
161 #endif /* !defined(__minix) */
163 while ((ch
= getopt(argc
, argv
, opstring
)) != -1)
166 inodesize
= (uint16_t)strtol(optarg
, &s1
, 0);
167 if (*s1
|| (inodesize
!= 128 && inodesize
!= 256))
168 errx(1, "Bad inode size %d "
169 "(only 128 and 256 supported)", inodesize
);
174 #if !defined(__minix)
178 #endif /* !defined(__minix) */
182 verbosity
= DEFAULT_VERBOSITY
;
185 Oflag
= strsuftoi64("format", optarg
, 0, 1, NULL
);
190 * non-512 byte sectors almost certainly don't work.
192 sectorsize
= strsuftoi64("sector size",
193 optarg
, 512, 65536, NULL
);
194 if (!powerof2(sectorsize
))
196 "sector size `%s' is not a power of 2.",
200 verbosity
= strsuftoi64("verbose", optarg
, 0, 4, NULL
);
202 #if !defined(__minix)
208 #endif /* !defined(__minix) */
210 bsize
= strsuftoi64("block size",
211 optarg
, MINBSIZE
, EXT2_MAXBSIZE
, NULL
);
214 fsize
= strsuftoi64("fragment size",
215 optarg
, MINBSIZE
, EXT2_MAXBSIZE
, NULL
);
218 density
= strsuftoi64("bytes per inode",
219 optarg
, 1, INT_MAX
, NULL
);
222 minfree
= strsuftoi64("free space %",
223 optarg
, 0, 99, NULL
);
226 num_inodes
= strsuftoi64("number of inodes",
227 optarg
, 1, INT_MAX
, NULL
);
230 fssize
= strsuftoi64("file system size",
231 optarg
, INT64_MIN
, INT64_MAX
, &byte_sized
);
235 if (volname
[0] == '\0')
237 "Volume name cannot be zero length");
247 /* Default to showing cg info */
248 verbosity
= DEFAULT_VERBOSITY
;
253 memset(&sb
, 0, sizeof(sb
));
254 #if !defined(__minix)
255 memset(&dkw
, 0, sizeof(dkw
));
256 #endif /* !defined(__minix) */
261 * It's a file system image
262 * no label, use fixed default for sectorsize.
265 sectorsize
= DFL_SECSIZE
;
267 /* creating image in a regular file */
272 fl
= O_RDWR
| O_CREAT
;
276 fsi
= open(special
, fl
, 0777);
278 err(EXIT_FAILURE
, "can't open file %s", special
);
279 if (fstat(fsi
, &sb
) == -1)
280 err(EXIT_FAILURE
, "can't fstat opened %s", special
);
283 } else { /* !Fflag */
284 fsi
= opendisk(special
, O_RDONLY
, device
, sizeof(device
), 0);
286 if (fsi
< 0 || fstat(fsi
, &sb
) == -1)
287 err(EXIT_FAILURE
, "%s: open for read", special
);
290 fso
= open(special
, O_WRONLY
, 0);
293 "%s: open for write", special
);
295 /* Bail if target special is mounted */
296 n
= getmntinfo(&mp
, MNT_NOWAIT
);
298 err(EXIT_FAILURE
, "%s: getmntinfo", special
);
300 len
= sizeof(_PATH_DEV
) - 1;
302 if (strncmp(_PATH_DEV
, s1
, len
) == 0)
306 s2
= mp
->f_mntfromname
;
307 if (strncmp(_PATH_DEV
, s2
, len
) == 0) {
311 if (strcmp(s1
, s2
) == 0 ||
312 strcmp(s1
, &s2
[1]) == 0)
314 "%s is mounted on %s",
315 special
, mp
->f_mntonname
);
320 #if !defined(__minix)
321 if (getdiskinfo(special
, fsi
, disktype
, &geo
, &dkw
) == -1)
322 errx(EXIT_FAILURE
, lmsg
, special
);
324 if (sectorsize
== 0) {
325 sectorsize
= geo
.dg_secsize
;
327 errx(EXIT_FAILURE
, "no default sector size");
330 if (dkw
.dkw_parent
[0]) {
331 if (dkw
.dkw_size
== 0)
333 "%s partition is unavailable", special
);
336 static const char m
[] =
337 "%s partition type is not `%s' (or use -I)";
338 if (strcmp(dkw
.dkw_ptype
, DKW_PTYPE_EXT2FS
))
339 errx(EXIT_FAILURE
, m
,
340 special
, "Linux Ext2");
344 if(minix_sizeup(special
, &minix_fssize
) < 0)
345 errx(EXIT_FAILURE
, "minix_sizeup failed");
347 fssize
= minix_fssize
;
352 #endif /* !defined(__minix) */
356 fssize
/= sectorsize
;
357 #if !defined(__minix)
360 fssize
+= sb
.st_size
/ sectorsize
;
362 fssize
+= dkw
.dkw_size
;
365 "Unable to determine file system size");
368 if (dkw
.dkw_parent
[0] && fssize
> dkw
.dkw_size
)
370 "size %" PRIu64
" exceeds maximum file system size on "
371 "`%s' of %" PRIu64
" sectors",
372 fssize
, special
, dkw
.dkw_size
);
373 #endif /* !defined(__minix) */
375 /* XXXLUKEM: only ftruncate() regular files ? (dsl: or at all?) */
376 if (Fflag
&& fso
!= -1
377 && ftruncate(fso
, (off_t
)fssize
* sectorsize
) == -1)
378 err(1, "can't ftruncate %s to %" PRId64
, special
, fssize
);
380 #if !defined(__minix)
381 if (Zflag
&& fso
!= -1) { /* pre-zero (and de-sparce) the file */
387 if (fstatvfs(fso
, &sfs
) == -1) {
388 warn("can't fstatvfs `%s'", special
);
391 bufsize
= sfs
.f_iosize
;
393 if ((buf
= calloc(1, bufsize
)) == NULL
)
394 err(1, "can't malloc buffer of %d",
396 bufrem
= fssize
* sectorsize
;
398 printf("Creating file system image in `%s', "
399 "size %" PRId64
" bytes, in %d byte chunks.\n",
400 special
, bufrem
, bufsize
);
402 i
= write(fso
, buf
, MIN(bufsize
, bufrem
));
404 err(1, "writing image");
409 #endif /* !defined(__minix) */
411 /* Sort out fragment and block sizes */
415 if (fssize
< SMALL_FSSIZE
)
417 else if (fssize
< MEDIUM_FSSIZE
)
426 blocks
= fssize
* sectorsize
/ bsize
;
428 if (num_inodes
== 0) {
430 num_inodes
= fssize
/ density
;
432 if (fssize
< SMALL_FSSIZE
)
433 num_inodes
= S_DFL_NINODE(blocks
);
434 else if (fssize
< MEDIUM_FSSIZE
)
435 num_inodes
= M_DFL_NINODE(blocks
);
437 num_inodes
= L_DFL_NINODE(blocks
);
440 mke2fs(special
, fsi
, fso
);
444 if (fso
!= -1 && fso
!= fsi
)
450 strsuftoi64(const char *desc
, const char *arg
, int64_t min
, int64_t max
,
458 r1
= strtoll(arg
, &ep
, 10);
459 if (ep
[0] != '\0' && ep
[1] != '\0')
461 "%s `%s' is not a valid number.", desc
, arg
);
466 if (num_suffix
!= NULL
)
483 if (num_suffix
!= NULL
)
488 "`%s' is not a valid suffix for %s.", ep
, desc
);
490 result
= r1
<< shift
;
491 if (errno
== ERANGE
|| result
>> shift
!= r1
)
493 "%s `%s' is too large to convert.", desc
, arg
);
496 "%s `%s' (%" PRId64
") is less than the minimum (%"
497 PRId64
").", desc
, arg
, result
, min
);
500 "%s `%s' (%" PRId64
") is greater than the maximum (%"
501 PRId64
").", desc
, arg
, result
, max
);
505 static const char help_strings
[] =
506 "\t-b bsize\tblock size\n"
507 "\t-D inodesize\tsize of an inode in bytes (128 or 256)\n"
508 "\t-F \t\tcreate file system image in regular file\n"
509 "\t-f fsize\tfragment size\n"
510 "\t-I \t\tdo not check that the file system type is `Linux Ext2'\n"
511 "\t-i density\tnumber of bytes per inode\n"
512 "\t-m minfree\tminimum free space %\n"
513 "\t-N \t\tdo not create file system, just print out parameters\n"
514 "\t-n inodes\tnumber of inodes (overrides -i density)\n"
515 "\t-O N\t\tfilesystem revision: 0 ==> REV0, 1 ==> REV1 (default 0)\n"
516 "\t-S secsize\tsector size\n"
517 "\t-s fssize\tfile system size (sectors)\n"
518 "\t-V verbose\toutput verbosity: 0 ==> none, 4 ==> max\n"
519 "\t-v volname\text2fs volume name\n"
520 "\t-Z \t\tpre-zero the image file\n";
527 "usage: %s [ fsoptions ] special-device\n", getprogname());
528 fprintf(stderr
, "where fsoptions are:\n");
529 fprintf(stderr
, "%s", help_strings
);