tar_file_read

This commit is contained in:
2026-04-09 16:08:19 +02:00
parent f91831616c
commit 17589d72cf
13 changed files with 278 additions and 15 deletions
+1
View File
@@ -14,3 +14,4 @@ symbols.S
build/
compile_commands.json
.cache/
*.tar
+9 -4
View File
@@ -43,14 +43,13 @@ limine/limine:
git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1
$(MAKE) -C limine
build-iso: limine/limine $(ELFFILE)
build-iso: limine/limine $(ELFFILE) initfs
rm -rf iso_root
mkdir -p iso_root/boot
cp -v $(ELFFILE) iso_root/boot
mkdir -p iso_root/boot/limine
cp -v limine.conf iso_root/boot/limine
cp $(BUILDDIR)/hello iso_root/boot/
cp $(BUILDDIR)/pedicel iso_root/boot/
cp calyx.tar iso_root/boot/
mkdir -p iso_root/EFI/BOOT
cp -v limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/
cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/
@@ -62,6 +61,12 @@ build-iso: limine/limine $(ELFFILE)
iso_root -o pepper.iso
./limine/limine bios-install pepper.iso
.PHONY: initfs
initfs:
cp $(BUILDDIR)/hello calyx/
cp $(BUILDDIR)/pedicel calyx/
tar cvf calyx.tar -C ./calyx .
.PHONY: debug
debug:
/usr/bin/qemu-system-x86_64 -drive file=pepper.iso -s -S -d int -D qemu.log -no-reboot -no-shutdown &
@@ -78,4 +83,4 @@ run: build-iso
.PHONY: clean
clean:
rm -rf $(BUILDDIR) symbols.map symbols.S $(ELFFILE) iso_root pepper.iso limine
rm -rf $(BUILDDIR) symbols.map symbols.S $(ELFFILE) iso_root pepper.iso limine calyx.tar
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
Welcome to the initial filesystem!
+3
View File
@@ -45,6 +45,9 @@
#define USER_STACK_PAGES 16 // 16*4096 = 64kb
#define USER_CODE_START 0x400000 // like linux
/* fs */
#define CALYXFS_FILES_MAX 10
/* paging */
#define PAGING_MAX_PHYS 0x200000000
+36
View File
@@ -0,0 +1,36 @@
/*
* @author xamidev <xamidev@riseup.net>
* @brief Tape archive (TAR) filesystem definitions
* @license GPL-3.0-only
*/
#ifndef TAR_H
#define TAR_H
#include <stdint.h>
#include <limine.h>
struct tar_header
{
char filename[100];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char typeflag[1];
};
struct tar_file
{
void* address;
uint64_t size;
};
unsigned int tar_parse(uint64_t address);
int tar_init_fs(struct limine_file* file);
struct tar_header* tar_file_lookup(const char* filename);
void tar_file_read(struct tar_header* header, uint8_t* buf);
#endif
+1
View File
@@ -13,5 +13,6 @@ char *strcpy(char *dest, const char *src);
char *strcat(char *dest, const char *src);
void strncpy(char* dst, const char* src, size_t n);
int strncmp(const char* s1, const char* s2, size_t n);
size_t strlen(const char *str);
#endif
+1 -2
View File
@@ -6,5 +6,4 @@ interface_branding: Welcome to the PepperOS disk!
comment: Default configuration (warning: spicy)
path: boot():/boot/pepperk
module_path: boot():/boot/hello
module_path: boot():/boot/pedicel
module_path: boot():/boot/calyx.tar
+182
View File
@@ -0,0 +1,182 @@
/*
* @author xamidev <xamidev@riseup.net>
* @brief Tape archive (TAR) initial filesystem routines
* @license GPL-3.0-only
*/
/*
TODO:
implement open, read, write, close for tar
eventually seek, stat, etc. would be nice to handle some more syscalls
*/
#include <fs/tar.h>
#include <config.h>
#include <stdint.h>
#include <kernel.h>
#include <stddef.h>
#include <string/string.h>
#include <mem/kheap.h>
#include <mem/utils.h>
#include <limine.h>
struct tar_header* headers[CALYXFS_FILES_MAX] = {0};
struct tar_file archive;
#define TAR_BLOCK_SIZE 512
// To get file content, just use file_offset[file]+header_size
// uint64_t file_offsets[CALYXFS_FILES_MAX] = {0};
/*
* tar_getsize - Get the size of a file contained in a tar archive
* @in: size attribute of a tar header
*
* Return:
* <size> - Size of file in bytes
*/
unsigned int tar_getsize(const char *in)
{
unsigned int size = 0;
unsigned int count = 1;
for (unsigned int j = 11; j > 0; j--, count *= 8) {
size += ((in[j - 1] - '0') * count);
}
return size;
}
/*
* tar_parse - Parse a TAR file
* @address: address of TAR file start in memory
*
* This function goes through all headers in a TAR file
* and populates the header array so we can work with
* the files contained in the archive.
*
* Return:
* <i> - number of files parsed/found
*/
unsigned int tar_parse(uint64_t address)
{
unsigned int i;
for (i = 0; i < CALYXFS_FILES_MAX; i++) {
struct tar_header *header = (struct tar_header*)address;
if (header->filename[0] == '\0') {
break;
}
unsigned int size = tar_getsize(header->size);
headers[i] = header;
DEBUG("found file %s of size %u", header->filename, size);
uint64_t file_blocks = (size + TAR_BLOCK_SIZE - 1) / TAR_BLOCK_SIZE;
address += TAR_BLOCK_SIZE + (file_blocks * TAR_BLOCK_SIZE);
}
return i;
}
/*
* tar_init_fs - Initialize the TAR filesystem
* @file: pointer to Limine file structure (corresponding
* to the loaded boot module)
*
* This function initializes the tar_file object
* to the values of the found TAR archive, namely
* its address and its size.
*
* It then parses the archive using tar_parse,
* so it can be looked up later.
*
* Return:
* %0 - on success
*/
int tar_init_fs(struct limine_file* file)
{
DEBUG("calyxfs found at 0x%p (size=%u)", file->address, file->size);
archive.address = file->address;
archive.size = file->size;
tar_parse((uint64_t)archive.address);
return 0;
}
/*
* tar_is_zeroed - Checks if a TAR header is zero
* @header: pointer to TAR header
*
* Return:
* True - TAR header is zeroed out
* False - TAR header contains something
*/
bool tar_is_zeroed(struct tar_header* header)
{
struct tar_header zeroed = {0};
return memcmp(header, &zeroed, sizeof(struct tar_header)) == 0;
}
/*
* tar_file_lookup - Find a file
*
* This functions looks up the @filename in the tar
* archive.
*
* Return:
* <addr> - Address of TAR header for the found file
* %0 - file not found
*/
struct tar_header* tar_file_lookup(const char* filename)
{
if (!filename || !archive.address) {
return 0;
}
int zero_counter = 0;
struct tar_header* curr = archive.address;
while (zero_counter < 2) {
if (tar_is_zeroed(curr)) {
zero_counter++;
curr = (struct tar_header*)((uint8_t*)curr + TAR_BLOCK_SIZE);
continue;
}
zero_counter = 0;
if (strncmp(filename, curr->filename, sizeof(curr->filename)) == 0) {
DEBUG("found file %s", filename);
return curr;
}
uint64_t sz = tar_getsize(curr->size);
uint64_t file_blocks = (sz + TAR_BLOCK_SIZE - 1) / TAR_BLOCK_SIZE;
curr = (struct tar_header*)((uint8_t*)curr + TAR_BLOCK_SIZE + (file_blocks * TAR_BLOCK_SIZE));
}
return 0;
}
/*
* tar_file_read - Read a file contained in TAR archive
* @header: Header of given file
* @buf: data out buffer
*
* This function reads the file, using its @header, to
* the @buf buffer. It needs to be big enough to contain
* the file, or else a buffer overrun might happen.
*/
void tar_file_read(struct tar_header* header, uint8_t* buf)
{
if (!header || !buf) {
return;
}
uint32_t sz = tar_getsize(header->size);
void* file_ptr = (void*)((uint8_t*)header + TAR_BLOCK_SIZE);
memcpy(buf, (void*)file_ptr, sz);
}
+16
View File
@@ -0,0 +1,16 @@
/*
* @author xamidev <xamidev@riseup.net>
* @brief Virtual filesystem (VFS) layer
* @license GPL-3.0-only
*/
/*
Around here we'll want to have some file operations struct with
function pointers (read, write, open, close) for different filesystems.
At init, the function pointers will be assigned to the corresponding
filesystem-dependent functions.
That way we have a nice abstraction layer and can just do calls no matter
the underlying fs.
*/
+13 -8
View File
@@ -25,6 +25,7 @@
#include <io/term/flanterm_backends/fb.h>
#include <arch/x86.h>
#include <boot/boot.h>
#include <fs/tar.h>
// Limine version used
__attribute__((used, section(".limine_requests")))
@@ -120,16 +121,20 @@ void kmain()
idle_proc = process_create("idle", (void*)idle_main, 0);
if (!boot_ctx.module) {
panic(NULL, "could not load 'hello' executable :(");
panic(NULL, "could not load calyx filesystem!");
}
if (boot_ctx.module->module_count == 2) {
file = boot_ctx.module->modules[0];
DEBUG("file: addr=%p size=%u", file->address, file->size);
process_create_user(file, "hello");
file = boot_ctx.module->modules[1];
process_create_user(file, "pedicel");
}
file = boot_ctx.module->modules[0];
tar_init_fs(file);
/* DANGER ZONE (tests)*/
struct tar_header* header = tar_file_lookup("./welcome.txt");
uint8_t buf[1000] = {0};
tar_file_read(header, buf);
DEBUG("-BEGIN BUFFER-%s-END BUFFER-", buf);
/* END DANGER ZONE */
scheduler_init();
printf(PEPPEROS_SPLASH);
+14
View File
@@ -99,3 +99,17 @@ int strncmp(const char* s1, const char* s2, size_t n)
return ( *(unsigned char *)s1 - *(unsigned char *)s2 );
}
}
/*
* strlen - Get a string's length (BSD implementation)
* @str: null-terminated string
*
* Return:
* <size> - length of the string in bytes
*/
size_t strlen(const char *str)
{
const char *s;
for (s = str; *s; ++s);
return (s - str);
}