88ee25bfd6c87d8c0ea4324abcdc529955bae7f8
[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 {
33         int pos=0;
34         int size;
35
36         memcpy(&size,xb,sizeof(int));
37         while(size > 0 && (size < xb_size) && (pos + size < xb_size)){
38                 if(strncmp(xb+pos+sizeof(int),name,size) == 0)
39                         return pos;
40                 pos += size;
41                 if(pos < xb_size -sizeof(int))
42                         memcpy(&size,xb + pos,sizeof(int));
43                 else
44                         size = 0;
45         }
46         return -1;
47 }
48
49 static int nval_used(const char *xb, int xb_size)
50 {
51         int pos=0;
52         int size;
53
54         memcpy(&size,xb + pos,sizeof(int));
55         while(size > 0 && (size < xb_size) && (pos + size < xb_size)){
56                 pos += size;
57                 if(pos < xb_size -sizeof(int))
58                         memcpy(&size,xb + pos,sizeof(int));
59                 else
60                         size = 0;
61         }
62         return pos;
63 }
64
65 int nval_del(char *xb, int xb_size, const char *name)
66 {
67         int pos  = nval_find(xb, xb_size, name);
68         int size;
69         
70         if(pos >= 0 && pos < xb_size){
71                 /* Find size, shift rest over this record, then zero out the rest of buffer */
72                 memcpy(&size,xb+pos,sizeof(int));
73                 memcpy(xb + pos, xb + pos + size, xb_size - (pos + size));
74                 memset(xb + (xb_size - size),0,size);
75                 return 0;
76         } else
77                 return -ENOENT;
78 }
79
80 int nval_set(char *xb, int xb_size, const char *name, const char *buf, int bsize, int flags)
81 {
82         int pos = nval_find(xb,xb_size,name);
83         int namelen = strnlen(name,xb_size);
84         int reclen;
85
86         if(flags & NVAL_CREATE && pos >= 0)
87                 return -EEXIST;
88         if(flags & NVAL_REPLACE && pos < 0)
89                 return -ENOENT;
90
91         nval_del(xb,xb_size,name);
92
93         pos = nval_used(xb, xb_size);
94         
95         if(pos < xb_size && bsize < xb_size && namelen < xb_size){
96                 reclen = (sizeof(int) + namelen + 1 + bsize);
97                 if( pos + reclen < xb_size){
98                         memcpy(xb + pos,&reclen,sizeof(int));
99                         pos +=sizeof(int);
100                         strncpy(xb + pos, name, reclen);
101                         pos+= (namelen+1);
102                         memcpy(xb + pos,buf,bsize);
103                         pos+= bsize;
104                         return 0;
105                 }
106         }
107         return -ENOSPC;
108 }
109
110 int nval_get(const char *xb, int xb_size, const char *name, char *buf, int bsize)
111 {
112         int pos = nval_find(xb,xb_size,name);
113         int size;
114         
115         if(pos >= 0 && pos< xb_size){
116                 
117                 memcpy(&size,xb +pos,sizeof(int));
118                 pos+=sizeof(int); /* advance past record length */
119                 size -= sizeof(int);
120
121                 /* Advance over name string */
122                 while(xb[pos] && size > 0 && pos < xb_size){
123                         pos++;
124                         size--;
125                 }
126                 /*Advance over NUL */
127                 pos++;
128                 size--;
129
130                 if(size <= bsize){
131                         memcpy(buf,xb + pos,size);
132                         return size;
133                 }
134                 
135         }
136         return -ENOENT;
137 }
138
139 int nval_list(const char *xb, int xb_size, char *buf, int bsize)
140 {
141         int pos = 0;
142         int size;
143         int name_len;
144         int ncopied = 0;
145         int filled = 0;
146
147         memcpy(&size,xb + pos,sizeof(int));
148         while(size > sizeof(int) && size <= xb_size && (pos + size) < xb_size && !filled){
149                 pos+= sizeof(int);
150                 size-=sizeof(int);
151                 name_len = strnlen(xb + pos, size);
152                 if(ncopied + name_len + 1 < bsize){
153                         memcpy(buf,xb+pos,name_len);
154                         buf+= name_len;
155                         *buf = '\0';
156                         buf++;
157                         ncopied += (name_len+1);
158                 } else
159                         filled = 1;
160                 pos+=size;
161                 if(pos < xb_size -sizeof(int))
162                         memcpy(&size,xb + pos,sizeof(int));
163                 else
164                         size = 0;
165         }
166         return ncopied;
167 }
168
169 int nval_load(char *xb, int xb_size, const char *src, int src_size)
170 {
171         int tx_size;
172         int used;
173         
174         tx_size = xb_size;
175         if(tx_size > src_size)
176                 tx_size = src_size;
177
178         memcpy(xb,src,tx_size);
179         used = nval_used(xb, xb_size);
180         
181         if( used < xb_size)
182                 memset(xb+ used, 0, xb_size - used);
183         return used;    
184 }
185
186 int nval_save(const char *xb, int xb_size, char *dest, int dest_size)
187 {
188         int tx_size;
189         
190         tx_size = xb_size;
191         if(tx_size > dest_size)
192                 tx_size = dest_size;
193
194         memcpy(dest,xb,tx_size);
195         return tx_size;
196 }