xref: /minix3/usr.sbin/makefs/chfs/chfs_mkfs.c (revision 9f988b79349f9b89ecc822458c30ec8897558560)
1*9f988b79SJean-Baptiste Boric /*-
2*9f988b79SJean-Baptiste Boric  * Copyright (c) 2012 Department of Software Engineering,
3*9f988b79SJean-Baptiste Boric  *		      University of Szeged, Hungary
4*9f988b79SJean-Baptiste Boric  * Copyright (c) 2012 Tamas Toth <ttoth@inf.u-szeged.hu>
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 the Department of Software Engineering, University of Szeged, Hungary
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 AUTHOR ``AS IS'' AND ANY EXPRESS OR
20*9f988b79SJean-Baptiste Boric  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21*9f988b79SJean-Baptiste Boric  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22*9f988b79SJean-Baptiste Boric  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23*9f988b79SJean-Baptiste Boric  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24*9f988b79SJean-Baptiste Boric  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25*9f988b79SJean-Baptiste Boric  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26*9f988b79SJean-Baptiste Boric  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27*9f988b79SJean-Baptiste Boric  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*9f988b79SJean-Baptiste Boric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*9f988b79SJean-Baptiste Boric  * 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/param.h>
37*9f988b79SJean-Baptiste Boric #include <sys/stat.h>
38*9f988b79SJean-Baptiste Boric 
39*9f988b79SJean-Baptiste Boric #include <assert.h>
40*9f988b79SJean-Baptiste Boric #include <fcntl.h>
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 <zlib.h>
45*9f988b79SJean-Baptiste Boric #include <util.h>
46*9f988b79SJean-Baptiste Boric 
47*9f988b79SJean-Baptiste Boric #if defined(__minix)
48*9f988b79SJean-Baptiste Boric #include <unistd.h>
49*9f988b79SJean-Baptiste Boric #endif
50*9f988b79SJean-Baptiste Boric 
51*9f988b79SJean-Baptiste Boric #include "makefs.h"
52*9f988b79SJean-Baptiste Boric #include "chfs_makefs.h"
53*9f988b79SJean-Baptiste Boric 
54*9f988b79SJean-Baptiste Boric #include "media.h"
55*9f988b79SJean-Baptiste Boric #include "ebh.h"
56*9f988b79SJean-Baptiste Boric 
57*9f988b79SJean-Baptiste Boric #include "chfs/chfs_mkfs.h"
58*9f988b79SJean-Baptiste Boric 
59*9f988b79SJean-Baptiste Boric static uint32_t img_ofs = 0;
60*9f988b79SJean-Baptiste Boric static uint64_t version = 0;
61*9f988b79SJean-Baptiste Boric static uint64_t max_serial = 0;
62*9f988b79SJean-Baptiste Boric static int lebnumber = 0;
63*9f988b79SJean-Baptiste Boric 
64*9f988b79SJean-Baptiste Boric static const unsigned char ffbuf[16] = {
65*9f988b79SJean-Baptiste Boric 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
66*9f988b79SJean-Baptiste Boric 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
67*9f988b79SJean-Baptiste Boric };
68*9f988b79SJean-Baptiste Boric 
69*9f988b79SJean-Baptiste Boric static void
buf_write(fsinfo_t * fsopts,const void * buf,size_t len)70*9f988b79SJean-Baptiste Boric buf_write(fsinfo_t *fsopts, const void *buf, size_t len)
71*9f988b79SJean-Baptiste Boric {
72*9f988b79SJean-Baptiste Boric 	ssize_t retval;
73*9f988b79SJean-Baptiste Boric 	const char *charbuf = buf;
74*9f988b79SJean-Baptiste Boric 
75*9f988b79SJean-Baptiste Boric 	while (len > 0) {
76*9f988b79SJean-Baptiste Boric 		retval = write(fsopts->fd, charbuf, len);
77*9f988b79SJean-Baptiste Boric 
78*9f988b79SJean-Baptiste Boric 		if (retval == -1) {
79*9f988b79SJean-Baptiste Boric 			err(EXIT_FAILURE, "ERROR while writing");
80*9f988b79SJean-Baptiste Boric 		}
81*9f988b79SJean-Baptiste Boric 
82*9f988b79SJean-Baptiste Boric 		len -= retval;
83*9f988b79SJean-Baptiste Boric 		charbuf += retval;
84*9f988b79SJean-Baptiste Boric 		img_ofs += retval;
85*9f988b79SJean-Baptiste Boric 	}
86*9f988b79SJean-Baptiste Boric }
87*9f988b79SJean-Baptiste Boric 
88*9f988b79SJean-Baptiste Boric void
padblock(fsinfo_t * fsopts)89*9f988b79SJean-Baptiste Boric padblock(fsinfo_t *fsopts)
90*9f988b79SJean-Baptiste Boric {
91*9f988b79SJean-Baptiste Boric 	chfs_opt_t *chfs_opts = fsopts->fs_specific;
92*9f988b79SJean-Baptiste Boric 	while (img_ofs % chfs_opts->eraseblock) {
93*9f988b79SJean-Baptiste Boric 		buf_write(fsopts, ffbuf, MIN(sizeof(ffbuf),
94*9f988b79SJean-Baptiste Boric 		    chfs_opts->eraseblock - (img_ofs % chfs_opts->eraseblock)));
95*9f988b79SJean-Baptiste Boric 	}
96*9f988b79SJean-Baptiste Boric }
97*9f988b79SJean-Baptiste Boric 
98*9f988b79SJean-Baptiste Boric static void
padword(fsinfo_t * fsopts)99*9f988b79SJean-Baptiste Boric padword(fsinfo_t *fsopts)
100*9f988b79SJean-Baptiste Boric {
101*9f988b79SJean-Baptiste Boric 	if (img_ofs % 4) {
102*9f988b79SJean-Baptiste Boric 		buf_write(fsopts, ffbuf, 4 - img_ofs % 4);
103*9f988b79SJean-Baptiste Boric 	}
104*9f988b79SJean-Baptiste Boric }
105*9f988b79SJean-Baptiste Boric 
106*9f988b79SJean-Baptiste Boric static void
pad_block_if_less_than(fsinfo_t * fsopts,int req)107*9f988b79SJean-Baptiste Boric pad_block_if_less_than(fsinfo_t *fsopts, int req)
108*9f988b79SJean-Baptiste Boric {
109*9f988b79SJean-Baptiste Boric 	chfs_opt_t *chfs_opts = fsopts->fs_specific;
110*9f988b79SJean-Baptiste Boric 	if ((img_ofs % chfs_opts->eraseblock) + req >
111*9f988b79SJean-Baptiste Boric 	    (uint32_t)chfs_opts->eraseblock) {
112*9f988b79SJean-Baptiste Boric 		padblock(fsopts);
113*9f988b79SJean-Baptiste Boric 		write_eb_header(fsopts);
114*9f988b79SJean-Baptiste Boric 	}
115*9f988b79SJean-Baptiste Boric }
116*9f988b79SJean-Baptiste Boric 
117*9f988b79SJean-Baptiste Boric void
write_eb_header(fsinfo_t * fsopts)118*9f988b79SJean-Baptiste Boric write_eb_header(fsinfo_t *fsopts)
119*9f988b79SJean-Baptiste Boric {
120*9f988b79SJean-Baptiste Boric 	chfs_opt_t *opts;
121*9f988b79SJean-Baptiste Boric 	struct chfs_eb_hdr ebhdr;
122*9f988b79SJean-Baptiste Boric 	char *buf;
123*9f988b79SJean-Baptiste Boric 
124*9f988b79SJean-Baptiste Boric 	opts = fsopts->fs_specific;
125*9f988b79SJean-Baptiste Boric 
126*9f988b79SJean-Baptiste Boric #define MINSIZE MAX(MAX(CHFS_EB_EC_HDR_SIZE, CHFS_EB_HDR_NOR_SIZE), \
127*9f988b79SJean-Baptiste Boric     CHFS_EB_HDR_NAND_SIZE)
128*9f988b79SJean-Baptiste Boric 	if ((uint32_t)opts->pagesize < MINSIZE)
129*9f988b79SJean-Baptiste Boric 		errx(EXIT_FAILURE, "pagesize cannot be less than %zu", MINSIZE);
130*9f988b79SJean-Baptiste Boric 	buf = emalloc(opts->pagesize);
131*9f988b79SJean-Baptiste Boric 	memset(buf, 0xFF, opts->pagesize);
132*9f988b79SJean-Baptiste Boric 
133*9f988b79SJean-Baptiste Boric 	ebhdr.ec_hdr.magic = htole32(CHFS_MAGIC_BITMASK);
134*9f988b79SJean-Baptiste Boric 	ebhdr.ec_hdr.erase_cnt = htole32(1);
135*9f988b79SJean-Baptiste Boric 	ebhdr.ec_hdr.crc_ec = htole32(crc32(0,
136*9f988b79SJean-Baptiste Boric 	    (uint8_t *)&ebhdr.ec_hdr + 8, 4));
137*9f988b79SJean-Baptiste Boric 
138*9f988b79SJean-Baptiste Boric 	memcpy(buf, &ebhdr.ec_hdr, CHFS_EB_EC_HDR_SIZE);
139*9f988b79SJean-Baptiste Boric 
140*9f988b79SJean-Baptiste Boric 	buf_write(fsopts, buf, opts->pagesize);
141*9f988b79SJean-Baptiste Boric 
142*9f988b79SJean-Baptiste Boric 	memset(buf, 0xFF, opts->pagesize);
143*9f988b79SJean-Baptiste Boric 
144*9f988b79SJean-Baptiste Boric 	if (opts->mediatype == TYPE_NAND) {
145*9f988b79SJean-Baptiste Boric 		ebhdr.u.nand_hdr.lid = htole32(lebnumber++);
146*9f988b79SJean-Baptiste Boric 		ebhdr.u.nand_hdr.serial = htole64(++(max_serial));
147*9f988b79SJean-Baptiste Boric 		ebhdr.u.nand_hdr.crc = htole32(crc32(0,
148*9f988b79SJean-Baptiste Boric 		    (uint8_t *)&ebhdr.u.nand_hdr + 4,
149*9f988b79SJean-Baptiste Boric 		    CHFS_EB_HDR_NAND_SIZE - 4));
150*9f988b79SJean-Baptiste Boric 		memcpy(buf, &ebhdr.u.nand_hdr, CHFS_EB_HDR_NAND_SIZE);
151*9f988b79SJean-Baptiste Boric 	} else {
152*9f988b79SJean-Baptiste Boric 		ebhdr.u.nor_hdr.lid = htole32(lebnumber++);
153*9f988b79SJean-Baptiste Boric 		ebhdr.u.nor_hdr.crc = htole32(crc32(0,
154*9f988b79SJean-Baptiste Boric 		    (uint8_t *)&ebhdr.u.nor_hdr + 4,
155*9f988b79SJean-Baptiste Boric 		    CHFS_EB_HDR_NOR_SIZE - 4));
156*9f988b79SJean-Baptiste Boric 		memcpy(buf, &ebhdr.u.nor_hdr, CHFS_EB_HDR_NOR_SIZE);
157*9f988b79SJean-Baptiste Boric 	}
158*9f988b79SJean-Baptiste Boric 
159*9f988b79SJean-Baptiste Boric 	buf_write(fsopts, buf, opts->pagesize);
160*9f988b79SJean-Baptiste Boric 	free(buf);
161*9f988b79SJean-Baptiste Boric }
162*9f988b79SJean-Baptiste Boric 
163*9f988b79SJean-Baptiste Boric void
write_vnode(fsinfo_t * fsopts,fsnode * node)164*9f988b79SJean-Baptiste Boric write_vnode(fsinfo_t *fsopts, fsnode *node)
165*9f988b79SJean-Baptiste Boric {
166*9f988b79SJean-Baptiste Boric 	struct chfs_flash_vnode fvnode;
167*9f988b79SJean-Baptiste Boric 	memset(&fvnode, 0, sizeof(fvnode));
168*9f988b79SJean-Baptiste Boric 
169*9f988b79SJean-Baptiste Boric 	fvnode.magic = htole16(CHFS_FS_MAGIC_BITMASK);
170*9f988b79SJean-Baptiste Boric 	fvnode.type = htole16(CHFS_NODETYPE_VNODE);
171*9f988b79SJean-Baptiste Boric 	fvnode.length = htole32(CHFS_PAD(sizeof(fvnode)));
172*9f988b79SJean-Baptiste Boric 	fvnode.hdr_crc = htole32(crc32(0, (uint8_t *)&fvnode,
173*9f988b79SJean-Baptiste Boric 	    CHFS_NODE_HDR_SIZE - 4));
174*9f988b79SJean-Baptiste Boric 	fvnode.vno = htole64(node->inode->ino);
175*9f988b79SJean-Baptiste Boric 	fvnode.version = htole64(version++);
176*9f988b79SJean-Baptiste Boric 	fvnode.mode = htole32(node->inode->st.st_mode);
177*9f988b79SJean-Baptiste Boric 	fvnode.dn_size = htole32(node->inode->st.st_size);
178*9f988b79SJean-Baptiste Boric 	fvnode.atime = htole32(node->inode->st.st_atime);
179*9f988b79SJean-Baptiste Boric 	fvnode.ctime = htole32(node->inode->st.st_ctime);
180*9f988b79SJean-Baptiste Boric 	fvnode.mtime = htole32(node->inode->st.st_mtime);
181*9f988b79SJean-Baptiste Boric 	fvnode.gid = htole32(node->inode->st.st_uid);
182*9f988b79SJean-Baptiste Boric 	fvnode.uid = htole32(node->inode->st.st_gid);
183*9f988b79SJean-Baptiste Boric 	fvnode.node_crc = htole32(crc32(0, (uint8_t *)&fvnode,
184*9f988b79SJean-Baptiste Boric 	    sizeof(fvnode) - 4));
185*9f988b79SJean-Baptiste Boric 
186*9f988b79SJean-Baptiste Boric 	pad_block_if_less_than(fsopts, sizeof(fvnode));
187*9f988b79SJean-Baptiste Boric 	buf_write(fsopts, &fvnode, sizeof(fvnode));
188*9f988b79SJean-Baptiste Boric 	padword(fsopts);
189*9f988b79SJean-Baptiste Boric }
190*9f988b79SJean-Baptiste Boric 
191*9f988b79SJean-Baptiste Boric void
write_dirent(fsinfo_t * fsopts,fsnode * node)192*9f988b79SJean-Baptiste Boric write_dirent(fsinfo_t *fsopts, fsnode *node)
193*9f988b79SJean-Baptiste Boric {
194*9f988b79SJean-Baptiste Boric 	struct chfs_flash_dirent_node fdirent;
195*9f988b79SJean-Baptiste Boric 	char *name;
196*9f988b79SJean-Baptiste Boric 
197*9f988b79SJean-Baptiste Boric 	name = emalloc(strlen(node->name));
198*9f988b79SJean-Baptiste Boric 	memcpy(name, node->name, strlen(node->name));
199*9f988b79SJean-Baptiste Boric 
200*9f988b79SJean-Baptiste Boric 	memset(&fdirent, 0, sizeof(fdirent));
201*9f988b79SJean-Baptiste Boric 	fdirent.magic = htole16(CHFS_FS_MAGIC_BITMASK);
202*9f988b79SJean-Baptiste Boric 	fdirent.type = htole16(CHFS_NODETYPE_DIRENT);
203*9f988b79SJean-Baptiste Boric 	fdirent.length = htole32(CHFS_PAD(sizeof(fdirent) + strlen(name)));
204*9f988b79SJean-Baptiste Boric 	fdirent.hdr_crc = htole32(crc32(0, (uint8_t *)&fdirent,
205*9f988b79SJean-Baptiste Boric 	    CHFS_NODE_HDR_SIZE - 4));
206*9f988b79SJean-Baptiste Boric 	fdirent.vno = htole64(node->inode->ino);
207*9f988b79SJean-Baptiste Boric 	if (node->parent != NULL) {
208*9f988b79SJean-Baptiste Boric 		fdirent.pvno = htole64(node->parent->inode->ino);
209*9f988b79SJean-Baptiste Boric 	} else {
210*9f988b79SJean-Baptiste Boric 		fdirent.pvno = htole64(node->inode->ino);
211*9f988b79SJean-Baptiste Boric 	}
212*9f988b79SJean-Baptiste Boric 
213*9f988b79SJean-Baptiste Boric 	fdirent.version = htole64(version++);
214*9f988b79SJean-Baptiste Boric 	fdirent.mctime = 0;
215*9f988b79SJean-Baptiste Boric 	fdirent.nsize = htole32(strlen(name));
216*9f988b79SJean-Baptiste Boric 	fdirent.dtype = htole32(IFTOCHT(node->type & S_IFMT));
217*9f988b79SJean-Baptiste Boric 	fdirent.name_crc = htole32(crc32(0, (uint8_t *)name, fdirent.nsize));
218*9f988b79SJean-Baptiste Boric 	fdirent.node_crc = htole32(crc32(0, (uint8_t *)&fdirent,
219*9f988b79SJean-Baptiste Boric 	    sizeof(fdirent) - 4));
220*9f988b79SJean-Baptiste Boric 
221*9f988b79SJean-Baptiste Boric 	pad_block_if_less_than(fsopts, sizeof(fdirent) + fdirent.nsize);
222*9f988b79SJean-Baptiste Boric 	buf_write(fsopts, &fdirent, sizeof(fdirent));
223*9f988b79SJean-Baptiste Boric 	buf_write(fsopts, name, fdirent.nsize);
224*9f988b79SJean-Baptiste Boric 	padword(fsopts);
225*9f988b79SJean-Baptiste Boric }
226*9f988b79SJean-Baptiste Boric 
227*9f988b79SJean-Baptiste Boric void
write_file(fsinfo_t * fsopts,fsnode * node,const char * dir)228*9f988b79SJean-Baptiste Boric write_file(fsinfo_t *fsopts, fsnode *node, const char *dir)
229*9f988b79SJean-Baptiste Boric {
230*9f988b79SJean-Baptiste Boric 	int fd;
231*9f988b79SJean-Baptiste Boric 	ssize_t len;
232*9f988b79SJean-Baptiste Boric 	char *name = node->name;
233*9f988b79SJean-Baptiste Boric 	chfs_opt_t *opts;
234*9f988b79SJean-Baptiste Boric 	unsigned char *buf;
235*9f988b79SJean-Baptiste Boric 	uint32_t fileofs = 0;
236*9f988b79SJean-Baptiste Boric 
237*9f988b79SJean-Baptiste Boric 	opts = fsopts->fs_specific;
238*9f988b79SJean-Baptiste Boric 	buf = emalloc(opts->pagesize);
239*9f988b79SJean-Baptiste Boric 	if (node->type == S_IFREG || node->type == S_IFSOCK) {
240*9f988b79SJean-Baptiste Boric 		char *longname;
241*9f988b79SJean-Baptiste Boric 		if (asprintf(&longname, "%s/%s", dir, name) == 1)
242*9f988b79SJean-Baptiste Boric 			goto out;
243*9f988b79SJean-Baptiste Boric 
244*9f988b79SJean-Baptiste Boric 		fd = open(longname, O_RDONLY, 0444);
245*9f988b79SJean-Baptiste Boric 		if (fd == -1)
246*9f988b79SJean-Baptiste Boric 			err(EXIT_FAILURE, "Cannot open `%s'", longname);
247*9f988b79SJean-Baptiste Boric 
248*9f988b79SJean-Baptiste Boric 		while ((len = read(fd, buf, opts->pagesize))) {
249*9f988b79SJean-Baptiste Boric 			if (len < 0) {
250*9f988b79SJean-Baptiste Boric 				warn("ERROR while reading %s", longname);
251*9f988b79SJean-Baptiste Boric 				free(longname);
252*9f988b79SJean-Baptiste Boric 				free(buf);
253*9f988b79SJean-Baptiste Boric 				close(fd);
254*9f988b79SJean-Baptiste Boric 				return;
255*9f988b79SJean-Baptiste Boric 			}
256*9f988b79SJean-Baptiste Boric 
257*9f988b79SJean-Baptiste Boric 			write_data(fsopts, node, buf, len, fileofs);
258*9f988b79SJean-Baptiste Boric 			fileofs += len;
259*9f988b79SJean-Baptiste Boric 		}
260*9f988b79SJean-Baptiste Boric 		free(longname);
261*9f988b79SJean-Baptiste Boric 		close(fd);
262*9f988b79SJean-Baptiste Boric 	} else if (node->type == S_IFLNK) {
263*9f988b79SJean-Baptiste Boric 		len = strlen(node->symlink);
264*9f988b79SJean-Baptiste Boric 		memcpy(buf, node->symlink, len);
265*9f988b79SJean-Baptiste Boric 		write_data(fsopts, node, buf, len, 0);
266*9f988b79SJean-Baptiste Boric 	} else if (node->type == S_IFCHR || node->type == S_IFBLK ||
267*9f988b79SJean-Baptiste Boric 		node->type == S_IFIFO) {
268*9f988b79SJean-Baptiste Boric 		len = sizeof(dev_t);
269*9f988b79SJean-Baptiste Boric 		memcpy(buf, &(node->inode->st.st_rdev), len);
270*9f988b79SJean-Baptiste Boric 		write_data(fsopts, node, buf, len, 0);
271*9f988b79SJean-Baptiste Boric 	}
272*9f988b79SJean-Baptiste Boric 
273*9f988b79SJean-Baptiste Boric 	free(buf);
274*9f988b79SJean-Baptiste Boric 	return;
275*9f988b79SJean-Baptiste Boric out:
276*9f988b79SJean-Baptiste Boric 	err(EXIT_FAILURE, "Memory allocation failed");
277*9f988b79SJean-Baptiste Boric }
278*9f988b79SJean-Baptiste Boric 
279*9f988b79SJean-Baptiste Boric void
write_data(fsinfo_t * fsopts,fsnode * node,unsigned char * buf,size_t len,uint32_t ofs)280*9f988b79SJean-Baptiste Boric write_data(fsinfo_t *fsopts, fsnode *node, unsigned char *buf, size_t len,
281*9f988b79SJean-Baptiste Boric     uint32_t ofs)
282*9f988b79SJean-Baptiste Boric {
283*9f988b79SJean-Baptiste Boric 	struct chfs_flash_data_node fdata;
284*9f988b79SJean-Baptiste Boric 
285*9f988b79SJean-Baptiste Boric 	memset(&fdata, 0, sizeof(fdata));
286*9f988b79SJean-Baptiste Boric 	if (len == 0) {
287*9f988b79SJean-Baptiste Boric 		return;
288*9f988b79SJean-Baptiste Boric 	}
289*9f988b79SJean-Baptiste Boric 
290*9f988b79SJean-Baptiste Boric 	pad_block_if_less_than(fsopts, sizeof(fdata) + len);
291*9f988b79SJean-Baptiste Boric 
292*9f988b79SJean-Baptiste Boric 	fdata.magic = htole16(CHFS_FS_MAGIC_BITMASK);
293*9f988b79SJean-Baptiste Boric 	fdata.type = htole16(CHFS_NODETYPE_DATA);
294*9f988b79SJean-Baptiste Boric 	fdata.length = htole32(CHFS_PAD(sizeof(fdata) + len));
295*9f988b79SJean-Baptiste Boric 	fdata.hdr_crc = htole32(crc32(0, (uint8_t *)&fdata,
296*9f988b79SJean-Baptiste Boric 	    CHFS_NODE_HDR_SIZE - 4));
297*9f988b79SJean-Baptiste Boric 	fdata.vno = htole64(node->inode->ino);
298*9f988b79SJean-Baptiste Boric 	fdata.data_length = htole32(len);
299*9f988b79SJean-Baptiste Boric 	fdata.offset = htole32(ofs);
300*9f988b79SJean-Baptiste Boric 	fdata.data_crc = htole32(crc32(0, (uint8_t *)buf, len));
301*9f988b79SJean-Baptiste Boric 	fdata.node_crc = htole32(crc32(0,
302*9f988b79SJean-Baptiste Boric 	    (uint8_t *)&fdata, sizeof(fdata) - 4));
303*9f988b79SJean-Baptiste Boric 
304*9f988b79SJean-Baptiste Boric 	buf_write(fsopts, &fdata, sizeof(fdata));
305*9f988b79SJean-Baptiste Boric 	buf_write(fsopts, buf, len);
306*9f988b79SJean-Baptiste Boric 	padword(fsopts);
307*9f988b79SJean-Baptiste Boric }
308