v7fs(7th edition(V7) file system) support.

This commit is contained in:
uch 2011-07-18 08:58:38 +00:00
parent 5dbbcf1470
commit dd9e830956
10 changed files with 853 additions and 8 deletions

View File

@ -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 @@ WARNS?= 3 # XXX -Wsign-compare
.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 @@ CPPFLAGS+= -I${.CURDIR} -I${MKNODSRC} -I${MTREESRC}
.include "${.CURDIR}/cd9660/Makefile.inc"
.include "${.CURDIR}/ffs/Makefile.inc"
.include "${.CURDIR}/v7fs/Makefile.inc"
.if (${HOSTPROG:U} == "")
DPADD+= ${LIBUTIL}

View File

@ -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 @@ makefs creates a file system image from a given directory tree.
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

View File

@ -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 @@ The following file system types are supported:
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 @@ Use RockRidge extensions (for longer filenames, etc.).
.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 @@ utility appeared in
.An Ryan Gabrys ,
.An Alan Perez-Rathke ,
.An Ram Vedam
(cd9660 support)
(cd9660 support),
.An UCHIYAMA Yasushi
(v7fs support)

View File

@ -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 @@ static fstype_t fstypes[] = {
{ "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 },
};

View File

@ -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 @@ int cd9660_parse_opts(const char *, fsinfo_t *);
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;

181
usr.sbin/makefs/v7fs.c Normal file
View File

@ -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);
}
}

View File

@ -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

View File

@ -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 */
}

View File

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

View File

@ -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_*/