yaffs: Improve xattrib to not modify if there is no space
authorCharles Manning <cdhmanning@gmail.com>
Fri, 11 Jun 2010 01:57:10 +0000 (13:57 +1200)
committerCharles Manning <cdhmanning@gmail.com>
Sat, 12 Jun 2010 17:27:07 +0000 (05:27 +1200)
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 <cdhmanning@gmail.com>
direct/dtest.c
yaffs_nameval.c

index cf832a9..34112c8 100644 (file)
@@ -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;
        
index 88ee25b..b098600 100644 (file)
 
 #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){