General cleanup and bugfixes
[tpg/acess2.git] / KernelLand / Kernel / vfs / open.c
index 1536d1a..344b2a1 100644 (file)
@@ -59,6 +59,9 @@ char *VFS_GetAbsPath(const char *Path)
        if( chroot == NULL )
                chroot = "";
        chrootLen = strlen(chroot);
+       // Trim trailing slash off chroot
+       if( chrootLen && chroot[chrootLen - 1] == '/' )
+               chrootLen -= 1;
        
        // Check if the path is already absolute
        if(Path[0] == '/') {
@@ -198,6 +201,7 @@ restart_parse:
                        *TruePath = malloc( gVFS_RootMount->MountPointLen+1 );
                        strcpy(*TruePath, gVFS_RootMount->MountPoint);
                }
+               gVFS_RootMount->OpenHandleCount ++;
                if(MountPoint)  *MountPoint = gVFS_RootMount;
                LEAVE('p', gVFS_RootMount->RootNode);
                return gVFS_RootMount->RootNode;
@@ -211,6 +215,7 @@ restart_parse:
        
        // Find Mountpoint
        longestMount = gVFS_RootMount;
+       RWLock_AcquireRead( &glVFS_MountList );
        for(mnt = gVFS_Mounts; mnt; mnt = mnt->Next)
        {
                // Quick Check
@@ -219,25 +224,29 @@ restart_parse:
                // Length Check - If the length is smaller than the longest match sofar
                if(mnt->MountPointLen < longestMount->MountPointLen)    continue;
                // String Compare
-               cmp = strcmp(Path, mnt->MountPoint);
+               cmp = strncmp(Path, mnt->MountPoint, mnt->MountPointLen);
+               // Not a match, continue
+               if(cmp != 0)    continue;
                
                #if OPEN_MOUNT_ROOT
                // Fast Break - Request Mount Root
-               if(cmp == 0) {
+               if(Path[mnt->MountPointLen] == '\0') {
                        if(TruePath) {
                                *TruePath = malloc( mnt->MountPointLen+1 );
                                strcpy(*TruePath, mnt->MountPoint);
                        }
                        if(MountPoint)
                                *MountPoint = mnt;
+                       RWLock_Release( &glVFS_MountList );
+                       LOG("Mount %p root", mnt);
                        LEAVE('p', mnt->RootNode);
                        return mnt->RootNode;
                }
                #endif
-               // Not a match, continue
-               if(cmp != '/')  continue;
                longestMount = mnt;
        }
+       longestMount->OpenHandleCount ++;       // Increment assuimg it worked
+       RWLock_Release( &glVFS_MountList );
        
        // Save to shorter variable
        mnt = longestMount;
@@ -269,14 +278,21 @@ restart_parse:
        
                // Check permissions on root of filesystem
                if( !VFS_CheckACL(curNode, VFS_PERM_EXECUTE) ) {
-                       //Log("Permissions fail on '%s'", Path);
+                       LOG("Permissions failure on '%s'", Path);
                        goto _error;
                }
                
                // Check if the node has a FindDir method
+               if( !curNode->Type )
+               {
+                       LOG("Finddir failure on '%s' - No type", Path);
+                       Log_Error("VFS", "Node at '%s' has no type (mount %s:%s)",
+                               Path, mnt->Filesystem->Name, mnt->MountPoint);
+                       goto _error;
+               }
                if( !curNode->Type->FindDir )
                {
-                       //Log("FindDir fail on '%s'", Path);
+                       LOG("Finddir failure on '%s' - No FindDir method in %s", Path, curNode->Type->Name);
                        goto _error;
                }
                LOG("FindDir{=%p}(%p, '%s')", curNode->Type->FindDir, curNode, pathEle);
@@ -330,6 +346,7 @@ restart_parse:
 
                        // EVIL: Goto :)
                        LOG("Symlink -> '%s', restart", Path);
+                       mnt->OpenHandleCount --;        // Not in this mountpoint
                        goto restart_parse;
                }
                
@@ -399,6 +416,8 @@ restart_parse:
                *MountPoint = mnt;
        }
        
+       // Leave the mointpoint's count increased
+       
        LEAVE('p', tmpNode);
        return tmpNode;
 
@@ -409,6 +428,9 @@ _error:
                free(*TruePath);
                *TruePath = NULL;
        }
+       // Open failed, so decrement the open handle count
+       mnt->OpenHandleCount --;
+       
        LEAVE('n');
        return NULL;
 }
@@ -482,7 +504,10 @@ int VFS_OpenEx(const char *Path, Uint Flags, Uint Mode)
        {
                // TODO: Translate `Mode` into ACL and node flags
                // Get parent, create node
-               VFS_MkNod(absPath, 0);
+               if( VFS_MkNod(absPath, 0) ) {
+                       free(absPath);
+                       return -1;
+               }
                node = VFS_ParsePath(absPath, NULL, &mnt);
        }
        
@@ -565,6 +590,9 @@ int VFS_OpenChild(int FD, const char *Name, Uint Mode)
                LEAVE_RET('i', -1);
        }
 
+       // Increment open handle count, no problems with the mount going away as `h` is already open on it
+       h->Mount->OpenHandleCount ++;
+
        LEAVE_RET('x', VFS_int_CreateHandle(node, h->Mount, Mode));
 }
 
@@ -625,7 +653,10 @@ void VFS_Close(int FD)
        #endif
        
        _CloseNode(h->Node);
-       
+
+       if( h->Mount )
+               h->Mount->OpenHandleCount --;   
+
        h->Node = NULL;
 }
 

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