yaffs Make directory for extracting common wince files
[yaffs2.git] / yaffs_nameval.c
1 /*
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2002-2010 Aleph One Ltd.
5  *   for Toby Churchill Ltd and Brightstar Engineering
6  *
7  * Created by Charles Manning <charles@aleph1.co.uk>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13
14 /*
15  * This simple implementation of a name-value store assumes a small number of values and fits
16  * into a small finite buffer.
17  *
18  * Each attribute is stored as a record:
19  *  sizeof(int) bytes   record size.
20  *  strnlen+1 bytes name null terminated.
21  *  nbytes    value.
22  *  ----------
23  *  total size  stored in record size 
24  */
25
26
27 #include "yaffs_nameval.h"
28
29 #include "yportenv.h"
30  
31 static int nval_find(const char *xb, int xb_size, const char *name,
32                 int *exist_size)
33 {
34         int pos=0;
35         int size;
36
37         memcpy(&size,xb,sizeof(int));
38         while(size > 0 && (size < xb_size) && (pos + size < xb_size)){
39                 if(strncmp(xb+pos+sizeof(int),name,size) == 0){
40                         if(exist_size)
41                                 *exist_size = size;
42                         return pos;
43                 }
44                 pos += size;
45                 if(pos < xb_size -sizeof(int))
46                         memcpy(&size,xb + pos,sizeof(int));
47                 else
48                         size = 0;
49         }
50         if(exist_size)
51                 *exist_size = 0;
52         return -1;
53 }
54
55 static int nval_used(const char *xb, int xb_size)
56 {
57         int pos=0;
58         int size;
59
60         memcpy(&size,xb + pos,sizeof(int));
61         while(size > 0 && (size < xb_size) && (pos + size < xb_size)){
62                 pos += size;
63                 if(pos < xb_size -sizeof(int))
64                         memcpy(&size,xb + pos,sizeof(int));
65                 else
66                         size = 0;
67         }
68         return pos;
69 }
70
71 int nval_del(char *xb, int xb_size, const char *name)
72 {
73         int pos  = nval_find(xb, xb_size, name, NULL);
74         int size;
75         
76         if(pos >= 0 && pos < xb_size){
77                 /* Find size, shift rest over this record, then zero out the rest of buffer */
78                 memcpy(&size,xb+pos,sizeof(int));
79                 memcpy(xb + pos, xb + pos + size, xb_size - (pos + size));
80                 memset(xb + (xb_size - size),0,size);
81                 return 0;
82         } else
83                 return -ENODATA;
84 }
85
86 int nval_set(char *xb, int xb_size, const char *name, const char *buf, int bsize, int flags)
87 {
88         int pos;
89         int namelen = strnlen(name,xb_size);
90         int reclen;
91         int size_exist = 0;
92         int space;
93         int start;
94
95         pos = nval_find(xb,xb_size,name, &size_exist);
96
97         if(flags & XATTR_CREATE && pos >= 0)
98                 return -EEXIST;
99         if(flags & XATTR_REPLACE && pos < 0)
100                 return -ENODATA;
101
102         start = nval_used(xb,xb_size);
103         space = xb_size - start + size_exist;
104
105         reclen = (sizeof(int) + namelen + 1 + bsize);
106
107         if(reclen > space)
108                 return -ENOSPC;
109
110         if(pos >= 0){
111                 nval_del(xb,xb_size,name);
112                 start = nval_used(xb, xb_size);
113         }
114
115         pos = start;
116
117         memcpy(xb + pos,&reclen,sizeof(int));
118         pos +=sizeof(int);
119         strncpy(xb + pos, name, reclen);
120         pos+= (namelen+1);
121         memcpy(xb + pos,buf,bsize);
122         return 0;
123 }
124
125 int nval_get(const char *xb, int xb_size, const char *name, char *buf, int bsize)
126 {
127         int pos = nval_find(xb,xb_size,name,NULL);
128         int size;
129         
130         if(pos >= 0 && pos< xb_size){
131                 
132                 memcpy(&size,xb +pos,sizeof(int));
133                 pos+=sizeof(int); /* advance past record length */
134                 size -= sizeof(int);
135
136                 /* Advance over name string */
137                 while(xb[pos] && size > 0 && pos < xb_size){
138                         pos++;
139                         size--;
140                 }
141                 /*Advance over NUL */
142                 pos++;
143                 size--;
144
145                 if(size <= bsize){
146                         memcpy(buf,xb + pos,size);
147                         return size;
148                 }
149                 
150         }
151         if(pos >= 0)
152                 return -ERANGE;
153         else
154                 return -ENODATA;
155 }
156
157 int nval_list(const char *xb, int xb_size, char *buf, int bsize)
158 {
159         int pos = 0;
160         int size;
161         int name_len;
162         int ncopied = 0;
163         int filled = 0;
164
165         memcpy(&size,xb + pos,sizeof(int));
166         while(size > sizeof(int) && size <= xb_size && (pos + size) < xb_size && !filled){
167                 pos+= sizeof(int);
168                 size-=sizeof(int);
169                 name_len = strnlen(xb + pos, size);
170                 if(ncopied + name_len + 1 < bsize){
171                         memcpy(buf,xb+pos,name_len);
172                         buf+= name_len;
173                         *buf = '\0';
174                         buf++;
175                         ncopied += (name_len+1);
176                 } else
177                         filled = 1;
178                 pos+=size;
179                 if(pos < xb_size -sizeof(int))
180                         memcpy(&size,xb + pos,sizeof(int));
181                 else
182                         size = 0;
183         }
184         return ncopied;
185 }
186
187 int nval_load(char *xb, int xb_size, const char *src, int src_size)
188 {
189         int tx_size;
190         int used;
191         
192         tx_size = xb_size;
193         if(tx_size > src_size)
194                 tx_size = src_size;
195
196         memcpy(xb,src,tx_size);
197         used = nval_used(xb, xb_size);
198         
199         if( used < xb_size)
200                 memset(xb+ used, 0, xb_size - used);
201         return used;    
202 }
203
204 int nval_save(const char *xb, int xb_size, char *dest, int dest_size)
205 {
206         int tx_size;
207         
208         tx_size = xb_size;
209         if(tx_size > dest_size)
210                 tx_size = dest_size;
211
212         memcpy(dest,xb,tx_size);
213         return tx_size;
214 }