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