Kernel - Cleaning up unneeded malloc() calls
[tpg/acess2.git] / Kernel / vfs / open.c
index 5d1d9fa..ed79ba1 100644 (file)
@@ -11,6 +11,8 @@
 // === CONSTANTS ===
 #define        OPEN_MOUNT_ROOT 1
 #define MAX_PATH_SLASHES       256
+#define MAX_NESTED_LINKS       4
+#define MAX_PATH_LEN   255
 
 // === IMPORTS ===
 extern tVFS_Node       gVFS_MemRoot;
@@ -59,13 +61,14 @@ char *VFS_GetAbsPath(const char *Path)
        
        // Check if the path is already absolute
        if(Path[0] == '/') {
-               ret = malloc(pathLen + 1);
+               ret = malloc(chrootLen + pathLen + 1);
                if(!ret) {
                        Log_Warning("VFS", "VFS_GetAbsPath: malloc() returned NULL");
                        return NULL;
                }
-               strcpy(ret, Path);
-       } else {
+               strcpy(ret + chrootLen, Path);
+       }
+       else {
                if(cwd == NULL) {
                        cwd = "/";
                        cwdLen = 1;
@@ -74,15 +77,15 @@ char *VFS_GetAbsPath(const char *Path)
                        cwdLen = strlen(cwd);
                }
                // Prepend the current directory
-               ret = malloc( cwdLen + 1 + pathLen + 1 );
-               strcpy(ret, cwd);
+               ret = malloc(chrootLen + cwdLen + 1 + pathLen + 1 );
+               strcpy(ret+chrootLen, cwd);
                ret[cwdLen] = '/';
-               strcpy(&ret[cwdLen+1], Path);
+               strcpy(ret+chrootLen+cwdLen+1, Path);
                //Log("ret = '%s'", ret);
        }
        
        // Parse Path
-       pathComps[iPos++] = tmpStr = ret+1;
+       pathComps[iPos++] = tmpStr = ret+chrootLen+1;
        while(*tmpStr)
        {
                if(*tmpStr++ == '/')
@@ -130,7 +133,7 @@ char *VFS_GetAbsPath(const char *Path)
        pathComps[iPos2] = NULL;
        
        // Build New Path
-       iPos2 = 1;      iPos = 0;
+       iPos2 = chrootLen + 1;  iPos = 0;
        ret[0] = '/';
        while(pathComps[iPos])
        {
@@ -147,17 +150,12 @@ char *VFS_GetAbsPath(const char *Path)
                ret[iPos2-1] = 0;
        else
                ret[iPos2] = 0;
-       
-       
+
        // Prepend the chroot
-       tmpStr = malloc(chrootLen + strlen(ret) + 1);
-       strcpy( tmpStr, chroot );
-       strcpy( tmpStr+chrootLen, ret );
-       free(ret);
-       ret = tmpStr;
+       memcpy( ret, chroot, chrootLen );
        
        LEAVE('s', ret);
-       //Log("VFS_GetAbsPath: RETURN '%s'", ret);
+//     Log_Debug("VFS", "VFS_GetAbsPath: RETURN '%s'", ret);
        return ret;
 }
 
@@ -167,12 +165,13 @@ char *VFS_GetAbsPath(const char *Path)
  */
 tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath)
 {
-       tVFS_Mount      *mnt;
-       tVFS_Mount      *longestMount = gVFS_RootMount; // Root is first
+       tVFS_Mount      *mnt, *longestMount;
         int    cmp, retLength = 0;
         int    ofs, nextSlash;
+        int    iNestedLinks = 0;
        tVFS_Node       *curNode, *tmpNode;
        char    *tmp;
+       char    path_buffer[MAX_PATH_LEN+1];
        
        ENTER("sPath pTruePath", Path, TruePath);
        
@@ -186,7 +185,8 @@ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath)
                LEAVE('p', curNode);
                return curNode;
        }
-       
+
+restart_parse: 
        // For root we always fast return
        if(Path[0] == '/' && Path[1] == '\0') {
                if(TruePath) {
@@ -197,16 +197,15 @@ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath)
                return gVFS_RootMount->RootNode;
        }
        
-       // Check if there is an`ything mounted
+       // Check if there is anything mounted
        if(!gVFS_Mounts) {
-               Warning("WTF! There's nothing mounted?");
+               Log_Error("VFS", "VFS_ParsePath - No filesystems mounted");
                return NULL;
        }
        
        // Find Mountpoint
-       for(mnt = gVFS_Mounts;
-               mnt;
-               mnt = mnt->Next)
+       longestMount = gVFS_RootMount;
+       for(mnt = gVFS_Mounts; mnt; mnt = mnt->Next)
        {
                // Quick Check
                if( Path[mnt->MountPointLen] != '/' && Path[mnt->MountPointLen] != '\0')
@@ -240,7 +239,8 @@ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath)
        // Initialise String
        if(TruePath)
        {
-               *TruePath = malloc( mnt->MountPointLen+1 );
+               // Assumes that the resultant path (here) will not be > strlen(Path) + 1
+               *TruePath = malloc( strlen(Path) + 1 );
                strcpy(*TruePath, mnt->MountPoint);
                retLength = mnt->MountPointLen;
        }
@@ -312,53 +312,48 @@ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath)
                                *TruePath = NULL;
                        }
                        if(!curNode->Read) {
-                               Warning("VFS_ParsePath - Read of node %p is NULL (%s)",
+                               Log_Warning("VFS", "VFS_ParsePath - Read of symlink node %p'%s' is NULL",
                                        curNode, Path);
                                if(curNode->Close)      curNode->Close(curNode);
-                               // No need to free *TruePath, see above
+                               // No need to free *TruePath, it should already be NULL
                                LEAVE('n');
                                return NULL;
                        }
                        
-                       tmp = malloc( curNode->Size + 1 );
-                       if(!tmp) {
-                               Log_Warning("VFS", "VFS_ParsePath - Malloc failure");
-                               // No need to free *TruePath, see above
+                       if(iNestedLinks > MAX_NESTED_LINKS) {
+                               if(curNode->Close)      curNode->Close(curNode);
                                LEAVE('n');
                                return NULL;
                        }
-                       curNode->Read( curNode, 0, curNode->Size, tmp );
-                       tmp[ curNode->Size ] = '\0';
                        
                        // Parse Symlink Path
-                       curNode = VFS_ParsePath(tmp, TruePath);
-                       if(TruePath)
-                               LOG("VFS", "*TruePath='%s'", *TruePath);
-                       
-                       // Error Check
-                       if(!curNode) {
-                               Log_Debug("VFS", "Symlink fail '%s'", tmp);
-                               free(tmp);      // Free temp string
-                               if(TruePath)    free(TruePath);
-                               LEAVE('n');
-                               return NULL;
+                       // - Just update the path variable and restart the function
+                       // > Count nested symlinks and limit to some value (counteracts loops)
+                       {
+                                int    remlen = strlen(Path) - (ofs + nextSlash);
+                               if( curNode->Size + remlen > MAX_PATH_LEN ) {
+                                       if(curNode->Close)      curNode->Close(curNode);
+                                       Log_Warning("VFS", "VFS_ParsePath - Symlinked path too long");
+                                       LEAVE('n');
+                                       return NULL;
+                               }
+                               curNode->Read( curNode, 0, curNode->Size, path_buffer );
+                               path_buffer[ curNode->Size ] = '\0';
+                               strcat(path_buffer, Path + ofs+nextSlash);
+                               
+                               Path = path_buffer;
+//                             Log_Debug("VFS", "VFS_ParsePath: Symlink translated to '%s'", Path);
+                               iNestedLinks ++;
                        }
-                       
-                       // Free temp link
-                       free(tmp);
-                       
-                       // Set Path Variable
-                       if(TruePath) {
-                               retLength = strlen(*TruePath);
-                       }
-                       
-                       continue;
+
+                       // EVIL: Goto :)
+                       goto restart_parse;
                }
                
                // Handle Non-Directories
                if( !(curNode->Flags & VFS_FFLAG_DIRECTORY) )
                {
-                       Warning("VFS_ParsePath - File in directory context");
+                       Log_Warning("VFS", "VFS_ParsePath - Path segment is not a directory");
                        if(TruePath)    free(*TruePath);
                        LEAVE('n');
                        return NULL;
@@ -371,7 +366,7 @@ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath)
                tmp = realloc( *TruePath, retLength + strlen(pathEle) + 1 + 1 );
                // Check if allocation succeeded
                if(!tmp) {
-                       Warning("VFS_ParsePath -  Unable to reallocate true path buffer");
+                       Log_Warning("VFS", "VFS_ParsePath - Unable to reallocate true path buffer");
                        free(*TruePath);
                        *TruePath = NULL;
                        if(curNode->Close)      curNode->Close(curNode);
@@ -395,7 +390,7 @@ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath)
                        free(*TruePath);
                        *TruePath = NULL;
                }
-               Log("FindDir fail on '%s'", Path);
+               Log_Warning("VFS", "VFS_ParsePath - FindDir doesn't exist for element of '%s'", Path);
                LEAVE('n');
                return NULL;
        }
@@ -421,7 +416,7 @@ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath)
                tmp = realloc(*TruePath, retLength + strlen(&Path[ofs]) + 1 + 1);
                // Check if allocation succeeded
                if(!tmp) {
-                       Warning("VFS_ParsePath -  Unable to reallocate true path buffer");
+                       Log_Warning("VFS", "VFS_ParsePath -  Unable to reallocate true path buffer");
                        free(*TruePath);
                        if(tmpNode->Close)      tmpNode->Close(curNode);
                        LEAVE('n');
@@ -455,7 +450,7 @@ int VFS_Open(const char *Path, Uint Mode)
        absPath = VFS_GetAbsPath(Path);
        if(absPath == NULL) {
                Log_Warning("VFS", "VFS_Open: Path expansion failed '%s'", Path);
-               return -1;
+               LEAVE_RET('i', -1);
        }
        LOG("absPath = \"%s\"", absPath);
        // Parse path and get mount point
@@ -465,31 +460,31 @@ int VFS_Open(const char *Path, Uint Mode)
        
        if(!node) {
                LOG("Cannot find node");
-               LEAVE('i', -1);
-               return -1;
+               LEAVE_RET('i', -1);
        }
        
        // Check for symlinks
        if( !(Mode & VFS_OPENFLAG_NOLINK) && (node->Flags & VFS_FFLAG_SYMLINK) )
        {
+               char    tmppath[node->Size+1];
+               if( node->Size > MAX_PATH_LEN ) {
+                       Log_Warning("VFS", "VFS_Open - Symlink is too long (%i)", node->Size);
+                       LEAVE_RET('i', -1);
+               }
                if( !node->Read ) {
-                       Warning("No read method on symlink");
-                       LEAVE('i', -1);
-                       return -1;
+                       Log_Warning("VFS", "VFS_Open - No read method on symlink");
+                       LEAVE_RET('i', -1);
+               }
+               // Read symlink's path
+               node->Read( node, 0, node->Size, tmppath );
+               tmppath[ node->Size ] = '\0';
+               if(node->Close) node->Close( node );
+               // Open the target
+               node = VFS_ParsePath(tmppath, NULL);
+               if(!node) {
+                       LOG("Cannot find symlink target node (%s)", tmppath);
+                       LEAVE_RET('i', -1);
                }
-               absPath = malloc(node->Size+1); // Allocate Buffer
-               node->Read( node, 0, node->Size, absPath );     // Read Path
-               
-               absPath[ node->Size ] = '\0';   // End String
-               if(node->Close) node->Close( node );    // Close old node
-               node = VFS_ParsePath(absPath, NULL);    // Get new node
-               free( absPath );        // Free allocated path
-       }
-       
-       if(!node) {
-               LOG("Cannot find node");
-               LEAVE('i', -1);
-               return -1;
        }
        
        i = 0;
@@ -502,20 +497,17 @@ int VFS_Open(const char *Path, Uint Mode)
        // Permissions Check
        if( !VFS_CheckACL(node, i) ) {
                if(node->Close) node->Close( node );
-               Log("VFS_Open: Permissions Failed");
-               LEAVE('i', -1);
-               return -1;
+               Log_Log("VFS", "VFS_Open: Permissions Failed");
+               LEAVE_RET('i', -1);
        }
        
        i = VFS_AllocHandle( !!(Mode & VFS_OPENFLAG_USER), node, Mode );
-       if( i >= 0 ) {
-               LEAVE('x', i);
-               return i;
+       if( i < 0 ) {
+               Log_Notice("VFS", "VFS_Open: Out of handles");
+               LEAVE_RET('i', -1);
        }
        
-       Log("VFS_Open: Out of handles");
-       LEAVE('i', -1);
-       return -1;
+       LEAVE_RET('x', i);      
 }
 
 
@@ -533,24 +525,21 @@ int VFS_OpenChild(Uint *Errno, int FD, const char *Name, Uint Mode)
        if(h == NULL) {
                Log_Warning("VFS", "VFS_OpenChild - Invalid file handle 0x%x", FD);
                if(Errno)       *Errno = EINVAL;
-               LEAVE('i', -1);
-               return -1;
+               LEAVE_RET('i', -1);
        }
        
        // Check for directory
        if( !(h->Node->Flags & VFS_FFLAG_DIRECTORY) ) {
                Log_Warning("VFS", "VFS_OpenChild - Passed handle is not a directory", FD);
                if(Errno)       *Errno = ENOTDIR;
-               LEAVE('i', -1);
-               return -1;
+               LEAVE_RET('i', -1);
        }
        
        // Find Child
        node = h->Node->FindDir(h->Node, Name);
        if(!node) {
                if(Errno)       *Errno = ENOENT;
-               LEAVE('i', -1);
-               return -1;
+               LEAVE_RET('i', -1);
        }
        
        i = 0;
@@ -563,20 +552,17 @@ int VFS_OpenChild(Uint *Errno, int FD, const char *Name, Uint Mode)
                if(node->Close) node->Close( node );
                Log_Notice("VFS", "VFS_OpenChild - Permissions Failed");
                if(Errno)       *Errno = EACCES;
-               LEAVE('i', -1);
-               return -1;
+               LEAVE_RET('i', -1);
        }
        
        i = VFS_AllocHandle( !!(Mode & VFS_OPENFLAG_USER), node, Mode );
        if( i >= 0 ) {
-               LEAVE('x', i);
-               return i;
+               LEAVE_RET('x', i);
        }
        
        Log_Error("VFS", "VFS_OpenChild - Out of handles");
        if(Errno)       *Errno = ENFILE;
-       LEAVE('i', -1);
-       return -1;
+       LEAVE_RET('i', -1);
 }
 
 /**

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