yaffs direct: Improve error reporting for yaffs_lseek
[yaffs2.git] / direct / yaffsfs.c
index f95c19906ac7f6cde771177700eacab25e7d01e9..3ee5f0c8644a9449b6ae3776533bd747c7cee6b5 100644 (file)
@@ -571,6 +571,8 @@ int yaffs_dup(int fd)
 
 }
 
+
+
 int yaffs_open_sharing(const YCHAR *path, int oflag, int mode, int sharing)
 {
        yaffs_obj_t *obj = NULL;
@@ -581,6 +583,7 @@ int yaffs_open_sharing(const YCHAR *path, int oflag, int mode, int sharing)
        int openDenied = 0;
        int symDepth = 0;
        int errorReported = 0;
+       int rwflags = oflag & ( O_RDWR | O_RDONLY | O_WRONLY);
        __u8 shareRead = (sharing & YAFFS_SHARE_READ) ?  1 : 0;
        __u8 shareWrite = (sharing & YAFFS_SHARE_WRITE) ? 1 : 0;
        __u8 sharedReadAllowed;
@@ -600,12 +603,19 @@ int yaffs_open_sharing(const YCHAR *path, int oflag, int mode, int sharing)
 
        /* Todo: Are there any more flag combos to sanitise ? */
 
+       /* Figure out if reading or writing is requested */
+
+       readRequested = (rwflags == O_RDWR || rwflags == O_RDONLY) ? 1 : 0;
+       writeRequested = (rwflags == O_RDWR || rwflags == O_WRONLY) ? 1 : 0;
 
        yaffsfs_Lock();
 
        handle = yaffsfs_GetNewHandle();
 
-       if(handle >= 0){
+       if(handle < 0){
+               yaffsfs_SetError(-ENFILE);
+               errorReported = 1;
+       } else {
 
                yh = yaffsfs_GetHandlePointer(handle);
 
@@ -640,16 +650,10 @@ int yaffs_open_sharing(const YCHAR *path, int oflag, int mode, int sharing)
                        }
 
                        /* Check file permissions */
-                       if( (oflag & (O_RDWR | O_WRONLY)) == 0 &&     /* ie O_RDONLY */
-                          !(obj->yst_mode & S_IREAD))
-                               openDenied = 1;
-
-                       if( (oflag & O_RDWR) &&
-                          !(obj->yst_mode & S_IREAD))
+                       if( readRequested && !(obj->yst_mode & S_IREAD))
                                openDenied = 1;
 
-                       if( (oflag & (O_RDWR | O_WRONLY)) &&
-                          !(obj->yst_mode & S_IWRITE))
+                       if( writeRequested && !(obj->yst_mode & S_IWRITE))
                                openDenied = 1;
 
                        /* Check sharing of an existing object. */
@@ -672,12 +676,11 @@ int yaffs_open_sharing(const YCHAR *path, int oflag, int mode, int sharing)
                                                if(hx->reading)
                                                        alreadyReading = 1;
                                                if(hx->writing)
-                                                       alreadyWriting = 0;
+                                                       alreadyWriting = 1;
                                        }
                                }
 
-                               readRequested = (oflag & (O_RDWR | O_RDONLY)) ? 1 : 0;
-                               writeRequested = (oflag & (O_RDWR | O_WRONLY)) ? 1 : 0;
+
 
                                if((!sharedReadAllowed && readRequested)|| 
                                        (!shareRead  && alreadyReading) ||
@@ -714,8 +717,8 @@ int yaffs_open_sharing(const YCHAR *path, int oflag, int mode, int sharing)
                        }
                        
                        yh->inodeId = inodeId;
-                       yh->reading = (oflag & (O_RDONLY | O_RDWR)) ? 1 : 0;
-                       yh->writing = (oflag & (O_WRONLY | O_RDWR)) ? 1 : 0;
+                       yh->reading = readRequested;
+                       yh->writing = writeRequested;
                        yh->append =  (oflag & O_APPEND) ? 1 : 0;
                        yh->position = 0;
                        yh->shareRead = shareRead;
@@ -831,7 +834,11 @@ int yaffsfs_do_read(int fd, void *vbuf, unsigned int nbyte, int isPread, int off
                /* bad handle */
                yaffsfs_SetError(-EBADF);
                totalRead = -1;
-       } else if( h && obj){
+       } else if(!h->reading){
+               /* Not a reading handle */
+               yaffsfs_SetError(-EINVAL);
+               totalRead = -1;
+       } else {
                if(isPread)
                        startPos = offset;
                else
@@ -926,7 +933,7 @@ int yaffsfs_do_write(int fd, const void *vbuf, unsigned int nbyte, int isPwrite,
        } else if( h && obj && (!h->writing || obj->my_dev->read_only)){
                yaffsfs_SetError(-EINVAL);
                totalWritten=-1;
-       } else if( h && obj){
+       } else {
                if(h->append)
                        startPos = yaffs_get_obj_length(obj);
                else if(isPwrite)
@@ -1051,30 +1058,28 @@ off_t yaffs_lseek(int fd, off_t offset, int whence)
        h = yaffsfs_GetHandlePointer(fd);
        obj = yaffsfs_GetHandleObject(fd);
 
-       if(!h || !obj)
+       if(!h || !obj){
                /* bad handle */
                yaffsfs_SetError(-EBADF);
-       else if(whence == SEEK_SET){
-               if(offset >= 0)
-                       pos = offset;
-       }
-       else if(whence == SEEK_CUR) {
-               if( (h->position + offset) >= 0)
-                       pos = (h->position + offset);
-       }
-       else if(whence == SEEK_END) {
-               fSize = yaffs_get_obj_length(obj);
-               if(fSize >= 0 && (fSize + offset) >= 0)
-                       pos = fSize + offset;
-       }
-
-       if(pos >= 0)
-               h->position = pos;
-       else {
-               /* todo error */
+       } else {
+               if(whence == SEEK_SET){
+                       if(offset >= 0)
+                               pos = offset;
+               } else if(whence == SEEK_CUR) {
+                       if( (h->position + offset) >= 0)
+                               pos = (h->position + offset);
+               } else if(whence == SEEK_END) {
+                       fSize = yaffs_get_obj_length(obj);
+                       if(fSize >= 0 && (fSize + offset) >= 0)
+                               pos = fSize + offset;
+               } 
+
+               if(pos >= 0)
+                       h->position = pos;
+               else
+                       yaffsfs_SetError(-EINVAL);
        }
 
-
        yaffsfs_Unlock();
 
        return pos;
@@ -1723,8 +1728,40 @@ int yaffs_mkdir(const YCHAR *path, mode_t mode)
        yaffs_obj_t *parent = NULL;
        yaffs_obj_t *dir = NULL;
        YCHAR *name;
+       YCHAR *use_path = NULL;
+       int path_length = 0;
        int retVal= -1;
+       int i;
+
+
+       /*
+        * We don't have a definition for max path length.
+        * We will use 3 * max name length instead.
+        */
+       
+       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])){
+               use_path = YMALLOC(path_length + 1);
+               if(!use_path){
+                       yaffsfs_SetError(-ENOMEM);
+                       return -1;
+               }
+               strcpy(use_path, path);
+               for(i = path_length-1;
+                       i >= 0 && yaffsfs_IsPathDivider(use_path[i]);
+                       i--)
+                       use_path[i] = (YCHAR) 0;
+               path = use_path;
+       }
+       
        yaffsfs_Lock();
        parent = yaffsfs_FindDirectory(NULL,path,&name,0);
        if(parent && yaffs_strnlen(name,5) == 0){
@@ -1750,6 +1787,9 @@ int yaffs_mkdir(const YCHAR *path, mode_t mode)
 
        yaffsfs_Unlock();
 
+       if(use_path)
+               YFREE(use_path);
+
        return retVal;
 }
 
@@ -2326,6 +2366,11 @@ int yaffs_n_handles(const YCHAR *path)
        return yaffsfs_CountHandles(obj);
 }
 
+int yaffs_get_error(void)
+{
+       return yaffsfs_GetLastError();
+}
+
 int yaffs_dump_dev(const YCHAR *path)
 {
 #if 0