From 1c8401d1235c9771c4086aa75e31c56c5cac121c Mon Sep 17 00:00:00 2001 From: Charles Manning Date: Fri, 11 Jun 2010 13:57:10 +1200 Subject: [PATCH 1/1] yaffs: Improve xattrib to not modify if there is no space Previously replacing an xattrib with a larger one that could not fit would result in the original xattrib being deleted. We now only replace an xattrib if there is space to do so. Signed-off-by: Charles Manning --- direct/dtest.c | 49 ++++++++++++++++++++++++++++++++++++++++++- yaffs_nameval.c | 55 +++++++++++++++++++++++++++++++------------------ 2 files changed, 83 insertions(+), 21 deletions(-) diff --git a/direct/dtest.c b/direct/dtest.c index cf832a9..34112c8 100644 --- a/direct/dtest.c +++ b/direct/dtest.c @@ -2492,7 +2492,7 @@ void rmdir_test(const char *mountpt) static void print_xattrib_val(const char *path, const char *name) { - char buffer[100]; + char buffer[1000]; int n; n = yaffs_getxattr(path,name,buffer,sizeof(buffer)); @@ -2500,6 +2500,8 @@ static void print_xattrib_val(const char *path, const char *name) __u8 *b = (__u8 *)buffer; printf("%d bytes:",n); + if(n > 10) + n = 10; while(n > 0){ printf("[%02X]",*b); b++; @@ -2527,6 +2529,7 @@ static void list_xattr(const char *path) } printf("end\n"); } + void basic_xattr_test(const char *mountpt) { char name[100]; @@ -2577,6 +2580,49 @@ void basic_xattr_test(const char *mountpt) list_xattr(name); } + +void big_xattr_test(const char *mountpt) +{ + char name[100]; + int h; + int result; + char val[1000]; + char valread[1000]; + + yaffs_StartUp(); + + yaffs_mount(mountpt); + + strcpy(name,mountpt); + strcat(name,"/"); + strcat(name,"xfile"); + + yaffs_unlink(name); + h = yaffs_open(name,O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE); + yaffs_close(h); + + printf("Start\n"); + list_xattr(name); + + printf("Add a large attribute\n"); + memset(val,0x1,sizeof(val)); + result = yaffs_setxattr(name,"aaa",val,200,0); + printf("wrote attribute aaa: result %d\n",result); + list_xattr(name); + + printf("Add a large attribute\n"); + memset(val,0x2,sizeof(val)); + result = yaffs_setxattr(name,"bbb",val,1000,0); + printf("wrote attribute bbb: result %d\n",result); + list_xattr(name); + + printf("Replace attribute\n"); + memset(val,0x3,sizeof(val)); + result = yaffs_setxattr(name,"aaa",val,1000,0); + printf("wrote attribute aaa: result %d\n",result); + list_xattr(name); + +} int random_seed; @@ -2641,6 +2687,7 @@ int main(int argc, char *argv[]) //check_resize_gc_bug("/flash"); basic_xattr_test("/yaffs2"); + big_xattr_test("/yaffs2"); return 0; diff --git a/yaffs_nameval.c b/yaffs_nameval.c index 88ee25b..b098600 100644 --- a/yaffs_nameval.c +++ b/yaffs_nameval.c @@ -28,21 +28,27 @@ #include "yportenv.h" -static int nval_find(const char *xb, int xb_size, const char *name) +static int nval_find(const char *xb, int xb_size, const char *name, + int *exist_size) { 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) + if(strncmp(xb+pos+sizeof(int),name,size) == 0){ + if(exist_size) + *exist_size = size; return pos; + } pos += size; if(pos < xb_size -sizeof(int)) memcpy(&size,xb + pos,sizeof(int)); else size = 0; } + if(exist_size) + *exist_size = 0; return -1; } @@ -64,7 +70,7 @@ static int nval_used(const char *xb, int xb_size) int nval_del(char *xb, int xb_size, const char *name) { - int pos = nval_find(xb, xb_size, name); + int pos = nval_find(xb, xb_size, name, NULL); int size; if(pos >= 0 && pos < xb_size){ @@ -79,37 +85,46 @@ int nval_del(char *xb, int xb_size, const char *name) 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 pos; int namelen = strnlen(name,xb_size); int reclen; + int size_exist = 0; + int space; + int start; + + pos = nval_find(xb,xb_size,name, &size_exist); if(flags & NVAL_CREATE && pos >= 0) return -EEXIST; if(flags & NVAL_REPLACE && pos < 0) return -ENOENT; - nval_del(xb,xb_size,name); + start = nval_used(xb,xb_size); + space = xb_size - start + size_exist; - 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; - } + reclen = (sizeof(int) + namelen + 1 + bsize); + + if(reclen > space) + return -ENOSPC; + + if(pos >= 0){ + nval_del(xb,xb_size,name); + start = nval_used(xb, xb_size); } - return -ENOSPC; + + pos = start; + + memcpy(xb + pos,&reclen,sizeof(int)); + pos +=sizeof(int); + strncpy(xb + pos, name, reclen); + pos+= (namelen+1); + memcpy(xb + pos,buf,bsize); + return 0; } 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 pos = nval_find(xb,xb_size,name,NULL); int size; if(pos >= 0 && pos< xb_size){ -- 2.30.2