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;
+}