Module Name: src Committed By: uch Date: Mon Jul 18 08:58:39 UTC 2011
Modified Files: src/usr.sbin/makefs: Makefile README makefs.8 makefs.c makefs.h Added Files: src/usr.sbin/makefs: v7fs.c v7fs_makefs.h src/usr.sbin/makefs/v7fs: Makefile.inc v7fs_estimate.c v7fs_populate.c Log Message: v7fs(7th edition(V7) file system) support. To generate a diff of this commit: cvs rdiff -u -r1.25 -r1.26 src/usr.sbin/makefs/Makefile cvs rdiff -u -r1.4 -r1.5 src/usr.sbin/makefs/README cvs rdiff -u -r1.33 -r1.34 src/usr.sbin/makefs/makefs.8 cvs rdiff -u -r1.26 -r1.27 src/usr.sbin/makefs/makefs.c cvs rdiff -u -r1.20 -r1.21 src/usr.sbin/makefs/makefs.h cvs rdiff -u -r0 -r1.1 src/usr.sbin/makefs/v7fs.c \ src/usr.sbin/makefs/v7fs_makefs.h cvs rdiff -u -r0 -r1.1 src/usr.sbin/makefs/v7fs/Makefile.inc \ src/usr.sbin/makefs/v7fs/v7fs_estimate.c \ src/usr.sbin/makefs/v7fs/v7fs_populate.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.sbin/makefs/Makefile diff -u src/usr.sbin/makefs/Makefile:1.25 src/usr.sbin/makefs/Makefile:1.26 --- src/usr.sbin/makefs/Makefile:1.25 Wed Apr 22 15:23:05 2009 +++ src/usr.sbin/makefs/Makefile Mon Jul 18 08:58:38 2011 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.25 2009/04/22 15:23:05 lukem Exp $ +# $NetBSD: Makefile,v 1.26 2011/07/18 08:58:38 uch Exp $ # WARNS?= 3 # XXX -Wsign-compare @@ -6,7 +6,7 @@ .include <bsd.own.mk> PROG= makefs -SRCS= cd9660.c ffs.c \ +SRCS= cd9660.c ffs.c v7fs.c \ getid.c \ makefs.c misc.c \ pack_dev.c \ @@ -22,6 +22,7 @@ .include "${.CURDIR}/cd9660/Makefile.inc" .include "${.CURDIR}/ffs/Makefile.inc" +.include "${.CURDIR}/v7fs/Makefile.inc" .if (${HOSTPROG:U} == "") DPADD+= ${LIBUTIL} Index: src/usr.sbin/makefs/README diff -u src/usr.sbin/makefs/README:1.4 src/usr.sbin/makefs/README:1.5 --- src/usr.sbin/makefs/README:1.4 Sat Jan 3 08:25:35 2009 +++ src/usr.sbin/makefs/README Mon Jul 18 08:58:38 2011 @@ -1,4 +1,4 @@ -$NetBSD: README,v 1.4 2009/01/03 08:25:35 lukem Exp $ +$NetBSD: README,v 1.5 2011/07/18 08:58:38 uch Exp $ makefs - build a file system image from a directory tree @@ -17,6 +17,7 @@ the following file system types can be built: ffs BSD fast file system cd9660 ISO 9660 file system + v7fs 7th edition(V7) file system Support for the following file systems maybe be added in the future ext2fs Linux EXT2 file system Index: src/usr.sbin/makefs/makefs.8 diff -u src/usr.sbin/makefs/makefs.8:1.33 src/usr.sbin/makefs/makefs.8:1.34 --- src/usr.sbin/makefs/makefs.8:1.33 Sun May 22 21:51:39 2011 +++ src/usr.sbin/makefs/makefs.8 Mon Jul 18 08:58:38 2011 @@ -1,4 +1,4 @@ -.\" $NetBSD: makefs.8,v 1.33 2011/05/22 21:51:39 christos Exp $ +.\" $NetBSD: makefs.8,v 1.34 2011/07/18 08:58:38 uch Exp $ .\" .\" Copyright (c) 2001-2003 Wasabi Systems, Inc. .\" All rights reserved. @@ -191,6 +191,8 @@ BSD fast file system (default). .It Sy cd9660 ISO 9660 file system. +.It Sy v7fs +7th Edition(V7) file system. .El .It Fl x Exclude file system nodes not explicitly listed in the specfile. @@ -327,6 +329,16 @@ .It Sy volumeid Volume set identifier of the image. .El +.Ss V7FS-specific options +The following keywords are supported: +.Pp +.Bl -tag -width optimization -offset indent -compact +.It Sy pdp +PDP endian. +.It Sy progress +Display a progress meter for the file system construction and file +popuration. +.El .Sh SEE ALSO .Xr strsuftoll 3 , .Xr installboot 8 , @@ -346,4 +358,6 @@ .An Ryan Gabrys , .An Alan Perez-Rathke , .An Ram Vedam -(cd9660 support) +(cd9660 support), +.An UCHIYAMA Yasushi +(v7fs support) Index: src/usr.sbin/makefs/makefs.c diff -u src/usr.sbin/makefs/makefs.c:1.26 src/usr.sbin/makefs/makefs.c:1.27 --- src/usr.sbin/makefs/makefs.c:1.26 Sun Oct 22 21:11:56 2006 +++ src/usr.sbin/makefs/makefs.c Mon Jul 18 08:58:38 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: makefs.c,v 1.26 2006/10/22 21:11:56 christos Exp $ */ +/* $NetBSD: makefs.c,v 1.27 2011/07/18 08:58:38 uch Exp $ */ /* * Copyright (c) 2001-2003 Wasabi Systems, Inc. @@ -41,7 +41,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) && !defined(__lint) -__RCSID("$NetBSD: makefs.c,v 1.26 2006/10/22 21:11:56 christos Exp $"); +__RCSID("$NetBSD: makefs.c,v 1.27 2011/07/18 08:58:38 uch Exp $"); #endif /* !__lint */ #include <assert.h> @@ -73,6 +73,8 @@ { "ffs", ffs_prep_opts, ffs_parse_opts, ffs_cleanup_opts, ffs_makefs }, { "cd9660", cd9660_prep_opts, cd9660_parse_opts, cd9660_cleanup_opts, cd9660_makefs}, + { "v7fs", v7fs_prep_opts, v7fs_parse_opts, v7fs_cleanup_opts, + v7fs_makefs }, { .type = NULL }, }; Index: src/usr.sbin/makefs/makefs.h diff -u src/usr.sbin/makefs/makefs.h:1.20 src/usr.sbin/makefs/makefs.h:1.21 --- src/usr.sbin/makefs/makefs.h:1.20 Sun Dec 28 21:51:46 2008 +++ src/usr.sbin/makefs/makefs.h Mon Jul 18 08:58:38 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: makefs.h,v 1.20 2008/12/28 21:51:46 christos Exp $ */ +/* $NetBSD: makefs.h,v 1.21 2011/07/18 08:58:38 uch Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -170,6 +170,10 @@ void cd9660_cleanup_opts(fsinfo_t *); void cd9660_makefs(const char *, const char *, fsnode *, fsinfo_t *); +void v7fs_prep_opts(fsinfo_t *); +int v7fs_parse_opts(const char *, fsinfo_t *); +void v7fs_cleanup_opts(fsinfo_t *); +void v7fs_makefs(const char *, const char *, fsnode *, fsinfo_t *); extern u_int debug; extern struct timespec start_time; Added files: Index: src/usr.sbin/makefs/v7fs.c diff -u /dev/null src/usr.sbin/makefs/v7fs.c:1.1 --- /dev/null Mon Jul 18 08:58:39 2011 +++ src/usr.sbin/makefs/v7fs.c Mon Jul 18 08:58:38 2011 @@ -0,0 +1,181 @@ +/* $NetBSD: v7fs.c,v 1.1 2011/07/18 08:58:38 uch Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include <sys/cdefs.h> +#if defined(__RCSID) && !defined(__lint) +__RCSID("$NetBSD: v7fs.c,v 1.1 2011/07/18 08:58:38 uch Exp $"); +#endif /* !__lint */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> + +#include "makefs.h" +#include "v7fs.h" +#include "v7fs_impl.h" +#include "v7fs_makefs.h" +#include "newfs_v7fs.h" +#include "progress.h" + +static v7fs_opt_t v7fs_opts; +static bool progress_bar_enable; +bool verbose; + +void +v7fs_prep_opts(fsinfo_t *fsopts) +{ + + fsopts->fs_specific = &v7fs_opts; +} + +void +v7fs_cleanup_opts(fsinfo_t *fsopts) +{ + /*NO-OP*/ +} + +int +v7fs_parse_opts(const char *option, fsinfo_t *fsopts) +{ + static option_t v7fs_options[] = { + { "pdp", &v7fs_opts.pdp_endian, false, true, "PDP endian" }, + { "progress", &v7fs_opts.progress, false, true, + "Progress bar" }, + { .name = NULL } + }; + + set_option(v7fs_options, option, "1"); + + return 1; +} + +void +v7fs_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts) +{ + struct v7fs_mount_device v7fs_mount; + int fd, endian, error = 1; + + verbose = debug; + if ((progress_bar_enable = v7fs_opts.progress)) { + progress_switch(progress_bar_enable); + progress_init(); + progress(&(struct progress_arg){ .cdev = image }); + } + + /* Determine filesystem image size */ + v7fs_estimate(dir, root, fsopts); + printf("Calculated size of `%s': %lld bytes, %ld inodes\n", + image, (long long)fsopts->size, (long)fsopts->inodes); + + if ((fd = open(image, O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1) { + err(EXIT_FAILURE, "%s", image); + } + if (lseek(fd, fsopts->size - 1, SEEK_SET) == -1) { + goto err_exit; + } + if (write(fd, &fd, 1) != 1) { + goto err_exit; + } + if (lseek(fd, 0, SEEK_SET) == -1) { + goto err_exit; + } + fsopts->fd = fd; + v7fs_mount.device.fd = fd; + +#if !defined BYTE_ORDER +#error +#endif +#if BYTE_ORDER == LITTLE_ENDIAN + if (fsopts->needswap) + endian = BIG_ENDIAN; + else + endian = LITTLE_ENDIAN; +#else + if (fsopts->needswap) + endian = LITTLE_ENDIAN; + else + endian = BIG_ENDIAN; +#endif + if (v7fs_opts.pdp_endian) { + endian = PDP_ENDIAN; + } + + v7fs_mount.endian = endian; + v7fs_mount.sectors = fsopts->size >> V7FS_BSHIFT; + if (v7fs_newfs(&v7fs_mount, fsopts->inodes) != 0) { + goto err_exit; + } + + if (v7fs_populate(dir, root, fsopts, &v7fs_mount) != 0) { + error = 2; /* some files couldn't add */ + goto err_exit; + } + + close(fd); + return; + + err_exit: + close(fd); + err(error, "%s", image); +} + +void +progress(const struct progress_arg *p) +{ + static struct progress_arg Progress; + static char cdev[32]; + static char label[32]; + + if (!progress_bar_enable) + return; + + if (p) { + Progress = *p; + if (p->cdev) + strcpy(cdev, p->cdev); + if (p->label) + strcpy(label, p->label); + } + + if (!Progress.tick) + return; + if (++Progress.cnt > Progress.tick) { + Progress.cnt = 0; + Progress.total++; + progress_bar(cdev, label, Progress.total, PROGRESS_BAR_GRANULE); + } +} Index: src/usr.sbin/makefs/v7fs_makefs.h diff -u /dev/null src/usr.sbin/makefs/v7fs_makefs.h:1.1 --- /dev/null Mon Jul 18 08:58:39 2011 +++ src/usr.sbin/makefs/v7fs_makefs.h Mon Jul 18 08:58:38 2011 @@ -0,0 +1,48 @@ +/* $NetBSD: v7fs_makefs.h,v 1.1 2011/07/18 08:58:38 uch Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MAKEFS_V7FS_H_ +#define _MAKEFS_V7FS_H_ + +typedef struct { + int pdp_endian; + int progress; + v7fs_daddr_t npuredatablk; /* for progress bar */ +} v7fs_opt_t; + +__BEGIN_DECLS +void v7fs_estimate(const char *, fsnode *, fsinfo_t *); +int v7fs_populate(const char *, fsnode *, fsinfo_t *, + const struct v7fs_mount_device *); +struct progress_arg; +void progress(const struct progress_arg *); +__END_DECLS +#endif /*!_MAKEFS_V7FS_H_*/ Index: src/usr.sbin/makefs/v7fs/Makefile.inc diff -u /dev/null src/usr.sbin/makefs/v7fs/Makefile.inc:1.1 --- /dev/null Mon Jul 18 08:58:39 2011 +++ src/usr.sbin/makefs/v7fs/Makefile.inc Mon Jul 18 08:58:39 2011 @@ -0,0 +1,18 @@ +# $NetBSD: Makefile.inc,v 1.1 2011/07/18 08:58:39 uch Exp $ +# + +V7FS= ${NETBSDSRCDIR}/sys/fs/v7fs +NEWFS= ${NETBSDSRCDIR}/sbin/newfs_v7fs +FSCK= ${NETBSDSRCDIR}/sbin/fsck # use progress meter. + +.PATH: ${.CURDIR}/v7fs ${V7FS} ${NEWFS} ${FSCK} + +CPPFLAGS+= -DV7FS_EI -I${V7FS} -I${NEWFS} -I${FSCK} + +SRCS += v7fs_endian.c v7fs_superblock.c v7fs_superblock_util.c v7fs_inode.c \ +v7fs_inode_util.c v7fs_datablock.c v7fs_dirent.c v7fs_io.c v7fs_file.c \ +v7fs_file_util.c v7fs_io_user.c +SRCS += main.c # newfs +SRCS += progress.c # progress bar (fsck) + +SRCS += v7fs_estimate.c v7fs_populate.c \ No newline at end of file Index: src/usr.sbin/makefs/v7fs/v7fs_estimate.c diff -u /dev/null src/usr.sbin/makefs/v7fs/v7fs_estimate.c:1.1 --- /dev/null Mon Jul 18 08:58:39 2011 +++ src/usr.sbin/makefs/v7fs/v7fs_estimate.c Mon Jul 18 08:58:39 2011 @@ -0,0 +1,277 @@ +/* $NetBSD: v7fs_estimate.c,v 1.1 2011/07/18 08:58:39 uch Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include <sys/cdefs.h> +#if defined(__RCSID) && !defined(__lint) +__RCSID("$NetBSD: v7fs_estimate.c,v 1.1 2011/07/18 08:58:39 uch Exp $"); +#endif /* !__lint */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> + +#if !HAVE_NBTOOL_CONFIG_H +#include <sys/mount.h> /*MAXPATHLEN */ +#endif + +#include "makefs.h" +#include "v7fs.h" +#include "v7fs_impl.h" +#include "v7fs_inode.h" +#include "v7fs_datablock.h" +#include "v7fs_makefs.h" + +struct v7fs_geometry { + v7fs_daddr_t ndatablock; + v7fs_ino_t ninode; + v7fs_daddr_t npuredatablk; +}; + +extern bool verbose; +#define VPRINTF(fmt, args...) { if (verbose) printf(fmt, ##args); } + +static int +v7fs_datablock_size(off_t sz, v7fs_daddr_t *nblk) +{ + struct v7fs_daddr_map map; + int error = 0; + + if (sz == 0) { + *nblk = 0; + return 0; + } + + if ((error = v7fs_datablock_addr(sz, &map))) { + return error; + } + switch (map.level) { + case 0: /* Direct */ + *nblk = map.index[0] + 1; + break; + case 1: + *nblk = V7FS_NADDR_DIRECT + /*direct */ + 1/*addr[V7FS_NADDR_INDEX1]*/ + map.index[0] + 1; + break; + case 2: + *nblk = V7FS_NADDR_DIRECT + /*direct */ + 1/*addr[V7FS_NADDR_INDEX1]*/ + + V7FS_DADDR_PER_BLOCK +/*idx1 */ + 1/*addr[V7FS_NADDR_INDEX2]*/ + + map.index[0] + /* # of idx2 index block(filled) */ + map.index[0] * V7FS_DADDR_PER_BLOCK + /* of its datablocks*/ + 1 + /*current idx2 indexblock */ + map.index[1] + 1; + break; + case 3: + *nblk = V7FS_NADDR_DIRECT + /*direct */ + 1/*addr[V7FS_NADDR_INDEX1]*/ + + V7FS_DADDR_PER_BLOCK +/*idx1 */ + 1/*addr[V7FS_NADDR_INDEX2]*/ + + V7FS_DADDR_PER_BLOCK + /* # of idx2 index block */ + V7FS_DADDR_PER_BLOCK * V7FS_DADDR_PER_BLOCK + + /*idx2 datablk */ + 1/*addr[v7FS_NADDR_INDEX3*/ + + map.index[0] + /* # of lv1 index block(filled) */ + map.index[0] * V7FS_DADDR_PER_BLOCK * V7FS_DADDR_PER_BLOCK + + 1 + /*lv1 */ + map.index[1] + /* #of lv2 index block(filled) */ + map.index[1] * V7FS_DADDR_PER_BLOCK + /*lv2 datablock */ + 1 + /* current lv2 index block */ + map.index[2] + 1; /*filled datablock */ + break; + default: + *nblk = 0; + error = EINVAL; + break; + } + + return error; +} + +static int +estimate_size_walk(fsnode *root, char *dir, struct v7fs_geometry *geom) +{ + fsnode *cur; + int nentries; + size_t pathlen = strlen(dir); + char *mydir = dir + pathlen; + fsinode *fnode; + v7fs_daddr_t nblk; + int n; + off_t sz; + + for (cur = root, nentries = 0; cur != NULL; cur = cur->next, + nentries++, geom->ninode++) { + switch (cur->type & S_IFMT) { + default: + break; + case S_IFDIR: + if (!cur->child) + break; + mydir[0] = '/'; + strncpy(&mydir[1], cur->name, MAXPATHLEN - pathlen); + n = estimate_size_walk(cur->child, dir, geom); + sz = (n + 1/*..*/) * sizeof(struct v7fs_dirent); + v7fs_datablock_size(sz, &nblk); + mydir[0] = '\0'; + geom->ndatablock += nblk; + geom->npuredatablk += + V7FS_ROUND_BSIZE(sz) >> V7FS_BSHIFT; + break; + case S_IFREG: + fnode = cur->inode; + if (!(fnode->flags & FI_SIZED)) { /*Skip hard-link */ + sz = fnode->st.st_size; + v7fs_datablock_size(sz, &nblk); + geom->ndatablock += nblk; + geom->npuredatablk += + V7FS_ROUND_BSIZE(sz) >> V7FS_BSHIFT; + fnode->flags |= FI_SIZED; + } + + break; + case S_IFLNK: + nblk = V7FSBSD_MAXSYMLINKLEN >> V7FS_BSHIFT; + geom->ndatablock += nblk; + geom->npuredatablk += nblk; + break; + } + } + + return nentries; +} + +static v7fs_daddr_t +calculate_fs_size(const struct v7fs_geometry *geom) +{ + v7fs_daddr_t fs_blk, ilist_blk; + + ilist_blk = V7FS_ROUND_BSIZE(geom->ninode * + sizeof(struct v7fs_inode_diskimage)) >> V7FS_BSHIFT; + fs_blk = geom->ndatablock + ilist_blk + V7FS_ILIST_SECTOR; + + VPRINTF("datablock:%d ilistblock:%d total:%d\n", geom->ndatablock, + ilist_blk, fs_blk); + + return fs_blk; +} + +static void +determine_fs_size(fsinfo_t *fsopts, struct v7fs_geometry *geom) +{ + v7fs_daddr_t nblk = geom->ndatablock; + v7fs_daddr_t fsblk; + int32_t nfiles = geom->ninode; + int n; + + VPRINTF("size=%lld inodes=%lld fd=%d superb=%p onlyspec=%d\n", + (long long)fsopts->size, (long long)fsopts->inodes, fsopts->fd, + fsopts->superblock, fsopts->onlyspec); + VPRINTF("minsize=%lld maxsize=%lld freefiles=%lld freefilepc=%d " + "freeblocks=%lld freeblockpc=%d sectorseize=%d\n", + (long long)fsopts->minsize, (long long)fsopts->maxsize, + (long long)fsopts->freefiles, fsopts->freefilepc, + (long long)fsopts->freeblocks, fsopts->freeblockpc, + fsopts->sectorsize); + + if ((fsopts->sectorsize > 0) && (fsopts->sectorsize != V7FS_BSIZE)) + warnx("v7fs sector size is 512byte only. '-S %d' is ignored.", + fsopts->sectorsize); + + /* Free inode */ + if (fsopts->freefiles) { + nfiles += fsopts->freefiles; + } else if ((n = fsopts->freefilepc)) { + nfiles += (nfiles * n) / (100 - n); + } + if (nfiles >= V7FS_INODE_MAX) { + errx(EXIT_FAILURE, "# of files(%d) over v7fs limit(%d).", + nfiles, V7FS_INODE_MAX); + } + + /* Free datablock */ + if (fsopts->freeblocks) { + nblk += fsopts->freeblocks; + } else if ((n = fsopts->freeblockpc)) { + nblk += (nblk * n) / (100 - n); + } + + /* Total size */ + geom->ndatablock = nblk; + geom->ninode = nfiles; + fsblk = calculate_fs_size(geom); + + if (fsblk >= V7FS_DADDR_MAX) { + errx(EXIT_FAILURE, "filesystem size(%d) over v7fs limit(%d).", + fsblk, V7FS_DADDR_MAX); + } + + n = fsopts->minsize >> V7FS_BSHIFT; + if (fsblk < n) + geom->ndatablock += (n - fsblk); + + n = fsopts->maxsize >> V7FS_BSHIFT; + if (fsopts->maxsize > 0 && fsblk > n) { + errx(EXIT_FAILURE, "# of datablocks %d > %d", fsblk, n); + } +} + +void +v7fs_estimate(const char *dir, fsnode *root, fsinfo_t *fsopts) +{ + v7fs_opt_t *v7fs_opts = fsopts->fs_specific; + char path[MAXPATHLEN + 1]; + int ndir; + off_t sz; + v7fs_daddr_t nblk; + struct v7fs_geometry geom; + + memset(&geom , 0, sizeof(geom)); + strncpy(path, dir, sizeof(path)); + + /* Calculate strict size. */ + ndir = estimate_size_walk(root, path, &geom); + sz = (ndir + 1/*..*/) * sizeof(struct v7fs_dirent); + v7fs_datablock_size(sz, &nblk); + geom.ndatablock += nblk; + + /* Consider options. */ + determine_fs_size(fsopts, &geom); + + fsopts->size = calculate_fs_size(&geom) << V7FS_BSHIFT; + fsopts->inodes = geom.ninode; + v7fs_opts->npuredatablk = geom.npuredatablk; /* for progress bar */ +} Index: src/usr.sbin/makefs/v7fs/v7fs_populate.c diff -u /dev/null src/usr.sbin/makefs/v7fs/v7fs_populate.c:1.1 --- /dev/null Mon Jul 18 08:58:39 2011 +++ src/usr.sbin/makefs/v7fs/v7fs_populate.c Mon Jul 18 08:58:39 2011 @@ -0,0 +1,299 @@ +/* $NetBSD: v7fs_populate.c,v 1.1 2011/07/18 08:58:39 uch Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by UCHIYAMA Yasushi. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include <sys/cdefs.h> +#if defined(__RCSID) && !defined(__lint) +__RCSID("$NetBSD: v7fs_populate.c,v 1.1 2011/07/18 08:58:39 uch Exp $"); +#endif /* !__lint */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <err.h> + +#if !HAVE_NBTOOL_CONFIG_H +#include <sys/mount.h> +#endif + +#include "makefs.h" +#include "v7fs.h" +#include "v7fs_impl.h" +#include "v7fs_inode.h" +#include "v7fs_superblock.h" +#include "v7fs_datablock.h" +#include "v7fs_endian.h" +#include "v7fs_file.h" +#include "v7fs_makefs.h" +#include "newfs_v7fs.h" + +extern bool verbose; +#define VPRINTF(fmt, args...) { if (verbose) printf(fmt, ##args); } + +static void +attr_setup(fsnode *node, struct v7fs_fileattr *attr) +{ + struct stat *st = &node->inode->st; + + attr->mode = node->type | st->st_mode; + attr->uid = st->st_uid; + attr->gid = st->st_gid; + attr->device = 0; + attr->ctime = st->st_ctime; + attr->atime = st->st_atime; + attr->mtime = st->st_mtime; +} + +static int +allocate(struct v7fs_self *fs, struct v7fs_inode *parent_inode, fsnode *node, + dev_t dev, struct v7fs_inode *inode) +{ + int error; + v7fs_ino_t ino; + struct v7fs_fileattr attr; + + memset(inode, 0, sizeof(*inode)); + + attr_setup(node, &attr); + attr.device = dev; + if ((error = v7fs_file_allocate(fs, parent_inode, node->name, &attr, + &ino))) { + errno = error; + warn("%s", node->name); + return error; + } + node->inode->ino = ino; + node->inode->flags |= FI_ALLOCATED; + if ((error = v7fs_inode_load(fs, inode, ino))) { + errno = error; + warn("%s", node->name); + return error; + } + + return 0; +} + +struct copy_arg { + int fd; + uint8_t buf[V7FS_BSIZE]; +}; + +static int +copy_subr(struct v7fs_self *fs, void *ctx, v7fs_daddr_t blk, size_t sz) +{ + struct copy_arg *p = ctx; + + if ((sz = read(p->fd, p->buf, sz)) != sz) { + return V7FS_ITERATOR_ERROR; + } + + if (!fs->io.write(fs->io.cookie, p->buf, blk)) { + errno = EIO; + return V7FS_ITERATOR_ERROR; + } + progress(0); + + return 0; +} + +static int +file_copy(struct v7fs_self *fs, struct v7fs_inode *parent_inode, fsnode *node, + const char *filepath) +{ + struct v7fs_inode inode; + const char *errmsg; + fsinode *fnode = node->inode; + int error = 0; + int fd; + + /* Check hard-link */ + if ((fnode->nlink > 1) && (fnode->flags & FI_ALLOCATED)) { + if ((error = v7fs_inode_load(fs, &inode, fnode->ino))) { + errmsg = "inode load"; + goto err_exit; + } + if ((error = v7fs_file_link(fs, parent_inode, &inode, + node->name))) { + errmsg = "hard link"; + goto err_exit; + } + return 0; + } + + /* Allocate file */ + if ((error = allocate(fs, parent_inode, node, 0, &inode))) { + errmsg = "file allocate"; + goto err_exit; + } + if ((error = v7fs_datablock_expand(fs, &inode, fnode->st.st_size))) { + errmsg = "datablock expand"; + goto err_exit; + } + + /* Data copy */ + if ((fd = open(filepath, O_RDONLY)) == -1) { + error = errno; + errmsg = "source file"; + goto err_exit; + } + + error = v7fs_datablock_foreach(fs, &inode, copy_subr, + &(struct copy_arg){ .fd = fd }); + if (error != V7FS_ITERATOR_END) { + errmsg = "data copy"; + close(fd); + goto err_exit; + } else { + error = 0; + } + close(fd); + + return error; + +err_exit: + errno = error; + warn("%s %s", node->name, errmsg); + + return error; +} + +static int +populate_walk(struct v7fs_self *fs, struct v7fs_inode *parent_inode, + fsnode *root, char *dir) +{ + fsnode *cur; + char *mydir = dir + strlen(dir); + char srcpath[MAXPATHLEN + 1]; + struct v7fs_inode inode; + int error = 0; + bool failed = false; + + for (cur = root; cur != NULL; cur = cur->next) { + switch (cur->type & S_IFMT) { + default: + VPRINTF("%x\n", cur->flags & S_IFMT); + break; + case S_IFCHR: + /*FALLTHROUGH*/ + case S_IFBLK: + if ((error = allocate(fs, parent_inode, cur, + cur->inode->st.st_rdev, &inode))) { + errno = error; + warn("%s", cur->name); + } + break; + case S_IFDIR: + if (!cur->child) /*'.'*/ + break; + /* Allocate this directory. */ + if ((error = allocate(fs, parent_inode, cur, 0, + &inode))) { + errno = error; + warn("%s", cur->name); + } else { + /* Populate children. */ + mydir[0] = '/'; + strcpy(&mydir[1], cur->name); + error = populate_walk(fs, &inode, cur->child, + dir); + mydir[0] = '\0'; + } + break; + case S_IFREG: + snprintf(srcpath, sizeof(srcpath), "%s/%s", dir, + cur->name); + error = file_copy(fs, parent_inode, cur, srcpath); + break; + case S_IFLNK: + if ((error = allocate(fs, parent_inode, cur, 0, + &inode))) { + errno = error; + warn("%s", cur->name); + } else { + v7fs_file_symlink(fs, &inode, cur->symlink); + } + break; + } + if (error) + failed = true; + } + + return failed ? 2 : 0; +} + +int +v7fs_populate(const char *dir, fsnode *root, fsinfo_t *fsopts, + const struct v7fs_mount_device *device) +{ + v7fs_opt_t *v7fs_opts = fsopts->fs_specific; + static char path[MAXPATHLEN + 1]; + struct v7fs_inode root_inode; + struct v7fs_self *fs; + int error; + + if ((error = v7fs_io_init(&fs, device, V7FS_BSIZE))) { + errno = error; + warn("I/O setup failed."); + return error; + } + fs->endian = device->endian; + v7fs_endian_init(fs); + + if ((error = v7fs_superblock_load(fs))) { + errno = error; + warn("Can't load superblock."); + return error; + } + fsopts->superblock = &fs->superblock; /* not used. */ + + if ((error = v7fs_inode_load(fs, &root_inode, V7FS_ROOT_INODE))) { + errno = error; + warn("Can't load root inode."); + return error; + } + + progress(&(struct progress_arg){ .label = "populate", .tick = + v7fs_opts->npuredatablk / PROGRESS_BAR_GRANULE }); + + strncpy(path, dir, sizeof(path)); + error = populate_walk(fs, &root_inode, root, path); + + v7fs_inode_writeback(fs, &root_inode); + v7fs_superblock_writeback(fs); + + return error; +}