yaffs direct: Fix some more error handling and directory name handling
authorCharles Manning <cdhmanning@gmail.com>
Tue, 23 Nov 2010 21:04:20 +0000 (10:04 +1300)
committerCharles Manning <cdhmanning@gmail.com>
Tue, 23 Nov 2010 21:04:20 +0000 (10:04 +1300)
All Timothy's tests passing.

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
direct/yaffsfs.c
yaffs_guts.c

index 2016101..29a9209 100644 (file)
@@ -340,6 +340,42 @@ int yaffsfs_CheckNameLength(const char *name)
        return retVal;  
 }
 
+
+static int yaffsfs_alt_dir_path(const YCHAR *path, YCHAR **ret_path)
+{
+       YCHAR *alt_path = NULL;
+       int path_length;
+       int i;
+
+       /*
+        * We don't have a definition for max path length.
+        * We will use 3 * max name length instead.
+        */
+       *ret_path = NULL;
+       path_length = strnlen(path,(YAFFS_MAX_NAME_LENGTH+1)*3 +1);
+
+       /* If the last character is a path divider, then we need to
+        * trim it back so that the name look-up works properly.
+        * eg. /foo/new_dir/ -> /foo/newdir
+        * Curveball: Need to handle multiple path dividers:
+        * eg. /foof/sdfse///// -> /foo/sdfse
+        */
+       if(path_length > 0 && 
+               yaffsfs_IsPathDivider(path[path_length-1])){
+               alt_path = YMALLOC(path_length + 1);
+               if(!alt_path)
+                       return -1;
+               strcpy(alt_path, path);
+               for(i = path_length-1;
+                       i >= 0 && yaffsfs_IsPathDivider(alt_path[i]);
+                       i--)
+                       alt_path[i] = (YCHAR) 0;
+       }
+       *ret_path = alt_path;
+       return 0;
+}
+
+
 LIST_HEAD(yaffsfs_deviceList);
 
 /*
@@ -1241,7 +1277,11 @@ int yaffsfs_DoUnlink(const YCHAR *path,int isDirectory)
 
        if(!dir && notDir)
                yaffsfs_SetError(-ENOTDIR);
-       else if(!dir || !obj)
+       else if(!dir)
+               yaffsfs_SetError(-ENOENT);
+       else if(yaffs_strncmp(name,_Y("."),2) == 0)
+               yaffsfs_SetError(-EINVAL);
+       else if(!obj)
                yaffsfs_SetError(-ENOENT);
        else if(obj->my_dev->read_only)
                yaffsfs_SetError(-EINVAL);
@@ -1249,6 +1289,8 @@ int yaffsfs_DoUnlink(const YCHAR *path,int isDirectory)
                yaffsfs_SetError(-EISDIR);
        else if(isDirectory && obj->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
                yaffsfs_SetError(-ENOTDIR);
+       else if(isDirectory && obj == obj->my_dev->root_dir)
+               yaffsfs_SetError(-EBUSY); /* Can't rmdir a root */
        else {
                result = yaffs_unlinker(dir,name);
 
@@ -1278,22 +1320,43 @@ int yaffs_rename(const YCHAR *oldPath, const YCHAR *newPath)
        int rename_allowed = 1;
        int notOldDir;
        int notNewDir;
-
-       yaffsfs_Lock();
+       YCHAR *alt_newpath=NULL;
 
        if(yaffsfs_CheckPath(newPath) < 0){
                yaffsfs_SetError(-ENAMETOOLONG);
                return -1;
        }
 
+       if(yaffsfs_alt_dir_path(newPath, &alt_newpath) < 0){
+               yaffsfs_SetError(-ENOMEM);
+               return -1;
+       }
+       if(alt_newpath)
+               newPath = alt_newpath;
+
+       yaffsfs_Lock();
+
+
        olddir = yaffsfs_FindDirectory(NULL,oldPath,&oldname,0,&notOldDir);
        newdir = yaffsfs_FindDirectory(NULL,newPath,&newname,0,&notNewDir);
        obj = yaffsfs_FindObject(NULL,oldPath,0,0,NULL,NULL);
 
+       /* If the object being renamed is a directory and the 
+        * path ended with a "/" then the olddir == obj.
+        * We pass through NULL for the old name to tell the lower layers
+        * to use olddir as the object.
+        */
+
+       if(olddir == obj)
+               oldname = NULL;
+
        if((!olddir && notOldDir) || (!newdir && notNewDir)) {
                yaffsfs_SetError(-ENOTDIR);
                rename_allowed = 0;
-       } else if(!olddir || !newdir || !obj) {
+       } else if (olddir && oldname && yaffs_strncmp(oldname, _Y("."),2) == 0){
+               yaffsfs_SetError(-EINVAL);
+               rename_allowed = 0;
+       }else if(!olddir || !newdir || !obj) {
                yaffsfs_SetError(-ENOENT);
                rename_allowed = 0;
        } else if(obj->my_dev->read_only){
@@ -1307,7 +1370,8 @@ int yaffs_rename(const YCHAR *oldPath, const YCHAR *newPath)
                /*
                 * It is a directory, check that it is not being renamed to
                 * being its own decendent.
-                * Do this by tracing from the new directory back to the root, checking for obj
+                * Do this by tracing from the new directory back to the root, 
+                * checking for obj
                 */
 
                struct yaffs_obj *xx = newdir;
@@ -1326,6 +1390,9 @@ int yaffs_rename(const YCHAR *oldPath, const YCHAR *newPath)
 
        yaffsfs_Unlock();
 
+       if(alt_newpath)
+               YFREE(alt_newpath);
+
        return (result == YAFFS_FAIL) ? -1 : 0;
 }
 
@@ -1933,41 +2000,6 @@ int yaffs_fchmod(int fd, mode_t mode)
        return retVal;
 }
 
-
-static int yaffsfs_alt_dir_path(const YCHAR *path, YCHAR **ret_path)
-{
-       YCHAR *alt_path = NULL;
-       int path_length;
-       int i;
-
-       /*
-        * We don't have a definition for max path length.
-        * We will use 3 * max name length instead.
-        */
-       *ret_path = NULL;
-       path_length = strnlen(path,(YAFFS_MAX_NAME_LENGTH+1)*3 +1);
-
-       /* If the last character is a path divider, then we need to
-        * trim it back so that the name look-up works properly.
-        * eg. /foo/new_dir/ -> /foo/newdir
-        * Curveball: Need to handle multiple path dividers:
-        * eg. /foof/sdfse///// -> /foo/sdfse
-        */
-       if(path_length > 0 && 
-               yaffsfs_IsPathDivider(path[path_length-1])){
-               alt_path = YMALLOC(path_length + 1);
-               if(!alt_path)
-                       return -1;
-               strcpy(alt_path, path);
-               for(i = path_length-1;
-                       i >= 0 && yaffsfs_IsPathDivider(alt_path[i]);
-                       i--)
-                       alt_path[i] = (YCHAR) 0;
-       }
-       *ret_path = alt_path;
-       return 0;
-}
-
 int yaffs_mkdir(const YCHAR *path, mode_t mode)
 {
        struct yaffs_obj *parent = NULL;
index 2348a94..1bc6d51 100644 (file)
@@ -1620,6 +1620,10 @@ static int yaffs_change_obj_name(struct yaffs_obj *obj,
        return YAFFS_FAIL;
 }
 
+
+/* Note:
+ * If old_name is NULL then we take old_dir as the object to be renamed.
+ */
 int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR * old_name,
                     struct yaffs_obj *new_dir, const YCHAR * new_name)
 {
@@ -1641,7 +1645,9 @@ int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR * old_name,
         * While look-up is case insensitive, the name isn't.
         * Therefore we might want to change x.txt to X.txt
         */
-       if (old_dir == new_dir && yaffs_strcmp(old_name, new_name) == 0)
+       if (old_dir == new_dir && 
+               old_name && new_name && 
+               yaffs_strcmp(old_name, new_name) == 0)
                force = 1;
 #endif
 
@@ -1650,7 +1656,13 @@ int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR * old_name,
                /* ENAMETOOLONG */
                return YAFFS_FAIL;
 
-       obj = yaffs_find_by_name(old_dir, old_name);
+       if(old_name)
+               obj = yaffs_find_by_name(old_dir, old_name);
+       else{
+               obj = old_dir;
+               old_dir = obj->parent;
+       }
+
 
        if (obj && obj->rename_allowed) {