2 * Copyright (c) 2012 Department of Software Engineering,
3 * University of Szeged, Hungary
4 * Copyright (c) 2012 Tamas Toth <ttoth@inf.u-szeged.hu>
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by the Department of Software Engineering, University of Szeged, Hungary
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 AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
36 #include <sys/param.h>
47 #include "chfs_makefs.h"
49 #include "chfs/chfs_mkfs.h"
51 static void chfs_validate(const char *, fsnode
*, fsinfo_t
*);
52 static int chfs_create_image(const char *, fsinfo_t
*);
53 static int chfs_populate_dir(const char *, fsnode
*, fsnode
*, fsinfo_t
*);
57 chfs_prep_opts(fsinfo_t
*fsopts
)
59 chfs_opt_t
*chfs_opts
= ecalloc(1, sizeof(*chfs_opts
));
61 const option_t chfs_options
[] = {
62 { 'p', "pagesize", &chfs_opts
->pagesize
, OPT_INT32
,
63 1, INT_MAX
, "page size" },
64 { 'e', "eraseblock", &chfs_opts
->eraseblock
, OPT_INT32
,
65 1, INT_MAX
, "eraseblock size" },
66 { 'm', "mediatype", &chfs_opts
->mediatype
, OPT_INT32
,
67 0, 1, "type of the media, 0 (nor) or 1 (nand)" },
71 chfs_opts
->pagesize
= -1;
72 chfs_opts
->eraseblock
= -1;
73 chfs_opts
->mediatype
= -1;
76 fsopts
->fs_specific
= chfs_opts
;
77 fsopts
->fs_options
= copy_opts(chfs_options
);
81 chfs_cleanup_opts(fsinfo_t
*fsopts
)
83 free(fsopts
->fs_specific
);
84 free(fsopts
->fs_options
);
88 chfs_parse_opts(const char *option
, fsinfo_t
*fsopts
)
91 assert(option
!= NULL
);
92 assert(fsopts
!= NULL
);
94 return set_option(fsopts
->fs_options
, option
, NULL
, 0) != -1;
98 chfs_makefs(const char *image
, const char *dir
, fsnode
*root
, fsinfo_t
*fsopts
)
100 struct timeval start
;
102 assert(image
!= NULL
);
104 assert(root
!= NULL
);
105 assert(fsopts
!= NULL
);
108 chfs_validate(dir
, root
, fsopts
);
109 TIMER_RESULTS(start
, "chfs_validate");
111 printf("Creating `%s'\n", image
);
113 if (chfs_create_image(image
, fsopts
) == -1) {
114 errx(EXIT_FAILURE
, "Image file `%s' not created", image
);
116 TIMER_RESULTS(start
, "chfs_create_image");
118 fsopts
->curinode
= CHFS_ROOTINO
;
119 root
->inode
->ino
= CHFS_ROOTINO
;
121 printf("Populating `%s'\n", image
);
123 write_eb_header(fsopts
);
124 if (!chfs_populate_dir(dir
, root
, root
, fsopts
)) {
125 errx(EXIT_FAILURE
, "Image file `%s' not populated", image
);
127 TIMER_RESULTS(start
, "chfs_populate_dir");
131 if (close(fsopts
->fd
) == -1) {
132 err(EXIT_FAILURE
, "Closing `%s'", image
);
136 printf("Image `%s' complete\n", image
);
140 chfs_validate(const char* dir
, fsnode
*root
, fsinfo_t
*fsopts
)
142 chfs_opt_t
*chfs_opts
;
144 assert(root
!= NULL
);
145 assert(fsopts
!= NULL
);
147 chfs_opts
= fsopts
->fs_specific
;
149 if (chfs_opts
->pagesize
== -1) {
150 chfs_opts
->pagesize
= DEFAULT_PAGESIZE
;
152 if (chfs_opts
->eraseblock
== -1) {
153 chfs_opts
->eraseblock
= DEFAULT_ERASEBLOCK
;
155 if (chfs_opts
->mediatype
== -1) {
156 chfs_opts
->mediatype
= DEFAULT_MEDIATYPE
;
161 chfs_create_image(const char *image
, fsinfo_t
*fsopts
)
163 assert(image
!= NULL
);
164 assert(fsopts
!= NULL
);
166 if ((fsopts
->fd
= open(image
, O_RDWR
| O_CREAT
| O_TRUNC
, 0666)) == -1) {
167 warn("Can't open `%s' for writing", image
);
175 chfs_populate_dir(const char *dir
, fsnode
*root
, fsnode
*parent
,
179 char path
[MAXPATHLEN
+ 1];
182 assert(root
!= NULL
);
183 assert(fsopts
!= NULL
);
185 for (cur
= root
->next
; cur
!= NULL
; cur
= cur
->next
) {
186 if ((cur
->inode
->flags
& FI_ALLOCATED
) == 0) {
187 cur
->inode
->flags
|= FI_ALLOCATED
;
190 cur
->inode
->ino
= fsopts
->curinode
;
191 cur
->parent
= parent
;
195 if (cur
->inode
->flags
& FI_WRITTEN
) {
196 continue; // hard link
198 cur
->inode
->flags
|= FI_WRITTEN
;
200 write_vnode(fsopts
, cur
);
201 write_dirent(fsopts
, cur
);
202 if (!S_ISDIR(cur
->type
& S_IFMT
)) {
203 write_file(fsopts
, cur
, dir
);
207 for (cur
= root
; cur
!= NULL
; cur
= cur
->next
) {
208 if (cur
->child
== NULL
) {
211 if ((size_t)snprintf(path
, sizeof(path
), "%s/%s", dir
,
212 cur
->name
) >= sizeof(path
)) {
213 errx(EXIT_FAILURE
, "Pathname too long");
215 if (!chfs_populate_dir(path
, cur
->child
, cur
, fsopts
)) {