2025-10-10 16:07:00 +08:00

692 lines
11 KiB
C

#include "os/os.h"
#include "os/str.h"
#include "os/mem.h"
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "bk_vfs.h"
#include "bk_fdtable.h"
#include "bk_filesystem.h"
#include "bk_file_utils.h"
#ifndef ENOTSUP
#define ENOTSUP EOPNOTSUPP
#endif
static void bk_set_errno(int _errno) {
errno = -_errno;
}
static struct bk_file *get_file(int fd) {
struct bk_file *file;
if (bk_vfs_lock() != 0) {
bk_set_errno(EFAULT);
return NULL;
}
file = bk_fd_to_file(fd);
if (!file) {
bk_set_errno(EBADF);
bk_vfs_unlock();
}
return file;
}
static void put_file(struct bk_file *file) {
if (!file)
return;
bk_vfs_unlock();
}
#if CONFIG_STARBURST_AIDIALOG_SDK
int bk_vfs_open(const char *path, int oflag) {
struct bk_file *file;
char *full_path = NULL;
struct bk_filesystem *fs;
int ret = -1;
int fd = -1;
if (bk_vfs_lock() != 0) {
return -1;
}
full_path = bk_normalize_path(path);
if (!full_path)
goto out;
fs = bk_vfs_lookup(full_path);
if (!fs) {
goto out;
}
file = bk_file_get(); //acquire file
if (!file) {
bk_set_errno(ENFILE);
goto out;
}
file->path = os_strdup(bk_sub_path(fs->mount_point, full_path));
if (!file->path) {
bk_set_errno(ENOMEM);
goto out;
}
file->filesystem = fs;
file->f_ops = fs->f_ops;
file->flags = oflag;
file->size = 0;
file->pos = 0;
if (file->f_ops && file->f_ops->open) {
ret = file->f_ops->open(file, file->path, oflag);
if (ret == 0)
fd = bk_file_to_fd(file);
else
bk_file_put(file);
} else {
bk_set_errno(ENOTSUP);
bk_file_put(file);
}
if( -1 == fd && file->path){
os_free(file->path);
file->path=NULL;
}
out :
if (full_path)
os_free(full_path);
bk_vfs_unlock();
return fd;
}
#else
int bk_vfs_open(const char *path, int oflag) {
struct bk_file *file;
char *full_path = NULL;
struct bk_filesystem *fs;
int ret = -1;
int fd = -1;
if (bk_vfs_lock() != 0) {
return -1;
}
full_path = bk_normalize_path(path);
if (!full_path)
goto out;
fs = bk_vfs_lookup(full_path);
if (!fs) {
goto out;
}
file = bk_file_get(); //acquire file
if (!file) {
bk_set_errno(ENFILE);
goto out;
}
file->path = strdup(bk_sub_path(fs->mount_point, full_path));
if (!file->path) {
bk_set_errno(ENOMEM);
goto cleanup_file;
}
file->filesystem = fs;
file->f_ops = fs->f_ops;
file->flags = oflag;
file->size = 0;
file->pos = 0;
if (file->f_ops && file->f_ops->open) {
ret = file->f_ops->open(file, file->path, oflag);
if (ret == 0) {
fd = bk_file_to_fd(file);
} else {
goto cleanup_file;
}
} else {
bk_set_errno(ENOTSUP);
goto cleanup_file;
}
goto out;
cleanup_file:
if (file->path) {
os_free(file->path);
}
bk_file_put(file);
out :
if (full_path)
os_free(full_path);
bk_vfs_unlock();
return fd;
}
#endif
int bk_vfs_close(int fd) {
struct bk_file *file;
int ret = -1;
file = get_file(fd);
if (!file) {
return -1;
}
if (file->f_ops && file->f_ops->close) {
ret = file->f_ops->close(file);
} else {
bk_set_errno(ENOTSUP);
}
if (file->path) {
os_free(file->path);
file->path = NULL;
}
put_file(file);
bk_file_put(file); //release file
return ret;
}
ssize_t bk_vfs_read(int fd, void *buf, size_t count) {
struct bk_file *file;
ssize_t ret = -1;
file = get_file(fd);
if (!file) {
return -1;
}
if (file->f_ops && file->f_ops->read) {
ret = file->f_ops->read(file, buf, count);
} else {
bk_set_errno(ENOTSUP);
}
put_file(file);
return ret;
}
ssize_t bk_vfs_write(int fd, const void *buf, size_t count) {
struct bk_file *file;
ssize_t ret = -1;
file = get_file(fd);
if (!file) {
return -1;
}
if (file->f_ops && file->f_ops->write) {
ret = file->f_ops->write(file, buf, count);
} else {
bk_set_errno(ENOTSUP);
}
put_file(file);
return ret;
}
off_t bk_vfs_lseek(int fd, off_t offset, int whence) {
struct bk_file *file;
off_t ret = -1;
file = get_file(fd);
if (!file) {
return -1;
}
if (file->f_ops && file->f_ops->lseek) {
ret = file->f_ops->lseek(file, offset, whence);
} else {
bk_set_errno(ENOTSUP);
}
put_file(file);
return ret;
}
int bk_vfs_unlink(const char *pathname) {
char *full_path = NULL;
struct bk_filesystem *fs;
int ret = -1;
if (bk_vfs_lock() != 0) {
return -1;
}
full_path = bk_normalize_path(pathname);
if (!full_path) {
goto out;
}
fs = bk_vfs_lookup(full_path);
if (!fs) {
goto out;
}
if (fs->f_ops->unlink) {
ret = fs->f_ops->unlink(fs, bk_sub_path(fs->mount_point, full_path));
} else {
bk_set_errno(ENOTSUP);
}
out:
if (full_path)
os_free(full_path);
bk_vfs_unlock();
return ret;
}
int bk_vfs_stat(const char *pathname, struct stat *statbuf) {
char *full_path = NULL;
struct bk_filesystem *fs;
int ret = -1;
if (bk_vfs_lock() != 0) {
return -1;
}
full_path = bk_normalize_path(pathname);
if (!full_path) {
goto out;
}
fs = bk_vfs_lookup(full_path);
if (!fs) {
goto out;
}
if (fs->f_ops->stat) {
ret = fs->f_ops->stat(fs, bk_sub_path(fs->mount_point, full_path), statbuf);
} else {
bk_set_errno(ENOTSUP);
}
out:
if (full_path)
os_free(full_path);
bk_vfs_unlock();
return ret;
}
int bk_vfs_fstat(int fd, struct stat *statbuf) {
return -1;
}
int bk_vfs_rename(const char *oldpath, const char *newpath) {
char *full_path_old = NULL;
char *full_path_new = NULL;
struct bk_filesystem *fs_old;
struct bk_filesystem *fs_new;
int ret = -1;
if (bk_vfs_lock() != 0) {
return -1;
}
full_path_old = bk_normalize_path(oldpath);
if (!full_path_old) {
goto out;
}
fs_old = bk_vfs_lookup(full_path_old);
if (!fs_old) {
goto out;
}
if (!fs_old->f_ops->rename) {
bk_set_errno(ENOTSUP);
goto out;
}
full_path_new = bk_normalize_path(newpath);
if (!full_path_new) {
goto out;
}
fs_new = bk_vfs_lookup(full_path_new);
if (!fs_new) {
goto out;
}
if (fs_old == fs_new) {
ret = fs_old->f_ops->rename(fs_old,
bk_sub_path(fs_old->mount_point, full_path_old),
bk_sub_path(fs_new->mount_point, full_path_new));
} else {
bk_set_errno(ENOTSUP);
}
out:
if (full_path_old)
os_free(full_path_old);
if (full_path_new)
os_free(full_path_new);
bk_vfs_unlock();
return ret;
}
int bk_vfs_fsync(int fd) {
struct bk_file *file;
int ret = -1;
file = get_file(fd);
if (!file) {
return -1;
}
if (file->f_ops && file->f_ops->fsync) {
ret = file->f_ops->fsync(file);
} else {
bk_set_errno(ENOTSUP);
}
put_file(file);
return ret;
}
int bk_vfs_ftruncate(int fd, off_t offset) {
struct bk_file *file;
int ret = -1;
file = get_file(fd);
if (!file) {
return -1;
}
if (file->f_ops && file->f_ops->ftruncate) {
ret = file->f_ops->ftruncate(file, offset);
} else {
bk_set_errno(ENOTSUP);
}
put_file(file);
return ret;
}
int bk_vfs_fcntl(int fd, int cmd, void *arg) {
struct bk_file *file;
int ret = -1;
file = get_file(fd);
if (!file) {
return -1;
}
if (file->f_ops && file->f_ops->fcntl) {
ret = file->f_ops->fcntl(file, cmd, arg);
} else {
bk_set_errno(ENOTSUP);
}
put_file(file);
return ret;
}
int bk_vfs_mkdir(const char *pathname, mode_t mode) {
char *full_path = NULL;
struct bk_filesystem *fs;
int ret = -1;
if (bk_vfs_lock() != 0) {
return -1;
}
full_path = bk_normalize_path(pathname);
if (!full_path) {
goto out;
}
fs = bk_vfs_lookup(full_path);
if (!fs) {
goto out;
}
if (fs->f_ops && fs->f_ops->mkdir) {
ret = fs->f_ops->mkdir(fs, bk_sub_path(fs->mount_point, full_path));
} else {
bk_set_errno(ENOTSUP);
}
out:
if (full_path)
os_free(full_path);
bk_vfs_unlock();
return ret;
}
int bk_vfs_rmdir(const char *pathname) {
char *full_path = NULL;
struct bk_filesystem *fs;
int ret = -1;
if (bk_vfs_lock() != 0) {
return -1;
}
full_path = bk_normalize_path(pathname);
if (!full_path) {
goto out;
}
fs = bk_vfs_lookup(full_path);
if (!fs) {
goto out;
}
if (fs->f_ops && fs->f_ops->rmdir) {
ret = fs->f_ops->rmdir(fs, bk_sub_path(fs->mount_point, full_path));
} else {
bk_set_errno(ENOTSUP);
}
out:
if (full_path)
os_free(full_path);
bk_vfs_unlock();
return ret;
}
DIR *bk_vfs_opendir(const char *name) {
bk_dir *dirp = NULL;
char *full_path = NULL;
struct bk_filesystem *fs;
int ret = -1;
if (bk_vfs_lock() != 0) {
return NULL;
}
full_path = bk_normalize_path(name);
if (!full_path) {
goto out;
}
fs = bk_vfs_lookup(full_path);
if (!fs) {
goto out;
}
if (fs->f_ops && fs->f_ops->opendir) {
dirp = (bk_dir *)os_malloc(sizeof(bk_dir));
if (!dirp) {
goto out;
}
dirp->filesystem = fs;
ret = fs->f_ops->opendir(dirp, bk_sub_path(fs->mount_point, full_path));
if (ret) {
os_free(dirp);
dirp = NULL;
}
} else {
bk_set_errno(ENOTSUP);
}
out:
if (full_path)
os_free(full_path);
bk_vfs_unlock();
return (DIR *)dirp;
}
int bk_vfs_closedir(DIR *dirp_) {
bk_dir *dirp;
int ret = -1;
if (!dirp_)
return -1;
dirp = (bk_dir *)dirp_;
if (bk_vfs_lock() != 0) {
return -1;
}
if (dirp->filesystem && dirp->filesystem->f_ops->closedir) {
ret = dirp->filesystem->f_ops->closedir(dirp);
} else {
bk_set_errno(ENOTSUP);
}
os_free(dirp);
bk_vfs_unlock();
return ret;
}
struct dirent *bk_vfs_readdir(DIR *dirp_) {
bk_dir *dirp;
int ret = -1;
if (!dirp_)
return NULL;
dirp = (bk_dir *)dirp_;
if (bk_vfs_lock() != 0) {
return NULL;
}
if (dirp->filesystem && dirp->filesystem->f_ops->readdir) {
ret = dirp->filesystem->f_ops->readdir(dirp, &dirp->dir_entry);
} else {
bk_set_errno(ENOTSUP);
}
bk_vfs_unlock();
if (ret == 0)
return &dirp->dir_entry;
else
return NULL;
}
void bk_vfs_seekdir(DIR *dirp, long loc) {
}
long bk_vfs_telldir(DIR *dirp) {
return -1;
}
void bk_vfs_rewinddir(DIR *dirp) {
}
static char working_directory[MAX_PATH_LEN] = {"/"};
int bk_vfs_chdir(const char *path) {
char *full_path;
if (!path)
return -1;
if (strlen(path) > MAX_PATH_LEN - 1)
return -1;
full_path = bk_normalize_path(path);
if (!full_path)
return -1;
strcpy(working_directory, full_path);
os_free(full_path);
return 0;
}
char *bk_vfs_getcwd(char *buf, size_t size) {
if (!buf)
return NULL;
strncpy(buf, working_directory, size);
return buf;
}
char *bk_vfs_refer_cwd(void) {
return working_directory;
}
#if CONFIG_STARBURST_AIDIALOG_SDK
off_t bk_vfs_ftell(int fd) {
struct bk_file *file;
off_t ret = -1;
file = get_file(fd);
if (!file) {
return -1;
}
if (file->f_ops && file->f_ops->ftell) {
ret = file->f_ops->ftell(file);
} else {
bk_set_errno(ENOTSUP);
}
put_file(file);
return ret;
}
int bk_vfs_feof(int fd) {
struct bk_file *file;
off_t ret = -1;
file = get_file(fd);
if (!file) {
return -1;
}
if (file->f_ops && file->f_ops->feof) {
ret = file->f_ops->feof(file);
} else {
bk_set_errno(ENOTSUP);
}
put_file(file);
return ret;
}
#endif