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

Reply via email to