nand_base: We have to ignore the -EUCLEAN error
[barebox-mini2440.git] / common / environment.c
blobc314d7ccccf0e30bfc6d5cf66febea9c00cd2d97
1 /*
2 * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
4 * See file CREDITS for list of people who contributed to this
5 * project.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2
9 * as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /**
22 * @file
23 * @brief Environment handling support (host and target)
25 * Important: This file will also be used on the host to create
26 * the default environment when building the U-Boot binary. So
27 * do not add any new U-Boot related functions here!
30 #ifdef __U_BOOT__
31 #include <common.h>
32 #include <command.h>
33 #include <malloc.h>
34 #include <errno.h>
35 #include <fs.h>
36 #include <fcntl.h>
37 #include <envfs.h>
38 #include <xfuncs.h>
39 #include <libbb.h>
40 #include <libgen.h>
41 #include <environment.h>
42 #else
43 # define errno_str(x) ("void")
44 #define EXPORT_SYMBOL(x)
45 #endif
47 int file_size_action(const char *filename, struct stat *statbuf,
48 void *userdata, int depth)
50 struct action_data *data = userdata;
52 data->writep += sizeof(struct envfs_inode);
53 data->writep += PAD4(strlen(filename) + 1 - strlen(data->base));
54 data->writep += PAD4(statbuf->st_size);
55 return 1;
58 int file_save_action(const char *filename, struct stat *statbuf,
59 void *userdata, int depth)
61 struct action_data *data = userdata;
62 struct envfs_inode *inode;
63 int fd;
64 int namelen = strlen(filename) + 1 - strlen(data->base);
66 debug("handling file %s size %ld namelen %d\n", filename + strlen(data->base),
67 statbuf->st_size, namelen);
69 inode = (struct envfs_inode*)data->writep;
70 inode->magic = ENVFS_32(ENVFS_INODE_MAGIC);
71 inode->namelen = ENVFS_32(namelen);
72 inode->size = ENVFS_32(statbuf->st_size);
73 data->writep += sizeof(struct envfs_inode);
75 strcpy(data->writep, filename + strlen(data->base));
76 data->writep += PAD4(namelen);
78 fd = open(filename, O_RDONLY);
79 if (fd < 0) {
80 printf("Open %s %s\n", filename, errno_str());
81 goto out;
84 if (read(fd, data->writep, statbuf->st_size) < statbuf->st_size) {
85 perror("read");
86 goto out;
88 close(fd);
90 data->writep += PAD4(statbuf->st_size);
92 out:
93 return 1;
96 /**
97 * Make the current environment persistent
98 * @param[in] filename where to store
99 * @param[in] dirname what to store (all files in this dir)
100 * @return 0 on success, anything else in case of failure
102 * Note: This function will also be used on the host! See note in the header
103 * of this file.
105 int envfs_save(char *filename, char *dirname)
107 struct envfs_super *super;
108 int envfd, size, ret;
109 struct action_data data;
110 void *buf = NULL;
112 data.writep = 0;
113 data.base = dirname;
115 /* first pass: calculate size */
116 recursive_action(dirname, ACTION_RECURSE, file_size_action,
117 NULL, &data, 0);
119 size = (unsigned long)data.writep;
121 buf = xzalloc(size + sizeof(struct envfs_super));
122 data.writep = buf + sizeof(struct envfs_super);
124 super = (struct envfs_super *)buf;
125 super->magic = ENVFS_32(ENVFS_MAGIC);
126 super->size = ENVFS_32(size);
128 /* second pass: copy files to buffer */
129 recursive_action(dirname, ACTION_RECURSE, file_save_action,
130 NULL, &data, 0);
132 super->crc = ENVFS_32(crc32(0, buf + sizeof(struct envfs_super), size));
133 super->sb_crc = ENVFS_32(crc32(0, buf, sizeof(struct envfs_super) - 4));
135 envfd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
136 if (envfd < 0) {
137 printf("Open %s %s\n", filename, errno_str());
138 ret = envfd;
139 goto out1;
142 if (write(envfd, buf, size + sizeof(struct envfs_super)) <
143 sizeof(struct envfs_super)) {
144 perror("write");
145 ret = -1; /* FIXME */
146 goto out;
149 ret = 0;
151 out:
152 close(envfd);
153 out1:
154 free(buf);
155 return ret;
157 EXPORT_SYMBOL(envfs_save);
160 * Restore the last environment into the current one
161 * @param[in] filename from where to restore
162 * @param[in] dir where to store the last content
163 * @return 0 on success, anything else in case of failure
165 * Note: This function will also be used on the host! See note in the header
166 * of this file.
168 int envfs_load(char *filename, char *dir)
170 struct envfs_super super;
171 void *buf = NULL, *buf_free = NULL;
172 int envfd;
173 int fd, ret = 0;
174 char *str, *tmp;
175 int namelen_full;
176 unsigned long size;
178 envfd = open(filename, O_RDONLY);
179 if (envfd < 0) {
180 printf("Open %s %s\n", filename, errno_str());
181 return -1;
184 /* read superblock */
185 ret = read(envfd, &super, sizeof(struct envfs_super));
186 if ( ret < sizeof(struct envfs_super)) {
187 perror("read");
188 ret = errno;
189 goto out;
192 if ( ENVFS_32(super.magic) != ENVFS_MAGIC) {
193 printf("envfs: wrong magic on %s\n", filename);
194 ret = -EIO;
195 goto out;
198 if (crc32(0, (unsigned char *)&super, sizeof(struct envfs_super) - 4)
199 != ENVFS_32(super.sb_crc)) {
200 printf("wrong crc on env superblock\n");
201 goto out;
204 size = ENVFS_32(super.size);
205 buf = xmalloc(size);
206 buf_free = buf;
207 ret = read(envfd, buf, size);
208 if (ret < size) {
209 perror("read");
210 goto out;
213 if (crc32(0, (unsigned char *)buf, size)
214 != ENVFS_32(super.crc)) {
215 printf("wrong crc on env\n");
216 goto out;
219 while (size) {
220 struct envfs_inode *inode;
221 uint32_t inode_size,inode_namelen;
223 inode = (struct envfs_inode *)buf;
225 if (ENVFS_32(inode->magic) != ENVFS_INODE_MAGIC) {
226 printf("envfs: wrong magic on %s\n", filename);
227 ret = -EIO;
228 goto out;
230 inode_size = ENVFS_32(inode->size);
231 inode_namelen = ENVFS_32(inode->namelen);
233 debug("loading %s size %d namelen %d\n", inode->data,
234 inode_size, inode_namelen);
236 str = concat_path_file(dir, inode->data);
237 tmp = strdup(str);
238 make_directory(dirname(tmp));
239 free(tmp);
241 fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644);
242 free(str);
243 if (fd < 0) {
244 printf("Open %s\n", errno_str());
245 ret = fd;
246 goto out;
249 namelen_full = PAD4(inode_namelen);
250 ret = write(fd, buf + namelen_full + sizeof(struct envfs_inode),
251 inode_size);
252 if (ret < inode_size) {
253 perror("write");
254 close(fd);
255 goto out;
257 close(fd);
259 buf += PAD4(inode_namelen) + PAD4(inode_size) +
260 sizeof(struct envfs_inode);
261 size -= PAD4(inode_namelen) + PAD4(inode_size) +
262 sizeof(struct envfs_inode);
265 ret = 0;
266 out:
267 close(envfd);
268 if (buf_free)
269 free(buf_free);
270 return ret;