about summary refs log tree commit diff stats
path: root/tools/iso/kernel.soso/fs.c
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-01-01 18:22:19 -0800
committerKartik Agaram <vc@akkartik.com>2020-01-01 18:42:48 -0800
commit65409d2312e702a48d3cf5b32479d25266bda3c3 (patch)
tree62a7262fce61f2302109246da4536ce6f8e9ef80 /tools/iso/kernel.soso/fs.c
parenta6da50ad30d2e1825575ffef497ab450a8f26e94 (diff)
downloadmu-65409d2312e702a48d3cf5b32479d25266bda3c3.tar.gz
5858
Move script to create a Soso boot image into a sub-directory.

I'm trying to streamline newcomer attention to just a couple of use cases.
Diffstat (limited to 'tools/iso/kernel.soso/fs.c')
-rw-r--r--tools/iso/kernel.soso/fs.c530
1 files changed, 530 insertions, 0 deletions
diff --git a/tools/iso/kernel.soso/fs.c b/tools/iso/kernel.soso/fs.c
new file mode 100644
index 00000000..0d072c33
--- /dev/null
+++ b/tools/iso/kernel.soso/fs.c
@@ -0,0 +1,530 @@
+#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);
+}