feature (virtual file system): implemented USTAR-archive unpacking and using this for the initrd archive as part of the VFS initialization.

This commit is contained in:
antifallobst 2023-02-27 22:50:05 +01:00
parent 8bcf895726
commit 0de9f843ba
4 changed files with 145 additions and 38 deletions

View File

@ -0,0 +1,58 @@
/*
* Copyright 2023 Antifallobst <antifallobst@systemausfall.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the Software), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef NOX_USTAR_H
#define NOX_USTAR_H
#include "utils/stdtypes.h"
typedef enum {
USTAR_FILE,
USTAR_LINK_HARD,
USTAR_LINK_SYM,
USTAR_CHAR_DEVICE,
USTAR_BLOCK_DEVICE,
USTAR_DIRECTORY,
USTAR_PIPE
} ustar_type_E;
typedef struct {
char name [100];
uint64_t mode;
uint64_t owner_id;
uint64_t group_id;
char size [12]; // octal based string (don't ask me why, the ustar standard is weird)
char last_modification [12]; // unix timestamp (octal)
uint64_t checksum;
uint8_t type;
char name_linked [100];
char indicator [6];
uint16_t version;
char owner_user_name [32];
char owner_group_name [32];
uint64_t device_major;
uint64_t device_minor;
char name_prefix [155];
}__attribute__((packed)) __attribute__((aligned(512))) ustar_header_T;
#endif //NOX_USTAR_H

View File

@ -88,8 +88,11 @@ void vfs_file_delete (vfs_node_T* file);
void vfs_file_write (vfs_node_T* file, uint64_t position, uint64_t size, uint8_t* buffer_in); void vfs_file_write (vfs_node_T* file, uint64_t position, uint64_t size, uint8_t* buffer_in);
void vfs_file_read (vfs_node_T* file, uint64_t position, uint64_t size, uint8_t* buffer_out); void vfs_file_read (vfs_node_T* file, uint64_t position, uint64_t size, uint8_t* buffer_out);
vfs_node_T* vfs_directory_create (fs_T* filesystem, string_t path);
void vfs_directory_delete (vfs_node_T* directory);
void vfs_init (boot_info_T* boot_info); void vfs_init (boot_info_T* boot_info);
vfs_node_T* vfs_resolve_path (fs_T* filesystem, string_t path); vfs_node_T* vfs_resolve_path (fs_T* filesystem, string_t path);
void vfs_unpack_archive_ustar (vfs_node_T* node, void* archive); void vfs_unpack_archive_ustar (fs_T* filesystem, void* archive);
#endif //NOX_VFS_H #endif //NOX_VFS_H

View File

@ -23,10 +23,13 @@
#include "drivers/fs/vfs.h" #include "drivers/fs/vfs.h"
#include "drivers/fs/ramfs.h" #include "drivers/fs/ramfs.h"
#include "drivers/fs/ustar.h"
#include "utils/memory.h" #include "utils/memory.h"
#include "utils/logger.h" #include "utils/logger.h"
#include "utils/math.h"
fs_T g_root_fs; fs_T g_root_fs;
fs_T g_ramdisk_fs;
string_t g_fs_names[FS_ENUM_END] = { string_t g_fs_names[FS_ENUM_END] = {
"RAMFS" "RAMFS"
@ -146,6 +149,8 @@ void vfs_node_dump_info(vfs_node_T* node, uint64_t indent) {
} }
case VFS_NODE_MOUNT: { case VFS_NODE_MOUNT: {
log(LOG_NONE, "%s[mount] %s -> %s", buf, node->name, g_fs_names[((fs_T*)node->specific)->type]); log(LOG_NONE, "%s[mount] %s -> %s", buf, node->name, g_fs_names[((fs_T*)node->specific)->type]);
vfs_node_dump_info(((fs_T*)node->specific)->root_node, indent+6);
break;
} }
} }
} }
@ -202,8 +207,6 @@ vfs_node_T* vfs_file_create(fs_T* filesystem, string_t path) {
} }
vfs_node_T* file = vfs_node_create(dir_node, &path[index], VFS_NODE_FILE, NULL); vfs_node_T* file = vfs_node_create(dir_node, &path[index], VFS_NODE_FILE, NULL);
log(LOG_DEBUG, "<VFS> created file %s", &path[index]);
switch (file->filesystem->type) { switch (file->filesystem->type) {
default: { default: {
break; break;
@ -249,14 +252,47 @@ void vfs_file_read(vfs_node_T* file, uint64_t position, uint64_t size, uint8_t*
} }
} }
vfs_node_T* vfs_directory_create(fs_T* filesystem, string_t path) {
// everything before index is the path and everything behind index is the name of the dir that will be created
uint64_t index = string_find_last(path, '/') + 1;
char dir_path[index];
memory_copy(path, dir_path, index); dir_path[index] = '\0';
vfs_node_T* dir_node = vfs_resolve_path(filesystem, dir_path);
if (dir_node == NULL) {
log(LOG_WARNING, "<VFS> failed to create directory %s (invalid path)", path);
return NULL;
}
vfs_node_T* dir = vfs_node_create(dir_node, &path[index], VFS_NODE_DIRECTORY, NULL);
switch (dir->filesystem->type) {
default: {
break;
}
}
return dir;
}
void vfs_directory_delete(vfs_node_T* directory) {
}
void vfs_init(boot_info_T* boot_info) { void vfs_init(boot_info_T* boot_info) {
g_root_fs.type = FS_RAMFS; g_root_fs.type = FS_RAMFS;
g_root_fs.root_node = vfs_node_create(NULL, "root", VFS_NODE_DIRECTORY, NULL); g_root_fs.root_node = vfs_node_create(NULL, "root", VFS_NODE_DIRECTORY, NULL);
g_root_fs.root_node->filesystem = &g_root_fs; g_root_fs.root_node->filesystem = &g_root_fs;
g_ramdisk_fs.type = FS_RAMFS;
g_ramdisk_fs.root_node = vfs_node_create(NULL, "root", VFS_NODE_DIRECTORY, NULL);
g_ramdisk_fs.root_node->filesystem = &g_ramdisk_fs;
// unpacking initial ramdisk to '/initrd/'
vfs_node_create(g_root_fs.root_node, "initrd", VFS_NODE_MOUNT, &g_ramdisk_fs);
vfs_unpack_archive_ustar(&g_ramdisk_fs, boot_info->ramdisk_file->address);
} }
vfs_node_T* vfs_resolve_path(fs_T* filesystem, string_t path) { vfs_node_T* vfs_resolve_path(fs_T* filesystem, string_t path) {
log(LOG_DEBUG, "<VFS> resolving path: %s", path);
if (*path != '/') { if (*path != '/') {
log(LOG_WARNING, "<VFS> failed to resolve node from invalid path '%s' (no root prefix)", path); log(LOG_WARNING, "<VFS> failed to resolve node from invalid path '%s' (no root prefix)", path);
return NULL; return NULL;
@ -283,28 +319,51 @@ vfs_node_T* vfs_resolve_path(fs_T* filesystem, string_t path) {
switch (node->type) { switch (node->type) {
case VFS_NODE_DIRECTORY: { case VFS_NODE_DIRECTORY: {
path++; path++; // remove the '/'
log(LOG_DEBUG, "<VFS> Node '%s' is a directory", node->name);
break;
}
case VFS_NODE_FILE: {
log(LOG_DEBUG, "<VFS> Node '%s' is a file", node->name);
break;
}
case VFS_NODE_BLOCK_DEVICE: {
log(LOG_DEBUG, "<VFS> Node '%s' is a block device", node->name);
break; break;
} }
case VFS_NODE_MOUNT: { case VFS_NODE_MOUNT: {
log(LOG_DEBUG, "<VFS> Node '%s' is a mount point to a %s filesystem", node->name, g_fs_names[((fs_T*)node->specific)->type]);
return vfs_resolve_path(node->specific, path); return vfs_resolve_path(node->specific, path);
} }
default: {
break;
}
} }
} }
return node; return node;
} }
void vfs_unpack_archive_ustar(vfs_node_T* node, void* archive) { void vfs_unpack_archive_ustar(fs_T* filesystem , void* archive) {
// skip the first header, that specifies the root directory
ustar_header_T* header = archive + sizeof(ustar_header_T);
log(LOG_INFO, "<VFS> unpacking initrd");
while (memory_compare(header->indicator, "ustar", 5)) {
uint64_t size = octal_string_to_int(header->size, 11);
uint32_t blocks = 1 + (size > 0 ? (size / 512) + 1 : 0);
if (header->type > 0) {
header->type -= '0';
}
log(LOG_INFO, " extracting: %s", header->name);
switch (header->type) {
case USTAR_FILE: {
vfs_node_T* file = vfs_file_create(filesystem, &header->name[1]);
vfs_file_write(file, 0, size, (uint8_t*)&header[1]);
break;
}
case USTAR_DIRECTORY: {
// get rid of the '/' at the end
header->name[string_length(header->name)-1] = '\0';
vfs_directory_create(filesystem, &header->name[1]);
break;
}
}
header = &header[blocks];
}
} }

View File

@ -89,26 +89,13 @@ void kmain(boot_info_T boot_info) {
limine_terminal_print(&boot_info, "Kernel initialized\n"); limine_terminal_print(&boot_info, "Kernel initialized\n");
log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n"); log(LOG_INFO, "!=====[ Kernel Initialized ]=====!\n");
// for (int i = 0; i < 150; i++) {
// log(LOG_DEBUG, "test log %d", i);
// }
vfs_node_T* node_temp = vfs_node_create(g_root_fs.root_node, "temp", VFS_NODE_DIRECTORY, NULL);
vfs_node_T* node_system = vfs_node_create(g_root_fs.root_node, "system", VFS_NODE_DIRECTORY, NULL);
vfs_node_T* node_test = vfs_file_create(&g_root_fs, "/system/test.txt");
char buffer[16] = "...............";
vfs_file_read(node_test, 0, 16, buffer);
log(LOG_DEBUG, "Buffer: \"%s\"", buffer);
vfs_file_write(node_test, 0, 4, "test");
log(LOG_DEBUG, "Writing data");
vfs_file_read(node_test, 0, 16, buffer);
log(LOG_DEBUG, "Buffer: \"%s\"", buffer);
vfs_node_dump_info(g_root_fs.root_node, 0); vfs_node_dump_info(g_root_fs.root_node, 0);
char buffer [129]; buffer[128] = 0;
vfs_file_read(vfs_resolve_path(&g_root_fs, "/initrd/test.txt"), 0, 128, (uint8_t*)buffer);
log(LOG_DEBUG, "Reading 128 bytes from '/initrd/test.txt':\n%s", buffer);
CORE_HALT_FOREVER CORE_HALT_FOREVER
} }