mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-14 03:46:47 +00:00
new: 在devfs中使用键盘文件(仍存在bug)
This commit is contained in:
parent
86a5f25e07
commit
d7423f36be
@ -138,6 +138,26 @@ static inline void list_del(struct List *entry)
|
|||||||
entry->prev->next = entry->next;
|
entry->prev->next = entry->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将新的链表结点替换掉旧的链表结点,并使得旧的结点的前后指针均为NULL
|
||||||
|
*
|
||||||
|
* @param old 要被替换的结点
|
||||||
|
* @param new 新的要换上去的结点
|
||||||
|
*/
|
||||||
|
static inline void list_replace(struct List* old, struct List * new)
|
||||||
|
{
|
||||||
|
if(old->prev!=NULL)
|
||||||
|
old->prev->next=new;
|
||||||
|
new->prev = old->prev;
|
||||||
|
if(old->next!=NULL)
|
||||||
|
old->next->prev = new;
|
||||||
|
new->next = old->next;
|
||||||
|
|
||||||
|
old->prev = NULL;
|
||||||
|
old->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline bool list_empty(struct List *entry)
|
static inline bool list_empty(struct List *entry)
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -39,7 +39,7 @@ long strnlen(const char *src, unsigned long maxlen)
|
|||||||
FirstPart < SecondPart => -1
|
FirstPart < SecondPart => -1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int strcmp(char *FirstPart, char *SecondPart)
|
int strcmp(const char *FirstPart, const char *SecondPart)
|
||||||
{
|
{
|
||||||
register int __res;
|
register int __res;
|
||||||
__asm__ __volatile__("cld \n\t"
|
__asm__ __volatile__("cld \n\t"
|
||||||
|
@ -38,7 +38,7 @@ long strnlen(const char *src, unsigned long maxlen);
|
|||||||
FirstPart < SecondPart => -1
|
FirstPart < SecondPart => -1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int strcmp(char *FirstPart, char *SecondPart);
|
int strcmp(const char *FirstPart, const char *SecondPart);
|
||||||
|
|
||||||
char *strncpy(char *dst, const char *src, long count);
|
char *strncpy(char *dst, const char *src, long count);
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "VFS.h"
|
#include "VFS.h"
|
||||||
|
#include "mount.h"
|
||||||
#include <common/kprint.h>
|
#include <common/kprint.h>
|
||||||
#include <common/dirent.h>
|
#include <common/dirent.h>
|
||||||
#include <common/string.h>
|
#include <common/string.h>
|
||||||
@ -8,6 +9,9 @@
|
|||||||
#include <process/ptrace.h>
|
#include <process/ptrace.h>
|
||||||
#include <process/process.h>
|
#include <process/process.h>
|
||||||
|
|
||||||
|
// todo: devfs完善后,删除这个
|
||||||
|
extern struct vfs_file_operations_t ps2_keyboard_fops;
|
||||||
|
|
||||||
// 为filesystem_type_t结构体实例化一个链表头
|
// 为filesystem_type_t结构体实例化一个链表头
|
||||||
static struct vfs_filesystem_type_t vfs_fs = {"filesystem", 0};
|
static struct vfs_filesystem_type_t vfs_fs = {"filesystem", 0};
|
||||||
struct vfs_superblock_t *vfs_root_sb = NULL;
|
struct vfs_superblock_t *vfs_root_sb = NULL;
|
||||||
@ -23,6 +27,16 @@ struct vfs_superblock_t *vfs_root_sb = NULL;
|
|||||||
struct vfs_superblock_t *vfs_mount_fs(const char *path, char *name, struct block_device *blk)
|
struct vfs_superblock_t *vfs_mount_fs(const char *path, char *name, struct block_device *blk)
|
||||||
{
|
{
|
||||||
// todo: 选择挂载点
|
// todo: 选择挂载点
|
||||||
|
// 判断挂载点是否存在
|
||||||
|
struct vfs_dir_entry_t *target_dentry = NULL;
|
||||||
|
// 由于目前还没有rootfs,因此挂载根目录时,不需要path walk
|
||||||
|
if (strcmp(path, "/") != 0)
|
||||||
|
{
|
||||||
|
target_dentry = vfs_path_walk(path, 0);
|
||||||
|
if (target_dentry == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct vfs_filesystem_type_t *p = NULL;
|
struct vfs_filesystem_type_t *p = NULL;
|
||||||
for (p = &vfs_fs; p; p = p->next)
|
for (p = &vfs_fs; p; p = p->next)
|
||||||
{
|
{
|
||||||
@ -31,6 +45,17 @@ struct vfs_superblock_t *vfs_mount_fs(const char *path, char *name, struct block
|
|||||||
struct vfs_superblock_t *sb = p->read_superblock(blk);
|
struct vfs_superblock_t *sb = p->read_superblock(blk);
|
||||||
if (strcmp(path, "/") == 0) // 如果挂载到的是'/'挂载点,则让其成为最顶层的文件系统
|
if (strcmp(path, "/") == 0) // 如果挂载到的是'/'挂载点,则让其成为最顶层的文件系统
|
||||||
vfs_root_sb = sb;
|
vfs_root_sb = sb;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kdebug("to mount %s", name);
|
||||||
|
// 调用mount机制,挂载文件系统
|
||||||
|
struct vfs_dir_entry_t *new_dentry = sb->root;
|
||||||
|
// 注意,umount的时候需要释放这些内存
|
||||||
|
new_dentry->name = kzalloc(target_dentry->name_length + 1, 0);
|
||||||
|
new_dentry->name_length = target_dentry->name_length;
|
||||||
|
|
||||||
|
do_mount(target_dentry, new_dentry);
|
||||||
|
}
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,6 +101,31 @@ uint64_t vfs_unregister_filesystem(struct vfs_filesystem_type_t *fs)
|
|||||||
return VFS_E_FS_NOT_EXIST;
|
return VFS_E_FS_NOT_EXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 在dentry的sub_dir_list中搜索指定名称的dentry
|
||||||
|
*
|
||||||
|
* @param dentry 目录项结构体dentry
|
||||||
|
* @param name 待搜索的dentry名称
|
||||||
|
* @return struct vfs_dir_entry_t* 目标dentry (无结果则返回NULL)
|
||||||
|
*/
|
||||||
|
static struct vfs_dir_entry_t *vfs_search_dentry_list(struct vfs_dir_entry_t *dentry, const char *name)
|
||||||
|
{
|
||||||
|
if (list_empty(&dentry->subdirs_list))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct List *ptr = &dentry->subdirs_list;
|
||||||
|
struct vfs_dir_entry_t *d_ptr = NULL;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ptr = list_next(ptr);
|
||||||
|
d_ptr = container_of(ptr, struct vfs_dir_entry_t, child_node_list);
|
||||||
|
if (strcmp(name, d_ptr->name) == 0)
|
||||||
|
return d_ptr;
|
||||||
|
} while (list_next(ptr) != (&dentry->subdirs_list));
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 按照路径查找文件
|
* @brief 按照路径查找文件
|
||||||
*
|
*
|
||||||
@ -94,42 +144,56 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags)
|
|||||||
if ((!*path) || (*path == '\0'))
|
if ((!*path) || (*path == '\0'))
|
||||||
return parent;
|
return parent;
|
||||||
|
|
||||||
struct vfs_dir_entry_t *dentry;
|
struct vfs_dir_entry_t *dentry = NULL;
|
||||||
// kdebug("path before walk:%s", path);
|
// kdebug("path before walk:%s", path);
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// 提取出下一级待搜索的目录名或文件名,并保存在dEntry_name中
|
// 提取出下一级待搜索的目录名或文件名,并保存在dEntry_name中
|
||||||
const char *tmp_path = path;
|
char *tmp_path = path;
|
||||||
while ((*path && *path != '\0') && (*path != '/'))
|
while ((*path && *path != '\0') && (*path != '/'))
|
||||||
++path;
|
++path;
|
||||||
int tmp_path_len = path - tmp_path;
|
int tmp_path_len = path - tmp_path;
|
||||||
dentry = (struct vfs_dir_entry_t *)kmalloc(sizeof(struct vfs_dir_entry_t), 0);
|
// 搜索是否有dentry缓存
|
||||||
memset(dentry, 0, sizeof(struct vfs_dir_entry_t));
|
|
||||||
// 为目录项的名称分配内存
|
|
||||||
dentry->name = (char *)kmalloc(tmp_path_len + 1, 0);
|
|
||||||
// 貌似这里不需要memset,因为空间会被覆盖
|
|
||||||
// memset(dentry->name, 0, tmp_path_len+1);
|
|
||||||
|
|
||||||
memcpy(dentry->name, (void *)tmp_path, tmp_path_len);
|
|
||||||
dentry->name[tmp_path_len] = '\0';
|
|
||||||
// kdebug("tmp_path_len=%d, dentry->name= %s", tmp_path_len, dentry->name);
|
|
||||||
dentry->name_length = tmp_path_len;
|
|
||||||
|
|
||||||
if (parent->dir_inode->inode_ops->lookup(parent->dir_inode, dentry) == NULL)
|
|
||||||
{
|
{
|
||||||
// 搜索失败
|
char bk = *(tmp_path + tmp_path_len);
|
||||||
// kerror("cannot find the file/dir : %s", dentry->name);
|
*(tmp_path + tmp_path_len) = '\0';
|
||||||
kfree(dentry->name);
|
kdebug("to search:%s", tmp_path);
|
||||||
kfree(dentry);
|
dentry = vfs_search_dentry_list(parent, tmp_path);
|
||||||
return NULL;
|
kdebug("search done, dentry=%#018lx", dentry);
|
||||||
|
*(tmp_path + tmp_path_len) = bk;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有找到dentry缓存,则申请新的dentry
|
||||||
|
if (dentry == NULL)
|
||||||
|
{
|
||||||
|
dentry = (struct vfs_dir_entry_t *)kzalloc(sizeof(struct vfs_dir_entry_t), 0);
|
||||||
|
// 为目录项的名称分配内存
|
||||||
|
dentry->name = (char *)kmalloc(tmp_path_len + 1, 0);
|
||||||
|
// 貌似这里不需要memset,因为空间会被覆盖
|
||||||
|
// memset(dentry->name, 0, tmp_path_len+1);
|
||||||
|
|
||||||
|
memcpy(dentry->name, (void *)tmp_path, tmp_path_len);
|
||||||
|
dentry->name[tmp_path_len] = '\0';
|
||||||
|
// kdebug("tmp_path_len=%d, dentry->name= %s", tmp_path_len, dentry->name);
|
||||||
|
dentry->name_length = tmp_path_len;
|
||||||
|
|
||||||
|
if (parent->dir_inode->inode_ops->lookup(parent->dir_inode, dentry) == NULL)
|
||||||
|
{
|
||||||
|
// 搜索失败
|
||||||
|
// kerror("cannot find the file/dir : %s", dentry->name);
|
||||||
|
kfree(dentry->name);
|
||||||
|
kfree(dentry);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// 找到子目录项
|
||||||
|
// 初始化子目录项的entry
|
||||||
|
list_init(&dentry->child_node_list);
|
||||||
|
list_init(&dentry->subdirs_list);
|
||||||
|
dentry->parent = parent;
|
||||||
|
|
||||||
|
list_add(&parent->subdirs_list, &dentry->child_node_list);
|
||||||
}
|
}
|
||||||
// 找到子目录项
|
|
||||||
// 初始化子目录项的entry
|
|
||||||
list_init(&dentry->child_node_list);
|
|
||||||
list_init(&dentry->subdirs_list);
|
|
||||||
dentry->parent = parent;
|
|
||||||
|
|
||||||
list_add(&parent->subdirs_list, &dentry->child_node_list);
|
|
||||||
while (*path == '/')
|
while (*path == '/')
|
||||||
++path;
|
++path;
|
||||||
|
|
||||||
@ -151,7 +215,7 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags)
|
|||||||
* @brief 填充dentry
|
* @brief 填充dentry
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int vfs_fill_dentry(void *buf, ino_t d_ino, char *name, int namelen, unsigned char type, off_t offset)
|
int vfs_fill_dirent(void *buf, ino_t d_ino, char *name, int namelen, unsigned char type, off_t offset)
|
||||||
{
|
{
|
||||||
struct dirent *dent = (struct dirent *)buf;
|
struct dirent *dent = (struct dirent *)buf;
|
||||||
|
|
||||||
@ -264,4 +328,216 @@ uint64_t sys_mkdir(struct pt_regs *regs)
|
|||||||
list_add(&parent_dir->subdirs_list, &subdir_dentry->child_node_list);
|
list_add(&parent_dir->subdirs_list, &subdir_dentry->child_node_list);
|
||||||
// kdebug("retval = %d", retval);
|
// kdebug("retval = %d", retval);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 打开文件
|
||||||
|
*
|
||||||
|
* @param filename 文件路径
|
||||||
|
* @param flags 标志位
|
||||||
|
* @return uint64_t 错误码
|
||||||
|
*/
|
||||||
|
uint64_t do_open(const char *filename, int flags)
|
||||||
|
{
|
||||||
|
long path_len = strnlen_user(filename, PAGE_4K_SIZE) + 1;
|
||||||
|
|
||||||
|
if (path_len <= 0) // 地址空间错误
|
||||||
|
{
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
else if (path_len >= PAGE_4K_SIZE) // 名称过长
|
||||||
|
{
|
||||||
|
return -ENAMETOOLONG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为待拷贝文件路径字符串分配内存空间
|
||||||
|
char *path = (char *)kmalloc(path_len, 0);
|
||||||
|
if (path == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
memset(path, 0, path_len);
|
||||||
|
|
||||||
|
strncpy_from_user(path, filename, path_len);
|
||||||
|
// 去除末尾的 '/'
|
||||||
|
if (path_len >= 2 && path[path_len - 2] == '/')
|
||||||
|
{
|
||||||
|
path[path_len - 2] = '\0';
|
||||||
|
--path_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 寻找文件
|
||||||
|
struct vfs_dir_entry_t *dentry = vfs_path_walk(path, 0);
|
||||||
|
|
||||||
|
// if (dentry != NULL)
|
||||||
|
// printk_color(ORANGE, BLACK, "Found %s\nDIR_FstClus:%#018lx\tDIR_FileSize:%#018lx\n", path, ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus, dentry->dir_inode->file_size);
|
||||||
|
// else
|
||||||
|
// printk_color(ORANGE, BLACK, "Can`t find file\n");
|
||||||
|
// kdebug("flags=%#018lx", flags);
|
||||||
|
if (dentry == NULL && flags & O_CREAT)
|
||||||
|
{
|
||||||
|
// 先找到倒数第二级目录
|
||||||
|
int tmp_index = -1;
|
||||||
|
for (int i = path_len - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
if (path[i] == '/')
|
||||||
|
{
|
||||||
|
tmp_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct vfs_dir_entry_t *parent_dentry = NULL;
|
||||||
|
// kdebug("tmp_index=%d", tmp_index);
|
||||||
|
if (tmp_index > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
path[tmp_index] = '\0';
|
||||||
|
dentry = vfs_path_walk(path, 0);
|
||||||
|
if (dentry == NULL)
|
||||||
|
{
|
||||||
|
kfree(path);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
parent_dentry = dentry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
parent_dentry = vfs_root_sb->root;
|
||||||
|
|
||||||
|
// 创建新的文件
|
||||||
|
dentry = (struct vfs_dir_entry_t *)kmalloc(sizeof(struct vfs_dir_entry_t), 0);
|
||||||
|
memset(dentry, 0, sizeof(struct vfs_dir_entry_t));
|
||||||
|
|
||||||
|
dentry->name_length = path_len - tmp_index - 1;
|
||||||
|
dentry->name = (char *)kmalloc(dentry->name_length, 0);
|
||||||
|
memset(dentry->name, 0, dentry->name_length);
|
||||||
|
strncpy(dentry->name, path + tmp_index + 1, dentry->name_length);
|
||||||
|
// kdebug("to create new file:%s namelen=%d", dentry->name, dentry->name_length)
|
||||||
|
dentry->parent = parent_dentry;
|
||||||
|
uint64_t retval = parent_dentry->dir_inode->inode_ops->create(parent_dentry->dir_inode, dentry, 0);
|
||||||
|
if (retval != 0)
|
||||||
|
{
|
||||||
|
kfree(dentry->name);
|
||||||
|
kfree(dentry);
|
||||||
|
kfree(path);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_init(&dentry->child_node_list);
|
||||||
|
list_init(&dentry->subdirs_list);
|
||||||
|
list_add(&parent_dentry->subdirs_list, &dentry->child_node_list);
|
||||||
|
// kdebug("created.");
|
||||||
|
}
|
||||||
|
kfree(path);
|
||||||
|
if (dentry == NULL)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
// 要求打开文件夹而目标不是文件夹
|
||||||
|
if ((flags & O_DIRECTORY) && (dentry->dir_inode->attribute != VFS_ATTR_DIR))
|
||||||
|
return -ENOTDIR;
|
||||||
|
|
||||||
|
// // 要找的目标是文件夹
|
||||||
|
// if ((flags & O_DIRECTORY) && dentry->dir_inode->attribute == VFS_ATTR_DIR)
|
||||||
|
// return -EISDIR;
|
||||||
|
|
||||||
|
// // todo: 引入devfs后删除这段代码
|
||||||
|
// // 暂时遇到设备文件的话,就将其first clus设置为特定值
|
||||||
|
// if (path_len >= 5 && filename[0] == '/' && filename[1] == 'd' && filename[2] == 'e' && filename[3] == 'v' && filename[4] == '/')
|
||||||
|
// {
|
||||||
|
// if (dentry->dir_inode->attribute & VFS_ATTR_FILE)
|
||||||
|
// {
|
||||||
|
// // 对于fat32文件系统上面的设备文件,设置其起始扇区
|
||||||
|
// ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus |= 0xf0000000;
|
||||||
|
// dentry->dir_inode->sb->sb_ops->write_inode(dentry->dir_inode);
|
||||||
|
// dentry->dir_inode->attribute |= VFS_ATTR_DEVICE;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 创建文件描述符
|
||||||
|
struct vfs_file_t *file_ptr = (struct vfs_file_t *)kzalloc(sizeof(struct vfs_file_t), 0);
|
||||||
|
|
||||||
|
int errcode = -1;
|
||||||
|
|
||||||
|
file_ptr->dEntry = dentry;
|
||||||
|
file_ptr->mode = flags;
|
||||||
|
|
||||||
|
file_ptr->file_ops = dentry->dir_inode->file_ops;
|
||||||
|
|
||||||
|
// 如果文件系统实现了打开文件的函数
|
||||||
|
if (file_ptr->file_ops && file_ptr->file_ops->open)
|
||||||
|
errcode = file_ptr->file_ops->open(dentry->dir_inode, file_ptr);
|
||||||
|
|
||||||
|
if (errcode != VFS_SUCCESS)
|
||||||
|
{
|
||||||
|
kfree(file_ptr);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_ptr->mode & O_TRUNC) // 清空文件
|
||||||
|
file_ptr->dEntry->dir_inode->file_size = 0;
|
||||||
|
|
||||||
|
if (file_ptr->mode & O_APPEND)
|
||||||
|
file_ptr->position = file_ptr->dEntry->dir_inode->file_size;
|
||||||
|
else
|
||||||
|
file_ptr->position = 0;
|
||||||
|
|
||||||
|
struct vfs_file_t **f = current_pcb->fds;
|
||||||
|
|
||||||
|
int fd_num = -1;
|
||||||
|
|
||||||
|
// 在指针数组中寻找空位
|
||||||
|
// todo: 当pcb中的指针数组改为动态指针数组之后,需要更改这里(目前还是静态指针数组)
|
||||||
|
for (int i = 0; i < PROC_MAX_FD_NUM; ++i)
|
||||||
|
{
|
||||||
|
if (f[i] == NULL) // 找到指针数组中的空位
|
||||||
|
{
|
||||||
|
fd_num = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 指针数组没有空位了
|
||||||
|
if (fd_num == -1)
|
||||||
|
{
|
||||||
|
kfree(file_ptr);
|
||||||
|
return -EMFILE;
|
||||||
|
}
|
||||||
|
// 保存文件描述符
|
||||||
|
f[fd_num] = file_ptr;
|
||||||
|
|
||||||
|
return fd_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t sys_open(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
char *filename = (char *)(regs->r8);
|
||||||
|
int flags = (int)(regs->r9);
|
||||||
|
|
||||||
|
return do_open(filename, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 动态分配dentry以及路径字符串名称
|
||||||
|
*
|
||||||
|
* @param name_size 名称字符串大小(字节)(注意考虑字符串最后需要有一个‘\0’作为结尾)
|
||||||
|
* @return struct vfs_dir_entry_t* 创建好的dentry
|
||||||
|
*/
|
||||||
|
struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size)
|
||||||
|
{
|
||||||
|
if (unlikely(name_size > VFS_MAX_PATHLEN))
|
||||||
|
return NULL;
|
||||||
|
struct vfs_dir_entry_t *dentry = (struct vfs_dir_entry_t *)kzalloc(sizeof(struct vfs_dir_entry_t), 0);
|
||||||
|
dentry->name = (char *)kzalloc(name_size, 0);
|
||||||
|
list_init(&dentry->child_node_list);
|
||||||
|
list_init(&dentry->subdirs_list);
|
||||||
|
return dentry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化vfs
|
||||||
|
*
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int vfs_init()
|
||||||
|
{
|
||||||
|
mount_init();
|
||||||
|
return 0;
|
||||||
}
|
}
|
@ -14,6 +14,7 @@
|
|||||||
#include <common/glib.h>
|
#include <common/glib.h>
|
||||||
#include <common/fcntl.h>
|
#include <common/fcntl.h>
|
||||||
#include <common/blk_types.h>
|
#include <common/blk_types.h>
|
||||||
|
#include <mm/slab.h>
|
||||||
|
|
||||||
extern struct vfs_superblock_t *vfs_root_sb;
|
extern struct vfs_superblock_t *vfs_root_sb;
|
||||||
|
|
||||||
@ -24,6 +25,8 @@ extern struct vfs_superblock_t *vfs_root_sb;
|
|||||||
#define VFS_E_FS_EXISTED 1 // 错误:文件系统已存在
|
#define VFS_E_FS_EXISTED 1 // 错误:文件系统已存在
|
||||||
#define VFS_E_FS_NOT_EXIST 2 // 错误:文件系统不存在
|
#define VFS_E_FS_NOT_EXIST 2 // 错误:文件系统不存在
|
||||||
|
|
||||||
|
#define VFS_MAX_PATHLEN 1024
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 目录项的属性
|
* @brief 目录项的属性
|
||||||
*
|
*
|
||||||
@ -54,6 +57,7 @@ struct vfs_superblock_t
|
|||||||
{
|
{
|
||||||
struct vfs_dir_entry_t *root;
|
struct vfs_dir_entry_t *root;
|
||||||
struct vfs_super_block_operations_t *sb_ops;
|
struct vfs_super_block_operations_t *sb_ops;
|
||||||
|
struct vfs_dir_entry_operations_t *dir_ops; // dentry's operations
|
||||||
struct block_device *blk_device;
|
struct block_device *blk_device;
|
||||||
void *private_sb_info;
|
void *private_sb_info;
|
||||||
};
|
};
|
||||||
@ -195,4 +199,28 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags);
|
|||||||
* @brief 填充dentry
|
* @brief 填充dentry
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int vfs_fill_dentry(void *buf, ino_t d_ino, char *name, int namelen, unsigned char type, off_t offset);
|
int vfs_fill_dirent(void *buf, ino_t d_ino, char *name, int namelen, unsigned char type, off_t offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化vfs
|
||||||
|
*
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int vfs_init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 动态分配dentry以及路径字符串名称
|
||||||
|
*
|
||||||
|
* @param name_size 名称字符串大小(字节)(注意考虑字符串最后需要有一个‘\0’作为结尾)
|
||||||
|
* @return struct vfs_dir_entry_t* 创建好的dentry
|
||||||
|
*/
|
||||||
|
struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 打开文件
|
||||||
|
*
|
||||||
|
* @param filename 文件路径
|
||||||
|
* @param flags 标志位
|
||||||
|
* @return uint64_t 错误码
|
||||||
|
*/
|
||||||
|
uint64_t do_open(const char *filename, int flags);
|
47
kernel/filesystem/VFS/mount.c
Normal file
47
kernel/filesystem/VFS/mount.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "mount.h"
|
||||||
|
#include "VFS.h"
|
||||||
|
#include <common/glib.h>
|
||||||
|
#include <common/string.h>
|
||||||
|
|
||||||
|
static struct List mnt_list_head; // 挂载点链表头
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化mount机制
|
||||||
|
*
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int mount_init()
|
||||||
|
{
|
||||||
|
list_init(&mnt_list_head);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将new_dentry挂载
|
||||||
|
*
|
||||||
|
* @param old_dentry 挂载点的dentry
|
||||||
|
* @param new_dentry 待挂载的新的dentry(需使用vfs_alloc_dentry来分配)
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int do_mount(struct vfs_dir_entry_t *old_dentry, struct vfs_dir_entry_t *new_dentry)
|
||||||
|
{
|
||||||
|
struct mountpoint *mp = (struct mountpoint *)kzalloc(sizeof(struct mountpoint), 0);
|
||||||
|
list_init(&mp->mnt_list);
|
||||||
|
mp->dentry = old_dentry;
|
||||||
|
mp->parent_dentry = old_dentry->parent;
|
||||||
|
|
||||||
|
kdebug("&new_dentry->name=%#018lx, &old_dentry->name=%#018lx", &new_dentry->name, &old_dentry->name);
|
||||||
|
// 拷贝名称
|
||||||
|
strncpy(new_dentry->name, old_dentry->name, old_dentry->name_length);
|
||||||
|
|
||||||
|
list_init(&new_dentry->child_node_list);
|
||||||
|
list_init(&new_dentry->subdirs_list);
|
||||||
|
new_dentry->parent = old_dentry->parent;
|
||||||
|
|
||||||
|
|
||||||
|
// 将新的dentry的list结点替换掉父dentry的列表中的old_dentry的list结点
|
||||||
|
list_replace(&old_dentry->child_node_list, &new_dentry->child_node_list);
|
||||||
|
list_append(&mnt_list_head, &mp->mnt_list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
29
kernel/filesystem/VFS/mount.h
Normal file
29
kernel/filesystem/VFS/mount.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <common/glib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 挂载点结构体(用来表示dentry被挂载其他文件系统之后,原先存在的数据)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct mountpoint
|
||||||
|
{
|
||||||
|
struct List mnt_list; // 挂载点串在一起的链表
|
||||||
|
struct vfs_dir_entry_t *dentry; // 被挂载前,当前目录项的dentry
|
||||||
|
struct vfs_dir_entry_t *parent_dentry; // 被挂载前,父目录项的dentry
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化mount机制
|
||||||
|
*
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int mount_init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将new_dentry挂载
|
||||||
|
*
|
||||||
|
* @param old_dentry 挂载点的dentry
|
||||||
|
* @param new_dentry 待挂载的新的dentry(需使用vfs_alloc_dentry来分配)
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int do_mount(struct vfs_dir_entry_t *old_dentry, struct vfs_dir_entry_t *new_dentry);
|
6
kernel/filesystem/devfs/chardev.c
Normal file
6
kernel/filesystem/devfs/chardev.c
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "chardev.h"
|
||||||
|
|
||||||
|
int chardev_register()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
4
kernel/filesystem/devfs/chardev.h
Normal file
4
kernel/filesystem/devfs/chardev.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem/VFS/VFS.h>
|
||||||
|
|
34
kernel/filesystem/devfs/devfs-types.h
Normal file
34
kernel/filesystem/devfs/devfs-types.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <filesystem/VFS/VFS.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief devfs_private_file_info_t的type字段值
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DEV_TYPE_UNDEF = 0,
|
||||||
|
DEV_TYPE_CHAR = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 字符设备的sub_type字段值
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CHAR_DEV_STYPE_PS2 = 1,
|
||||||
|
CHAR_DEV_STYPE_USB,
|
||||||
|
CHAR_DEV_STYPE_BLUETOOTH,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 设备文件私有信息结构体
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct devfs_private_inode_info_t
|
||||||
|
{
|
||||||
|
uint16_t type; // 设备主类型
|
||||||
|
uint16_t sub_type; // 设备子类型
|
||||||
|
struct vfs_file_operations_t *f_ops;
|
||||||
|
};
|
@ -1,10 +1,171 @@
|
|||||||
#include "devfs.h"
|
#include "devfs.h"
|
||||||
|
#include <filesystem/VFS/VFS.h>
|
||||||
|
#include <common/glib.h>
|
||||||
|
#include <common/string.h>
|
||||||
|
#include <mm/slab.h>
|
||||||
|
|
||||||
|
static struct vfs_super_block_operations_t devfs_sb_ops;
|
||||||
|
static struct vfs_dir_entry_operations_t devfs_dentry_ops;
|
||||||
|
static struct vfs_file_operations_t devfs_file_ops;
|
||||||
|
static struct vfs_inode_operations_t devfs_inode_ops;
|
||||||
|
|
||||||
|
static struct vfs_dir_entry_t *devfs_root_dentry; // 根结点的dentry
|
||||||
|
static struct vfs_superblock_t devfs_sb = {0};
|
||||||
|
|
||||||
|
extern struct vfs_file_operations_t ps2_keyboard_fops;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建devfs的super block
|
||||||
|
*
|
||||||
|
* @param blk 未使用(devfs为伪文件系统,不需要物理设备)
|
||||||
|
* @return struct vfs_superblock_t*
|
||||||
|
*/
|
||||||
|
struct vfs_superblock_t *devfs_read_superblock(struct block_device *blk)
|
||||||
|
{
|
||||||
|
devfs_sb.blk_device = NULL;
|
||||||
|
devfs_sb.root = devfs_root_dentry;
|
||||||
|
devfs_sb.sb_ops = &devfs_sb_ops;
|
||||||
|
devfs_sb.dir_ops = &devfs_dentry_ops;
|
||||||
|
// todo: 为devfs增加私有信息
|
||||||
|
devfs_sb.private_sb_info = NULL;
|
||||||
|
kdebug("devfs read superblock done");
|
||||||
|
return &devfs_sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void devfs_write_superblock(struct vfs_superblock_t *sb) {}
|
||||||
|
|
||||||
|
static void devfs_put_superblock(struct vfs_superblock_t *sb) {}
|
||||||
|
|
||||||
|
static void devfs_write_inode(struct vfs_index_node_t *inode) {}
|
||||||
|
static struct vfs_super_block_operations_t devfs_sb_ops =
|
||||||
|
{
|
||||||
|
.write_superblock = &devfs_write_superblock,
|
||||||
|
.put_superblock = &devfs_put_superblock,
|
||||||
|
.write_inode = &devfs_write_inode,
|
||||||
|
};
|
||||||
|
|
||||||
|
static long devfs_compare(struct vfs_dir_entry_t *parent_dEntry, char *source_filename, char *dest_filename) {}
|
||||||
|
|
||||||
|
static long devfs_hash(struct vfs_dir_entry_t *dEntry, char *filename) {}
|
||||||
|
|
||||||
|
static long devfs_release(struct vfs_dir_entry_t *dEntry) {}
|
||||||
|
|
||||||
|
static long devfs_iput(struct vfs_dir_entry_t *dEntry, struct vfs_index_node_t *inode) {}
|
||||||
|
|
||||||
|
static struct vfs_dir_entry_operations_t devfs_dentry_ops =
|
||||||
|
{
|
||||||
|
.compare = &devfs_compare,
|
||||||
|
.hash = &devfs_hash,
|
||||||
|
.release = &devfs_release,
|
||||||
|
.iput = &devfs_iput,
|
||||||
|
};
|
||||||
|
|
||||||
|
static long devfs_open(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr) { return 0; }
|
||||||
|
static long devfs_close(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr) {}
|
||||||
|
static long devfs_read(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position) {}
|
||||||
|
static long devfs_write(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position) {}
|
||||||
|
static long devfs_lseek(struct vfs_file_t *file_ptr, long offset, long origin) {}
|
||||||
|
static long devfs_ioctl(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr, uint64_t cmd, uint64_t arg) {return 0;}
|
||||||
|
static long devfs_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t filler) {return 0;}
|
||||||
|
|
||||||
|
static struct vfs_file_operations_t devfs_file_ops =
|
||||||
|
{
|
||||||
|
.open = &devfs_open,
|
||||||
|
.close = &devfs_close,
|
||||||
|
.read = &devfs_read,
|
||||||
|
.write = &devfs_write,
|
||||||
|
.lseek = &devfs_lseek,
|
||||||
|
.ioctl = &devfs_ioctl,
|
||||||
|
.readdir = &devfs_readdir,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建新的文件
|
||||||
|
* @param parent_inode 父目录的inode结构体
|
||||||
|
* @param dest_dEntry 新文件的dentry
|
||||||
|
* @param mode 创建模式
|
||||||
|
*/
|
||||||
|
static long devfs_create(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry, int mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static struct vfs_dir_entry_t *devfs_lookup(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry)
|
||||||
|
{
|
||||||
|
kdebug("devfs_lookup: %s", dest_dEntry->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
static long devfs_mkdir(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry, int mode) {}
|
||||||
|
static long devfs_rmdir(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry) {}
|
||||||
|
static long devfs_rename(struct vfs_index_node_t *old_inode, struct vfs_dir_entry_t *old_dEntry, struct vfs_index_node_t *new_inode, struct vfs_dir_entry_t *new_dEntry) {}
|
||||||
|
static long devfs_getAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr) {}
|
||||||
|
static long devfs_setAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr) {}
|
||||||
|
static struct vfs_inode_operations_t devfs_inode_ops = {
|
||||||
|
.create = &devfs_create,
|
||||||
|
.lookup = &devfs_lookup,
|
||||||
|
.mkdir = &devfs_mkdir,
|
||||||
|
.rmdir = &devfs_rmdir,
|
||||||
|
.rename = &devfs_rename,
|
||||||
|
.getAttr = &devfs_getAttr,
|
||||||
|
.setAttr = &devfs_setAttr,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct vfs_filesystem_type_t devfs_fs_type =
|
||||||
|
{
|
||||||
|
.name = "DEVFS",
|
||||||
|
.fs_flags = 0,
|
||||||
|
.read_superblock = devfs_read_superblock,
|
||||||
|
.next = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static __always_inline void __devfs_init_root_inode()
|
||||||
|
{
|
||||||
|
devfs_root_dentry->dir_inode->file_ops = &devfs_file_ops;
|
||||||
|
devfs_root_dentry->dir_inode->inode_ops = &devfs_inode_ops;
|
||||||
|
|
||||||
|
// todo: 增加private inode info
|
||||||
|
devfs_root_dentry->dir_inode->private_inode_info = NULL;
|
||||||
|
devfs_root_dentry->dir_inode->sb = &devfs_sb;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief 初始化devfs的根dentry
|
||||||
|
*/
|
||||||
|
static __always_inline void __devfs_init_root_dentry()
|
||||||
|
{
|
||||||
|
devfs_root_dentry = (struct vfs_dir_entry_t *)kzalloc(sizeof(struct vfs_dir_entry_t), 0);
|
||||||
|
list_init(&devfs_root_dentry->child_node_list);
|
||||||
|
list_init(&devfs_root_dentry->subdirs_list);
|
||||||
|
devfs_root_dentry->dir_ops = &devfs_dentry_ops;
|
||||||
|
devfs_root_dentry->dir_inode = (struct vfs_index_node_t *)kzalloc(sizeof(struct vfs_index_node_t), 0);
|
||||||
|
__devfs_init_root_inode();
|
||||||
|
}
|
||||||
|
|
||||||
|
int devfs_register_device()
|
||||||
|
{
|
||||||
|
char name[] = "keyboard.dev";
|
||||||
|
struct vfs_dir_entry_t *dentry = vfs_alloc_dentry(sizeof(name));
|
||||||
|
strcpy(dentry->name, name);
|
||||||
|
dentry->name_length = strlen(name);
|
||||||
|
dentry->dir_inode = (struct vfs_index_node_t *)kzalloc(sizeof(struct vfs_index_node_t), 0);
|
||||||
|
dentry->dir_ops = &devfs_dentry_ops;
|
||||||
|
dentry->dir_inode->file_ops = &ps2_keyboard_fops;
|
||||||
|
dentry->dir_inode->inode_ops = &devfs_inode_ops;
|
||||||
|
dentry->dir_inode->private_inode_info = NULL; // todo:
|
||||||
|
dentry->dir_inode->sb = &devfs_sb;
|
||||||
|
dentry->parent = devfs_root_dentry;
|
||||||
|
list_init(&dentry->child_node_list);
|
||||||
|
list_init(&dentry->subdirs_list);
|
||||||
|
list_append(&devfs_root_dentry->subdirs_list, &dentry->child_node_list);
|
||||||
|
kdebug("add dev: %s", dentry->name);
|
||||||
|
// devfs_create(&devfs_root_dentry->dir_inode, dentry->dir_inode, 0);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @brief 初始化devfs
|
* @brief 初始化devfs
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void devfs_init()
|
void devfs_init()
|
||||||
{
|
{
|
||||||
|
__devfs_init_root_dentry();
|
||||||
|
vfs_register_filesystem(&devfs_fs_type);
|
||||||
|
vfs_mount_fs("/dev", "DEVFS", NULL);
|
||||||
|
|
||||||
|
devfs_register_device();
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化devfs
|
* @brief 初始化devfs
|
||||||
*
|
*
|
||||||
|
@ -343,6 +343,7 @@ struct vfs_superblock_t *fat32_read_superblock(struct block_device *blk)
|
|||||||
struct vfs_superblock_t *sb_ptr = (struct vfs_superblock_t *)kzalloc(sizeof(struct vfs_superblock_t), 0);
|
struct vfs_superblock_t *sb_ptr = (struct vfs_superblock_t *)kzalloc(sizeof(struct vfs_superblock_t), 0);
|
||||||
blk->bd_superblock = sb_ptr;
|
blk->bd_superblock = sb_ptr;
|
||||||
sb_ptr->sb_ops = &fat32_sb_ops;
|
sb_ptr->sb_ops = &fat32_sb_ops;
|
||||||
|
sb_ptr->dir_ops = &fat32_dEntry_ops;
|
||||||
sb_ptr->private_sb_info = kzalloc(sizeof(fat32_sb_info_t), 0);
|
sb_ptr->private_sb_info = kzalloc(sizeof(fat32_sb_info_t), 0);
|
||||||
sb_ptr->blk_device = blk;
|
sb_ptr->blk_device = blk;
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <driver/usb/usb.h>
|
#include <driver/usb/usb.h>
|
||||||
#include <exception/gate.h>
|
#include <exception/gate.h>
|
||||||
#include <filesystem/fat32/fat32.h>
|
#include <filesystem/fat32/fat32.h>
|
||||||
|
#include <filesystem/devfs/devfs.h>
|
||||||
#include <mm/slab.h>
|
#include <mm/slab.h>
|
||||||
#include <common/spinlock.h>
|
#include <common/spinlock.h>
|
||||||
#include <syscall/syscall.h>
|
#include <syscall/syscall.h>
|
||||||
@ -464,7 +465,9 @@ ul initial_kernel_thread(ul arg)
|
|||||||
{
|
{
|
||||||
// kinfo("initial proc running...\targ:%#018lx", arg);
|
// kinfo("initial proc running...\targ:%#018lx", arg);
|
||||||
ahci_init();
|
ahci_init();
|
||||||
|
vfs_init();
|
||||||
fat32_init();
|
fat32_init();
|
||||||
|
devfs_init();
|
||||||
// 使用单独的内核线程来初始化usb驱动程序
|
// 使用单独的内核线程来初始化usb驱动程序
|
||||||
int usb_pid = kernel_thread(usb_init, 0, 0);
|
int usb_pid = kernel_thread(usb_init, 0, 0);
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include <common/string.h>
|
#include <common/string.h>
|
||||||
#include <filesystem/fat32/fat32.h>
|
#include <filesystem/fat32/fat32.h>
|
||||||
#include <filesystem/VFS/VFS.h>
|
#include <filesystem/VFS/VFS.h>
|
||||||
#include <driver/keyboard/ps2_keyboard.h>
|
|
||||||
#include <process/process.h>
|
#include <process/process.h>
|
||||||
#include <time/sleep.h>
|
#include <time/sleep.h>
|
||||||
|
|
||||||
@ -19,6 +18,7 @@ extern void syscall_int(void);
|
|||||||
|
|
||||||
extern uint64_t sys_clock(struct pt_regs *regs);
|
extern uint64_t sys_clock(struct pt_regs *regs);
|
||||||
extern uint64_t sys_mstat(struct pt_regs *regs);
|
extern uint64_t sys_mstat(struct pt_regs *regs);
|
||||||
|
extern uint64_t sys_open(struct pt_regs *regs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 导出系统调用处理函数的符号
|
* @brief 导出系统调用处理函数的符号
|
||||||
@ -121,186 +121,7 @@ ul sys_put_string(struct pt_regs *regs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t sys_open(struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
char *filename = (char *)(regs->r8);
|
|
||||||
int flags = (int)(regs->r9);
|
|
||||||
// kdebug("filename=%s", filename);
|
|
||||||
|
|
||||||
long path_len = strnlen_user(filename, PAGE_4K_SIZE) + 1;
|
|
||||||
|
|
||||||
if (path_len <= 0) // 地址空间错误
|
|
||||||
{
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
else if (path_len >= PAGE_4K_SIZE) // 名称过长
|
|
||||||
{
|
|
||||||
return -ENAMETOOLONG;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 为待拷贝文件路径字符串分配内存空间
|
|
||||||
char *path = (char *)kmalloc(path_len, 0);
|
|
||||||
if (path == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
memset(path, 0, path_len);
|
|
||||||
|
|
||||||
strncpy_from_user(path, filename, path_len);
|
|
||||||
// 去除末尾的 '/'
|
|
||||||
if (path_len >= 2 && path[path_len - 2] == '/')
|
|
||||||
{
|
|
||||||
path[path_len - 2] = '\0';
|
|
||||||
--path_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 寻找文件
|
|
||||||
struct vfs_dir_entry_t *dentry = vfs_path_walk(path, 0);
|
|
||||||
|
|
||||||
// if (dentry != NULL)
|
|
||||||
// printk_color(ORANGE, BLACK, "Found %s\nDIR_FstClus:%#018lx\tDIR_FileSize:%#018lx\n", path, ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus, dentry->dir_inode->file_size);
|
|
||||||
// else
|
|
||||||
// printk_color(ORANGE, BLACK, "Can`t find file\n");
|
|
||||||
// kdebug("flags=%#018lx", flags);
|
|
||||||
if (dentry == NULL && flags & O_CREAT)
|
|
||||||
{
|
|
||||||
// 先找到倒数第二级目录
|
|
||||||
int tmp_index = -1;
|
|
||||||
for (int i = path_len - 1; i >= 0; --i)
|
|
||||||
{
|
|
||||||
if (path[i] == '/')
|
|
||||||
{
|
|
||||||
tmp_index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct vfs_dir_entry_t *parent_dentry = NULL;
|
|
||||||
// kdebug("tmp_index=%d", tmp_index);
|
|
||||||
if (tmp_index > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
path[tmp_index] = '\0';
|
|
||||||
dentry = vfs_path_walk(path, 0);
|
|
||||||
if (dentry == NULL)
|
|
||||||
{
|
|
||||||
kfree(path);
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
parent_dentry = dentry;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
parent_dentry = vfs_root_sb->root;
|
|
||||||
|
|
||||||
// 创建新的文件
|
|
||||||
dentry = (struct vfs_dir_entry_t *)kmalloc(sizeof(struct vfs_dir_entry_t), 0);
|
|
||||||
memset(dentry, 0, sizeof(struct vfs_dir_entry_t));
|
|
||||||
|
|
||||||
dentry->name_length = path_len - tmp_index - 1;
|
|
||||||
dentry->name = (char *)kmalloc(dentry->name_length, 0);
|
|
||||||
memset(dentry->name, 0, dentry->name_length);
|
|
||||||
strncpy(dentry->name, path + tmp_index + 1, dentry->name_length);
|
|
||||||
// kdebug("to create new file:%s namelen=%d", dentry->name, dentry->name_length)
|
|
||||||
dentry->parent = parent_dentry;
|
|
||||||
uint64_t retval = parent_dentry->dir_inode->inode_ops->create(parent_dentry->dir_inode, dentry, 0);
|
|
||||||
if (retval != 0)
|
|
||||||
{
|
|
||||||
kfree(dentry->name);
|
|
||||||
kfree(dentry);
|
|
||||||
kfree(path);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_init(&dentry->child_node_list);
|
|
||||||
list_init(&dentry->subdirs_list);
|
|
||||||
list_add(&parent_dentry->subdirs_list, &dentry->child_node_list);
|
|
||||||
// kdebug("created.");
|
|
||||||
}
|
|
||||||
kfree(path);
|
|
||||||
if (dentry == NULL)
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
// 要求打开文件夹而目标不是文件夹
|
|
||||||
if ((flags & O_DIRECTORY) && (dentry->dir_inode->attribute != VFS_ATTR_DIR))
|
|
||||||
return -ENOTDIR;
|
|
||||||
|
|
||||||
// // 要找的目标是文件夹
|
|
||||||
// if ((flags & O_DIRECTORY) && dentry->dir_inode->attribute == VFS_ATTR_DIR)
|
|
||||||
// return -EISDIR;
|
|
||||||
|
|
||||||
// todo: 引入devfs后删除这段代码
|
|
||||||
// 暂时遇到设备文件的话,就将其first clus设置为特定值
|
|
||||||
if (path_len >= 5 && filename[0] == '/' && filename[1] == 'd' && filename[2] == 'e' && filename[3] == 'v' && filename[4] == '/')
|
|
||||||
{
|
|
||||||
if (dentry->dir_inode->attribute & VFS_ATTR_FILE)
|
|
||||||
{
|
|
||||||
// 对于fat32文件系统上面的设备文件,设置其起始扇区
|
|
||||||
((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus |= 0xf0000000;
|
|
||||||
dentry->dir_inode->sb->sb_ops->write_inode(dentry->dir_inode);
|
|
||||||
dentry->dir_inode->attribute |= VFS_ATTR_DEVICE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建文件描述符
|
|
||||||
struct vfs_file_t *file_ptr = (struct vfs_file_t *)kmalloc(sizeof(struct vfs_file_t), 0);
|
|
||||||
memset(file_ptr, 0, sizeof(struct vfs_file_t));
|
|
||||||
|
|
||||||
int errcode = -1;
|
|
||||||
|
|
||||||
file_ptr->dEntry = dentry;
|
|
||||||
file_ptr->mode = flags;
|
|
||||||
|
|
||||||
// todo: 接入devfs
|
|
||||||
// 特判一下是否为键盘文件
|
|
||||||
if (dentry->dir_inode->attribute & VFS_ATTR_DEVICE)
|
|
||||||
{
|
|
||||||
file_ptr->file_ops = &ps2_keyboard_fops; // 如果是设备文件,暂时认为它是键盘文件
|
|
||||||
}
|
|
||||||
else
|
|
||||||
file_ptr->file_ops = dentry->dir_inode->file_ops;
|
|
||||||
|
|
||||||
// 如果文件系统实现了打开文件的函数
|
|
||||||
if (file_ptr->file_ops && file_ptr->file_ops->open)
|
|
||||||
errcode = file_ptr->file_ops->open(dentry->dir_inode, file_ptr);
|
|
||||||
|
|
||||||
if (errcode != VFS_SUCCESS)
|
|
||||||
{
|
|
||||||
kfree(file_ptr);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_ptr->mode & O_TRUNC) // 清空文件
|
|
||||||
file_ptr->dEntry->dir_inode->file_size = 0;
|
|
||||||
|
|
||||||
if (file_ptr->mode & O_APPEND)
|
|
||||||
file_ptr->position = file_ptr->dEntry->dir_inode->file_size;
|
|
||||||
else
|
|
||||||
file_ptr->position = 0;
|
|
||||||
|
|
||||||
struct vfs_file_t **f = current_pcb->fds;
|
|
||||||
|
|
||||||
int fd_num = -1;
|
|
||||||
|
|
||||||
// 在指针数组中寻找空位
|
|
||||||
// todo: 当pcb中的指针数组改为动态指针数组之后,需要更改这里(目前还是静态指针数组)
|
|
||||||
for (int i = 0; i < PROC_MAX_FD_NUM; ++i)
|
|
||||||
{
|
|
||||||
if (f[i] == NULL) // 找到指针数组中的空位
|
|
||||||
{
|
|
||||||
fd_num = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 指针数组没有空位了
|
|
||||||
if (fd_num == -1)
|
|
||||||
{
|
|
||||||
kfree(file_ptr);
|
|
||||||
return -EMFILE;
|
|
||||||
}
|
|
||||||
// 保存文件描述符
|
|
||||||
f[fd_num] = file_ptr;
|
|
||||||
|
|
||||||
return fd_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 关闭文件系统调用
|
* @brief 关闭文件系统调用
|
||||||
@ -624,7 +445,7 @@ uint64_t sys_getdents(struct pt_regs *regs)
|
|||||||
|
|
||||||
uint64_t retval = 0;
|
uint64_t retval = 0;
|
||||||
if (filp->file_ops && filp->file_ops->readdir)
|
if (filp->file_ops && filp->file_ops->readdir)
|
||||||
retval = filp->file_ops->readdir(filp, dirent, &vfs_fill_dentry);
|
retval = filp->file_ops->readdir(filp, dirent, &vfs_fill_dirent);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user