1 /* $NetBSD: v7fs_populate.c,v 1.3 2011/08/10 11:31:49 uch Exp $ */
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
36 #include <sys/cdefs.h>
37 #if defined(__RCSID) && !defined(__lint)
38 __RCSID("$NetBSD: v7fs_populate.c,v 1.3 2011/08/10 11:31:49 uch Exp $");
49 #if !HAVE_NBTOOL_CONFIG_H
50 #include <sys/mount.h>
55 #include "v7fs_impl.h"
56 #include "v7fs_inode.h"
57 #include "v7fs_superblock.h"
58 #include "v7fs_datablock.h"
59 #include "v7fs_endian.h"
60 #include "v7fs_file.h"
61 #include "v7fs_makefs.h"
62 #include "newfs_v7fs.h"
64 #define VPRINTF(fmt, args...) { if (v7fs_newfs_verbose) printf(fmt, ##args); }
67 attr_setup(fsnode
*node
, struct v7fs_fileattr
*attr
)
69 struct stat
*st
= &node
->inode
->st
;
71 attr
->mode
= node
->type
| st
->st_mode
;
72 attr
->uid
= st
->st_uid
;
73 attr
->gid
= st
->st_gid
;
75 attr
->ctime
= st
->st_ctime
;
76 attr
->atime
= st
->st_atime
;
77 attr
->mtime
= st
->st_mtime
;
81 allocate(struct v7fs_self
*fs
, struct v7fs_inode
*parent_inode
, fsnode
*node
,
82 dev_t dev
, struct v7fs_inode
*inode
)
86 struct v7fs_fileattr attr
;
88 memset(inode
, 0, sizeof(*inode
));
90 attr_setup(node
, &attr
);
92 if ((error
= v7fs_file_allocate(fs
, parent_inode
, node
->name
, &attr
,
95 warn("%s", node
->name
);
98 node
->inode
->ino
= ino
;
99 node
->inode
->flags
|= FI_ALLOCATED
;
100 if ((error
= v7fs_inode_load(fs
, inode
, ino
))) {
102 warn("%s", node
->name
);
111 uint8_t buf
[V7FS_BSIZE
];
115 copy_subr(struct v7fs_self
*fs
, void *ctx
, v7fs_daddr_t blk
, size_t sz
)
117 struct copy_arg
*p
= ctx
;
119 if (read(p
->fd
, p
->buf
, sz
) != (ssize_t
)sz
) {
120 return V7FS_ITERATOR_ERROR
;
123 if (!fs
->io
.write(fs
->io
.cookie
, p
->buf
, blk
)) {
125 return V7FS_ITERATOR_ERROR
;
133 file_copy(struct v7fs_self
*fs
, struct v7fs_inode
*parent_inode
, fsnode
*node
,
134 const char *filepath
)
136 struct v7fs_inode inode
;
138 fsinode
*fnode
= node
->inode
;
142 /* Check hard-link */
143 if ((fnode
->nlink
> 1) && (fnode
->flags
& FI_ALLOCATED
)) {
144 if ((error
= v7fs_inode_load(fs
, &inode
, fnode
->ino
))) {
145 errmsg
= "inode load";
148 if ((error
= v7fs_file_link(fs
, parent_inode
, &inode
,
150 errmsg
= "hard link";
157 if ((error
= allocate(fs
, parent_inode
, node
, 0, &inode
))) {
158 errmsg
= "file allocate";
161 if ((error
= v7fs_datablock_expand(fs
, &inode
, fnode
->st
.st_size
))) {
162 errmsg
= "datablock expand";
167 if ((fd
= open(filepath
, O_RDONLY
)) == -1) {
169 errmsg
= "source file";
173 error
= v7fs_datablock_foreach(fs
, &inode
, copy_subr
,
174 &(struct copy_arg
){ .fd
= fd
});
175 if (error
!= V7FS_ITERATOR_END
) {
176 errmsg
= "data copy";
188 warn("%s %s", node
->name
, errmsg
);
194 populate_walk(struct v7fs_self
*fs
, struct v7fs_inode
*parent_inode
,
195 fsnode
*root
, char *dir
)
198 char *mydir
= dir
+ strlen(dir
);
199 char srcpath
[MAXPATHLEN
+ 1];
200 struct v7fs_inode inode
;
204 for (cur
= root
; cur
!= NULL
; cur
= cur
->next
) {
205 switch (cur
->type
& S_IFMT
) {
207 VPRINTF("%x\n", cur
->flags
& S_IFMT
);
212 if ((error
= allocate(fs
, parent_inode
, cur
,
213 cur
->inode
->st
.st_rdev
, &inode
))) {
215 warn("%s", cur
->name
);
219 if (!cur
->child
) /*'.'*/
221 /* Allocate this directory. */
222 if ((error
= allocate(fs
, parent_inode
, cur
, 0,
225 warn("%s", cur
->name
);
227 /* Populate children. */
229 strcpy(&mydir
[1], cur
->name
);
230 error
= populate_walk(fs
, &inode
, cur
->child
,
236 snprintf(srcpath
, sizeof(srcpath
), "%s/%s", dir
,
238 error
= file_copy(fs
, parent_inode
, cur
, srcpath
);
241 if ((error
= allocate(fs
, parent_inode
, cur
, 0,
244 warn("%s", cur
->name
);
246 v7fs_file_symlink(fs
, &inode
, cur
->symlink
);
254 return failed
? 2 : 0;
258 v7fs_populate(const char *dir
, fsnode
*root
, fsinfo_t
*fsopts
,
259 const struct v7fs_mount_device
*device
)
261 v7fs_opt_t
*v7fs_opts
= fsopts
->fs_specific
;
262 static char path
[MAXPATHLEN
+ 1];
263 struct v7fs_inode root_inode
;
264 struct v7fs_self
*fs
;
267 if ((error
= v7fs_io_init(&fs
, device
, V7FS_BSIZE
))) {
269 warn("I/O setup failed.");
272 fs
->endian
= device
->endian
;
273 v7fs_endian_init(fs
);
275 if ((error
= v7fs_superblock_load(fs
))) {
277 warn("Can't load superblock.");
280 fsopts
->superblock
= &fs
->superblock
; /* not used. */
282 if ((error
= v7fs_inode_load(fs
, &root_inode
, V7FS_ROOT_INODE
))) {
284 warn("Can't load root inode.");
288 progress(&(struct progress_arg
){ .label
= "populate", .tick
=
289 v7fs_opts
->npuredatablk
/ PROGRESS_BAR_GRANULE
});
291 strncpy(path
, dir
, sizeof(path
));
292 error
= populate_walk(fs
, &root_inode
, root
, path
);
294 v7fs_inode_writeback(fs
, &root_inode
);
295 v7fs_superblock_writeback(fs
);