Fix readdir for ext2

This commit is contained in:
Mark
2019-12-30 04:06:16 +02:00
parent 3d807708cf
commit 689d0d9534
7 changed files with 78 additions and 5 deletions
+3
View File
@@ -2,6 +2,8 @@
#include "sys/types.h"
#include "sys/dev.h"
struct vfs_node;
struct blkdev {
void *dev_data;
struct dev_entry *ent;
@@ -15,6 +17,7 @@ struct blkdev {
ssize_t blk_read(struct blkdev *blk, void *buf, size_t off, size_t count);
ssize_t blk_write(struct blkdev *blk, const void *buf, size_t off, size_t count);
int blk_mount_auto(struct vfs_node *at, struct blkdev *blkdev, const char *opt);
struct blkdev *blk_by_name(const char *name);
int blk_enumerate_partitions(struct blkdev *blk);
+1
View File
@@ -91,6 +91,7 @@ void vfs_node_free(struct vfs_node *n);
*/
struct vfs_node *vfs_node_create(const char *name, vnode_t *vn);
int vfs_mount_internal(struct vfs_node *at, void *blkdev, const char *fs_name, const char *opt);
/**
* @brief Create a mountpoint in a filesystem tree so that
* a "source" directory actually refers to the root
+12
View File
@@ -6,6 +6,7 @@
#include "sys/debug.h"
#include "sys/heap.h"
#include "sys/spin.h"
#include "sys/fs/ext2.h"
#include "sys/fs/vfs.h"
#include "sys/fcntl.h"
#include "sys/errno.h"
@@ -50,6 +51,7 @@ void init_func(void *arg) {
struct ofile fd;
struct stat st;
int res;
ext2_class_init();
if (root_blk) {
if ((res = vfs_mount(&ioctx, "/", root_blk, "ustar", NULL)) != 0) {
@@ -61,6 +63,16 @@ void init_func(void *arg) {
panic("mount devfs: %s\n", kstrerror(res));
}
// Try to mount /dev/sda1 at /mnt (don't panic on failure, though)
struct blkdev *sda1_blk = blk_by_name("sda1");
if (sda1_blk) {
kinfo("Trying to mount /dev/sda1 -> /mnt\n");
if ((res = vfs_mount(&ioctx, "/mnt", sda1_blk, "auto", NULL)) != 0) {
kwarn("/dev/sda1: %s\n", kstrerror(res));
}
}
if ((res = vfs_stat(&ioctx, "/init", &st)) != 0) {
panic("/init: %s\n", kstrerror(res));
}
+14
View File
@@ -4,6 +4,10 @@
#include "sys/errno.h"
#include "sys/string.h"
#include "sys/heap.h"
#include "sys/fs/vfs.h"
// Taken as-is from MBR partition types
#define PART_HINT_LINUX 0x83
ssize_t blk_read(struct blkdev *blk, void *buf, size_t off, size_t lim) {
_assert(blk);
@@ -48,6 +52,16 @@ struct blk_part {
uint64_t lba_size;
};
int blk_mount_auto(struct vfs_node *at, struct blkdev *blk, const char *opt) {
int res;
if ((res = vfs_mount_internal(at, blk, "ext2", opt)) == 0) {
return 0;
}
return -1;
}
static ssize_t blk_part_read(struct blkdev *dev, void *buf, size_t off, size_t count) {
struct blk_part *part = (struct blk_part *) dev->dev_data;
size_t part_size_bytes = part->lba_size * 512;
+40 -3
View File
@@ -474,6 +474,7 @@ static int ext2_vnode_readdir(struct ofile *fd) {
vnode_t *vn = fd->vnode;
struct ext2_inode *inode = (struct ext2_inode *) vn->fs_data;
struct ext2_extsb *sb = vn->fs->fs_private;
ssize_t res;
if (fd->pos >= inode->size_lower) {
return -1;
@@ -482,8 +483,8 @@ static int ext2_vnode_readdir(struct ofile *fd) {
size_t block_number = fd->pos / sb->block_size;
char block_buffer[sb->block_size];
if (ext2_read_inode_block(vn->fs, inode, block_number, block_buffer) < 0) {
return -EIO;
if ((res = ext2_read_inode_block(vn->fs, inode, block_number, block_buffer)) < 0) {
return res;
}
size_t block_offset = fd->pos % sb->block_size;
@@ -501,7 +502,43 @@ static int ext2_vnode_readdir(struct ofile *fd) {
strncpy(vfsdir->d_name, ext2dir->name, ext2dir->name_len);
vfsdir->d_name[ext2dir->name_len] = 0;
vfsdir->d_reclen = ext2dir->len;
vfsdir->d_type = ext2dir->type_ind;
if (sb->required_features & 2 /* Directory entries contain type field */) {
switch (ext2dir->type_ind) {
case 1:
// Regular file
vfsdir->d_type = DT_REG;
break;
case 2:
// Directory
vfsdir->d_type = DT_DIR;
break;
// XXX: Don't know if I should have ANY devices in ext2, we have devfs for that
// kind of shit
case 0:
default:
vfsdir->d_type = DT_UNKNOWN;
break;
}
} else {
// Have to read each fucking inode to sort this mess out
struct ext2_inode ent_inode_buf;
if ((res = ext2_read_inode(vn->fs, &ent_inode_buf, ext2dir->ino)) < 0) {
return res;
}
switch (ent_inode_buf.type_perm & 0xF000) {
case EXT2_TYPE_REG:
vfsdir->d_type = DT_REG;
break;
case EXT2_TYPE_DIR:
vfsdir->d_type = DT_DIR;
break;
default:
vfsdir->d_type = DT_UNKNOWN;
break;
}
}
// Not implemented, I guess
vfsdir->d_off = 0;
+7 -1
View File
@@ -7,6 +7,7 @@
#include "sys/errno.h"
#include "sys/panic.h"
#include "sys/heap.h"
#include "sys/blk.h"
#include "sys/chr.h"
// #include <stddef.h>
@@ -393,10 +394,15 @@ void vfs_vnode_path(char *path, vnode_t *vn) {
path[0] = 0;
}
static int vfs_mount_internal(struct vfs_node *at, void *blkdev, const char *fs_name, const char *opt) {
int vfs_mount_internal(struct vfs_node *at, void *blkdev, const char *fs_name, const char *opt) {
struct fs_class *fs_class;
if (!strcmp(fs_name, "auto")) {
return blk_mount_auto(at, blkdev, opt);
}
if ((fs_class = fs_class_by_name(fs_name)) == NULL) {
kdebug("Unknown filesystem class: %s\n", fs_name);
return -EINVAL;
}
+1 -1
View File
@@ -46,7 +46,7 @@ mkdirs:
mkdir -p $(DIRS)
mkstage-etc:
mkdir -p $(STAGE)/dev
mkdir -p $(STAGE)/dev $(STAGE)/mnt
cp -r etc $(STAGE)
# Application building