aos/lib/fs/fopen.c
Daniel Schwyn 6d444bf552 Main handout
Signed-off-by: Daniel Schwyn <daniel.schwyn@inf.ethz.ch>
2022-03-03 14:57:51 +01:00

299 lines
6.9 KiB
C

/**
* \file fopen.c
* \brief
*/
/*
* Copyright (c) 2016 ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
* If you do not find this file, copies can be found by writing to:
* ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
*/
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <aos/aos.h>
#include <fs/fs.h>
#include <fs/dirent.h>
#include <fs/ramfs.h>
#include "fs_internal.h"
static void *mount;
/*
* FD table
*/
#define STDIN_FILENO 0 /* standard input file descriptor */
#define STDOUT_FILENO 1 /* standard output file descriptor */
#define STDERR_FILENO 2 /* standard error file descriptor */
static struct fdtab_entry fdtab[MAX_FD] = {
[STDIN_FILENO] = {
.type = FDTAB_TYPE_STDIN,
.handle = NULL,
},
[STDOUT_FILENO] = {
.type = FDTAB_TYPE_STDOUT,
.handle = NULL,
},
[STDERR_FILENO] = {
.type = FDTAB_TYPE_STDERR,
.handle = NULL,
},
};
static int fdtab_alloc(struct fdtab_entry *h)
{
for (int fd = MIN_FD; fd < MAX_FD; fd++) {
if (fdtab[fd].type == FDTAB_TYPE_AVAILABLE) {
fdtab[fd].inherited = 0; // Just precautionary
memcpy(&fdtab[fd], h, sizeof(struct fdtab_entry));
return fd;
}
}
// table full
errno = EMFILE;
return -1;
}
static struct fdtab_entry *fdtab_get(int fd)
{
static struct fdtab_entry invalid = {
.type = FDTAB_TYPE_AVAILABLE,
.handle = NULL,
.inherited = 0,
};
if (fd < MIN_FD || fd >= MAX_FD) {
return &invalid;
} else {
return &fdtab[fd];
}
}
static void fdtab_free(int fd)
{
assert(fd >= MIN_FD && fd < MAX_FD);
assert(fdtab[fd].type != FDTAB_TYPE_AVAILABLE);
fdtab[fd].type = FDTAB_TYPE_AVAILABLE;
fdtab[fd].handle = NULL;
fdtab[fd].fd = 0;
fdtab[fd].inherited = 0;
}
//XXX: flags are ignored...
static int fs_libc_open(char *path, int flags)
{
ramfs_handle_t vh;
errval_t err;
// If O_CREAT was given, we use ramfsfs_create()
if(flags & O_CREAT) {
// If O_EXCL was also given, we check whether we can open() first
if(flags & O_EXCL) {
err = ramfs_open(mount, path, &vh);
if(err_is_ok(err)) {
ramfs_close(mount, vh);
errno = EEXIST;
return -1;
}
assert(err_no(err) == FS_ERR_NOTFOUND);
}
err = ramfs_create(mount, path, &vh);
if (err_is_fail(err) && err == FS_ERR_EXISTS) {
err = ramfs_open(mount, path, &vh);
}
} else {
// Regular open()
err = ramfs_open(mount, path, &vh);
}
if (err_is_fail(err)) {
switch(err_no(err)) {
case FS_ERR_NOTFOUND:
errno = ENOENT;
break;
default:
break;
}
return -1;
}
struct fdtab_entry e = {
.type = FDTAB_TYPE_FILE,
.handle = vh,
.epoll_fd = -1,
};
int fd = fdtab_alloc(&e);
if (fd < 0) {
ramfs_close(mount, vh);
return -1;
} else {
return fd;
}
}
static int fs_libc_read(int fd, void *buf, size_t len)
{
errval_t err;
struct fdtab_entry *e = fdtab_get(fd);
size_t retlen = 0;
switch(e->type) {
case FDTAB_TYPE_FILE:
{
ramfs_handle_t fh = e->handle;
assert(e->handle);
err = ramfs_read(mount, fh, buf, len, &retlen);
if (err_is_fail(err)) {
return -1;
}
}
break;
default :
return -1;
}
return retlen;
}
static int fs_libc_write(int fd, void *buf, size_t len)
{
struct fdtab_entry *e = fdtab_get(fd);
if (e->type == FDTAB_TYPE_AVAILABLE) {
return -1;
}
size_t retlen = 0;
switch(e->type) {
case FDTAB_TYPE_FILE:
{
ramfs_handle_t fh = e->handle;
errval_t err = ramfs_write(mount, fh, buf, len, &retlen);
if (err_is_fail(err)) {
return -1;
}
}
break;
default :
return -1;
}
return retlen;
}
static int fs_libc_close(int fd)
{
errval_t err;
struct fdtab_entry *e = fdtab_get(fd);
if (e->type == FDTAB_TYPE_AVAILABLE) {
return -1;
}
ramfs_handle_t fh = e->handle;
switch(e->type) {
case FDTAB_TYPE_FILE:
err = ramfs_close(mount, fh);
if (err_is_fail(err)) {
return -1;
}
break;
default:
return -1;
}
fdtab_free(fd);
return 0;
}
static off_t fs_libc_lseek(int fd, off_t offset, int whence)
{
struct fdtab_entry *e = fdtab_get(fd);
ramfs_handle_t fh = e->handle;
switch(e->type) {
case FDTAB_TYPE_FILE:
{
enum fs_seekpos fs_whence;
errval_t err;
size_t retpos;
switch(whence) {
case SEEK_SET:
fs_whence = FS_SEEK_SET;
break;
case SEEK_CUR:
fs_whence = FS_SEEK_CUR;
break;
case SEEK_END:
fs_whence = FS_SEEK_END;
break;
default:
return -1;
}
err = ramfs_seek(mount, fh, fs_whence, offset);
if(err_is_fail(err)) {
DEBUG_ERR(err, "vfs_seek");
return -1;
}
err = ramfs_tell(mount, fh, &retpos);
if(err_is_fail(err)) {
return -1;
}
return retpos;
}
break;
default:
return -1;
}
}
static errval_t fs_mkdir(const char *path){ return ramfs_mkdir(mount, path);}
static errval_t fs_rmdir(const char *path){ return ramfs_rmdir(mount, path); }
static errval_t fs_rm(const char *path){ return ramfs_remove(mount, path); }
static errval_t fs_opendir(const char *path, fs_dirhandle_t *h){ return ramfs_opendir(mount, path, h); }
static errval_t fs_readdir(fs_dirhandle_t h, char **name) { return ramfs_dir_read_next(mount, h, name, NULL); }
static errval_t fs_closedir(fs_dirhandle_t h) { return ramfs_closedir(mount, h); }
static errval_t fs_fstat(fs_dirhandle_t h, struct fs_fileinfo *b) { return ramfs_stat(mount, h, b); }
typedef int fsopen_fn_t(char *, int);
typedef int fsread_fn_t(int, void *buf, size_t);
typedef int fswrite_fn_t(int, void *, size_t);
typedef int fsclose_fn_t(int);
typedef off_t fslseek_fn_t(int, off_t, int);
void
newlib_register_fsops__(fsopen_fn_t *open_fn,
fsread_fn_t *read_fn,
fswrite_fn_t *write_fn,
fsclose_fn_t *close_fn,
fslseek_fn_t *lseek_fn);
void fs_libc_init(void *fs_state)
{
newlib_register_fsops__(fs_libc_open, fs_libc_read, fs_libc_write,
fs_libc_close, fs_libc_lseek);
/* register directory operations */
fs_register_dirops(fs_mkdir, fs_rmdir, fs_rm, fs_opendir,
fs_readdir, fs_closedir, fs_fstat);
mount = fs_state;
}