X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=direct%2Fyaffsfs.c;h=76a397cf6a06e803dc7d9673c009b76c3b4a5674;hp=2016101702021c0796e2e5f83be791e360ce8fed;hb=10d09f1cb066885e3934db0c2c7c86dd10cbc8bf;hpb=20eedfb9d60adc929129d28efcd8d7582178be5b diff --git a/direct/yaffsfs.c b/direct/yaffsfs.c index 2016101..76a397c 100644 --- a/direct/yaffsfs.c +++ b/direct/yaffsfs.c @@ -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); @@ -1272,33 +1314,59 @@ int yaffs_rename(const YCHAR *oldPath, const YCHAR *newPath) struct yaffs_obj *olddir = NULL; struct yaffs_obj *newdir = NULL; struct yaffs_obj *obj = NULL; + struct yaffs_obj *newobj = NULL; YCHAR *oldname; YCHAR *newname; int result= YAFFS_FAIL; 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,¬OldDir); newdir = yaffsfs_FindDirectory(NULL,newPath,&newname,0,¬NewDir); obj = yaffsfs_FindObject(NULL,oldPath,0,0,NULL,NULL); + newobj = yaffsfs_FindObject(NULL,newPath,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){ yaffsfs_SetError(-EROFS); rename_allowed = 0; + } else if(yaffs_is_non_empty_dir(newobj)){ + yaffsfs_SetError(-ENOTEMPTY); + rename_allowed = 0; } else if(olddir->my_dev != newdir->my_dev) { /* Rename must be on same device */ yaffsfs_SetError(-EXDEV); @@ -1307,7 +1375,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 +1395,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 +2005,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;