We can now open and read files on the harddisk through a messy virtual filesystem
The uri has to contain 8.3 filenames for now as I have not yet figured out how to convert from that to regular filenaming for the name comparison. reading files is still limited to 1 sector
This commit is contained in:
@ -14,17 +14,21 @@ int VirtualFileSystem::superblock_number =0;
|
||||
int VirtualFileSystem::filesystem_number =0;
|
||||
|
||||
filesystem* VirtualFileSystem::filesystems[4];
|
||||
superblock* VirtualFileSystem::superblocks[8];
|
||||
FS_SUPER* VirtualFileSystem::superblocks[8];
|
||||
vfsmount* VirtualFileSystem::mounts[12];
|
||||
|
||||
void VirtualFileSystem::Mount(filesystem* fs, const char* name)
|
||||
{
|
||||
vfsmount* mnt_point = (vfsmount*) malloc(sizeof(vfsmount));
|
||||
superblock* sb = fs->mount(fs, name, mnt_point);
|
||||
|
||||
vfsmount* mnt_point = (vfsmount*) malloc(sizeof(vfsmount));
|
||||
FS_SUPER* sb = fs->mount(fs, name, mnt_point);
|
||||
if( sb == nullptr){
|
||||
printf("mount failed!\n");
|
||||
return;
|
||||
}
|
||||
mounts[mount_number++] = mnt_point;
|
||||
superblocks[superblock_number++] = sb;
|
||||
|
||||
mnt_point->mnt_count = 1;
|
||||
rootfs = mnt_point;
|
||||
}
|
||||
|
||||
@ -54,64 +58,58 @@ int VirtualFileSystem::register_filesystem(struct filesystem* fs) {
|
||||
|
||||
}
|
||||
|
||||
struct file* VirtualFileSystem::open(const char* pathname, int flags){
|
||||
FILE* VirtualFileSystem::open(const char* pathname, int flags){
|
||||
// 1. Lookup pathname from the root node
|
||||
// 2. Create a new file descriptor for this v_node if found.
|
||||
// 2. Create a new file descriptor for this inode if found.
|
||||
// 3. Create a new file if O_CREATE is specified in the flags.
|
||||
|
||||
// See reference material (1) https://man7.org/linux/man-pages/man7/path_resolution.7.html
|
||||
|
||||
// FILE file = ->Open(filename);
|
||||
if(pathname[0] != '/'){
|
||||
printf("We won't handle relative paths yet!");
|
||||
file file;
|
||||
file.flags = 1;
|
||||
return &file;
|
||||
}
|
||||
|
||||
|
||||
|
||||
auto* dentry = rootfs->root;
|
||||
|
||||
int result = dentry->op->compare(dentry, "/", dentry->name);
|
||||
if(result != 0 ){
|
||||
printf("rootfs not called / \n");
|
||||
file file;
|
||||
file.flags = 1;
|
||||
return &file;
|
||||
}
|
||||
|
||||
FILE* file = (FILE*) malloc(sizeof (FILE)) ;
|
||||
auto* rootentry = rootfs->root;
|
||||
char* tokstate = nullptr;
|
||||
auto nextdir = strtok ((char*)pathname, "/", &tokstate );
|
||||
while (nextdir)
|
||||
{
|
||||
printf("Look for dentry: %s\n", nextdir);
|
||||
// look to its children
|
||||
if (dentry->children ) {
|
||||
printf("No children | children unknown!\n");
|
||||
break;
|
||||
}
|
||||
if (dentry->op->compare(dentry, nextdir, dentry->name))
|
||||
{
|
||||
// file found
|
||||
nextdir = strtok(nullptr, "/", &tokstate);
|
||||
}
|
||||
|
||||
// look up children if not filled
|
||||
if(rootentry->children == nullptr)
|
||||
{
|
||||
rootentry = rootentry->node->lookup(rootentry->node, rootentry);
|
||||
}
|
||||
|
||||
file file;
|
||||
file.flags = 1;
|
||||
return &file;
|
||||
if(rootentry->children == nullptr)
|
||||
{
|
||||
file->flags =1;
|
||||
return file;
|
||||
}
|
||||
|
||||
// let's just loop through the folder first
|
||||
auto* child = rootentry->children;
|
||||
while(child->next != nullptr){
|
||||
|
||||
auto* directory = (DirectoryNode*)child->data;
|
||||
if( directory->compare(directory, directory->name, nextdir) == 0){
|
||||
nextdir = strtok(nullptr, "/", &tokstate);
|
||||
if(nextdir == NULL){
|
||||
file->root = directory->node;
|
||||
file->flags =0;
|
||||
file->read = FAT::Read;
|
||||
return file;
|
||||
}
|
||||
}
|
||||
child = child->next;
|
||||
}
|
||||
|
||||
|
||||
|
||||
file->flags = 1;
|
||||
return file;
|
||||
}
|
||||
|
||||
int VirtualFileSystem::close (struct file* file){
|
||||
int VirtualFileSystem::close (struct FILE* file){
|
||||
// 1. release the file descriptor
|
||||
}
|
||||
int VirtualFileSystem::write(struct file* file, const void* buf, size_t len){
|
||||
int VirtualFileSystem::write(struct FILE* file, const void* buf, unsigned int len){
|
||||
// 1. Write len bytes from buf to the opened file.
|
||||
// 2. return written size or error code if an error occurs
|
||||
}
|
||||
int VirtualFileSystem::read (struct file* file, void* buf, size_t len){
|
||||
int VirtualFileSystem::read (struct FILE* file, void* buf, unsigned int len){
|
||||
// 1. read min(len, readable file data size) bytes ro buf from the opened file.
|
||||
// 2. return read size or error code if an error occurs
|
||||
}
|
||||
|
@ -11,10 +11,10 @@
|
||||
|
||||
static int register_filesystem(struct filesystem* fs);
|
||||
|
||||
static struct file* open(const char* pathname, int flags);
|
||||
static int close(struct file* file);
|
||||
static int write(struct file* file, const void* buf, size_t len);
|
||||
static int read(struct file* file, void* buf, size_t len);
|
||||
static FILE* open(const char* pathname, int flags);
|
||||
static int close(struct FILE* file);
|
||||
static int write(struct FILE* file, const void* buf, unsigned int len);
|
||||
static int read(struct FILE* file, void* buf, unsigned int len);
|
||||
|
||||
private:
|
||||
static vfsmount* rootfs;
|
||||
@ -25,7 +25,7 @@
|
||||
static int filesystem_number;
|
||||
|
||||
static filesystem* filesystems[];
|
||||
static superblock* superblocks[];
|
||||
static FS_SUPER* superblocks[];
|
||||
static vfsmount* mounts[];
|
||||
|
||||
};
|
||||
|
@ -5,55 +5,52 @@
|
||||
// grasslab.github.io/osdi/en/labs/lab7.html
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "../../../CoreLib/List.h"
|
||||
|
||||
struct inode_operations;
|
||||
struct vfsmount;
|
||||
struct superblock;
|
||||
struct FS_SUPER;
|
||||
struct inode;
|
||||
struct dentry_operations;
|
||||
struct directoryEntry;
|
||||
struct DirectoryNode;
|
||||
struct filesystem;
|
||||
struct superblock;
|
||||
struct file;
|
||||
struct FS_SUPER;
|
||||
struct FILE;
|
||||
|
||||
|
||||
struct file_operations{
|
||||
int(*write) (file* file, const void* buf, size_t len);
|
||||
int(*read) (file* file, void* buf, size_t len);
|
||||
};
|
||||
struct inode_operations {
|
||||
int (*create)(inode*, directoryEntry*, const char* );
|
||||
directoryEntry* (*lookup)(inode* , directoryEntry*);
|
||||
int (*link)(directoryEntry*, inode* , directoryEntry*);
|
||||
int (*unlink)(inode*, directoryEntry*);
|
||||
int (*symlink)(inode*, directoryEntry*);
|
||||
int (*mkdir)(inode*, directoryEntry*, const char*);
|
||||
int (*rmdir)(inode*, directoryEntry*);
|
||||
int (*rename)(inode*, directoryEntry*, inode*, directoryEntry*);
|
||||
void (*truncate)(inode*);
|
||||
int (*permission)(inode*, int);
|
||||
int (*setattr)(directoryEntry, unsigned long*);
|
||||
int (*getattr)(vfsmount* mnt, directoryEntry*, unsigned long*);
|
||||
};
|
||||
// Describes a mount
|
||||
struct vfsmount {
|
||||
vfsmount* mnt_parent; // fs we are mounted on
|
||||
directoryEntry* mountpoint; // dentry of mount point
|
||||
directoryEntry* root; // root of the mounted tree
|
||||
superblock* sb; // pointer to the superblock
|
||||
DirectoryNode* mountpoint; // dentry of mount point
|
||||
DirectoryNode* root; // root of the mounted tree
|
||||
FS_SUPER* sb; // pointer to the superblock
|
||||
unsigned int mnt_count; // keep track of users of this structure
|
||||
int mnt_flags;
|
||||
char* mnt_devname; // name of device eg /dev/dsk/hda1
|
||||
|
||||
};
|
||||
struct superblock;
|
||||
struct FS_SUPER;
|
||||
// Represents a filesystem object (i.e. a file or directory or device)
|
||||
struct inode {
|
||||
unsigned long mode; // access permissions
|
||||
unsigned long uid; // user id owner
|
||||
unsigned long gid; // group id owner
|
||||
unsigned int flags;
|
||||
inode_operations* i_op; // operations possible on inode
|
||||
superblock* sb;
|
||||
// operations possible on inode
|
||||
int (*create)(inode*, DirectoryNode*, const char* );
|
||||
DirectoryNode* (*lookup)(inode* , DirectoryNode*);
|
||||
int (*link)(DirectoryNode*, inode* , DirectoryNode*);
|
||||
int (*unlink)(inode*, DirectoryNode*);
|
||||
int (*symlink)(inode*, DirectoryNode*);
|
||||
int (*mkdir)(inode*, DirectoryNode*, const char*);
|
||||
int (*rmdir)(inode*, DirectoryNode*);
|
||||
int (*rename)(inode*, DirectoryNode*, inode*, DirectoryNode*);
|
||||
void (*truncate)(inode*);
|
||||
int (*permission)(inode*, int);
|
||||
int (*setattr)(DirectoryNode, unsigned long*);
|
||||
int (*getattr)(vfsmount* mnt, DirectoryNode*, unsigned long*);
|
||||
|
||||
FS_SUPER* sb;
|
||||
unsigned long ino; // unique number of this inode
|
||||
unsigned int links; // number of hard links
|
||||
void* device;
|
||||
@ -62,43 +59,39 @@ struct inode {
|
||||
unsigned long mtime; // Modify time
|
||||
unsigned long ctime; // Creation time
|
||||
unsigned short bytes; // bytes consumed
|
||||
file_operations* fop;
|
||||
// File operations possible on Inode;
|
||||
int(*write) (FILE* file, const void* buf, unsigned int len);
|
||||
int(*read) (FILE* file, void* buf, unsigned int len);
|
||||
void* internal; // point to underlying representation of this virtual node (e.g. FAT entry or Directory Entry)
|
||||
};
|
||||
// Represents the possible operations on a directory entry
|
||||
struct dentry_operations
|
||||
{
|
||||
int (*compare)(directoryEntry*, char*, char* );
|
||||
int (*o_delete)(directoryEntry*);
|
||||
void (*release)(directoryEntry*);
|
||||
void (*iput)(directoryEntry*, inode* );
|
||||
|
||||
};
|
||||
// Represents the name of files in the filesystem
|
||||
// it identifies the file that an inode represents
|
||||
struct directoryEntry {
|
||||
struct DirectoryNode {
|
||||
char* name; // name of the file on the disk
|
||||
directoryEntry* parent; // parent of the file
|
||||
DirectoryNode* parent; // parent of the file
|
||||
inode* node; // node belongs to...
|
||||
dentry_operations* op;
|
||||
directoryEntry* children[];
|
||||
|
||||
int (*compare)(DirectoryNode*, char*, char* );
|
||||
int (*o_delete)(DirectoryNode*);
|
||||
void (*release)(DirectoryNode*);
|
||||
void (*iput)(DirectoryNode*, inode*);
|
||||
List* children;
|
||||
};
|
||||
// Represents a filesystem type
|
||||
struct filesystem {
|
||||
const char* name;
|
||||
superblock* (*mount)(filesystem* self, const char* name, vfsmount* mnt);
|
||||
FS_SUPER* (*mount)(filesystem* self, const char* name, vfsmount* mnt);
|
||||
};
|
||||
|
||||
// Represents a mounted filesystem
|
||||
struct superblock {
|
||||
struct FS_SUPER {
|
||||
|
||||
void* device; // device associated with the filesystem
|
||||
unsigned long blocksize;
|
||||
unsigned long maxbytes;
|
||||
filesystem* type;
|
||||
unsigned long magic; // IDK
|
||||
directoryEntry* root; // Root dentry
|
||||
DirectoryNode* root; // Root dentry
|
||||
int count; // IDK
|
||||
void* fs_info; // pointer to raw filesystem info
|
||||
dentry_operations* d_op;
|
||||
@ -106,10 +99,11 @@ struct superblock {
|
||||
};
|
||||
|
||||
// Represents an opened file
|
||||
struct file {
|
||||
struct FILE {
|
||||
inode* root;
|
||||
size_t f_pos; // The next read/write position of this file descriptor;
|
||||
file_operations* f_ops;
|
||||
unsigned int f_pos; // The next read/write position of this file descriptor;
|
||||
int(*write) (FILE* file, const void* buf, unsigned int len);
|
||||
int(*read) (FILE* file, void* buf, unsigned int len);
|
||||
int flags;
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user