about summary refs log blame commit diff stats
path: root/tools/iso/kernel.soso/fs.c
blob: 0d072c33f719fd3e83335e4cbfdaea1a8c52b2f0 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                                                                      
                      







                                                                              
                                         


                           

                                                                    

                                            
                       










                                                                 


                                                                                  




                             
              








                                 
                       


                                     
                            


                      
                                









                                                           
                                                                                   
 
                           







                                           
                                                                  

                                  
                         


                     
                         







                        
                                    






                                                           
                             



                                                        
              


                                          
                              
                                 
                                                 
                              
                                         

                                  
                                                     








                                               
                                                     


                         
                                                             





                                                                
                                              





                                            

                                             






                                           

                                                        





                                                    

                                                         





                                                     
                                                   


                                                               
                                                                              

                                     
                                                                                          


                                
                             







                                               
                      
                                                       

                                                             
                         






                                                           
              








                        

                                    







                                               

                                                        





                                                      

                                                        





                                                       

                                              





                                                   
                                                       







                                                        
                             

                                          
                       

                                                                          
                                                                  

                                         
                                                                                   

                                         
                                                                           

                                         
                                                             

                                         
                                                                             

                                         
                                                             






                                         
              






                       
                                                                  
                                                                         
 

                                                                                          

                                                           
              


                                                                      
                                                                                          





                                          
                                                              
                                             
 

                                                                                          

                                                           
              


                                                                     
                                                                                          





                                         


                                                                                          


                                                                          
                                                                                        





                                              

                                                                     





                                                           

                                                        





                                                       
                                                     
                                                 
 
                         








                                                     
                            





                                       
                         




                    
                                                 


                                                   
                          






                                
                                                 


                    
        



                                                    
                             



                                       
                            




                                                  
              



                                      
                                                     


                                        
                                                     
 
                           







                            
                                                                                         

                                

                              

                   
                                  



                                           
              

                      
                                            

                                 
                                                                                         


                                         
                                                                                    









                                                     

                                         


                     

                                                                    









                                                         
                                                                                                            

                          

                                                                  




                                            
                     





                                                  
                                                                                                                 

                          

                                                                  




                                            
                     




                                                       
#include "fs.h"
#include "alloc.h"
#include "screen.h"
#include "rootfs.h"

FileSystemNode *gFileSystemRoot = NULL; // The root of the filesystem.

#define FILESYSTEM_CAPACITY 10

static FileSystem gRegisteredFileSystems[FILESYSTEM_CAPACITY];
static int gNextFileSystemIndex = 0;

void initializeVFS() {
    memset((uint8*)gRegisteredFileSystems, 0, sizeof(gRegisteredFileSystems));

    gFileSystemRoot = initializeRootFS();

    mkdir_fs(gFileSystemRoot, "dev", 0);
    mkdir_fs(gFileSystemRoot, "initrd", 0);
}

FileSystemNode* getFileSystemRootNode() {
    return gFileSystemRoot;
}

void copyFileDescriptors(Process* fromProcess, Process* toProcess) {
    for (int i = 0; i < MAX_OPENED_FILES; ++i) {
        File* original = fromProcess->fd[i];

        if (original) {
            File* file = kmalloc(sizeof(File));
            memcpy((uint8*)file, (uint8*)original, sizeof(File));
            file->process = toProcess;
            file->thread = NULL;

            toProcess->fd[i] = file;

        }
    }
}

int getFileSystemNodePath(FileSystemNode *node, char* buffer, uint32 bufferSize) {
    if (node == gFileSystemRoot) {
        if (bufferSize > 1) {
            buffer[0] = '/';
            buffer[1] = '\0';

            return 1;
        }
        else {
            return -1;
        }
    }

    char targetPath[128];

    FileSystemNode *n = node;
    int charIndex = 127;
    targetPath[charIndex] = '\0';
    while (NULL != n) {
        int length = strlen(n->name);
        charIndex -= length;

        if (charIndex < 2) {
            return -1;
        }

        if (NULL != n->parent) {
            strcpyNonNull(targetPath + charIndex, n->name);
            charIndex -= 1;
            targetPath[charIndex] = '/';
        }

        n = n->parent;
    }

    int len = 127 - charIndex;

    //printkf("getFileSystemNodePath: len:[%s] %d\n", targetPath + charIndex, len);

    if (bufferSize < len) {
        return -1;
    }

    strcpy(buffer, targetPath + charIndex);

    return len;
}

BOOL resolvePath(const char* path, char* buffer, int bufferSize) {
    int lengthPath = strlen(path);

    if (path[0] != '/') {
        return FALSE;
    }

    if (bufferSize < 2) {
        return FALSE;
    }

    buffer[0] = '/';
    buffer[1] = '\0';
    int index = 0;
    int indexBuffer = 1;

    while (index < lengthPath - 1) {
        while (path[++index] == '/');//eliminate successive

        const char* current = path + index;
        int nextIndex = strFirstIndexOf(path + index, '/');

        int lengthToken = 0;

        if (nextIndex >= 0) {
            const char* next = path + index + nextIndex;

            lengthToken = next - (path + index);
        }
        else {
            lengthToken = strlen(current);
        }

        if (lengthToken > 0) {
            index += lengthToken;
            if (strncmp(current, "..", 2) == 0) {
                --indexBuffer;
                while (indexBuffer > 0) {
                    --indexBuffer;

                    if (buffer[indexBuffer] == '/') {
                        break;
                    }

                    buffer[indexBuffer] = '\0';
                }

                ++indexBuffer;
                continue;
            }
            else if (strncmp(current, ".", 1) == 0) {
                continue;
            }

            if (indexBuffer + lengthToken + 2 > bufferSize) {
                return FALSE;
            }

            strncpy(buffer + indexBuffer, current, lengthToken);
            indexBuffer += lengthToken;

            if (current[lengthToken] == '/') {
                buffer[indexBuffer++] = '/';
            }
            buffer[indexBuffer] = '\0';
        }
    }

    if (indexBuffer > 2) {
        if (buffer[indexBuffer - 1] == '/') {
            buffer[indexBuffer - 1] = '\0';
        }
    }

    return TRUE;
}

uint32 read_fs(File *file, uint32 size, uint8 *buffer) {
    if (file->node->read != 0) {
        return file->node->read(file, size, buffer);
    }

    return -1;
}

uint32 write_fs(File *file, uint32 size, uint8 *buffer) {
    if (file->node->write != 0) {
        return file->node->write(file, size, buffer);
    }

    return -1;
}

File *open_fs(FileSystemNode *node, uint32 flags) {
    return open_fs_forProcess(getCurrentThread(), node, flags);
}

File *open_fs_forProcess(Thread* thread, FileSystemNode *node, uint32 flags) {
    Process* process = thread->owner;

    if ( (node->nodeType & FT_MountPoint) == FT_MountPoint && node->mountPoint != NULL ) {
        node = node->mountPoint;
    }

    if (node->open != NULL) {
        File* file = kmalloc(sizeof(File));
        memset((uint8*)file, 0, sizeof(File));
        file->node = node;
        file->process = process;
        file->thread = thread;

        BOOL success = node->open(file, flags);

        if (success) {
            //printkf("Opened:%s\n", file->node->name);
            int32 fd = addFileToProcess(file->process, file);

            if (fd < 0) {
                //TODO: sett errno max files opened already
                printkf("Maxfiles opened already!!\n");

                close_fs(file);
                file = NULL;
            }
        }
        else {
            kfree(file);
        }

        return file;
    }

    return NULL;
}

void close_fs(File *file) {
    if (file->node->close != NULL) {
        file->node->close(file);
    }

    removeFileFromProcess(file->process, file);

    kfree(file);
}

int32 ioctl_fs(File *file, int32 request, void * argp) {
    if (file->node->ioctl != NULL) {
        return file->node->ioctl(file, request, argp);
    }

    return 0;
}

int32 lseek_fs(File *file, int32 offset, int32 whence) {
    if (file->node->lseek != NULL) {
        return file->node->lseek(file, offset, whence);
    }

    return 0;
}

int32 ftruncate_fs(File* file, int32 length) {
    if (file->node->ftruncate != NULL) {
        return file->node->ftruncate(file, length);
    }

    return -1;
}

int32 stat_fs(FileSystemNode *node, struct stat *buf) {
#define	__S_IFDIR	0040000	/* Directory.  */
#define	__S_IFCHR	0020000	/* Character device.  */
#define	__S_IFBLK	0060000	/* Block device.  */
#define	__S_IFREG	0100000	/* Regular file.  */
#define	__S_IFIFO	0010000	/* FIFO.  */
#define	__S_IFLNK	0120000	/* Symbolic link.  */
#define	__S_IFSOCK	0140000	/* Socket.  */

    if (node->stat != NULL) {
        int32 val = node->stat(node, buf);

        if (val == 1) {
            //return value of 1 from driver means we should fill buf here.

            if ((node->nodeType & FT_Directory) == FT_Directory) {
                buf->st_mode = __S_IFDIR;
            }
            else if ((node->nodeType & FT_CharacterDevice) == FT_CharacterDevice) {
                buf->st_mode = __S_IFCHR;
            }
            else if ((node->nodeType & FT_BlockDevice) == FT_BlockDevice) {
                buf->st_mode = __S_IFBLK;
            }
            else if ((node->nodeType & FT_Pipe) == FT_Pipe) {
                buf->st_mode = __S_IFIFO;
            }
            else if ((node->nodeType & FT_SymbolicLink) == FT_SymbolicLink) {
                buf->st_mode = __S_IFLNK;
            }
            else if ((node->nodeType & FT_File) == FT_File) {
                buf->st_mode = __S_IFREG;
            }

            buf->st_size = node->length;

            return 0;
        }
        else {
            return val;
        }
    }

    return -1;
}

FileSystemDirent *readdir_fs(FileSystemNode *node, uint32 index) {
    //printkf("readdir_fs: node->name:%s index:%d\n", node->name, index);

    if ( (node->nodeType & FT_MountPoint) == FT_MountPoint && node->mountPoint != NULL ) {
        if (NULL == node->mountPoint->readdir) {
            WARNING("mounted fs does not have readdir!\n");
        }
        else {
            return node->mountPoint->readdir(node->mountPoint, index);
        }
    }
    else if ( (node->nodeType & FT_Directory) == FT_Directory && node->readdir != NULL ) {
        return node->readdir(node, index);
    }

    return NULL;
}

FileSystemNode *finddir_fs(FileSystemNode *node, char *name) {
    //printkf("finddir_fs: name:%s\n", name);

    if ( (node->nodeType & FT_MountPoint) == FT_MountPoint && node->mountPoint != NULL ) {
        if (NULL == node->mountPoint->finddir) {
            WARNING("mounted fs does not have finddir!\n");
        }
        else {
            return node->mountPoint->finddir(node->mountPoint, name);
        }
    }
    else if ( (node->nodeType & FT_Directory) == FT_Directory && node->finddir != NULL ) {
        return node->finddir(node, name);
    }

    return NULL;
}

BOOL mkdir_fs(FileSystemNode *node, const char *name, uint32 flags) {
    if ( (node->nodeType & FT_MountPoint) == FT_MountPoint && node->mountPoint != NULL ) {
        if (node->mountPoint->mkdir) {
            return node->mountPoint->mkdir(node->mountPoint, name, flags);
        }
    }
    else if ( (node->nodeType & FT_Directory) == FT_Directory && node->mkdir != NULL ) {
        return node->mkdir(node, name, flags);
    }

    return FALSE;
}

void* mmap_fs(File* file, uint32 size, uint32 offset, uint32 flags) {
    if (file->node->mmap) {
        return file->node->mmap(file, size, offset, flags);
    }

    return NULL;
}

BOOL munmap_fs(File* file, void* address, uint32 size) {
    if (file->node->munmap) {
        return file->node->munmap(file, address, size);
    }

    return FALSE;
}

FileSystemNode *getFileSystemNode(const char *path) {
    //printkf("getFileSystemNode:%s *0\n", path);

    if (path[0] != '/') {
        //We require absolute path!
        return NULL;
    }


    char realPath[256];

    BOOL resolved = resolvePath(path, realPath, 256);

    if (FALSE == resolved) {
        return NULL;
    }

    const char* inputPath = realPath;
    int pathLength = strlen(inputPath);

    if (pathLength < 1) {
        return NULL;
    }



    //printkf("getFileSystemNode:%s *1\n", path);

    FileSystemNode* root = getFileSystemRootNode();

    if (pathLength == 1) {
        return root;
    }

    int nextIndex = 0;

    FileSystemNode* node = root;

    //printkf("getFileSystemNode:%s *2\n", path);

    char buffer[64];

    do {
        do_start:
        inputPath = inputPath + nextIndex + 1;
        nextIndex = strFirstIndexOf(inputPath, '/');

        if (nextIndex == 0) {
            //detected successive slash
            goto do_start;
        }

        if (nextIndex > 0) {
            int tokenSize = nextIndex;

            strncpy(buffer, inputPath, tokenSize);
            buffer[tokenSize] = '\0';
        }
        else {
            //Last part
            strcpy(buffer, inputPath);
        }

        //printkf("getFileSystemNode:%s *3\n", path);

        node = finddir_fs(node, buffer);

        //printkf("getFileSystemNode:%s *4\n", path);

        if (NULL == node) {
            return NULL;
        }

    } while (nextIndex > 0);

    return node;
}

FileSystemNode* getFileSystemNodeAbsoluteOrRelative(const char* path, Process* process) {
    FileSystemNode* node = NULL;

    if (process) {
        if ('\0' == path[0]) {
            //empty
        }
        else if ('/' == path[0]) {
            //absolute

            node = getFileSystemNode(path);
        }
        else {
            //relative

            if (process->workingDirectory) {
                char buffer[256];

                if (getFileSystemNodePath(process->workingDirectory, buffer, 256) >= 0) {
                    strcat(buffer, "/");
                    strcat(buffer, path);

                    //printkf("getFileSystemNodeAbsoluteOrRelative:[%s]\n", buffer);

                    node = getFileSystemNode(buffer);
                }
            }
        }
    }

    return node;
}

BOOL registerFileSystem(FileSystem* fs) {
    if (strlen(fs->name) <= 0) {
        return FALSE;
    }

    for (int i = 0; i < gNextFileSystemIndex; ++i) {
        if (strcmp(gRegisteredFileSystems[i].name, fs->name) == 0) {
            //name is in use
            return FALSE;
        }
    }

    gRegisteredFileSystems[gNextFileSystemIndex++] = *fs;

    return TRUE;
}

BOOL mountFileSystem(const char *source, const char *target, const char *fsType, uint32 flags, void *data) {
    FileSystem* fs = NULL;

    for (int i = 0; i < gNextFileSystemIndex; ++i) {
        if (strcmp(gRegisteredFileSystems[i].name, fsType) == 0) {
            fs = &gRegisteredFileSystems[i];
            break;
        }
    }

    if (NULL == fs) {
        return FALSE;
    }

    return fs->mount(source, target, flags, data);
}

BOOL checkMountFileSystem(const char *source, const char *target, const char *fsType, uint32 flags, void *data) {
    FileSystem* fs = NULL;

    for (int i = 0; i < gNextFileSystemIndex; ++i) {
        if (strcmp(gRegisteredFileSystems[i].name, fsType) == 0) {
            fs = &gRegisteredFileSystems[i];
            break;
        }
    }

    if (NULL == fs) {
        return FALSE;
    }

    return fs->checkMount(source, target, flags, data);
}