1*9f988b79SJean-Baptiste Boric /* $NetBSD: v7fs_populate.c,v 1.3 2011/08/10 11:31:49 uch Exp $ */
2*9f988b79SJean-Baptiste Boric
3*9f988b79SJean-Baptiste Boric /*-
4*9f988b79SJean-Baptiste Boric * Copyright (c) 2011 The NetBSD Foundation, Inc.
5*9f988b79SJean-Baptiste Boric * All rights reserved.
6*9f988b79SJean-Baptiste Boric *
7*9f988b79SJean-Baptiste Boric * This code is derived from software contributed to The NetBSD Foundation
8*9f988b79SJean-Baptiste Boric * by UCHIYAMA Yasushi.
9*9f988b79SJean-Baptiste Boric *
10*9f988b79SJean-Baptiste Boric * Redistribution and use in source and binary forms, with or without
11*9f988b79SJean-Baptiste Boric * modification, are permitted provided that the following conditions
12*9f988b79SJean-Baptiste Boric * are met:
13*9f988b79SJean-Baptiste Boric * 1. Redistributions of source code must retain the above copyright
14*9f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer.
15*9f988b79SJean-Baptiste Boric * 2. Redistributions in binary form must reproduce the above copyright
16*9f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer in the
17*9f988b79SJean-Baptiste Boric * documentation and/or other materials provided with the distribution.
18*9f988b79SJean-Baptiste Boric *
19*9f988b79SJean-Baptiste Boric * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*9f988b79SJean-Baptiste Boric * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*9f988b79SJean-Baptiste Boric * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*9f988b79SJean-Baptiste Boric * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*9f988b79SJean-Baptiste Boric * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*9f988b79SJean-Baptiste Boric * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*9f988b79SJean-Baptiste Boric * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*9f988b79SJean-Baptiste Boric * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*9f988b79SJean-Baptiste Boric * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*9f988b79SJean-Baptiste Boric * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*9f988b79SJean-Baptiste Boric * POSSIBILITY OF SUCH DAMAGE.
30*9f988b79SJean-Baptiste Boric */
31*9f988b79SJean-Baptiste Boric
32*9f988b79SJean-Baptiste Boric #if HAVE_NBTOOL_CONFIG_H
33*9f988b79SJean-Baptiste Boric #include "nbtool_config.h"
34*9f988b79SJean-Baptiste Boric #endif
35*9f988b79SJean-Baptiste Boric
36*9f988b79SJean-Baptiste Boric #include <sys/cdefs.h>
37*9f988b79SJean-Baptiste Boric #if defined(__RCSID) && !defined(__lint)
38*9f988b79SJean-Baptiste Boric __RCSID("$NetBSD: v7fs_populate.c,v 1.3 2011/08/10 11:31:49 uch Exp $");
39*9f988b79SJean-Baptiste Boric #endif /* !__lint */
40*9f988b79SJean-Baptiste Boric
41*9f988b79SJean-Baptiste Boric #include <stdio.h>
42*9f988b79SJean-Baptiste Boric #include <stdlib.h>
43*9f988b79SJean-Baptiste Boric #include <string.h>
44*9f988b79SJean-Baptiste Boric #include <unistd.h>
45*9f988b79SJean-Baptiste Boric #include <fcntl.h>
46*9f988b79SJean-Baptiste Boric #include <errno.h>
47*9f988b79SJean-Baptiste Boric #include <err.h>
48*9f988b79SJean-Baptiste Boric
49*9f988b79SJean-Baptiste Boric #if !HAVE_NBTOOL_CONFIG_H
50*9f988b79SJean-Baptiste Boric #include <sys/mount.h>
51*9f988b79SJean-Baptiste Boric #endif
52*9f988b79SJean-Baptiste Boric
53*9f988b79SJean-Baptiste Boric #include "makefs.h"
54*9f988b79SJean-Baptiste Boric #include "v7fs.h"
55*9f988b79SJean-Baptiste Boric #include "v7fs_impl.h"
56*9f988b79SJean-Baptiste Boric #include "v7fs_inode.h"
57*9f988b79SJean-Baptiste Boric #include "v7fs_superblock.h"
58*9f988b79SJean-Baptiste Boric #include "v7fs_datablock.h"
59*9f988b79SJean-Baptiste Boric #include "v7fs_endian.h"
60*9f988b79SJean-Baptiste Boric #include "v7fs_file.h"
61*9f988b79SJean-Baptiste Boric #include "v7fs_makefs.h"
62*9f988b79SJean-Baptiste Boric #include "newfs_v7fs.h"
63*9f988b79SJean-Baptiste Boric
64*9f988b79SJean-Baptiste Boric #define VPRINTF(fmt, args...) { if (v7fs_newfs_verbose) printf(fmt, ##args); }
65*9f988b79SJean-Baptiste Boric
66*9f988b79SJean-Baptiste Boric static void
attr_setup(fsnode * node,struct v7fs_fileattr * attr)67*9f988b79SJean-Baptiste Boric attr_setup(fsnode *node, struct v7fs_fileattr *attr)
68*9f988b79SJean-Baptiste Boric {
69*9f988b79SJean-Baptiste Boric struct stat *st = &node->inode->st;
70*9f988b79SJean-Baptiste Boric
71*9f988b79SJean-Baptiste Boric attr->mode = node->type | st->st_mode;
72*9f988b79SJean-Baptiste Boric attr->uid = st->st_uid;
73*9f988b79SJean-Baptiste Boric attr->gid = st->st_gid;
74*9f988b79SJean-Baptiste Boric attr->device = 0;
75*9f988b79SJean-Baptiste Boric attr->ctime = st->st_ctime;
76*9f988b79SJean-Baptiste Boric attr->atime = st->st_atime;
77*9f988b79SJean-Baptiste Boric attr->mtime = st->st_mtime;
78*9f988b79SJean-Baptiste Boric }
79*9f988b79SJean-Baptiste Boric
80*9f988b79SJean-Baptiste Boric static int
allocate(struct v7fs_self * fs,struct v7fs_inode * parent_inode,fsnode * node,dev_t dev,struct v7fs_inode * inode)81*9f988b79SJean-Baptiste Boric allocate(struct v7fs_self *fs, struct v7fs_inode *parent_inode, fsnode *node,
82*9f988b79SJean-Baptiste Boric dev_t dev, struct v7fs_inode *inode)
83*9f988b79SJean-Baptiste Boric {
84*9f988b79SJean-Baptiste Boric int error;
85*9f988b79SJean-Baptiste Boric v7fs_ino_t ino;
86*9f988b79SJean-Baptiste Boric struct v7fs_fileattr attr;
87*9f988b79SJean-Baptiste Boric
88*9f988b79SJean-Baptiste Boric memset(inode, 0, sizeof(*inode));
89*9f988b79SJean-Baptiste Boric
90*9f988b79SJean-Baptiste Boric attr_setup(node, &attr);
91*9f988b79SJean-Baptiste Boric attr.device = dev;
92*9f988b79SJean-Baptiste Boric if ((error = v7fs_file_allocate(fs, parent_inode, node->name, &attr,
93*9f988b79SJean-Baptiste Boric &ino))) {
94*9f988b79SJean-Baptiste Boric errno = error;
95*9f988b79SJean-Baptiste Boric warn("%s", node->name);
96*9f988b79SJean-Baptiste Boric return error;
97*9f988b79SJean-Baptiste Boric }
98*9f988b79SJean-Baptiste Boric node->inode->ino = ino;
99*9f988b79SJean-Baptiste Boric node->inode->flags |= FI_ALLOCATED;
100*9f988b79SJean-Baptiste Boric if ((error = v7fs_inode_load(fs, inode, ino))) {
101*9f988b79SJean-Baptiste Boric errno = error;
102*9f988b79SJean-Baptiste Boric warn("%s", node->name);
103*9f988b79SJean-Baptiste Boric return error;
104*9f988b79SJean-Baptiste Boric }
105*9f988b79SJean-Baptiste Boric
106*9f988b79SJean-Baptiste Boric return 0;
107*9f988b79SJean-Baptiste Boric }
108*9f988b79SJean-Baptiste Boric
109*9f988b79SJean-Baptiste Boric struct copy_arg {
110*9f988b79SJean-Baptiste Boric int fd;
111*9f988b79SJean-Baptiste Boric uint8_t buf[V7FS_BSIZE];
112*9f988b79SJean-Baptiste Boric };
113*9f988b79SJean-Baptiste Boric
114*9f988b79SJean-Baptiste Boric static int
copy_subr(struct v7fs_self * fs,void * ctx,v7fs_daddr_t blk,size_t sz)115*9f988b79SJean-Baptiste Boric copy_subr(struct v7fs_self *fs, void *ctx, v7fs_daddr_t blk, size_t sz)
116*9f988b79SJean-Baptiste Boric {
117*9f988b79SJean-Baptiste Boric struct copy_arg *p = ctx;
118*9f988b79SJean-Baptiste Boric
119*9f988b79SJean-Baptiste Boric if (read(p->fd, p->buf, sz) != (ssize_t)sz) {
120*9f988b79SJean-Baptiste Boric return V7FS_ITERATOR_ERROR;
121*9f988b79SJean-Baptiste Boric }
122*9f988b79SJean-Baptiste Boric
123*9f988b79SJean-Baptiste Boric if (!fs->io.write(fs->io.cookie, p->buf, blk)) {
124*9f988b79SJean-Baptiste Boric errno = EIO;
125*9f988b79SJean-Baptiste Boric return V7FS_ITERATOR_ERROR;
126*9f988b79SJean-Baptiste Boric }
127*9f988b79SJean-Baptiste Boric progress(0);
128*9f988b79SJean-Baptiste Boric
129*9f988b79SJean-Baptiste Boric return 0;
130*9f988b79SJean-Baptiste Boric }
131*9f988b79SJean-Baptiste Boric
132*9f988b79SJean-Baptiste Boric static int
file_copy(struct v7fs_self * fs,struct v7fs_inode * parent_inode,fsnode * node,const char * filepath)133*9f988b79SJean-Baptiste Boric file_copy(struct v7fs_self *fs, struct v7fs_inode *parent_inode, fsnode *node,
134*9f988b79SJean-Baptiste Boric const char *filepath)
135*9f988b79SJean-Baptiste Boric {
136*9f988b79SJean-Baptiste Boric struct v7fs_inode inode;
137*9f988b79SJean-Baptiste Boric const char *errmsg;
138*9f988b79SJean-Baptiste Boric fsinode *fnode = node->inode;
139*9f988b79SJean-Baptiste Boric int error = 0;
140*9f988b79SJean-Baptiste Boric int fd;
141*9f988b79SJean-Baptiste Boric
142*9f988b79SJean-Baptiste Boric /* Check hard-link */
143*9f988b79SJean-Baptiste Boric if ((fnode->nlink > 1) && (fnode->flags & FI_ALLOCATED)) {
144*9f988b79SJean-Baptiste Boric if ((error = v7fs_inode_load(fs, &inode, fnode->ino))) {
145*9f988b79SJean-Baptiste Boric errmsg = "inode load";
146*9f988b79SJean-Baptiste Boric goto err_exit;
147*9f988b79SJean-Baptiste Boric }
148*9f988b79SJean-Baptiste Boric if ((error = v7fs_file_link(fs, parent_inode, &inode,
149*9f988b79SJean-Baptiste Boric node->name))) {
150*9f988b79SJean-Baptiste Boric errmsg = "hard link";
151*9f988b79SJean-Baptiste Boric goto err_exit;
152*9f988b79SJean-Baptiste Boric }
153*9f988b79SJean-Baptiste Boric return 0;
154*9f988b79SJean-Baptiste Boric }
155*9f988b79SJean-Baptiste Boric
156*9f988b79SJean-Baptiste Boric /* Allocate file */
157*9f988b79SJean-Baptiste Boric if ((error = allocate(fs, parent_inode, node, 0, &inode))) {
158*9f988b79SJean-Baptiste Boric errmsg = "file allocate";
159*9f988b79SJean-Baptiste Boric goto err_exit;
160*9f988b79SJean-Baptiste Boric }
161*9f988b79SJean-Baptiste Boric if ((error = v7fs_datablock_expand(fs, &inode, fnode->st.st_size))) {
162*9f988b79SJean-Baptiste Boric errmsg = "datablock expand";
163*9f988b79SJean-Baptiste Boric goto err_exit;
164*9f988b79SJean-Baptiste Boric }
165*9f988b79SJean-Baptiste Boric
166*9f988b79SJean-Baptiste Boric /* Data copy */
167*9f988b79SJean-Baptiste Boric if ((fd = open(filepath, O_RDONLY)) == -1) {
168*9f988b79SJean-Baptiste Boric error = errno;
169*9f988b79SJean-Baptiste Boric errmsg = "source file";
170*9f988b79SJean-Baptiste Boric goto err_exit;
171*9f988b79SJean-Baptiste Boric }
172*9f988b79SJean-Baptiste Boric
173*9f988b79SJean-Baptiste Boric error = v7fs_datablock_foreach(fs, &inode, copy_subr,
174*9f988b79SJean-Baptiste Boric &(struct copy_arg){ .fd = fd });
175*9f988b79SJean-Baptiste Boric if (error != V7FS_ITERATOR_END) {
176*9f988b79SJean-Baptiste Boric errmsg = "data copy";
177*9f988b79SJean-Baptiste Boric close(fd);
178*9f988b79SJean-Baptiste Boric goto err_exit;
179*9f988b79SJean-Baptiste Boric } else {
180*9f988b79SJean-Baptiste Boric error = 0;
181*9f988b79SJean-Baptiste Boric }
182*9f988b79SJean-Baptiste Boric close(fd);
183*9f988b79SJean-Baptiste Boric
184*9f988b79SJean-Baptiste Boric return error;
185*9f988b79SJean-Baptiste Boric
186*9f988b79SJean-Baptiste Boric err_exit:
187*9f988b79SJean-Baptiste Boric errno = error;
188*9f988b79SJean-Baptiste Boric warn("%s %s", node->name, errmsg);
189*9f988b79SJean-Baptiste Boric
190*9f988b79SJean-Baptiste Boric return error;
191*9f988b79SJean-Baptiste Boric }
192*9f988b79SJean-Baptiste Boric
193*9f988b79SJean-Baptiste Boric static int
populate_walk(struct v7fs_self * fs,struct v7fs_inode * parent_inode,fsnode * root,char * dir)194*9f988b79SJean-Baptiste Boric populate_walk(struct v7fs_self *fs, struct v7fs_inode *parent_inode,
195*9f988b79SJean-Baptiste Boric fsnode *root, char *dir)
196*9f988b79SJean-Baptiste Boric {
197*9f988b79SJean-Baptiste Boric fsnode *cur;
198*9f988b79SJean-Baptiste Boric char *mydir = dir + strlen(dir);
199*9f988b79SJean-Baptiste Boric char srcpath[MAXPATHLEN + 1];
200*9f988b79SJean-Baptiste Boric struct v7fs_inode inode;
201*9f988b79SJean-Baptiste Boric int error = 0;
202*9f988b79SJean-Baptiste Boric bool failed = false;
203*9f988b79SJean-Baptiste Boric
204*9f988b79SJean-Baptiste Boric for (cur = root; cur != NULL; cur = cur->next) {
205*9f988b79SJean-Baptiste Boric switch (cur->type & S_IFMT) {
206*9f988b79SJean-Baptiste Boric default:
207*9f988b79SJean-Baptiste Boric VPRINTF("%x\n", cur->flags & S_IFMT);
208*9f988b79SJean-Baptiste Boric break;
209*9f988b79SJean-Baptiste Boric case S_IFCHR:
210*9f988b79SJean-Baptiste Boric /*FALLTHROUGH*/
211*9f988b79SJean-Baptiste Boric case S_IFBLK:
212*9f988b79SJean-Baptiste Boric if ((error = allocate(fs, parent_inode, cur,
213*9f988b79SJean-Baptiste Boric cur->inode->st.st_rdev, &inode))) {
214*9f988b79SJean-Baptiste Boric errno = error;
215*9f988b79SJean-Baptiste Boric warn("%s", cur->name);
216*9f988b79SJean-Baptiste Boric }
217*9f988b79SJean-Baptiste Boric break;
218*9f988b79SJean-Baptiste Boric case S_IFDIR:
219*9f988b79SJean-Baptiste Boric if (!cur->child) /*'.'*/
220*9f988b79SJean-Baptiste Boric break;
221*9f988b79SJean-Baptiste Boric /* Allocate this directory. */
222*9f988b79SJean-Baptiste Boric if ((error = allocate(fs, parent_inode, cur, 0,
223*9f988b79SJean-Baptiste Boric &inode))) {
224*9f988b79SJean-Baptiste Boric errno = error;
225*9f988b79SJean-Baptiste Boric warn("%s", cur->name);
226*9f988b79SJean-Baptiste Boric } else {
227*9f988b79SJean-Baptiste Boric /* Populate children. */
228*9f988b79SJean-Baptiste Boric mydir[0] = '/';
229*9f988b79SJean-Baptiste Boric strcpy(&mydir[1], cur->name);
230*9f988b79SJean-Baptiste Boric error = populate_walk(fs, &inode, cur->child,
231*9f988b79SJean-Baptiste Boric dir);
232*9f988b79SJean-Baptiste Boric mydir[0] = '\0';
233*9f988b79SJean-Baptiste Boric }
234*9f988b79SJean-Baptiste Boric break;
235*9f988b79SJean-Baptiste Boric case S_IFREG:
236*9f988b79SJean-Baptiste Boric snprintf(srcpath, sizeof(srcpath), "%s/%s", dir,
237*9f988b79SJean-Baptiste Boric cur->name);
238*9f988b79SJean-Baptiste Boric error = file_copy(fs, parent_inode, cur, srcpath);
239*9f988b79SJean-Baptiste Boric break;
240*9f988b79SJean-Baptiste Boric case S_IFLNK:
241*9f988b79SJean-Baptiste Boric if ((error = allocate(fs, parent_inode, cur, 0,
242*9f988b79SJean-Baptiste Boric &inode))) {
243*9f988b79SJean-Baptiste Boric errno = error;
244*9f988b79SJean-Baptiste Boric warn("%s", cur->name);
245*9f988b79SJean-Baptiste Boric } else {
246*9f988b79SJean-Baptiste Boric v7fs_file_symlink(fs, &inode, cur->symlink);
247*9f988b79SJean-Baptiste Boric }
248*9f988b79SJean-Baptiste Boric break;
249*9f988b79SJean-Baptiste Boric }
250*9f988b79SJean-Baptiste Boric if (error)
251*9f988b79SJean-Baptiste Boric failed = true;
252*9f988b79SJean-Baptiste Boric }
253*9f988b79SJean-Baptiste Boric
254*9f988b79SJean-Baptiste Boric return failed ? 2 : 0;
255*9f988b79SJean-Baptiste Boric }
256*9f988b79SJean-Baptiste Boric
257*9f988b79SJean-Baptiste Boric int
v7fs_populate(const char * dir,fsnode * root,fsinfo_t * fsopts,const struct v7fs_mount_device * device)258*9f988b79SJean-Baptiste Boric v7fs_populate(const char *dir, fsnode *root, fsinfo_t *fsopts,
259*9f988b79SJean-Baptiste Boric const struct v7fs_mount_device *device)
260*9f988b79SJean-Baptiste Boric {
261*9f988b79SJean-Baptiste Boric v7fs_opt_t *v7fs_opts = fsopts->fs_specific;
262*9f988b79SJean-Baptiste Boric static char path[MAXPATHLEN + 1];
263*9f988b79SJean-Baptiste Boric struct v7fs_inode root_inode;
264*9f988b79SJean-Baptiste Boric struct v7fs_self *fs;
265*9f988b79SJean-Baptiste Boric int error;
266*9f988b79SJean-Baptiste Boric
267*9f988b79SJean-Baptiste Boric if ((error = v7fs_io_init(&fs, device, V7FS_BSIZE))) {
268*9f988b79SJean-Baptiste Boric errno = error;
269*9f988b79SJean-Baptiste Boric warn("I/O setup failed.");
270*9f988b79SJean-Baptiste Boric return error;
271*9f988b79SJean-Baptiste Boric }
272*9f988b79SJean-Baptiste Boric fs->endian = device->endian;
273*9f988b79SJean-Baptiste Boric v7fs_endian_init(fs);
274*9f988b79SJean-Baptiste Boric
275*9f988b79SJean-Baptiste Boric if ((error = v7fs_superblock_load(fs))) {
276*9f988b79SJean-Baptiste Boric errno = error;
277*9f988b79SJean-Baptiste Boric warn("Can't load superblock.");
278*9f988b79SJean-Baptiste Boric return error;
279*9f988b79SJean-Baptiste Boric }
280*9f988b79SJean-Baptiste Boric fsopts->superblock = &fs->superblock; /* not used. */
281*9f988b79SJean-Baptiste Boric
282*9f988b79SJean-Baptiste Boric if ((error = v7fs_inode_load(fs, &root_inode, V7FS_ROOT_INODE))) {
283*9f988b79SJean-Baptiste Boric errno = error;
284*9f988b79SJean-Baptiste Boric warn("Can't load root inode.");
285*9f988b79SJean-Baptiste Boric return error;
286*9f988b79SJean-Baptiste Boric }
287*9f988b79SJean-Baptiste Boric
288*9f988b79SJean-Baptiste Boric progress(&(struct progress_arg){ .label = "populate", .tick =
289*9f988b79SJean-Baptiste Boric v7fs_opts->npuredatablk / PROGRESS_BAR_GRANULE });
290*9f988b79SJean-Baptiste Boric
291*9f988b79SJean-Baptiste Boric strncpy(path, dir, sizeof(path));
292*9f988b79SJean-Baptiste Boric error = populate_walk(fs, &root_inode, root, path);
293*9f988b79SJean-Baptiste Boric
294*9f988b79SJean-Baptiste Boric v7fs_inode_writeback(fs, &root_inode);
295*9f988b79SJean-Baptiste Boric v7fs_superblock_writeback(fs);
296*9f988b79SJean-Baptiste Boric
297*9f988b79SJean-Baptiste Boric return error;
298*9f988b79SJean-Baptiste Boric }
299