X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=direct%2Fyaffsfs.c;h=9ac4493d7cf842171753097bd9c2521defe2b4b2;hp=956df2c751bc60eb7cded9d29bed0f580772350c;hb=70f8f5a74a83c0e0f8ee869a6d1c77c07b0e74f3;hpb=8d87e1a358bf0184a82c586d362d994094a1e9ed diff --git a/direct/yaffsfs.c b/direct/yaffsfs.c index 956df2c..9ac4493 100644 --- a/direct/yaffsfs.c +++ b/direct/yaffsfs.c @@ -25,7 +25,7 @@ #endif -const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.6 2005-09-20 05:05:40 charles Exp $"; +const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.15 2006-11-17 01:43:48 charles Exp $"; // configurationList is the list of devices that are supported static yaffsfs_DeviceConfiguration *yaffsfs_configurationList; @@ -144,30 +144,47 @@ int yaffsfs_Match(char a, char b) // yaffsfs_FindDevice // yaffsfs_FindRoot // Scan the configuration list to find the root. +// Curveballs: Should match paths that end in '/' too +// Curveball2 Might have "/x/ and "/x/y". Need to return the longest match static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath) { yaffsfs_DeviceConfiguration *cfg = yaffsfs_configurationList; const char *leftOver; const char *p; + yaffs_Device *retval = NULL; + int thisMatchLength; + int longestMatch = -1; + // Check all configs, choose the one that: + // 1) Actually matches a prefix (ie /a amd /abc will not match + // 2) Matches the longest. while(cfg && cfg->prefix && cfg->dev) { leftOver = path; p = cfg->prefix; - while(*p && *leftOver && yaffsfs_Match(*p,*leftOver)) + thisMatchLength = 0; + + while(*p && //unmatched part of prefix + strcmp(p,"/") && // the rest of the prefix is not / (to catch / at end) + *leftOver && + yaffsfs_Match(*p,*leftOver)) { p++; leftOver++; + thisMatchLength++; } - if(!*p && (!*leftOver || *leftOver == '/')) + if((!*p || strcmp(p,"/") == 0) && // end of prefix + (!*leftOver || *leftOver == '/') && // no more in this path name part + (thisMatchLength > longestMatch)) { // Matched prefix *restOfPath = (char *)leftOver; - return cfg->dev; + retval = cfg->dev; + longestMatch = thisMatchLength; } cfg++; } - return NULL; + return retval; } static yaffs_Object *yaffsfs_FindRoot(const char *path, char **restOfPath) @@ -603,7 +620,7 @@ int yaffs_write(int fd, const void *buf, unsigned int nbyte) } -int yaffs_truncate(int fd, unsigned int newSize) +int yaffs_truncate(int fd, off_t newSize) { yaffsfs_Handle *h = NULL; yaffs_Object *obj = NULL; @@ -712,10 +729,6 @@ int yaffsfs_DoUnlink(const char *path,int isDirectory) { yaffsfs_SetError(-ENOTDIR); } - else if(isDirectory && obj->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) - { - yaffsfs_SetError(-ENOTDIR); - } else { result = yaffs_Unlink(dir,name); @@ -834,7 +847,7 @@ static int yaffsfs_DoStat(yaffs_Object *obj,struct yaffs_stat *buf) buf->st_gid = 0;; buf->st_rdev = obj->yst_rdev; buf->st_size = yaffs_GetObjectFileLength(obj); - buf->st_blksize = obj->myDev->nBytesPerChunk; + buf->st_blksize = obj->myDev->nDataBytesPerChunk; buf->st_blocks = (buf->st_size + buf->st_blksize -1)/buf->st_blksize; buf->yst_atime = obj->yst_atime; buf->yst_ctime = obj->yst_ctime; @@ -982,13 +995,14 @@ int yaffs_fchmod(int fd, mode_t mode) int yaffs_mkdir(const char *path, mode_t mode) { yaffs_Object *parent = NULL; - yaffs_Object *dir; + yaffs_Object *dir = NULL; char *name; int retVal= -1; yaffsfs_Lock(); parent = yaffsfs_FindDirectory(NULL,path,&name,0); - dir = yaffs_MknodDirectory(parent,name,mode,0,0); + if(parent) + dir = yaffs_MknodDirectory(parent,name,mode,0,0); if(dir) { retVal = 0; @@ -1058,6 +1072,10 @@ int yaffs_unmount(const char *path) { int i; int inUse; + + yaffs_FlushEntireDeviceCache(dev); + yaffs_CheckpointSave(dev); + for(i = inUse = 0; i < YAFFSFS_N_HANDLES && !inUse; i++) { if(yaffsfs_handle[i].inUse && yaffsfs_handle[i].obj->myDev == dev) @@ -1096,9 +1114,9 @@ int yaffs_unmount(const char *path) } -off_t yaffs_freespace(const char *path) +loff_t yaffs_freespace(const char *path) { - off_t retVal=-1; + loff_t retVal=-1; yaffs_Device *dev=NULL; char *dummy; @@ -1107,7 +1125,7 @@ off_t yaffs_freespace(const char *path) if(dev && dev->isMounted) { retVal = yaffs_GetNumberOfFreeChunks(dev); - retVal *= dev->nBytesPerChunk; + retVal *= dev->nDataBytesPerChunk; } else @@ -1250,8 +1268,9 @@ yaffs_DIR *yaffs_opendir(const char *dirname) dir = (yaffs_DIR *)dsc; if(dsc) { + memset(dsc,0,sizeof(yaffsfs_DirectorySearchContext)); dsc->magic = YAFFS_MAGIC; - memset(dsc->name,0,NAME_MAX+1); + dsc->dirObj = obj; strncpy(dsc->name,dirname,NAME_MAX); INIT_LIST_HEAD(&dsc->others); @@ -1259,7 +1278,7 @@ yaffs_DIR *yaffs_opendir(const char *dirname) INIT_LIST_HEAD(&search_contexts); list_add(&dsc->others,&search_contexts); - } + yaffsfs_SetDirRewound(dsc); } } @@ -1279,8 +1298,14 @@ struct yaffs_dirent *yaffs_readdir(yaffs_DIR *dirp) yaffsfs_SetError(0); if(dsc->nextReturn){ dsc->de.d_ino = yaffs_GetEquivalentObject(dsc->nextReturn)->objectId; + dsc->de.d_dont_use = (unsigned)dsc->nextReturn; dsc->de.d_off = dsc->offset++; - yaffs_GetObjectName(dsc->nextReturn,dsc->de.d_name,NAME_MAX+1); + yaffs_GetObjectName(dsc->nextReturn,dsc->de.d_name,NAME_MAX); + if(strlen(dsc->de.d_name) == 0) + { + // this should not happen! + strcpy(dsc->de.d_name,"zz"); + } dsc->de.d_reclen = sizeof(struct yaffs_dirent); retVal = &dsc->de; yaffsfs_DirAdvance(dsc); @@ -1384,7 +1409,66 @@ int yaffs_readlink(const char *path, char *buf, int bufsiz) return retVal; } -int yaffs_link(const char *oldpath, const char *newpath); +int yaffs_link(const char *oldpath, const char *newpath) +{ + // Creates a link called newpath to existing oldpath + yaffs_Object *obj = NULL; + yaffs_Object *target = NULL; + int retVal = 0; + + + yaffsfs_Lock(); + + obj = yaffsfs_FindObject(NULL,oldpath,0); + target = yaffsfs_FindObject(NULL,newpath,0); + + if(!obj) + { + yaffsfs_SetError(-ENOENT); + retVal = -1; + } + else if(target) + { + yaffsfs_SetError(-EEXIST); + retVal = -1; + } + else + { + yaffs_Object *newdir = NULL; + yaffs_Object *link = NULL; + + char *newname; + + newdir = yaffsfs_FindDirectory(NULL,newpath,&newname,0); + + if(!newdir) + { + yaffsfs_SetError(-ENOTDIR); + retVal = -1; + } + else if(newdir->myDev != obj->myDev) + { + yaffsfs_SetError(-EXDEV); + retVal = -1; + } + if(newdir && strlen(newname) > 0) + { + link = yaffs_Link(newdir,newname,obj); + if(link) + retVal = 0; + else + { + yaffsfs_SetError(-ENOSPC); + retVal = -1; + } + + } + } + yaffsfs_Unlock(); + + return retVal; +} + int yaffs_mknod(const char *pathname, mode_t mode, dev_t dev); int yaffs_DumpDevStruct(const char *path)