X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_nameval.c;fp=yaffs_nameval.c;h=88ee25bfd6c87d8c0ea4324abcdc529955bae7f8;hp=0000000000000000000000000000000000000000;hb=4a96d43bb566f00596a31a41c535cabbf52d4f20;hpb=523109e39ed14c0153c7947ad7a8f31a0917df93;ds=sidebyside diff --git a/yaffs_nameval.c b/yaffs_nameval.c new file mode 100644 index 0000000..88ee25b --- /dev/null +++ b/yaffs_nameval.c @@ -0,0 +1,196 @@ +/* + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. + * + * Copyright (C) 2002-2010 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * This simple implementation of a name-value store assumes a small number of values and fits + * into a small finite buffer. + * + * Each attribute is stored as a record: + * sizeof(int) bytes record size. + * strnlen+1 bytes name null terminated. + * nbytes value. + * ---------- + * total size stored in record size + */ + + +#include "yaffs_nameval.h" + +#include "yportenv.h" + +static int nval_find(const char *xb, int xb_size, const char *name) +{ + int pos=0; + int size; + + memcpy(&size,xb,sizeof(int)); + while(size > 0 && (size < xb_size) && (pos + size < xb_size)){ + if(strncmp(xb+pos+sizeof(int),name,size) == 0) + return pos; + pos += size; + if(pos < xb_size -sizeof(int)) + memcpy(&size,xb + pos,sizeof(int)); + else + size = 0; + } + return -1; +} + +static int nval_used(const char *xb, int xb_size) +{ + int pos=0; + int size; + + memcpy(&size,xb + pos,sizeof(int)); + while(size > 0 && (size < xb_size) && (pos + size < xb_size)){ + pos += size; + if(pos < xb_size -sizeof(int)) + memcpy(&size,xb + pos,sizeof(int)); + else + size = 0; + } + return pos; +} + +int nval_del(char *xb, int xb_size, const char *name) +{ + int pos = nval_find(xb, xb_size, name); + int size; + + if(pos >= 0 && pos < xb_size){ + /* Find size, shift rest over this record, then zero out the rest of buffer */ + memcpy(&size,xb+pos,sizeof(int)); + memcpy(xb + pos, xb + pos + size, xb_size - (pos + size)); + memset(xb + (xb_size - size),0,size); + return 0; + } else + return -ENOENT; +} + +int nval_set(char *xb, int xb_size, const char *name, const char *buf, int bsize, int flags) +{ + int pos = nval_find(xb,xb_size,name); + int namelen = strnlen(name,xb_size); + int reclen; + + if(flags & NVAL_CREATE && pos >= 0) + return -EEXIST; + if(flags & NVAL_REPLACE && pos < 0) + return -ENOENT; + + nval_del(xb,xb_size,name); + + pos = nval_used(xb, xb_size); + + if(pos < xb_size && bsize < xb_size && namelen < xb_size){ + reclen = (sizeof(int) + namelen + 1 + bsize); + if( pos + reclen < xb_size){ + memcpy(xb + pos,&reclen,sizeof(int)); + pos +=sizeof(int); + strncpy(xb + pos, name, reclen); + pos+= (namelen+1); + memcpy(xb + pos,buf,bsize); + pos+= bsize; + return 0; + } + } + return -ENOSPC; +} + +int nval_get(const char *xb, int xb_size, const char *name, char *buf, int bsize) +{ + int pos = nval_find(xb,xb_size,name); + int size; + + if(pos >= 0 && pos< xb_size){ + + memcpy(&size,xb +pos,sizeof(int)); + pos+=sizeof(int); /* advance past record length */ + size -= sizeof(int); + + /* Advance over name string */ + while(xb[pos] && size > 0 && pos < xb_size){ + pos++; + size--; + } + /*Advance over NUL */ + pos++; + size--; + + if(size <= bsize){ + memcpy(buf,xb + pos,size); + return size; + } + + } + return -ENOENT; +} + +int nval_list(const char *xb, int xb_size, char *buf, int bsize) +{ + int pos = 0; + int size; + int name_len; + int ncopied = 0; + int filled = 0; + + memcpy(&size,xb + pos,sizeof(int)); + while(size > sizeof(int) && size <= xb_size && (pos + size) < xb_size && !filled){ + pos+= sizeof(int); + size-=sizeof(int); + name_len = strnlen(xb + pos, size); + if(ncopied + name_len + 1 < bsize){ + memcpy(buf,xb+pos,name_len); + buf+= name_len; + *buf = '\0'; + buf++; + ncopied += (name_len+1); + } else + filled = 1; + pos+=size; + if(pos < xb_size -sizeof(int)) + memcpy(&size,xb + pos,sizeof(int)); + else + size = 0; + } + return ncopied; +} + +int nval_load(char *xb, int xb_size, const char *src, int src_size) +{ + int tx_size; + int used; + + tx_size = xb_size; + if(tx_size > src_size) + tx_size = src_size; + + memcpy(xb,src,tx_size); + used = nval_used(xb, xb_size); + + if( used < xb_size) + memset(xb+ used, 0, xb_size - used); + return used; +} + +int nval_save(const char *xb, int xb_size, char *dest, int dest_size) +{ + int tx_size; + + tx_size = xb_size; + if(tx_size > dest_size) + tx_size = dest_size; + + memcpy(dest,xb,tx_size); + return tx_size; +}