diff options
Diffstat (limited to 'fs/yaffs2/yaffs_nameval.c')
-rw-r--r-- | fs/yaffs2/yaffs_nameval.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/fs/yaffs2/yaffs_nameval.c b/fs/yaffs2/yaffs_nameval.c new file mode 100644 index 00000000000..daa36f989d3 --- /dev/null +++ b/fs/yaffs2/yaffs_nameval.c | |||
@@ -0,0 +1,201 @@ | |||
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 | * This code has not been tested with unicode yet. | ||
26 | */ | ||
27 | |||
28 | #include "yaffs_nameval.h" | ||
29 | |||
30 | #include "yportenv.h" | ||
31 | |||
32 | static int nval_find(const char *xb, int xb_size, const YCHAR * name, | ||
33 | int *exist_size) | ||
34 | { | ||
35 | int pos = 0; | ||
36 | int size; | ||
37 | |||
38 | memcpy(&size, xb, sizeof(int)); | ||
39 | while (size > 0 && (size < xb_size) && (pos + size < xb_size)) { | ||
40 | if (strncmp | ||
41 | ((YCHAR *) (xb + pos + sizeof(int)), name, size) == 0) { | ||
42 | if (exist_size) | ||
43 | *exist_size = size; | ||
44 | return pos; | ||
45 | } | ||
46 | pos += size; | ||
47 | if (pos < xb_size - sizeof(int)) | ||
48 | memcpy(&size, xb + pos, sizeof(int)); | ||
49 | else | ||
50 | size = 0; | ||
51 | } | ||
52 | if (exist_size) | ||
53 | *exist_size = 0; | ||
54 | return -1; | ||
55 | } | ||
56 | |||
57 | static int nval_used(const char *xb, int xb_size) | ||
58 | { | ||
59 | int pos = 0; | ||
60 | int size; | ||
61 | |||
62 | memcpy(&size, xb + pos, sizeof(int)); | ||
63 | while (size > 0 && (size < xb_size) && (pos + size < xb_size)) { | ||
64 | pos += size; | ||
65 | if (pos < xb_size - sizeof(int)) | ||
66 | memcpy(&size, xb + pos, sizeof(int)); | ||
67 | else | ||
68 | size = 0; | ||
69 | } | ||
70 | return pos; | ||
71 | } | ||
72 | |||
73 | int nval_del(char *xb, int xb_size, const YCHAR * name) | ||
74 | { | ||
75 | int pos = nval_find(xb, xb_size, name, NULL); | ||
76 | int size; | ||
77 | |||
78 | if (pos >= 0 && pos < xb_size) { | ||
79 | /* Find size, shift rest over this record, then zero out the rest of buffer */ | ||
80 | memcpy(&size, xb + pos, sizeof(int)); | ||
81 | memcpy(xb + pos, xb + pos + size, xb_size - (pos + size)); | ||
82 | memset(xb + (xb_size - size), 0, size); | ||
83 | return 0; | ||
84 | } else { | ||
85 | return -ENODATA; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | int nval_set(char *xb, int xb_size, const YCHAR * name, const char *buf, | ||
90 | int bsize, int flags) | ||
91 | { | ||
92 | int pos; | ||
93 | int namelen = strnlen(name, xb_size); | ||
94 | int reclen; | ||
95 | int size_exist = 0; | ||
96 | int space; | ||
97 | int start; | ||
98 | |||
99 | pos = nval_find(xb, xb_size, name, &size_exist); | ||
100 | |||
101 | if (flags & XATTR_CREATE && pos >= 0) | ||
102 | return -EEXIST; | ||
103 | if (flags & XATTR_REPLACE && pos < 0) | ||
104 | return -ENODATA; | ||
105 | |||
106 | start = nval_used(xb, xb_size); | ||
107 | space = xb_size - start + size_exist; | ||
108 | |||
109 | reclen = (sizeof(int) + namelen + 1 + bsize); | ||
110 | |||
111 | if (reclen > space) | ||
112 | return -ENOSPC; | ||
113 | |||
114 | if (pos >= 0) { | ||
115 | nval_del(xb, xb_size, name); | ||
116 | start = nval_used(xb, xb_size); | ||
117 | } | ||
118 | |||
119 | pos = start; | ||
120 | |||
121 | memcpy(xb + pos, &reclen, sizeof(int)); | ||
122 | pos += sizeof(int); | ||
123 | strncpy((YCHAR *) (xb + pos), name, reclen); | ||
124 | pos += (namelen + 1); | ||
125 | memcpy(xb + pos, buf, bsize); | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | int nval_get(const char *xb, int xb_size, const YCHAR * name, char *buf, | ||
130 | int bsize) | ||
131 | { | ||
132 | int pos = nval_find(xb, xb_size, name, NULL); | ||
133 | int size; | ||
134 | |||
135 | if (pos >= 0 && pos < xb_size) { | ||
136 | |||
137 | memcpy(&size, xb + pos, sizeof(int)); | ||
138 | pos += sizeof(int); /* advance past record length */ | ||
139 | size -= sizeof(int); | ||
140 | |||
141 | /* Advance over name string */ | ||
142 | while (xb[pos] && size > 0 && pos < xb_size) { | ||
143 | pos++; | ||
144 | size--; | ||
145 | } | ||
146 | /*Advance over NUL */ | ||
147 | pos++; | ||
148 | size--; | ||
149 | |||
150 | if (size <= bsize) { | ||
151 | memcpy(buf, xb + pos, size); | ||
152 | return size; | ||
153 | } | ||
154 | |||
155 | } | ||
156 | if (pos >= 0) | ||
157 | return -ERANGE; | ||
158 | else | ||
159 | return -ENODATA; | ||
160 | } | ||
161 | |||
162 | int nval_list(const char *xb, int xb_size, char *buf, int bsize) | ||
163 | { | ||
164 | int pos = 0; | ||
165 | int size; | ||
166 | int name_len; | ||
167 | int ncopied = 0; | ||
168 | int filled = 0; | ||
169 | |||
170 | memcpy(&size, xb + pos, sizeof(int)); | ||
171 | while (size > sizeof(int) && size <= xb_size && (pos + size) < xb_size | ||
172 | && !filled) { | ||
173 | pos += sizeof(int); | ||
174 | size -= sizeof(int); | ||
175 | name_len = strnlen((YCHAR *) (xb + pos), size); | ||
176 | if (ncopied + name_len + 1 < bsize) { | ||
177 | memcpy(buf, xb + pos, name_len * sizeof(YCHAR)); | ||
178 | buf += name_len; | ||
179 | *buf = '\0'; | ||
180 | buf++; | ||
181 | if (sizeof(YCHAR) > 1) { | ||
182 | *buf = '\0'; | ||
183 | buf++; | ||
184 | } | ||
185 | ncopied += (name_len + 1); | ||
186 | } else { | ||
187 | filled = 1; | ||
188 | } | ||
189 | pos += size; | ||
190 | if (pos < xb_size - sizeof(int)) | ||
191 | memcpy(&size, xb + pos, sizeof(int)); | ||
192 | else | ||
193 | size = 0; | ||
194 | } | ||
195 | return ncopied; | ||
196 | } | ||
197 | |||
198 | int nval_hasvalues(const char *xb, int xb_size) | ||
199 | { | ||
200 | return nval_used(xb, xb_size) > 0; | ||
201 | } | ||