385 lines
5.6 KiB
C
385 lines
5.6 KiB
C
/*
|
|
* Copyright (c) 2018 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <kernel.h>
|
|
#include <limits.h>
|
|
#include <posix/pthread.h>
|
|
#include <posix/unistd.h>
|
|
#include <string.h>
|
|
|
|
BUILD_ASSERT_MSG(PATH_MAX > MAX_FILE_NAME,
|
|
"PATH_MAX is less than MAX_FILE_NAME");
|
|
|
|
union file_desc {
|
|
struct fs_file_t file;
|
|
struct fs_dir_t dir;
|
|
};
|
|
|
|
struct posix_fs_desc {
|
|
union file_desc desc;
|
|
bool is_dir;
|
|
bool used;
|
|
};
|
|
|
|
static struct posix_fs_desc desc_array[CONFIG_POSIX_MAX_OPEN_FILES];
|
|
|
|
static struct fs_dirent fdirent;
|
|
static struct dirent pdirent;
|
|
|
|
static int posix_fs_alloc_fd(union file_desc **ptr, bool is_dir)
|
|
{
|
|
int fd;
|
|
unsigned int key = irq_lock();
|
|
|
|
for (fd = 0; fd < CONFIG_POSIX_MAX_OPEN_FILES; fd++) {
|
|
if (desc_array[fd].used == false) {
|
|
*ptr = &desc_array[fd].desc;
|
|
desc_array[fd].used = true;
|
|
desc_array[fd].is_dir = is_dir;
|
|
break;
|
|
}
|
|
}
|
|
irq_unlock(key);
|
|
|
|
if (fd >= CONFIG_POSIX_MAX_OPEN_FILES) {
|
|
return -1;
|
|
}
|
|
|
|
return fd;
|
|
}
|
|
|
|
static int posix_fs_get_ptr(int fd, union file_desc **ptr, bool is_dir)
|
|
{
|
|
int rc = 0;
|
|
unsigned int key;
|
|
|
|
if (fd < 0 || fd >= CONFIG_POSIX_MAX_OPEN_FILES) {
|
|
return -1;
|
|
}
|
|
|
|
key = irq_lock();
|
|
|
|
if ((desc_array[fd].used == true) &&
|
|
(desc_array[fd].is_dir == is_dir)) {
|
|
*ptr = &desc_array[fd].desc;
|
|
} else {
|
|
rc = -1;
|
|
}
|
|
irq_unlock(key);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static inline void posix_fs_free_ptr(struct posix_fs_desc *ptr)
|
|
{
|
|
struct posix_fs_desc *desc = ptr;
|
|
unsigned int key = irq_lock();
|
|
|
|
desc->used = false;
|
|
desc->is_dir = false;
|
|
irq_unlock(key);
|
|
}
|
|
|
|
static inline void posix_fs_free_fd(int fd)
|
|
{
|
|
posix_fs_free_ptr(&desc_array[fd]);
|
|
}
|
|
|
|
/**
|
|
* @brief Open a file.
|
|
*
|
|
* See IEEE 1003.1
|
|
*/
|
|
int open(const char *name, int flags)
|
|
{
|
|
int rc, fd;
|
|
struct fs_file_t *ptr = NULL;
|
|
|
|
ARG_UNUSED(flags);
|
|
|
|
fd = posix_fs_alloc_fd((union file_desc **)&ptr, false);
|
|
if ((fd < 0) || (ptr == NULL)) {
|
|
errno = ENFILE;
|
|
return -1;
|
|
}
|
|
memset(ptr, 0, sizeof(struct fs_file_t));
|
|
|
|
rc = fs_open(ptr, name);
|
|
if (rc < 0) {
|
|
posix_fs_free_fd(fd);
|
|
errno = -rc;
|
|
return -1;
|
|
}
|
|
|
|
return fd;
|
|
}
|
|
|
|
/**
|
|
* @brief Close a file descriptor.
|
|
*
|
|
* See IEEE 1003.1
|
|
*/
|
|
int close(int fd)
|
|
{
|
|
int rc;
|
|
struct fs_file_t *ptr = NULL;
|
|
|
|
if (posix_fs_get_ptr(fd, (union file_desc **)&ptr, false)) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
rc = fs_close(ptr);
|
|
|
|
/* Free file ptr memory */
|
|
posix_fs_free_fd(fd);
|
|
|
|
if (rc < 0) {
|
|
errno = -rc;
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Write to a file.
|
|
*
|
|
* See IEEE 1003.1
|
|
*/
|
|
ssize_t write(int fd, char *buffer, unsigned int count)
|
|
{
|
|
ssize_t rc;
|
|
struct fs_file_t *ptr = NULL;
|
|
|
|
if (posix_fs_get_ptr(fd, (union file_desc **)&ptr, false)) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
rc = fs_write(ptr, buffer, count);
|
|
if (rc < 0) {
|
|
errno = -rc;
|
|
return -1;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* @brief Read from a file.
|
|
*
|
|
* See IEEE 1003.1
|
|
*/
|
|
ssize_t read(int fd, char *buffer, unsigned int count)
|
|
{
|
|
ssize_t rc;
|
|
struct fs_file_t *ptr = NULL;
|
|
|
|
if (posix_fs_get_ptr(fd, (union file_desc **)&ptr, false)) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
rc = fs_read(ptr, buffer, count);
|
|
if (rc < 0) {
|
|
errno = -rc;
|
|
return -1;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* @brief Move read/write file offset.
|
|
*
|
|
* See IEEE 1003.1
|
|
*/
|
|
int lseek(int fd, int offset, int whence)
|
|
{
|
|
int rc;
|
|
struct fs_file_t *ptr = NULL;
|
|
|
|
if (posix_fs_get_ptr(fd, (union file_desc **)&ptr, false)) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
rc = fs_seek(ptr, offset, whence);
|
|
if (rc < 0) {
|
|
errno = -rc;
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Open a directory stream.
|
|
*
|
|
* See IEEE 1003.1
|
|
*/
|
|
DIR *opendir(const char *dirname)
|
|
{
|
|
int rc, fd;
|
|
struct fs_dir_t *ptr = NULL;
|
|
|
|
fd = posix_fs_alloc_fd((union file_desc **)&ptr, true);
|
|
if ((fd < 0) || (ptr == NULL)) {
|
|
errno = EMFILE;
|
|
return NULL;
|
|
}
|
|
memset(ptr, 0, sizeof(struct fs_dir_t));
|
|
|
|
rc = fs_opendir(ptr, dirname);
|
|
if (rc < 0) {
|
|
posix_fs_free_fd(fd);
|
|
errno = -rc;
|
|
return NULL;
|
|
}
|
|
|
|
return ptr;
|
|
}
|
|
|
|
/**
|
|
* @brief Close a directory stream.
|
|
*
|
|
* See IEEE 1003.1
|
|
*/
|
|
int closedir(DIR *dirp)
|
|
{
|
|
int rc;
|
|
|
|
if (dirp == NULL) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
rc = fs_closedir(dirp);
|
|
|
|
/* Free file ptr memory */
|
|
posix_fs_free_ptr((struct posix_fs_desc *)dirp);
|
|
|
|
if (rc < 0) {
|
|
errno = -rc;
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Read a directory.
|
|
*
|
|
* See IEEE 1003.1
|
|
*/
|
|
struct dirent *readdir(DIR *dirp)
|
|
{
|
|
int rc;
|
|
|
|
if (dirp == NULL) {
|
|
errno = EBADF;
|
|
return NULL;
|
|
}
|
|
|
|
rc = fs_readdir(dirp, &fdirent);
|
|
if (rc < 0) {
|
|
errno = -rc;
|
|
return NULL;
|
|
}
|
|
|
|
rc = strlen(fdirent.name);
|
|
rc = (rc < PATH_MAX) ? rc : (PATH_MAX - 1);
|
|
memcpy(pdirent.d_name, fdirent.name, rc);
|
|
|
|
/* Make sure the name is NULL terminated */
|
|
pdirent.d_name[rc + 1] = '\0';
|
|
return &pdirent;
|
|
}
|
|
|
|
/**
|
|
* @brief Rename a file.
|
|
*
|
|
* See IEEE 1003.1
|
|
*/
|
|
int rename(const char *old, const char *new)
|
|
{
|
|
int rc;
|
|
|
|
rc = fs_rename(old, new);
|
|
if (rc < 0) {
|
|
errno = -rc;
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Remove a directory entry.
|
|
*
|
|
* See IEEE 1003.1
|
|
*/
|
|
int unlink(const char *path)
|
|
{
|
|
int rc;
|
|
|
|
rc = fs_unlink(path);
|
|
if (rc < 0) {
|
|
errno = -rc;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Get file status.
|
|
*
|
|
* See IEEE 1003.1
|
|
*/
|
|
int stat(const char *path, struct stat *buf)
|
|
{
|
|
int rc;
|
|
struct fs_statvfs stat;
|
|
|
|
if (buf == NULL) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
|
|
rc = fs_statvfs(path, &stat);
|
|
if (rc < 0) {
|
|
errno = -rc;
|
|
return -1;
|
|
}
|
|
|
|
buf->st_size = stat.f_bsize * stat.f_blocks;
|
|
buf->st_blksize = stat.f_bsize;
|
|
buf->st_blocks = stat.f_blocks;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Make a directory.
|
|
*
|
|
* See IEEE 1003.1
|
|
*/
|
|
int mkdir(const char *path, mode_t mode)
|
|
{
|
|
int rc;
|
|
|
|
ARG_UNUSED(mode);
|
|
|
|
rc = fs_mkdir(path);
|
|
if (rc < 0) {
|
|
errno = -rc;
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|