v7fs(7th edition(V7) file system) support.
This commit is contained in:
parent
5dbbcf1470
commit
dd9e830956
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 },
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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 */
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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_*/
|
Loading…
Reference in New Issue