|
|
|
/*
|
|
|
|
* Interface functions between file system and kernel/processes. added @lab4_1
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "proc_file.h"
|
|
|
|
|
|
|
|
#include "hostfs.h"
|
|
|
|
#include "pmm.h"
|
|
|
|
#include "process.h"
|
|
|
|
#include "ramdev.h"
|
|
|
|
#include "rfs.h"
|
|
|
|
#include "riscv.h"
|
|
|
|
#include "spike_interface/spike_file.h"
|
|
|
|
#include "spike_interface/spike_utils.h"
|
|
|
|
#include "util/functions.h"
|
|
|
|
#include "util/string.h"
|
|
|
|
|
|
|
|
//
|
|
|
|
// initialize file system
|
|
|
|
//
|
|
|
|
void fs_init(void) {
|
|
|
|
// initialize the vfs
|
|
|
|
vfs_init();
|
|
|
|
|
|
|
|
// register hostfs and mount it as the root
|
|
|
|
if( register_hostfs() < 0 ) panic( "fs_init: cannot register hostfs.\n" );
|
|
|
|
struct device *hostdev = init_host_device("HOSTDEV");
|
|
|
|
vfs_mount("HOSTDEV", MOUNT_AS_ROOT);
|
|
|
|
|
|
|
|
// register and mount rfs
|
|
|
|
if( register_rfs() < 0 ) panic( "fs_init: cannot register rfs.\n" );
|
|
|
|
struct device *ramdisk0 = init_rfs_device("RAMDISK0");
|
|
|
|
rfs_format_dev(ramdisk0);
|
|
|
|
vfs_mount("RAMDISK0", MOUNT_DEFAULT);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// initialize a proc_file_management data structure for a process.
|
|
|
|
// return the pointer to the page containing the data structure.
|
|
|
|
//
|
|
|
|
proc_file_management *init_proc_file_management(void) {
|
|
|
|
proc_file_management *pfiles = (proc_file_management *)alloc_page();
|
|
|
|
pfiles->cwd = vfs_root_dentry; // by default, cwd is the root
|
|
|
|
pfiles->nfiles = 0;
|
|
|
|
|
|
|
|
for (int fd = 0; fd < MAX_FILES; ++fd)
|
|
|
|
pfiles->opened_files[fd].status = FD_NONE;
|
|
|
|
|
|
|
|
sprint("FS: created a file management struct for a process.\n");
|
|
|
|
return pfiles;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// reclaim the open-file management data structure of a process.
|
|
|
|
// note: this function is not used as PKE does not actually reclaim a process.
|
|
|
|
//
|
|
|
|
void reclaim_proc_file_management(proc_file_management *pfiles) {
|
|
|
|
free_page(pfiles);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// get an opened file from proc->opened_file array.
|
|
|
|
// return: the pointer to the opened file structure.
|
|
|
|
//
|
|
|
|
struct file *get_opened_file(int fd) {
|
|
|
|
struct file *pfile = NULL;
|
|
|
|
|
|
|
|
// browse opened file list to locate the fd
|
|
|
|
for (int i = 0; i < MAX_FILES; ++i) {
|
|
|
|
pfile = &(current->pfiles->opened_files[i]); // file entry
|
|
|
|
if (i == fd) break;
|
|
|
|
}
|
|
|
|
if (pfile == NULL) panic("do_read: invalid fd!\n");
|
|
|
|
return pfile;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// open a file named as "pathname" with the permission of "flags".
|
|
|
|
// return: -1 on failure; non-zero file-descriptor on success.
|
|
|
|
//
|
|
|
|
int do_open(char *pathname, int flags) {
|
|
|
|
struct file *opened_file = NULL;
|
|
|
|
if ((opened_file = vfs_open(pathname, flags)) == NULL) return -1;
|
|
|
|
|
|
|
|
int fd = 0;
|
|
|
|
if (current->pfiles->nfiles >= MAX_FILES) {
|
|
|
|
panic("do_open: no file entry for current process!\n");
|
|
|
|
}
|
|
|
|
struct file *pfile;
|
|
|
|
for (fd = 0; fd < MAX_FILES; ++fd) {
|
|
|
|
pfile = &(current->pfiles->opened_files[fd]);
|
|
|
|
if (pfile->status == FD_NONE) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// initialize this file structure
|
|
|
|
memcpy(pfile, opened_file, sizeof(struct file));
|
|
|
|
|
|
|
|
++current->pfiles->nfiles;
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// read content of a file ("fd") into "buf" for "count".
|
|
|
|
// return: actual length of data read from the file.
|
|
|
|
//
|
|
|
|
int do_read(int fd, char *buf, uint64 count) {
|
|
|
|
struct file *pfile = get_opened_file(fd);
|
|
|
|
|
|
|
|
if (pfile->readable == 0) panic("do_read: no readable file!\n");
|
|
|
|
|
|
|
|
char buffer[count + 1];
|
|
|
|
int len = vfs_read(pfile, buffer, count);
|
|
|
|
buffer[count] = '\0';
|
|
|
|
strcpy(buf, buffer);
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// write content ("buf") whose length is "count" to a file "fd".
|
|
|
|
// return: actual length of data written to the file.
|
|
|
|
//
|
|
|
|
int do_write(int fd, char *buf, uint64 count) {
|
|
|
|
struct file *pfile = get_opened_file(fd);
|
|
|
|
|
|
|
|
if (pfile->writable == 0) panic("do_write: cannot write file!\n");
|
|
|
|
|
|
|
|
int len = vfs_write(pfile, buf, count);
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// reposition the file offset
|
|
|
|
//
|
|
|
|
int do_lseek(int fd, int offset, int whence) {
|
|
|
|
struct file *pfile = get_opened_file(fd);
|
|
|
|
return vfs_lseek(pfile, offset, whence);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// read the vinode information
|
|
|
|
//
|
|
|
|
int do_stat(int fd, struct istat *istat) {
|
|
|
|
struct file *pfile = get_opened_file(fd);
|
|
|
|
return vfs_stat(pfile, istat);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// read the inode information on the disk
|
|
|
|
//
|
|
|
|
int do_disk_stat(int fd, struct istat *istat) {
|
|
|
|
struct file *pfile = get_opened_file(fd);
|
|
|
|
return vfs_disk_stat(pfile, istat);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// close a file
|
|
|
|
//
|
|
|
|
int do_close(int fd) {
|
|
|
|
struct file *pfile = get_opened_file(fd);
|
|
|
|
return vfs_close(pfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// open a directory
|
|
|
|
// return: the fd of the directory file
|
|
|
|
//
|
|
|
|
int do_opendir(char *pathname) {
|
|
|
|
struct file *opened_file = NULL;
|
|
|
|
if ((opened_file = vfs_opendir(pathname)) == NULL) return -1;
|
|
|
|
|
|
|
|
int fd = 0;
|
|
|
|
struct file *pfile;
|
|
|
|
for (fd = 0; fd < MAX_FILES; ++fd) {
|
|
|
|
pfile = &(current->pfiles->opened_files[fd]);
|
|
|
|
if (pfile->status == FD_NONE) break;
|
|
|
|
}
|
|
|
|
if (pfile->status != FD_NONE) // no free entry
|
|
|
|
panic("do_opendir: no file entry for current process!\n");
|
|
|
|
|
|
|
|
// initialize this file structure
|
|
|
|
memcpy(pfile, opened_file, sizeof(struct file));
|
|
|
|
|
|
|
|
++current->pfiles->nfiles;
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// read a directory entry
|
|
|
|
//
|
|
|
|
int do_readdir(int fd, struct dir *dir) {
|
|
|
|
struct file *pfile = get_opened_file(fd);
|
|
|
|
return vfs_readdir(pfile, dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// make a new directory
|
|
|
|
//
|
|
|
|
int do_mkdir(char *pathname) {
|
|
|
|
return vfs_mkdir(pathname);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// close a directory
|
|
|
|
//
|
|
|
|
int do_closedir(int fd) {
|
|
|
|
struct file *pfile = get_opened_file(fd);
|
|
|
|
return vfs_closedir(pfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// create hard link to a file
|
|
|
|
//
|
|
|
|
int do_link(char *oldpath, char *newpath) {
|
|
|
|
return vfs_link(oldpath, newpath);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// remove a hard link to a file
|
|
|
|
//
|
|
|
|
int do_unlink(char *path) {
|
|
|
|
return vfs_unlink(path);
|
|
|
|
}
|