Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / nvram / nvram_linux.c
blob465c110fc04f40b458caea202fbf56d3e0813a3d
1 /*
2 * NVRAM variable manipulation (Linux user mode half)
4 * Copyright 2005, Broadcom Corporation
5 * All Rights Reserved.
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
12 * $Id: nvram_linux.c,v 1.18 2005/05/16 12:35:03 honor Exp $
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <errno.h>
19 #include <error.h>
20 #include <string.h>
21 #include <sys/ioctl.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <sys/mman.h>
27 #include <typedefs.h>
28 #include <bcmnvram.h>
29 #include <nvram_convert.h>
30 #include <shutils.h>
31 #include <utils.h>
32 #include <shared.h>
34 #define PATH_DEV_NVRAM "/dev/nvram"
36 /* Globals */
37 static int nvram_fd = -1;
38 static char *nvram_buf = NULL;
40 int nvram_init(void *unused)
42 if ((nvram_fd = open(PATH_DEV_NVRAM, O_RDWR)) >= 0) {
43 /* Map kernel string buffer into user space */
44 if ((nvram_buf = mmap(NULL, NVRAM_SPACE, PROT_READ, MAP_SHARED, nvram_fd, 0)) != MAP_FAILED) {
45 fcntl(nvram_fd, F_SETFD, FD_CLOEXEC); // zzz
46 return 0;
48 close(nvram_fd);
49 nvram_fd = -1;
51 perror(PATH_DEV_NVRAM);
52 return errno;
55 char *nvram_get(const char *name)
57 char tmp[100];
58 char *value;
59 size_t count = strlen(name) + 1;
60 unsigned long *off = (unsigned long *)tmp;
62 if (nvram_fd < 0) {
63 if (nvram_init(NULL) != 0) return NULL;
66 if (count > sizeof(tmp)) {
67 if ((off = malloc(count)) == NULL) return NULL;
70 /* Get offset into mmap() space */
71 strcpy((char *) off, name);
72 count = read(nvram_fd, off, count);
74 if (count == sizeof(*off)) {
75 value = &nvram_buf[*off];
77 else {
78 value = NULL;
79 if (count < 0) perror(PATH_DEV_NVRAM);
82 if (off != (unsigned long *)tmp) free(off);
83 return value;
86 int nvram_getall(char *buf, int count)
88 int r;
90 if (count <= 0) return 0;
92 *buf = 0;
93 if (nvram_fd < 0) {
94 if ((r = nvram_init(NULL)) != 0) return r;
96 r = read(nvram_fd, buf, count);
97 if (r < 0) perror(PATH_DEV_NVRAM);
98 return (r == count) ? 0 : r;
101 static int _nvram_set(const char *name, const char *value)
103 size_t count = strlen(name) + 1;
104 char tmp[100];
105 char *buf = tmp;
106 int ret;
108 if (nvram_fd < 0) {
109 if ((ret = nvram_init(NULL)) != 0) return ret;
112 /* Unset if value is NULL */
113 if (value) count += strlen(value) + 1;
115 if (count > sizeof(tmp)) {
116 if ((buf = malloc(count)) == NULL) return -ENOMEM;
119 if (value) {
120 sprintf(buf, "%s=%s", name, value);
122 else {
123 strcpy(buf, name);
126 ret = write(nvram_fd, buf, count);
127 if (ret < 0) perror(PATH_DEV_NVRAM);
129 if (buf != tmp) free(buf);
131 return (ret == count) ? 0 : ret;
134 int nvram_set(const char *name, const char *value)
136 struct nvram_convert *v;
138 for (v = nvram_converts; v->name; v++) {
139 if (!strcmp(v->name, name)) {
140 _nvram_set(v->wl0_name, value);
141 break;
145 if (strncmp(name, "wl_", 3) == 0) {
146 char wl0[48];
148 if (strlen(name) < 32) {
149 sprintf(wl0, "wl0_%s", name + 3);
150 _nvram_set(wl0, value);
154 return _nvram_set(name, value);
157 int nvram_unset(const char *name)
159 return _nvram_set(name, NULL);
162 int nvram_commit(void)
164 int r = 0;
166 if (wait_action_idle(10)) {
167 if (nvram_fd < 0) {
168 if ((r = nvram_init(NULL)) != 0) return r;
170 set_action(ACT_NVRAM_COMMIT);
171 // nvram_unset("dirty");
172 r = ioctl(nvram_fd, NVRAM_MAGIC, NULL);
173 set_action(ACT_IDLE);
174 if (r < 0) {
175 perror(PATH_DEV_NVRAM);
176 cprintf("commit: error\n");
179 else {
180 cprintf("commit: system busy\n");
183 return r;
187 * Write a file to an NVRAM variable.
188 * @param name name of variable to get
189 * @param filenname name of file to write
190 * @return return code
192 * Preserve mode (permissions) of the file.
193 * Create the output directory.
195 #define MAX_FS 4096
196 #define MAGICNUM 0x12161770 /* Ludwig van Beethoven's birthdate. */
197 int nvram_file2nvram(const char *varname, const char *filename)
199 FILE *fp;
200 int c,count;
201 int i=0,j=0;
202 struct stat stbuf;
203 unsigned char mem[MAX_FS], buf[3 * MAX_FS];
205 if ( !(fp=fopen(filename,"rb") )) {
206 perror("");
207 return 1;
210 stat(filename, &stbuf);
211 *((mode_t *)mem) = stbuf.st_mode;
212 *((mode_t *)mem+1) = MAGICNUM;
214 count=fread(mem + 2*sizeof(mode_t), 1, sizeof(mem) - 2*sizeof(mode_t), fp);
215 if (!feof(fp)) {
216 fclose(fp);
217 fprintf(stderr, "File too big.\n");
218 return(1);
220 fclose(fp);
221 count += 2*sizeof(mode_t);
222 for (j = 0; j < count; j++) {
223 if (i > sizeof(buf)-3 )
224 break;
225 c=mem[j];
226 if (c >= 32 && c <= 126 && c != '\\' && c != '~') {
227 buf[i++]=(unsigned char) c;
228 } else if (c==0) {
229 buf[i++]='~';
230 } else {
231 buf[i++]='\\';
232 sprintf(buf+i,"%02X",c);
233 i+=2;
236 buf[i]=0;
237 nvram_set(varname,buf);
238 return 0;
242 * Get the value of an NVRAM variable and write it to a file.
243 * It must have been written with nvram_file2nvram.
244 * Directory path(s) are created, and permissions are preserved.
245 * @param name name of variable to get
246 * @param filenname name of file to write
247 * @return return code
249 int nvram_nvram2file(const char *varname, const char *filename)
251 int fnum;
252 int c,tmp;
253 int i=0,j=0;
254 unsigned char *cp;
255 unsigned char mem[MAX_FS], buf[3 * MAX_FS];
257 cp = nvram_get(varname);
258 if (cp == NULL) {
259 printf("Key does not exist: %s\n", varname);
260 return(1);
262 strcpy(buf, cp);
263 while (buf[i] && j < sizeof(mem)-3 ) {
264 if (buf[i] == '\\') {
265 i++;
266 tmp=buf[i+2];
267 buf[i+2]=0;
268 sscanf(buf+i,"%02X",&c);
269 buf[i+2]=tmp;
270 i+=2;
271 mem[j]=c;j++;
272 } else if (buf[i] == '~') {
273 mem[j++]=0;
274 i++;
275 } else {
276 mem[j++]=buf[i++];
280 if (j<=0)
281 return j;
282 if (*((mode_t *)mem+1) != MAGICNUM) {
283 printf("Error: '%s' not created by nvram setfile.\n", varname);
284 return(-1);
287 /* Create the directories to the path, as necessary. */
288 strcpy(buf, filename);
289 cp = strrchr(buf, '/');
290 if (cp && cp > buf) {
291 *cp = 0;
292 eval("mkdir", "-m", "0777", "-p", buf);
295 if ( (fnum=open(filename, O_WRONLY | O_CREAT | O_TRUNC, *((mode_t *)mem))) < 0) {
296 printf("failed. errno: %d\n", errno);
297 perror(filename);
298 return (-1);
300 i = write(fnum, mem + 2*sizeof(mode_t), j- 2* sizeof(mode_t));
301 if (i != j- 2* sizeof(mode_t))
302 perror(filename);
303 close(fnum);
304 return (i != (j- 2* sizeof(mode_t)));