Add Beat's test
[yaffs/.git] / direct / yaffsfs.c
index 8f2f06e82ff7f0cefc71a645fa3a21ee84d528ca..efd5f8cc70fd0799d1e016b17dcf37ec23cc4a54 100644 (file)
@@ -25,7 +25,7 @@
 #endif
 
 
-const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.2 2003-01-31 00:57:35 charles Exp $";
+const char *yaffsfs_c_version="$Id: yaffsfs.c,v 1.8 2005-08-31 09:21:12 charles Exp $";
 
 // configurationList is the list of devices that are supported
 static yaffsfs_DeviceConfiguration *yaffsfs_configurationList;
@@ -180,7 +180,7 @@ static yaffs_Device *yaffsfs_FindDevice(const char *path, char **restOfPath)
                        p++;
                        leftOver++;
                }
-               if(!*p)
+               if(!*p && (!*leftOver || *leftOver == '/'))
                {
                        // Matched prefix
                        *restOfPath = (char *)leftOver;
@@ -348,6 +348,7 @@ int yaffs_open(const char *path, int oflag, int mode)
        int alreadyExclusive = 0;
        int openDenied = 0;
        int symDepth = 0;
+       int errorReported = 0;
        
        int i;
        
@@ -399,21 +400,29 @@ int yaffs_open(const char *path, int oflag, int mode)
                                openDenied = 1;
                        }
                        
+                       // Open should fail if O_CREAT and O_EXCL are specified
+                       if((oflag & O_EXCL) && (oflag & O_CREAT))
+                       {
+                               openDenied = 1;
+                               yaffsfs_SetError(-EEXIST);
+                               errorReported = 1;
+                       }
+                       
                        // Check file permissions
                        if( (oflag & (O_RDWR | O_WRONLY)) == 0 &&     // ie O_RDONLY
-                          !(obj->st_mode & S_IREAD))
+                          !(obj->yst_mode & S_IREAD))
                        {
                                openDenied = 1;
                        }
 
                        if( (oflag & O_RDWR) && 
-                          !(obj->st_mode & S_IREAD))
+                          !(obj->yst_mode & S_IREAD))
                        {
                                openDenied = 1;
                        }
 
                        if( (oflag & (O_RDWR | O_WRONLY)) && 
-                          !(obj->st_mode & S_IWRITE))
+                          !(obj->yst_mode & S_IWRITE))
                        {
                                openDenied = 1;
                        }
@@ -430,7 +439,8 @@ int yaffs_open(const char *path, int oflag, int mode)
                        }
                        else
                        {
-                       } yaffsfs_SetError(-ENOTDIR);
+                               yaffsfs_SetError(-ENOTDIR);
+                       }
                }
                
                if(obj && !openDenied)
@@ -453,7 +463,11 @@ int yaffs_open(const char *path, int oflag, int mode)
                else
                {
                        yaffsfs_PutHandle(handle);
-                       yaffsfs_SetError(-EACCESS);
+                       if(!errorReported)
+                       {
+                               yaffsfs_SetError(-EACCESS);
+                               errorReported = 1;
+                       }
                        handle = -1;
                }
                
@@ -546,7 +560,7 @@ int yaffs_read(int fd, void *buf, unsigned int nbyte)
                }
                else
                {
-                       //todo error
+                       nRead = 0;
                }
                
        }
@@ -725,27 +739,51 @@ int yaffs_rename(const char *oldPath, const char *newPath)
 {
        yaffs_Object *olddir = NULL;
        yaffs_Object *newdir = NULL;
+       yaffs_Object *obj = NULL;
        char *oldname;
        char *newname;
        int result= YAFFS_FAIL;
+       int renameAllowed = 1;
        
        yaffsfs_Lock();
        
        olddir = yaffsfs_FindDirectory(NULL,oldPath,&oldname,0);
        newdir = yaffsfs_FindDirectory(NULL,newPath,&newname,0);
+       obj = yaffsfs_FindObject(NULL,oldPath,0);
        
-       if(!olddir || !newdir)
+       if(!olddir || !newdir || !obj)
        {
-               // bad handle
-               yaffsfs_SetError(-EBADF);               
+               // bad file
+               yaffsfs_SetError(-EBADF);       
+               renameAllowed = 0;      
        }
        else if(olddir->myDev != newdir->myDev)
        {
                // oops must be on same device
                // todo error
                yaffsfs_SetError(-EXDEV);
+               renameAllowed = 0;      
        }
-       else
+       else if(obj && obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
+       {
+               // 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
+               
+               yaffs_Object *xx = newdir;
+               
+               while( renameAllowed && xx)
+               {
+                       if(xx == obj)
+                       {
+                               renameAllowed = 0;
+                       }
+                       xx = xx->parent;
+               }
+               if(!renameAllowed) yaffsfs_SetError(-EACCESS);
+       }
+       
+       if(renameAllowed)
        {
                result = yaffs_RenameObject(olddir,oldname,newdir,newname);
        }
@@ -767,33 +805,33 @@ static int yaffsfs_DoStat(yaffs_Object *obj,struct yaffs_stat *buf)
 
        if(obj && buf)
        {
-       buf->st_dev = (int)obj->myDev->genericDevice;
-       buf->st_ino = obj->objectId;
-       buf->st_mode = obj->st_mode & ~S_IFMT; // clear out file type bits
+       buf->yst_dev = (int)obj->myDev->genericDevice;
+       buf->yst_ino = obj->objectId;
+       buf->yst_mode = obj->yst_mode & ~S_IFMT; // clear out file type bits
        
                if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) 
                {
-                       buf->st_mode |= S_IFDIR;
+                       buf->yst_mode |= S_IFDIR;
                }
                else if(obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) 
                {
-                       buf->st_mode |= S_IFLNK;
+                       buf->yst_mode |= S_IFLNK;
                }
                else if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
                {
-                       buf->st_mode |= S_IFREG;
+                       buf->yst_mode |= S_IFREG;
                }
                
-       buf->st_nlink = yaffs_GetObjectLinkCount(obj);
-       buf->st_uid = 0;    
-       buf->st_gid = 0;;     
-       buf->st_rdev = obj->st_rdev;
-       buf->st_size = yaffs_GetObjectFileLength(obj);
-               buf->st_blksize = YAFFS_BYTES_PER_CHUNK;
-       buf->st_blocks = (buf->st_size + YAFFS_BYTES_PER_CHUNK -1)/YAFFS_BYTES_PER_CHUNK;
-       buf->st_atime = obj->st_atime; 
-       buf->st_ctime = obj->st_ctime; 
-       buf->st_mtime = obj->st_mtime; 
+       buf->yst_nlink = yaffs_GetObjectLinkCount(obj);
+       buf->yst_uid = 0;    
+       buf->yst_gid = 0;;     
+       buf->yst_rdev = obj->yst_rdev;
+       buf->yst_size = yaffs_GetObjectFileLength(obj);
+               buf->yst_blksize = YAFFS_BYTES_PER_CHUNK;
+       buf->yst_blocks = (buf->yst_size + YAFFS_BYTES_PER_CHUNK -1)/YAFFS_BYTES_PER_CHUNK;
+       buf->yst_atime = obj->yst_atime; 
+       buf->yst_ctime = obj->yst_ctime; 
+       buf->yst_mtime = obj->yst_mtime; 
                retVal = 0;
        }
        return retVal;
@@ -874,7 +912,7 @@ static int yaffsfs_DoChMod(yaffs_Object *obj,mode_t mode)
        
        if(obj)
        {
-               obj->st_mode = mode;
+               obj->yst_mode = mode;
                obj->dirty = 1;
                result = yaffs_FlushFile(obj,0);
        }
@@ -1339,5 +1377,6 @@ int yaffs_DumpDevStruct(const char *path)
                                dev->passiveGarbageCollections
                );
        }
+       return 0;
 }