bootstrap: tar: implement readdir()

This commit is contained in:
2026-03-24 12:44:33 +00:00
parent d2df4259e6
commit 20723d4dff

View File

@@ -11,6 +11,7 @@
#include <mango/vm.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <xpc/buffer.h>
struct tar_superblock {
@@ -148,6 +149,24 @@ static struct tar_entry *entry_get_child(
return NULL;
}
static struct tar_entry *entry_get_child_at(struct tar_entry *entry, size_t at)
{
struct queue_entry *cur = queue_first(&entry->e_children);
while (cur) {
struct tar_entry *child
= QUEUE_CONTAINER(struct tar_entry, e_entry, cur);
if (at == 0) {
return child;
}
at--;
cur = queue_next(cur);
}
return NULL;
}
static const struct fs_dentry_ops dentry_ops = {};
static enum fs_status dir_lookup(
@@ -189,7 +208,7 @@ static enum fs_status file_read(
char *src = (char *)entry->e_data + offset;
size_t w;
xpc_buffer_write(buf, src, count, &w);
xpc_buffer_write(buf, 0, src, count, &w);
offset += w;
*seek = offset;
@@ -197,10 +216,66 @@ static enum fs_status file_read(
return FS_SUCCESS;
}
static enum fs_status dir_readdir(
struct fs_file *f,
xpc_buffer_t *out,
off_t *seek)
{
off_t offset = *seek;
struct tar_entry *entry = entry_from_inode(fs_file_get_inode(f));
if (!entry) {
return FS_ERR_BAD_STATE;
}
size_t bytes_written = 0;
size_t available = xpc_buffer_capacity(out);
while (1) {
struct tar_entry *child = entry_get_child_at(entry, offset);
if (!child) {
break;
}
struct dentry dent = {0};
size_t name_len = strlen(child->e_dentry.d_name);
size_t to_write
= offsetof(struct dentry, d_name) + name_len + 1;
if (to_write > available) {
break;
}
dent.d_reclen = to_write;
kern_iovec_t iov[] = {
IOVEC(&dent, offsetof(struct dentry, d_name)),
IOVEC(child->e_dentry.d_name, name_len + 1),
};
size_t tmp = 0;
kern_status_t status
= xpc_buffer_writev(out, bytes_written, iov, 2, &tmp);
if (status != KERN_OK) {
break;
}
bytes_written += tmp;
available -= tmp;
offset++;
}
*seek = offset;
out->buf_len = bytes_written;
return FS_SUCCESS;
}
static const struct fs_file_ops file_ops = {
.f_read = file_read,
};
static const struct fs_file_ops dir_ops = {
.f_readdir = dir_readdir,
};
static const struct fs_inode_ops file_inode_ops = {
.i_lookup = NULL,
};
@@ -224,6 +299,7 @@ static struct tar_entry *create_dir_entry(
entry->e_inode.i_sb = &sb->sb_base;
entry->e_inode.i_mode = FS_INODE_DIR;
entry->e_inode.i_ops = &dir_inode_ops;
entry->e_inode.i_fops = &dir_ops;
entry->e_dentry.d_sb = &sb->sb_base;
entry->e_dentry.d_ops = &dentry_ops;