Minimal working vfs refactor

This commit is contained in:
Mark
2020-01-10 15:37:54 +02:00
parent 7272b762c0
commit 2e795d2ebf
18 changed files with 582 additions and 640 deletions
+6 -5
View File
@@ -59,19 +59,20 @@ OBJS+=$(O)/sys/debug.o \
$(O)/sys/net/arp.o \
$(O)/sys/net/in.o \
$(O)/sys/net/netdev.o \
$(O)/sys/vfs/pseudo.o \
$(O)/sys/vfs/ext2/ext2.o \
$(O)/sys/vfs/ext2/ext2blk.o \
$(O)/sys/vfs/tar.o \
$(O)/sys/blk/ram.o \
$(O)/sys/reboot.o \
$(O)/sys/random.o
# $(O)/sys/vfs/pseudo.o \
# \
$(O)/sys/tty.o \
$(O)/sys/vfs/pty.o \
$(O)/sys/vfs/ext2/ext2alloc.o \
$(O)/sys/vfs/ext2/ext2blk.o \
$(O)/sys/vfs/ext2/ext2.o \
$(O)/sys/vfs/ext2/ext2dir.o \
$(O)/sys/vfs/ext2/ext2vnop.o \
$(O)/sys/vfs/tar.o \
$(O)/sys/blk/ram.o \
ifeq ($(VESA_ENABLE),1)
OBJS+=$(O)/sys/psf.o \
+21 -15
View File
@@ -1,12 +1,15 @@
#pragma once
#include "sys/types.h"
struct vnode;
// TODO: something like device name alias
// for example, /dev/root aliased to
// /dev/ramN or /dev/sdXN
enum dev_class {
DEV_CLASS_BLOCK,
DEV_CLASS_CHAR
DEV_CLASS_BLOCK = 1,
DEV_CLASS_CHAR = 2,
DEV_CLASS_ANY = 255
};
#define DEV_BLOCK_SDx 1
@@ -17,19 +20,22 @@ enum dev_class {
#define DEV_CHAR_TTY 1
struct dev_entry {
char dev_name[64];
int dev_add(enum dev_class cls, int subcls, void *dev, const char *name);
int dev_find(enum dev_class cls, const char *name, struct vnode **dev_node);
enum dev_class dev_class;
uint16_t dev_subclass;
uint16_t dev_number;
//struct dev_entry {
// char dev_name[64];
//
// enum dev_class dev_class;
// uint16_t dev_subclass;
// uint16_t dev_number;
//
// void *dev;
// struct dev_entry *cdr;
//};
void *dev;
struct dev_entry *cdr;
};
//struct dev_entry *dev_iter(void);
struct dev_entry *dev_iter(void);
int dev_alloc_name(enum dev_class cls, uint16_t subclass, char *name);
int dev_by_name(struct dev_entry **ent, const char *name);
void dev_entry_add(struct dev_entry *ent);
//int dev_alloc_name(enum dev_class cls, uint16_t subclass, char *name);
//int dev_by_name(struct dev_entry **ent, const char *name);
//void dev_entry_add(struct dev_entry *ent);
+15 -15
View File
@@ -124,24 +124,24 @@ void ext2_class_init(void);
enum vnode_type ext2_inode_type(struct ext2_inode *i);
// Implemented in ext2blk.c
int ext2_write_superblock(fs_t *ext2);
int ext2_read_block(fs_t *ext2, uint32_t block_no, void *buf);
int ext2_write_block(fs_t *ext2, uint32_t block_no, const void *buf);
int ext2_read_inode_block(fs_t *ext2, struct ext2_inode *inode, uint32_t index, void *buf);
int ext2_write_inode_block(fs_t *ext2, struct ext2_inode *inode, uint32_t index, const void *buf);
int ext2_read_inode(fs_t *ext2, struct ext2_inode *inode, uint32_t ino);
int ext2_write_inode(fs_t *ext2, const struct ext2_inode *inode, uint32_t ino);
int ext2_write_superblock(struct fs *ext2);
int ext2_read_block(struct fs *ext2, uint32_t block_no, void *buf);
int ext2_write_block(struct fs *ext2, uint32_t block_no, const void *buf);
int ext2_read_inode_block(struct fs *ext2, struct ext2_inode *inode, uint32_t index, void *buf);
int ext2_write_inode_block(struct fs *ext2, struct ext2_inode *inode, uint32_t index, const void *buf);
int ext2_read_inode(struct fs *ext2, struct ext2_inode *inode, uint32_t ino);
int ext2_write_inode(struct fs *ext2, const struct ext2_inode *inode, uint32_t ino);
// Implemented in ext2alloc.c
int ext2_alloc_block(fs_t *ext2, uint32_t *block_no);
int ext2_free_block(fs_t *ext2, uint32_t block_no);
int ext2_inode_alloc_block(fs_t *ext2, struct ext2_inode *inode, uint32_t ino, uint32_t index);
int ext2_free_inode_block(fs_t *ext2, struct ext2_inode *inode, uint32_t ino, uint32_t index);
int ext2_free_inode(fs_t *ext2, uint32_t ino);
int ext2_alloc_inode(fs_t *ext2, uint32_t *ino);
int ext2_alloc_block(struct fs *ext2, uint32_t *block_no);
int ext2_free_block(struct fs *ext2, uint32_t block_no);
int ext2_inode_alloc_block(struct fs *ext2, struct ext2_inode *inode, uint32_t ino, uint32_t index);
int ext2_free_inode_block(struct fs *ext2, struct ext2_inode *inode, uint32_t ino, uint32_t index);
int ext2_free_inode(struct fs *ext2, uint32_t ino);
int ext2_alloc_inode(struct fs *ext2, uint32_t *ino);
// Implemented in ext2dir.c
int ext2_dir_add_inode(fs_t *ext2, struct vnode *dir, const char *name, uint32_t ino);
int ext2_dir_remove_inode(fs_t *ext2, struct vnode *dir, const char *name, uint32_t ino);
int ext2_dir_add_inode(struct fs *ext2, struct vnode *dir, const char *name, uint32_t ino);
int ext2_dir_remove_inode(struct fs *ext2, struct vnode *dir, const char *name, uint32_t ino);
extern struct vnode_operations ext2_vnode_ops;
+4 -7
View File
@@ -3,15 +3,15 @@
#include "sys/blk.h"
struct statvfs;
struct vfs_node;
struct fs_class {
char name[64];
int opt;
struct vnode *(*get_root) (fs_t *fs);
int (*mount) (struct fs *fs, const char *opt);
struct vnode *(*get_root) (struct fs *fs);
int (*init) (struct fs *fs, const char *opt);
int (*mount) (struct fs *fs);
int (*umount) (struct fs *fs);
int (*statvfs) (struct fs *fs, struct statvfs *st);
};
@@ -19,9 +19,6 @@ struct fs_class {
// The actual filesystem instance,
// one per each mount
struct fs {
// Mount details here
struct vnode *mnt_at;
// Block device on which the filesystem resides
struct blkdev *blk;
@@ -31,7 +28,7 @@ struct fs {
struct fs_class *cls;
};
struct fs *fs_create(struct fs_class *cls, struct blkdev *blk, struct vnode *mnt_at);
struct fs *fs_create(struct fs_class *cls, struct blkdev *blk);
void fs_release(struct fs *fs);
struct fs_class *fs_class_by_name(const char *name);
int fs_class_register(struct fs_class *cls);
+26 -29
View File
@@ -10,62 +10,48 @@
#define NODE_MAXLEN 256
// Means the node has no physical storage and resides only
// in memory
#define VN_MEMORY (1 << 0)
struct ofile;
struct vfs_ioctx;
struct vnode;
typedef struct fs fs_t;
struct fs;
enum vnode_type {
VN_REG,
VN_DIR,
VN_BLK,
VN_CHR,
// VN_LNK
VN_UNK,
};
struct vnode_operations {
// File tree traversal, node instance operations
int (*find) (struct vnode *node, const char *path, struct vnode **res);
void (*destroy) (struct vnode *node);
// Symlink
// int (*readlink) (struct vnode *node, char *path);
// int (*symlink) (struct vnode *at, struct vfs_ioctx *ctx, const char *name, const char *dst);
// File entry operations
int (*access) (struct vnode *node, uid_t *uid, gid_t *gid, mode_t *mode);
int (*creat) (struct vnode *node, struct vfs_ioctx *ctx, const char *name, mode_t mode, int opt, struct vnode **res);
int (*mkdir) (struct vnode *at, const char *name, mode_t mode);
int (*unlink) (struct vnode *at, struct vnode *vn, const char *name);
int (*stat) (struct vnode *node, struct stat *st);
int (*chmod) (struct vnode *node, mode_t mode);
int (*chown) (struct vnode *node, uid_t uid, gid_t gid);
// Directory access
int (*opendir) (struct vnode *node, int opt);
int (*readdir) (struct ofile *fd);
// File access
int (*open) (struct vnode *node, int opt);
int (*open) (struct ofile *fd);
void (*close) (struct ofile *fd);
ssize_t (*read) (struct ofile *fd, void *buf, size_t count);
ssize_t (*write) (struct ofile *fd, const void *buf, size_t count);
int (*truncate) (struct ofile *fd, size_t length);
};
struct vnode {
enum vnode_type type;
char name[NODE_MAXLEN];
uint32_t flags;
struct vnode *first_child;
struct vnode *next_child;
struct vnode *parent;
uint32_t refcount;
uint32_t open_count;
uint64_t ino;
fs_t *fs;
gid_t gid;
uid_t uid;
struct fs *fs;
void *fs_data;
/*
* (struct blkdev *) if type == VN_BLK
@@ -76,4 +62,15 @@ struct vnode {
struct vnode_operations *op;
};
struct vnode *vnode_create(const char *name);
// Node itself
struct vnode *vnode_create(enum vnode_type t, const char *name);
// Tree manipulation
void vnode_attach(struct vnode *parent, struct vnode *child);
void vnode_detach(struct vnode *node);
// Tree traversal
void vnode_dump_tree(int level, struct vnode *node, int depth);
int vnode_lookup_child(struct vnode *of, const char *name, struct vnode **child);
int vnode_lookup_tree(struct vnode *at, const char *rel_path, struct vnode **child);
+24 -15
View File
@@ -62,26 +62,35 @@ static ssize_t ahci_blk_write(struct blkdev *blk, const void *buf, size_t off, s
}
static int ahci_add_port_dev(struct ahci_port_registers *port) {
void *buf = kmalloc(sizeof(struct blkdev) + sizeof(struct dev_entry));
struct dev_entry *ent = (struct dev_entry *) buf;
struct blkdev *blk = (struct blkdev *) ((uintptr_t) buf + sizeof(struct dev_entry));
_assert(ent);
// Create a new device
// XXX: Replace kmalloc with dev_blk_create
struct blkdev *blk = kmalloc(sizeof(struct blkdev));
blk->dev_data = port;
blk->read = ahci_blk_read;
blk->write = ahci_blk_write;
ent->dev = blk;
ent->dev_class = DEV_CLASS_BLOCK;
ent->dev_subclass = DEV_BLOCK_SDx;
if (dev_alloc_name(ent->dev_class, ent->dev_subclass, ent->dev_name) != 0) {
return -1;
}
dev_entry_add(ent);
return 0;
return dev_add(DEV_CLASS_BLOCK, DEV_BLOCK_SDx, blk, NULL);
}
// //void *buf = kmalloc(sizeof(struct blkdev) + sizeof(struct dev_entry));
// //struct dev_entry *ent = (struct dev_entry *) buf;
// //struct blkdev *blk = (struct blkdev *) ((uintptr_t) buf + sizeof(struct dev_entry));
// //_assert(ent);
//
// //blk->dev_data = port;
// //blk->read = ahci_blk_read;
// //blk->write = ahci_blk_write;
//
// //ent->dev = blk;
// //ent->dev_class = DEV_CLASS_BLOCK;
// //ent->dev_subclass = DEV_BLOCK_SDx;
// //if (dev_alloc_name(ent->dev_class, ent->dev_subclass, ent->dev_name) != 0) {
// // return -1;
// //}
//
// //dev_entry_add(ent);
//
// return 0;
//}
uint32_t ahci_irq(void *ctx) {
struct ahci_registers *controller = ctx;
+28 -28
View File
@@ -287,39 +287,39 @@ int ide_ata_read_pio(struct ide_device *dev, void *buf, size_t nsect, uint64_t l
return 0;
}
static ssize_t ide_blk_read(struct blkdev *blk, void *buf, size_t off, size_t count) {
_assert(blk && blk->dev_data);
_assert(!(off & 511));
_assert(!(count & 511));
size_t nsect = count / 512;
size_t lba = off / 512;
// XXX: DMA fucks up for some reason, investigate that
ide_ata_read_pio((struct ide_device *) blk->dev_data, buf, nsect, lba);
return count;
}
//static ssize_t ide_blk_read(struct blkdev *blk, void *buf, size_t off, size_t count) {
// _assert(blk && blk->dev_data);
// _assert(!(off & 511));
// _assert(!(count & 511));
//
// size_t nsect = count / 512;
// size_t lba = off / 512;
//
// // XXX: DMA fucks up for some reason, investigate that
// ide_ata_read_pio((struct ide_device *) blk->dev_data, buf, nsect, lba);
//
// return count;
//}
static int ide_add_ata_dev(struct ide_device *dev) {
void *buf = kmalloc(sizeof(struct blkdev) + sizeof(struct dev_entry));
struct dev_entry *ent = (struct dev_entry *) buf;
struct blkdev *blk = (struct blkdev *) ((uintptr_t) buf + sizeof(struct dev_entry));
_assert(ent);
//void *buf = kmalloc(sizeof(struct blkdev) + sizeof(struct dev_entry));
//struct dev_entry *ent = (struct dev_entry *) buf;
//struct blkdev *blk = (struct blkdev *) ((uintptr_t) buf + sizeof(struct dev_entry));
//_assert(ent);
blk->dev_data = dev;
blk->write = NULL;
blk->read = ide_blk_read;
//blk->write = ahci_blk_write;
//blk->dev_data = dev;
//blk->write = NULL;
//blk->read = ide_blk_read;
////blk->write = ahci_blk_write;
ent->dev = blk;
ent->dev_class = DEV_CLASS_BLOCK;
ent->dev_subclass = DEV_BLOCK_HDx;
if (dev_alloc_name(ent->dev_class, ent->dev_subclass, ent->dev_name) != 0) {
return -1;
}
//ent->dev = blk;
//ent->dev_class = DEV_CLASS_BLOCK;
//ent->dev_subclass = DEV_BLOCK_HDx;
//if (dev_alloc_name(ent->dev_class, ent->dev_subclass, ent->dev_name) != 0) {
// return -1;
//}
dev_entry_add(ent);
//dev_entry_add(ent);
return 0;
}
+5 -2
View File
@@ -50,6 +50,9 @@ void kernel_main(struct amd64_loader_data *data) {
amd64_gdt_init();
amd64_idt_init();
amd64_mm_init(data);
// XXX: HEAP IS ONLY AVAILABLE AT THIS POINT
extern void pseudo_init();
pseudo_init();
amd64_acpi_init();
#if defined(VESA_ENABLE)
amd64_vesa_init(multiboot_info);
@@ -64,8 +67,8 @@ void kernel_main(struct amd64_loader_data *data) {
//tty_init();
if (data->initrd_ptr) {
// Create ram0 block device
//ramblk_init(MM_VIRTUALIZE(data->initrd_ptr), data->initrd_len);
//tarfs_init();
ramblk_init(MM_VIRTUALIZE(data->initrd_ptr), data->initrd_len);
tarfs_init();
}
// Initial random seed
+46 -2
View File
@@ -75,10 +75,54 @@ void init_func(void *arg) {
// Mount rootfs if available
//struct blkdev *root_blk = blk_by_name("ram0");
struct vfs_ioctx ioctx = {0};
struct ofile fd;
struct stat st;
int res;
//ext2_class_init();
ext2_class_init();
struct fs_class *tarfs_class = fs_class_by_name("ustar");
_assert(tarfs_class);
// Find _ramblk0
struct vnode *ramblk0;
if ((res = dev_find(DEV_CLASS_BLOCK, "ram0", &ramblk0)) != 0) {
panic("Failed to find root device\n");
}
kinfo("Found root device: %s\n", ramblk0->name);
// Create a filesystem instance at this device
struct fs *fs_instance = fs_create(tarfs_class, ramblk0->dev);
_assert(fs_instance);
// Get tarfs root node
struct vnode *root_node = tarfs_class->get_root(fs_instance);
_assert(root_node);
vnode_dump_tree(DEBUG_INFO, root_node, 0);
// Find some file in rootfs
struct vnode *etc_file_txt;
_assert(vnode_lookup_tree(root_node, "etc/file.txt", &etc_file_txt) == 0);
_assert(etc_file_txt);
// Open it
_assert(etc_file_txt->op);
_assert(etc_file_txt->op->read);
struct ofile fd = {
.vnode = etc_file_txt,
.pos = 0,
};
char buf[512];
ssize_t bread;
_assert((bread = etc_file_txt->op->read(&fd, buf, sizeof(buf))) > 0);
buf[bread] = 0;
kdebug("\n%s\n", buf);
kinfo("Done\n");
//if (root_blk) {
// if ((res = vfs_mount(&ioctx, "/", root_blk, "ustar", NULL)) != 0) {
-214
View File
@@ -28,217 +28,3 @@ ssize_t blk_write(struct blkdev *blk, const void *buf, size_t off, size_t lim) {
return -EINVAL;
}
}
const char GUID_EMPTY[16] = {0};
// TODO: guess this would better be in blk_part.c or something like that
struct mbr {
char bootstrap[440];
uint32_t uuid;
uint16_t opt;
struct mbr_entry {
uint8_t attr;
uint8_t chs_start[3];
uint8_t type;
uint8_t chs_end[3];
uint32_t lba_start;
uint32_t nsectors;
} __attribute__((packed)) entries[4];
uint16_t sign;
} __attribute__((packed));
struct gpt_header {
char signature[8];
uint32_t revision;
uint32_t header_size;
uint32_t header_crc32;
uint32_t __res0;
uint64_t my_lba;
uint64_t alt_lba;
uint64_t first_lba;
uint64_t last_lba;
char disk_guid[16];
uint64_t partition_entry_lba;
uint32_t partition_count;
uint32_t partition_entry_size;
uint32_t partition_array_crc32;
} __attribute__((packed));
struct gpt_part_entry {
char type_guid[16];
char part_guid[16];
uint64_t start_lba;
uint64_t end_lba;
uint64_t attr;
char part_name[72];
};
struct blk_part {
struct blkdev *device;
uint64_t lba_start;
uint64_t lba_size;
};
int blk_mount_auto(struct vnode *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_write(struct blkdev *dev, const 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;
size_t part_off_bytes = part->lba_start * 512;
if (off >= part_size_bytes) {
return -1;
}
size_t l = MIN(part_size_bytes - off, count);
return blk_write(part->device, buf, off + part_off_bytes, l);
}
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;
size_t part_off_bytes = part->lba_start * 512;
if (off >= part_size_bytes) {
return -1;
}
size_t l = MIN(part_size_bytes - off, count);
return blk_read(part->device, buf, off + part_off_bytes, l);
}
static int blk_enumerate_mbr(struct blkdev *dev, uint8_t *head) {
kdebug("Enumerating MBR partitions\n");
struct mbr *mbr = (struct mbr *) head;
for (size_t i = 0; i < 4; ++i) {
if (mbr->entries[i].chs_start[1] && mbr->entries[i].nsectors) {
kdebug("Partition %u: Start %u, End %u, %u Sectors (%S), Type 0x%02x\n",
i,
mbr->entries[i].lba_start,
mbr->entries[i].lba_start + mbr->entries[i].nsectors,
mbr->entries[i].nsectors,
mbr->entries[i].nsectors * 512,
mbr->entries[i].type);
struct blk_part *part = (struct blk_part *) kmalloc(sizeof(struct blk_part));
part->device = dev;
part->lba_start = mbr->entries[i].lba_start;
part->lba_size = mbr->entries[i].nsectors * 512;
void *buf = kmalloc(sizeof(struct blkdev) + sizeof(struct dev_entry));
struct dev_entry *ent = (struct dev_entry *) buf;
struct blkdev *blk = (struct blkdev *) ((uintptr_t) buf + sizeof(struct dev_entry));
_assert(ent);
blk->dev_data = part;
blk->read = blk_part_read;
blk->write = blk_part_write;
blk->ent_parent = dev->ent;
ent->dev = blk;
ent->dev_class = DEV_CLASS_BLOCK;
ent->dev_subclass = DEV_BLOCK_PART;
// XXX: This is ugly
strcpy(ent->dev_name, dev->ent->dev_name);
char digit[2] = { '1' + i, 0 };
strcat(ent->dev_name, digit);
dev_entry_add(ent);
}
}
return 0;
}
static int blk_enumerate_gpt(struct blkdev *dev, uint8_t *head) {
// LBA1 - GPT header
struct gpt_header *hdr = (struct gpt_header *) &head[512];
// Read a single block for partition table entries
char buf[512];
_assert(blk_read(dev, buf, hdr->partition_entry_lba * 512, 512) >= 0);
size_t offset = 0;
size_t part_n = 0;
for (size_t i = 0; i < hdr->partition_count; ++i) {
struct gpt_part_entry *ent = (struct gpt_part_entry *) &buf[offset];
if (strncmp(ent->type_guid, GUID_EMPTY, 16)) {
// Maybe some known filesystem here, ignore partition type guid
struct blk_part *part = (struct blk_part *) kmalloc(sizeof(struct blk_part));
part->device = dev;
part->lba_start = ent->start_lba;
part->lba_size = ent->end_lba - ent->start_lba;
void *buf = kmalloc(sizeof(struct blkdev) + sizeof(struct dev_entry));
struct dev_entry *ent = (struct dev_entry *) buf;
struct blkdev *blk = (struct blkdev *) ((uintptr_t) buf + sizeof(struct dev_entry));
_assert(ent);
blk->dev_data = part;
blk->read = blk_part_read;
blk->write = blk_part_write;
blk->ent_parent = dev->ent;
ent->dev = blk;
ent->dev_class = DEV_CLASS_BLOCK;
ent->dev_subclass = DEV_BLOCK_PART;
// XXX: This is ugly
strcpy(ent->dev_name, dev->ent->dev_name);
char digit[2] = { '1' + part_n++, 0 };
strcat(ent->dev_name, digit);
dev_entry_add(ent);
}
offset += hdr->partition_entry_size;
if (offset >= 512) {
break;
}
}
return 0;
}
//struct blkdev *blk_by_name(const char *name) {
// struct dev_entry *it = dev_iter();
//
// for (; it; it = it->cdr) {
// if (!strcmp(it->dev_name, name)) {
// return (struct blkdev *) it->dev;
// }
// }
//
// return NULL;
//}
int blk_enumerate_partitions(struct blkdev *dev) {
kdebug("Enumerating partitions of %s\n", dev->ent->dev_name);
// TODO: handle stuff where block size is not 512
uint8_t buf[1024];
_assert(blk_read(dev, buf, 0, 1024) >= 0);
if (!strncmp((const char *) (buf + 512), "EFI PART", 8)) {
// Found GPT
return blk_enumerate_gpt(dev, buf);
} else if (buf[510] == 0x55 && buf[511] == 0xAA) {
// Found MBR
return blk_enumerate_mbr(dev, buf);
}
// No partition table - just a plain block device
return 0;
}
+12 -11
View File
@@ -32,15 +32,16 @@ void ramblk_init(uintptr_t at, size_t len) {
ram_priv.begin = at;
ram_priv.lim = len;
struct dev_entry *ent = (struct dev_entry *) kmalloc(sizeof(struct dev_entry));
_assert(ent);
ent->dev = ramblk0;
ent->dev_class = DEV_CLASS_BLOCK;
ent->dev_subclass = DEV_BLOCK_RAM;
if (dev_alloc_name(ent->dev_class, ent->dev_subclass, ent->dev_name) != 0) {
panic("Failed to allocate a name for ram device\n");
}
dev_entry_add(ent);
dev_add(DEV_CLASS_BLOCK, DEV_BLOCK_RAM, &_ramblk0, "ram0");
// struct dev_entry *ent = (struct dev_entry *) kmalloc(sizeof(struct dev_entry));
// _assert(ent);
//
// ent->dev = ramblk0;
// ent->dev_class = DEV_CLASS_BLOCK;
// ent->dev_subclass = DEV_BLOCK_RAM;
// if (dev_alloc_name(ent->dev_class, ent->dev_subclass, ent->dev_name) != 0) {
// panic("Failed to allocate a name for ram device\n");
// }
//
// dev_entry_add(ent);
}
+51 -45
View File
@@ -10,63 +10,69 @@
#include "sys/fs/fs.h"
#include "sys/attr.h"
#include "sys/heap.h"
#include "sys/errno.h"
static struct vnode *devfs_root = NULL;
static uint64_t dev_scsi_bitmap = 0;
static uint64_t dev_ide_bitmap = 0;
static int dev_ram_count = 0;
static uint64_t dev_count = 0;
static int dev_alloc_block_name(uint16_t subclass, char *name) {
if (subclass == DEV_BLOCK_RAM) {
strcpy(name, "ram");
name[3] = dev_ram_count++ + '0';
name[4] = 0;
return 0;
int dev_add(enum dev_class cls, int subcls, void *dev, const char *name) {
char node_name[5];
struct vnode *node;
if (!name) {
// TODO: generate proper names for device nodes
node_name[4] = 0;
node_name[3] = '0' + ++dev_count;
node_name[0] = 'd';
node_name[1] = 'e';
node_name[2] = 'v';
name = node_name;
}
if (subclass == DEV_BLOCK_SDx || subclass == DEV_BLOCK_HDx) {
uint64_t *bmp = subclass == DEV_BLOCK_SDx ? &dev_scsi_bitmap : &dev_ide_bitmap;
name[1] = 'd';
name[0] = subclass == DEV_BLOCK_SDx ? 's' : 'h';
for (size_t i = 0; i < 64; ++i) {
if (!(*bmp & (1ULL << i))) {
*bmp |= 1ULL << i;
name[2] = 'a' + i;
name[3] = 0;
return 0;
}
}
// Create a filesystem node for the device
node = vnode_create(cls == DEV_CLASS_BLOCK ? VN_BLK : VN_CHR, name);
node->dev = dev;
// Use inode number to store full device class:subclass
node->ino = ((uint32_t) cls) | ((uint64_t) subcls << 32);
// If root does not yet exist, make one
if (!devfs_root) {
devfs_root = vnode_create(VN_DIR, NULL);
}
return -1;
}
int dev_alloc_name(enum dev_class cls, uint16_t subclass, char *name) {
switch (cls) {
case DEV_CLASS_BLOCK:
return dev_alloc_block_name(subclass, name);
default:
panic("Not implemented\n");
}
}
// TODO: some devices are located in subdirs
vnode_attach(devfs_root, node);
static int dev_post_add(struct dev_entry *ent) {
if (ent->dev_class == DEV_CLASS_BLOCK) {
struct blkdev *blk = (struct blkdev *) ent->dev;
kinfo("Created device node: %s\n", node->name);
blk->ent = ent;
if (ent->dev_subclass < DEV_BLOCK_PART) {
if (blk_enumerate_partitions((struct blkdev *) ent->dev) != 0) {
return -1;
}
}
}
// Self-test
struct vnode *test_node = NULL;
_assert(vnode_lookup_child(devfs_root, name, &test_node) == 0);
_assert(test_node == node);
_assert(vnode_lookup_tree(devfs_root, name, &test_node) == 0);
_assert(test_node == node);
return 0;
}
void dev_entry_add(struct dev_entry *ent) {
// For example: enumerate partitions on block devices
_assert(dev_post_add(ent) == 0);
int dev_find(enum dev_class cls, const char *name, struct vnode **node) {
_assert(node);
int res;
if (!devfs_root) {
return -ENODEV;
}
if ((res = vnode_lookup_tree(devfs_root, name, node)) != 0) {
return res;
}
if (cls == DEV_CLASS_BLOCK && (*node)->type != VN_BLK) {
return -ENODEV;
}
if (cls == DEV_CLASS_CHAR && (*node)->type != VN_CHR) {
return -ENODEV;
}
return 0;
}
+27 -23
View File
@@ -12,8 +12,8 @@ enum vnode_type ext2_inode_type(struct ext2_inode *i) {
return VN_DIR;
case EXT2_TYPE_REG:
return VN_REG;
case EXT2_TYPE_LNK:
return VN_LNK;
//case EXT2_TYPE_LNK:
// return VN_LNK;
default:
// fprintf(stderr, "Unknown file type: %x\n", v);
// abort();
@@ -22,9 +22,9 @@ enum vnode_type ext2_inode_type(struct ext2_inode *i) {
}
}
static int ext2_fs_mount(fs_t *fs, const char *opt) {
static int ext2_fs_init(struct fs *fs, const char *opt) {
int res;
kdebug("ext2_fs_mount()\n");
kdebug("ext2_fs_init()\n");
struct ext2_extsb *sb;
// ext2's private data is its superblock structure
sb = (struct ext2_extsb *) kmalloc(EXT2_SBSIZ);
@@ -84,7 +84,7 @@ static int ext2_fs_mount(fs_t *fs, const char *opt) {
return 0;
}
static int ext2_fs_umount(fs_t *fs) {
static int ext2_fs_umount(struct fs *fs) {
struct ext2_extsb *sb = (struct ext2_extsb *) fs->fs_private;
// Free block group descriptor table
kfree(sb->block_group_descriptor_table);
@@ -93,29 +93,32 @@ static int ext2_fs_umount(fs_t *fs) {
return 0;
}
static vnode_t *ext2_fs_get_root(fs_t *fs) {
struct ext2_extsb *sb = fs->fs_private;
kdebug("ext2_fs_get_root()\n");
static struct vnode *ext2_fs_get_root(struct fs *fs) {
// TODO: make sure get_root is only called once per filesystem
//struct ext2_extsb *sb = fs->fs_private;
//kdebug("ext2_fs_get_root()\n");
struct ext2_inode *inode = (struct ext2_inode *) kmalloc(sb->inode_struct_size);
// Read root inode (2)
if (ext2_read_inode(fs, inode, EXT2_ROOTINO) != 0) {
kfree(inode);
return NULL;
}
//struct ext2_inode *inode = (struct ext2_inode *) kmalloc(sb->inode_struct_size);
//// Read root inode (2)
//if (ext2_read_inode(fs, inode, EXT2_ROOTINO) != 0) {
// kfree(inode);
// return NULL;
//}
vnode_t *res = (vnode_t *) kmalloc(sizeof(vnode_t));
//vnode_t *res = (vnode_t *) kmalloc(sizeof(vnode_t));
res->fs = fs;
res->fs_data = inode;
res->fs_number = EXT2_ROOTINO;
res->op = &ext2_vnode_ops;
res->type = ext2_inode_type(inode);
//res->fs = fs;
//res->fs_data = inode;
//res->fs_number = EXT2_ROOTINO;
//res->op = &ext2_vnode_ops;
//res->type = ext2_inode_type(inode);
return res;
//return res;
panic("ext2 get root\n");
return NULL;
}
static int ext2_fs_statvfs(fs_t *fs, struct statvfs *st) {
static int ext2_fs_statvfs(struct fs *fs, struct statvfs *st) {
struct ext2_extsb *sb = fs->fs_private;
st->f_blocks = sb->sb.block_count;
@@ -141,7 +144,8 @@ static int ext2_fs_statvfs(fs_t *fs, struct statvfs *st) {
static struct fs_class ext2_class = {
.name = "ext2",
.get_root = ext2_fs_get_root,
.mount = ext2_fs_mount,
.init = ext2_fs_init,
.mount = NULL,
.umount = ext2_fs_umount,
.statvfs = ext2_fs_statvfs
};
+7 -7
View File
@@ -6,12 +6,12 @@
#define ext2_super(e) ((struct ext2_extsb *) (e)->fs_private)
int ext2_write_superblock(fs_t *ext2) {
int ext2_write_superblock(struct fs *ext2) {
struct ext2_extsb *sb = (struct ext2_extsb *) ext2->fs_private;
return blk_write(ext2->blk, sb, EXT2_SBOFF, EXT2_SBSIZ);
}
int ext2_read_block(fs_t *ext2, uint32_t block_no, void *buf) {
int ext2_read_block(struct fs *ext2, uint32_t block_no, void *buf) {
if (!block_no) {
return -1;
}
@@ -26,7 +26,7 @@ int ext2_read_block(fs_t *ext2, uint32_t block_no, void *buf) {
return res;
}
int ext2_write_block(fs_t *ext2, uint32_t block_no, const void *buf) {
int ext2_write_block(struct fs *ext2, uint32_t block_no, const void *buf) {
if (!block_no) {
return -1;
}
@@ -41,7 +41,7 @@ int ext2_write_block(fs_t *ext2, uint32_t block_no, const void *buf) {
return res;
}
int ext2_write_inode_block(fs_t *ext2, struct ext2_inode *inode, uint32_t index, const void *buf) {
int ext2_write_inode_block(struct fs *ext2, struct ext2_inode *inode, uint32_t index, const void *buf) {
if (index < 12) {
uint32_t block_number = inode->direct_blocks[index];
return ext2_write_block(ext2, block_number, buf);
@@ -52,7 +52,7 @@ int ext2_write_inode_block(fs_t *ext2, struct ext2_inode *inode, uint32_t index,
}
}
int ext2_read_inode_block(fs_t *ext2, struct ext2_inode *inode, uint32_t index, void *buf) {
int ext2_read_inode_block(struct fs *ext2, struct ext2_inode *inode, uint32_t index, void *buf) {
if (index < 12) {
// Use direct ptrs
uint32_t block_number = inode->direct_blocks[index];
@@ -76,7 +76,7 @@ int ext2_read_inode_block(fs_t *ext2, struct ext2_inode *inode, uint32_t index,
}
}
int ext2_read_inode(fs_t *ext2, struct ext2_inode *inode, uint32_t ino) {
int ext2_read_inode(struct fs *ext2, struct ext2_inode *inode, uint32_t ino) {
struct ext2_extsb *sb = (struct ext2_extsb *) ext2->fs_private;
//printf("ext2_read_inode %d\n", ino);
char inode_block_buffer[sb->block_size];
@@ -104,7 +104,7 @@ int ext2_read_inode(fs_t *ext2, struct ext2_inode *inode, uint32_t ino) {
return 0;
}
int ext2_write_inode(fs_t *ext2, const struct ext2_inode *inode, uint32_t ino) {
int ext2_write_inode(struct fs *ext2, const struct ext2_inode *inode, uint32_t ino) {
struct ext2_extsb *sb = (struct ext2_extsb *) ext2->fs_private;
//printf("ext2_read_inode %d\n", ino);
char inode_block_buffer[sb->block_size];
+24 -5
View File
@@ -1,5 +1,6 @@
#include "sys/string.h"
#include "sys/fs/fs.h"
#include "sys/debug.h"
#include "sys/errno.h"
// #include <stddef.h>
@@ -9,16 +10,34 @@
static struct fs_class *fses[10] = { NULL };
static struct fs mounts[10];
struct fs *fs_create(struct fs_class *cls, struct blkdev *blk, struct vnode *at) {
struct fs *fs_create(struct fs_class *cls, struct blkdev *blk) {
struct fs *fs = NULL;
// XXX: I hate heap allocations, but why not use one?
for (size_t i = 0; i < 10; ++i) {
if (mounts[i].cls == NULL) {
mounts[i].cls = cls;
mounts[i].blk= blk;
mounts[i].mnt_at = at;
return &mounts[i];
mounts[i].blk = blk;
fs = &mounts[i];
break;
}
}
return NULL;
if (!fs) {
return NULL;
}
// Try to initialize filesystem instance at device
if (cls->init) {
if (cls->init(fs, NULL) != 0) {
fs->cls = NULL;
kerror("%s init failed\n", cls->name);
return NULL;
}
} else {
kwarn("%s provides no init function\n", cls->name);
}
return fs;
}
struct fs_class *fs_class_by_name(const char *name) {
+196 -2
View File
@@ -1,20 +1,52 @@
#include "sys/fs/node.h"
#include "sys/fs/vfs.h"
#include "sys/fs/fs.h"
#include "sys/errno.h"
#include "sys/debug.h"
#include "sys/assert.h"
#include "sys/heap.h"
#include "sys/panic.h"
#include "sys/string.h"
#include "sys/heap.h"
struct vnode *vnode_create(const char *name) {
static const char *path_element(const char *path, char *element) {
const char *sep = strchr(path, '/');
if (!sep) {
strcpy(element, path);
return NULL;
} else {
_assert(sep - path < NODE_MAXLEN);
strncpy(element, path, sep - path);
element[sep - path] = 0;
while (*sep == '/') {
++sep;
}
if (!*sep) {
return NULL;
}
return sep;
}
}
struct vnode *vnode_create(enum vnode_type t, const char *name) {
struct vnode *node = (struct vnode *) kmalloc(sizeof(struct vnode));
_assert(node);
node->type = t;
node->flags = 0;
node->parent = NULL;
node->first_child = NULL;
node->next_child = NULL;
node->fs = NULL;
node->fs_data = NULL;
node->op = NULL;
node->dev = NULL;
if (name) {
_assert(strlen(name) < NODE_MAXLEN);
strcpy(node->name, name);
@@ -24,3 +56,165 @@ struct vnode *vnode_create(const char *name) {
return node;
}
void vnode_attach(struct vnode *parent, struct vnode *child) {
_assert(parent);
_assert(child);
_assert(!child->parent);
child->parent = parent;
child->next_child = parent->first_child;
parent->first_child = child;
}
void vnode_detach(struct vnode *node) {
_assert(node);
struct vnode *parent = node->parent;
node->parent = NULL;
if (!parent) {
return;
}
if (node == parent->first_child) {
parent->first_child = node->next_child;
node->next_child = NULL;
return;
}
for (struct vnode *ch = parent->first_child; ch; ch = ch->next_child) {
if (ch->next_child == node) {
ch->next_child = node->next_child;
node->next_child = NULL;
return;
}
}
panic("Parent has no link to its child node\n");
}
// Only dumps cached nodes in filesystem tree
void vnode_dump_tree(int level, struct vnode *node, int depth) {
for (int i = 0; i < depth; ++i) {
debugs(level, " ");
}
switch (node->type) {
case VN_DIR:
debugs(level, "\033[33m");
break;
case VN_REG:
debugs(level, "\033[1m");
break;
case VN_BLK:
case VN_CHR:
debugs(level, "\033[32m");
break;
default:
debugs(level, "\033[41m");
break;
}
if (node->name[0]) {
debugs(level, node->name);
} else {
debugs(level, "[root]");
}
debugs(level, "\033[0m");
if (node->first_child) {
debugs(level, " {\n");
for (struct vnode *ch = node->first_child; ch; ch = ch->next_child) {
vnode_dump_tree(level, ch, depth + 1);
}
for (int i = 0; i < depth; ++i) {
debugs(level, " ");
}
debugs(level, "}\n");
} else {
debugc(level, '\n');
}
}
// NOTE: Only looks up in-memory nodes, does not perform any operations to fetch
// the nodes from storage
// NOTE: Resolution of .. and . is performed when resolving paths, as a node can
// have multiple parents (roots of filesystems mounted at different locations)
int vnode_lookup_child(struct vnode *of, const char *name, struct vnode **child) {
_assert(of);
_assert(child);
_assert(name);
_assert(strlen(name) < NODE_MAXLEN);
for (struct vnode *ch = of->first_child; ch; ch = ch->next_child) {
if (!strcmp(ch->name, name)) {
*child = ch;
return 0;
}
}
return -ENOENT;
}
int vnode_lookup_tree(struct vnode *at, const char *path, struct vnode **child) {
char name[NODE_MAXLEN];
const char *child_path;
struct vnode *node;
int err;
_assert(at);
_assert(child);
if (!path || !*path) {
*child = at;
kdebug("empty hit-final %s\n", at->name);
return 0;
}
// The paths are always assumed to be relative
while (*path == '/') {
++path;
}
while (1) {
child_path = path_element(path, name);
if (!strcmp(name, ".")) {
// Refers to this node
kdebug(". hit %s\n", at->name);
continue;
} else if (!strcmp(name, "..")) {
// Refers to node's parent
// And this won't work for filesystem mountpoints:
// Path like a/mnt/.. would still resolve the same point as
// a/mnt
struct vnode *parent = at->parent;
if (!parent) {
parent = at;
}
kdebug(".. hit %s\n", parent->name);
return vnode_lookup_tree(parent, child_path, child);
}
break;
}
// TODO: lookup_or_load
if ((err = vnode_lookup_child(at, name, &node)) != 0) {
kdebug("miss %s\n", name);
return err;
}
_assert(node);
if (!child_path) {
kdebug("hit-final %s\n", name);
*child = node;
return 0;
} else {
kdebug("hit %s\n", name);
return vnode_lookup_tree(node, child_path, child);
}
}
+6 -22
View File
@@ -31,34 +31,16 @@ static struct blkdev _dev_null = {
.write = pseudo_write,
.read = pseudo_read
};
static struct dev_entry _ent_null = {
.dev = &_dev_null,
.dev_class = DEV_CLASS_BLOCK,
.dev_subclass = DEV_BLOCK_PSEUDO,
.dev_name = "null"
};
static struct blkdev _dev_zero = {
.dev_data = (void *) DEV_ZERO,
.write = pseudo_write,
.read = pseudo_read
};
static struct dev_entry _ent_zero = {
.dev = &_dev_zero,
.dev_class = DEV_CLASS_BLOCK,
.dev_subclass = DEV_BLOCK_PSEUDO,
.dev_name = "zero"
};
static struct blkdev _dev_urandom = {
.dev_data = (void *) DEV_URANDOM,
.write = pseudo_write,
.read = pseudo_read
};
static struct dev_entry _ent_urandom = {
.dev = &_dev_urandom,
.dev_class = DEV_CLASS_BLOCK,
.dev_subclass = DEV_BLOCK_PSEUDO,
.dev_name = "urandom"
};
static ssize_t pseudo_write(struct blkdev *dev, const void *buf, size_t pos, size_t lim) {
switch ((uint64_t) dev->dev_data) {
@@ -87,8 +69,10 @@ static ssize_t pseudo_read(struct blkdev *dev, void *buf, size_t pos, size_t lim
}
}
static __init void pseudo_init(void) {
dev_entry_add(&_ent_null);
dev_entry_add(&_ent_zero);
dev_entry_add(&_ent_urandom);
// XXX: This is called before heap init, fucked up?
void pseudo_init(void) {
// FIXME: They're actually character devices
dev_add(DEV_CLASS_BLOCK, DEV_BLOCK_PSEUDO, &_dev_null, "null");
dev_add(DEV_CLASS_BLOCK, DEV_BLOCK_PSEUDO, &_dev_zero, "zero");
dev_add(DEV_CLASS_BLOCK, DEV_BLOCK_PSEUDO, &_dev_urandom, "urandom");
}
+84 -193
View File
@@ -20,23 +20,15 @@ struct tar {
};
struct tarfs_vnode_attr {
uint32_t type_perm;
uint32_t uid;
uint32_t gid;
size_t block;
size_t first_block;
size_t size;
};
static int tarfs_vnode_access(vnode_t *vn, uid_t *uid, gid_t *gid, mode_t *mode);
static int tarfs_vnode_stat(vnode_t *vn, struct stat *st);
static int tarfs_vnode_open(vnode_t *vn, int opt);
static ssize_t tarfs_vnode_read(struct ofile *fd, void *buf, size_t count);
static struct vnode_operations _tarfs_vnode_op = {
.access = tarfs_vnode_access,
.stat = tarfs_vnode_stat,
.open = tarfs_vnode_open,
.read = tarfs_vnode_read
.read = tarfs_vnode_read,
NULL
};
static ssize_t tarfs_octal(const char *buf, size_t lim) {
@@ -52,66 +44,64 @@ static ssize_t tarfs_octal(const char *buf, size_t lim) {
return res;
}
static const char *tarfs_path_element(char *dst, const char *src) {
const char *sep = strchr(src, '/');
static const char *path_element(const char *path, char *element) {
const char *sep = strchr(path, '/');
if (!sep) {
strcpy(dst, src);
strcpy(element, path);
return NULL;
} else {
strncpy(dst, src, sep - src);
dst[sep - src] = 0;
_assert(sep - path < NODE_MAXLEN);
strncpy(element, path, sep - path);
element[sep - path] = 0;
while (*sep == '/') {
++sep;
}
if (!*sep) {
return NULL;
}
return sep;
}
}
static int tarfs_node_add(struct vfs_node *at, struct vfs_node **res, const char *name) {
// Try to find the node
for (struct vfs_node *child = at->child; child; child = child->cdr) {
if (!strcmp(child->name, name)) {
*res = child;
// Already exists
return 0;
}
static int tarfs_mapper_create_node(struct vnode *at, struct vnode **res, const char *name, int dir) {
_assert(at->type == VN_DIR); // Can only attach child to a directory
if (vnode_lookup_child(at, name, res) == 0) {
// Already exists
return 0;
}
// Else we need to insert it
struct vfs_node *node_new = (struct vfs_node *) kmalloc(sizeof(struct vfs_node));
strcpy(node_new->name, name);
node_new->ismount = 0;
node_new->parent = at;
node_new->child = NULL;
node_new->cdr = at->child;
node_new->real_vnode = NULL;
node_new->vnode = NULL;
at->child = node_new;
struct vnode *node_new = vnode_create(dir ? VN_DIR : VN_REG, name);
node_new->flags |= VN_MEMORY;
node_new->op = &_tarfs_vnode_op;
vnode_attach(at, node_new);
*res = node_new;
return 0;
}
static int tarfs_mapper_create_path(struct vfs_node *root, struct vfs_node **res, const char *path, int isdir) {
char path_element[256];
const char *remaining = path;
struct vfs_node *node = root;
struct vfs_node *new_node;
static int tarfs_mapper_create_path(struct vnode *root, const char *path, struct vnode **res, int dir) {
char name[NODE_MAXLEN];
const char *child_path = path;
struct vnode *node = root;
struct vnode *new_node;
int err;
kdebug("Add path %s\n", path);
while (1) {
remaining = tarfs_path_element(path_element, remaining);
if (tarfs_node_add(node, &new_node, path_element) < 0) {
panic("Failed\n");
while (1) {
child_path = path_element(child_path, name);
if ((err = tarfs_mapper_create_node(node, &new_node, name, dir)) != 0) {
return err;
}
node = new_node;
if (!remaining) {
if (!child_path) {
break;
}
}
@@ -121,74 +111,34 @@ static int tarfs_mapper_create_path(struct vfs_node *root, struct vfs_node **res
return 0;
}
static vnode_t *tarfs_create_vnode(fs_t *fs, struct vfs_node *node, struct tar *hdr, size_t off) {
if (hdr) {
struct tarfs_vnode_attr *attr = (struct tarfs_vnode_attr *) kmalloc(sizeof(struct tarfs_vnode_attr));
attr->block = off + 512;
attr->gid = tarfs_octal(hdr->gid, 8);
attr->uid = tarfs_octal(hdr->uid, 8);
attr->type_perm = tarfs_octal(hdr->mode, 8);
if (!(hdr->typeflag[0] == '\0' || hdr->typeflag[0] == '0')) {
attr->type_perm |= (1 << 16);
attr->size = 0;
} else {
attr->size = tarfs_octal(hdr->size, 12);
}
vnode_t *res = (vnode_t *) kmalloc(sizeof(vnode_t));
res->tree_node = node;
res->fs = fs;
res->fs_data = attr;
res->refcount = 0;
res->op = &_tarfs_vnode_op;
res->type = (attr->type_perm & (1 << 16)) ? VN_DIR : VN_REG;
return res;
} else {
vnode_t *res = (vnode_t *) kmalloc(sizeof(vnode_t));
res->tree_node = node;
res->fs = fs;
res->fs_data = NULL;
res->refcount = 0;
res->op = &_tarfs_vnode_op;
res->type = VN_DIR;
return res;
}
}
static int tarfs_node_mapper(fs_t *tar, struct vfs_node **root) {
kdebug("tar: node mapper\n");
char block_buffer[512];
static int tar_init(struct fs *tar, const char *opt) {
char block[512];
size_t off = 0;
int was0 = 0;
int prev_zero = 0;
ssize_t res;
struct vfs_node *_root = (struct vfs_node *) kmalloc(sizeof(struct vfs_node));
_root->child = NULL;
_root->cdr = NULL;
_root->ismount = 0;
_root->parent = NULL;
_root->real_vnode = NULL;
_root->vnode = NULL;
struct vfs_node *curr_node;
// Create filesystem root node
struct vnode *tar_root = vnode_create(VN_DIR, NULL);
tar->fs_private = tar_root;
tar_root->fs = tar;
struct vnode *node;
while (1) {
if (blk_read(tar->blk, block_buffer, off, 512) < 0) {
return -EIO;
if ((res = blk_read(tar->blk, block, off, 512)) < 0) {
return res;
}
struct tar *hdr = (struct tar *) block_buffer;
if (hdr->filename[0] == 0) {
if (was0) {
// End of archive
struct tar *hdr = (struct tar *) block;
if (!hdr->filename[0]) {
if (prev_zero) {
break;
} else {
was0 = 1;
off += 512;
continue;
}
prev_zero = 1;
off += 512;
continue;
}
size_t node_size = 0;
@@ -199,117 +149,58 @@ static int tarfs_node_mapper(fs_t *tar, struct vfs_node **root) {
isdir = 0;
}
kdebug("Node %c:%s:%S\n", isdir ? 'd' : '-', hdr->filename, node_size);
if ((res = tarfs_mapper_create_path(tar_root, hdr->filename, &node, isdir)) < 0) {
return res;
}
_assert(node);
tarfs_mapper_create_path(_root, &curr_node, hdr->filename, isdir);
_assert(curr_node);
vnode_t *vnode = tarfs_create_vnode(tar, curr_node, hdr, off);
_assert(vnode);
curr_node->vnode = vnode;
// Initialize the vnode
node->uid = 0;
node->gid = 0;
struct tarfs_vnode_attr *attr = kmalloc(sizeof(struct tarfs_vnode_attr));
_assert(attr);
node->fs_data = attr;
node->fs = tar;
attr->first_block = off + 512;
attr->size = node_size;
off += 512 + ((node_size + 0x1FF) & ~0x1FF);
}
// Make a vnode for root
vnode_t *vnode = tarfs_create_vnode(tar, _root, NULL, 0);
_root->vnode = vnode;
*root = _root;
return 0;
}
static struct vnode *tar_get_root(struct fs *tar) {
return tar->fs_private;
}
static struct fs_class _tarfs = {
.name = "ustar",
.opt = FS_NODE_MAPPER,
.mapper = tarfs_node_mapper
.opt = 0,
.init = tar_init,
.get_root = tar_get_root
};
// Vnode operations
static int tarfs_vnode_access(vnode_t *vn, uid_t *uid, gid_t *gid, mode_t *mode) {
_assert(vn && uid && gid && mode);
if (!vn->fs_data) {
*uid = 0;
*gid = 0;
*mode = S_IFDIR | 0755;
} else {
struct tarfs_vnode_attr *attr = (struct tarfs_vnode_attr *) vn->fs_data;
*uid = attr->uid;
*gid = attr->gid;
*mode = (attr->type_perm & 0x1FF) | ((attr->type_perm & (1 << 16)) ? S_IFDIR : S_IFREG);
}
return 0;
}
static int tarfs_vnode_stat(vnode_t *vn, struct stat *st) {
_assert(vn && st);
if (!vn->fs_data) {
// Root node
st->st_atime = 0;
st->st_ctime = 0;
st->st_mtime = 0;
st->st_dev = 0;
st->st_rdev = 0;
st->st_gid = 0;
st->st_uid = 0;
st->st_mode = S_IFDIR | 0755;
st->st_ino = 0;
st->st_nlink = 1;
st->st_blksize = 512;
st->st_blocks = 0;
st->st_size = 0;
return 0;
}
struct tarfs_vnode_attr *attr = (struct tarfs_vnode_attr *) vn->fs_data;
st->st_atime = 0;
st->st_mtime = 0;
st->st_ctime = 0;
st->st_dev = 0;
st->st_rdev = 0;
st->st_gid = attr->gid;
st->st_uid = attr->uid;
st->st_mode = (attr->type_perm & 0x1FF) | ((attr->type_perm & (1 << 16)) ? S_IFDIR : S_IFREG);
st->st_ino = (attr->block / 512) - 1;
st->st_nlink = 1;
st->st_blksize = 512;
st->st_blocks = (attr->size + 511) & ~511;
st->st_size = attr->size;
return 0;
}
static int tarfs_vnode_open(vnode_t *vnode, int opt) {
if ((opt & O_ACCMODE) != O_RDONLY) {
return -EROFS;
}
return 0;
}
#define MIN(x, y) ((x) < (y) ? (x) : (y))
static ssize_t tarfs_vnode_read(struct ofile *fd, void *buf, size_t count) {
_assert(fd && buf && fd->vnode);
vnode_t *vn = fd->vnode;
_assert(fd);
_assert(buf);
_assert(fd->vnode);
struct vnode *vn = fd->vnode;
_assert(vn->fs_data);
struct tarfs_vnode_attr *attr = (struct tarfs_vnode_attr *) vn->fs_data;
_assert(vn->fs && vn->fs->blk);
struct tarfs_vnode_attr *attr = vn->fs_data;
if (fd->pos >= attr->size) {
return -1;
}
size_t can = MIN(attr->size - fd->pos, count);
// TODO: do it properly with block buffer
blk_read(vn->fs->blk, buf, fd->pos + attr->block, can);
// TODO: size is not block-size aligned, may fuck up
blk_read(vn->fs->blk, buf, fd->pos + attr->first_block, can);
return can;
}