Cut down on debug, fixed tabs, made process tree be killed when root is killed
[tpg/acess2.git] / Kernel / vfs / open.c
index fa5fe66..0494294 100644 (file)
@@ -2,26 +2,16 @@
  * AcessMicro VFS
  * - Open, Close and ChDir
  */
+#define DEBUG  0
 #include <common.h>
 #include "vfs.h"
 #include "vfs_int.h"
 #include "vfs_ext.h"
 
-#define DEBUG  0
-
-#if DEBUG
-#else
-# undef ENTER
-# undef LOG
-# undef LEAVE
-# define ENTER(...)
-# define LOG(...)
-# define LEAVE(...)
-#endif
-
 // === CONSTANTS ===
 #define        OPEN_MOUNT_ROOT 1
 #define MAX_KERNEL_FILES       128
+#define MAX_PATH_SLASHES       256
 
 // === IMPORTS ===
 extern tVFS_Node       gVFS_MemRoot;
@@ -41,8 +31,9 @@ char *VFS_GetAbsPath(char *Path)
        char    *ret;
         int    pathLen = strlen(Path);
         int    read, write;
-        int    pos, slashNum=0, baseLen;
-       Uint    slashOffsets[256];
+        int    pos, endLen;
+        int    slashNum = 0;
+       Uint    slashOffsets[MAX_PATH_SLASHES];
        char    *cwd = CFGPTR(CFG_VFS_CWD);
         int    cwdLen;
        
@@ -51,6 +42,10 @@ char *VFS_GetAbsPath(char *Path)
        // Memory File
        if(Path[0] == '$') {
                ret = malloc(strlen(Path)+1);
+               if(!ret) {
+                       Warning("VFS_GetAbsPath - malloc() returned NULL");
+                       return NULL;
+               }
                strcpy(ret, Path);
                LEAVE('p', ret);
                return ret;
@@ -58,31 +53,30 @@ char *VFS_GetAbsPath(char *Path)
        
        // Check if the path is already absolute
        if(Path[0] == '/') {
+               endLen = pathLen + 1;
                ret = malloc(pathLen + 1);
+               if(!ret) {
+                       Warning("VFS_GetAbsPath - malloc() returned NULL");
+                       return NULL;
+               }
                strcpy(ret, Path);
-               baseLen = 1;
        } else {
                cwdLen = strlen(cwd);
+               endLen = cwdLen + pathLen + 2;
                // Prepend the current directory
-               ret = malloc(cwdLen+pathLen+1);
+               ret = malloc(endLen);
                strcpy(ret, cwd);
-               strcpy(&ret[cwdLen], Path);
-       
-               // Pre-fill the slash positions
-               pos = 0;
-               while( (pos = strpos( &ret[pos+1], '/' )) != -1 )
-                       slashOffsets[slashNum++] = pos;
-                       
-               baseLen = cwdLen;
+               ret[cwdLen] = '/';
+               strcpy(&ret[cwdLen+1], Path);
        }
        
        // Remove . and ..
-       read = write = baseLen; // Cwd has already been parsed
-       for(; read < baseLen+pathLen; read = pos+1)
+       read = write = 1;       // Cwd has already been parsed
+       for(; read < endLen; read = pos+1)
        {
                pos = strpos( &ret[read], '/' );
                // If we are in the last section, force a break at the end of the itteration
-               if(pos == -1)   pos = baseLen+pathLen;
+               if(pos == -1)   pos = endLen;
                else    pos += read;    // Else, Adjust to absolute
                
                // Check Length
@@ -94,9 +88,12 @@ char *VFS_GetAbsPath(char *Path)
                        if(strncmp(&ret[read], "..", pos-read) == 0)
                        {
                                // If there is no higher, silently ignore
-                               if(!slashNum)   continue;
+                               if(slashNum < 1) {
+                                       write = 1;
+                                       continue;
+                               }
                                // Reverse write pointer
-                               write = slashOffsets[ slashNum-- ];
+                               write = slashOffsets[ --slashNum ];
                                continue;
                        }
                }
@@ -104,21 +101,27 @@ char *VFS_GetAbsPath(char *Path)
                
                // Only copy if the positions differ
                if(read != write) {
+                       //Log("write = %i, read = %i, pos-read+1 = %i", write, read, pos-read+1);
                        memcpy( &ret[write], &ret[read], pos-read+1 );
+                       //Log("ret = '%s'", ret);
                }
-               write = pos+1;
-               if(slashNum < 256)
-                       slashOffsets[ slashNum++ ] = pos;
+               
+               if(slashNum < MAX_PATH_SLASHES)
+                       slashOffsets[ slashNum++ ] = write;
                else {
                        LOG("Path '%s' has too many elements", Path);
                        free(ret);
                        LEAVE('n');
                        return NULL;
                }
+               
+               // Increment write pointer
+               write += (pos-read)+1;
        }
        
        // `ret` should now be the absolute path
        LEAVE('s', ret);
+       //Log("VFS_GetAbsPath: RETURN '%s'", ret);
        return ret;
 }
 
@@ -392,7 +395,7 @@ int VFS_Open(char *Path, Uint Mode)
        if( !(Mode & VFS_OPENFLAG_NOLINK) && (node->Flags & VFS_FFLAG_SYMLINK) )
        {
                if( !node->Read ) {
-                       LOG("No read method on symlink");
+                       Warning("No read method on symlink");
                        LEAVE('i', -1);
                        return -1;
                }
@@ -495,20 +498,70 @@ void VFS_Close(int FD)
        h->Node = NULL;
 }
 
+/**
+ * \fn int VFS_ChDir(char *New)
+ * \brief Change current working directory
+ */
+int VFS_ChDir(char *New)
+{
+       char    *buf;
+        int    fd;
+       tVFS_Handle     *h;
+       
+       // Create Absolute
+       buf = VFS_GetAbsPath(New);
+       if(buf == NULL) {
+               Log("VFS_ChDir: Path expansion failed");
+               return -1;
+       }
+       
+       // Check if path exists
+       fd = VFS_Open(buf, VFS_OPENFLAG_EXEC);
+       if(fd == -1) {
+               Log("VFS_ChDir: Path is invalid");
+               return -1;
+       }
+       
+       // Get node so we can check for directory
+       h = VFS_GetHandle(fd);
+       if( !(h->Node->Flags & VFS_FFLAG_DIRECTORY) ) {
+               Log("VFS_ChDir: Path is not a directory");
+               VFS_Close(fd);
+               return -1;
+       }
+       
+       // Close file
+       VFS_Close(fd);
+       
+       // Free old working directory
+       if( CFGPTR(CFG_VFS_CWD) )       free( CFGPTR(CFG_VFS_CWD) );
+       // Set new
+       CFGPTR(CFG_VFS_CWD) = buf;
+       
+       Log("Updated CWD to '%s'", buf);
+       
+       return 1;
+}
+
 /**
  * \fn tVFS_Handle *VFS_GetHandle(int FD)
  * \brief Gets a pointer to the handle information structure
  */
 tVFS_Handle *VFS_GetHandle(int FD)
 {
+       tVFS_Handle     *h;
+       
        if(FD < 0)      return NULL;
        
        if(FD & VFS_KERNEL_FLAG) {
                FD &= (VFS_KERNEL_FLAG - 1);
                if(FD >= MAX_KERNEL_FILES)      return NULL;
-               return &gaKernelHandles[ FD ];
+               h = &gaKernelHandles[ FD ];
        } else {
                if(FD >= CFGINT(CFG_VFS_MAXFILES))      return NULL;
-               return &gaUserHandles[ FD ];
+               h = &gaUserHandles[ FD ];
        }
+       
+       if(h->Node == NULL)     return NULL;
+       return h;
 }

UCC git Repository :: git.ucc.asn.au