ArcherChang 921fbfbc21 [1] 添加Andes N1068体系;
[2] 基于AE210P EVB板;
[3] 详细信息参阅bsp/AE210P/readme文件夹;
    《Andes工程创建和调试》文档;等。
2017-08-25 10:25:33 +08:00

521 lines
12 KiB
C

#include <stdio.h>
#include "ndsvfs.h"
#include "dirent.h"
__attribute__((used))
FILE *fopen(const char *path_name, const char *mode)
{
NDSVFS_DENTRY *vde = HAL_NULL;
NDSVFS_FILE *file = HAL_NULL;
UINT32 mode_len;
UINT32 fmode = 0;
UINT32 i;
if (HAL_SUCCESS != _ndsvfs_lock())
return HAL_NULL;
// alloc file object
file = _ndsvfs_alloc_file();
if (file == HAL_NULL)
goto _safe_exit;
// open flags
if (mode == HAL_NULL)
mode_len = 0;
else
mode_len = (UINT32)strlen(mode);
for (i = 0; i < mode_len; ++i)
{
switch (mode[i])
{
case 'r':
fmode |= NDSVFS_FOPEN_READ;
break;
case 'w':
fmode |= NDSVFS_FOPEN_WRITE;
break;
case 'a':
fmode |= NDSVFS_FOPEN_APPEND;
break;
case '+':
fmode |= NDSVFS_FOPEN_PLUS;
break;
}
}
if (fmode == 0)
goto _safe_exit;
#if 0
// (todo) current imp should be read only
if (fmode & ~NDSVFS_FOPEN_READ)
goto _safe_exit;
if (!(fmode & NDSVFS_FOPEN_READ))
goto _safe_exit;
// ~(todo)
#endif
// lookup file entry
if (path_name == HAL_NULL)
goto _safe_exit;
if ((INT)strlen(path_name) == 0)
goto _safe_exit;
vde = _ndsvfs_path_lookup((const char *)path_name);
if (!vde)
{
// (todo) create the file if not exist and flag is not read only
goto _safe_exit;
}
// current imp allows only regular file
// we can open dir now, so I comments the codes
#if 0
if (vde->inode->mode & NDSVFS_INM_ATTR_MASK)
goto _safe_exit;
#endif
// notify file system to open the file
// (todo) call this only when user mode reference to the file is 0.
if (HAL_SUCCESS != vde->sb->open_file(vde, fmode))
goto _safe_exit;
file->flags = fmode;
file->vde = vde;
//file->pos = 0;
//DEBUG(0, 1,"fopen() 0x%08lx\r\n", (UINT32)file);
_ndsvfs_unlock();
// todo
return (FILE *)file;
_safe_exit:
if (vde)
NDSVFS_DEREF(vde);
file->vde = HAL_NULL;
if (file)
NDSVFS_DEREF(file);
_ndsvfs_unlock();
return HAL_NULL;
}
__attribute__((used))
int fclose(FILE *stream)
{
if (stream == HAL_NULL)
return (int)-NDS_VFSD_INVALID_PARAMETER;
if (HAL_SUCCESS != _ndsvfs_lock())
return (int)HAL_ERR_INVALID_OPERATION;
//DEBUG(0, 1,"fclose() 0x%08lx\r\n", (UINT32)stream);
// (todo) flush the file contents if ever been modified
// notify file system to close the file
// (todo) call this only when user mode reference to the file decreased to 0.
((NDSVFS_FILE *)stream)->vde->sb->close_file(((NDSVFS_FILE *)stream)->vde);
// release file references
if (stream)
NDSVFS_DEREF(stream);
if (HAL_SUCCESS != _ndsvfs_unlock())
return (int)HAL_ERR_INVALID_OPERATION;
return (int)HAL_SUCCESS;
}
__attribute__((used))
size_t fread(void *ptr, size_t size, size_t count, FILE *stream)
{
STATUS status;
UINT32 d_size = (UINT32)size * (UINT32)count;
UINT32 r_size; // size actually been read
#if 1
DEBUG(0, 1,"fread() 0x%08lx ptr(0x%08lx) size(0x%08lx) count(0x%08lx)\r\n",
(UINT32)stream, (UINT32)ptr, (UINT32)size, (UINT32)count);
#endif
if (stream == HAL_NULL)
{
((NDSVFS_FILE *)stream)->err = NDS_VFSD_INVALID_PARAMETER;
return 0;
}
if (HAL_SUCCESS != _ndsvfs_lock())
{
((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_OPERATION;
return 0;
}
DEBUG(0, 1,"fread() 0x%08lx >>\r\n", (UINT32)stream);
if (((NDSVFS_FILE *)stream)->pos < 0)
{
DEBUG(0, 1,"fread() 0x%08lx <<\r\n", (UINT32)stream);
_ndsvfs_unlock();
((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_START;
return 0;
}
status = ((NDSVFS_FILE *)stream)->vde->sb->read_file(((NDSVFS_FILE *)stream)->vde,
ptr, (UINT32)((NDSVFS_FILE *)stream)->pos, d_size, &r_size);
if (status == NDS_VFSD_END_OF_FILE)
{
((NDSVFS_FILE *)stream)->eof = HAL_TRUE;
status = HAL_SUCCESS;
}
if (status == HAL_SUCCESS)
((NDSVFS_FILE *)stream)->pos += (INT32)r_size;
else
r_size = 0;
DEBUG(0, 1,"fread() 0x%08lx <<\r\n", (UINT32)stream);
if (HAL_SUCCESS != _ndsvfs_unlock())
{
((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_OPERATION;
DEBUG(0, 1,"fread() 0x%08lx << unlock fail\r\n", (UINT32)stream);
return 0;
}
return (int)((size_t)r_size / size);
}
__attribute__((used))
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
{
STATUS status;
UINT32 d_size = (UINT32)size * (UINT32)count;
UINT32 w_size; // size actually been write
#if 1
DEBUG(0, 1,"fwrite() 0x%08lx ptr(0x%08lx) size(0x%08lx) count(0x%08lx)\r\n",
(UINT32)stream, (UINT32)ptr, (UINT32)size, (UINT32)count);
#endif
if (stream == HAL_NULL)
{
((NDSVFS_FILE *)stream)->err = NDS_VFSD_INVALID_PARAMETER;
return 0;
}
if (HAL_SUCCESS != _ndsvfs_lock())
{
((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_OPERATION;
return 0;
}
DEBUG(0, 1,"fwrite() 0x%08lx >>\r\n", (UINT32)stream);
if (((NDSVFS_FILE *)stream)->pos < 0)
{
DEBUG(0, 1,"fwrite() 0x%08lx <<\r\n", (UINT32)stream);
_ndsvfs_unlock();
((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_START;
return 0;
}
status = ((NDSVFS_FILE *)stream)->vde->sb->write_file(((NDSVFS_FILE *)stream)->vde,
ptr, (UINT32)((NDSVFS_FILE *)stream)->pos, d_size, &w_size);
if (status == NDS_VFSD_END_OF_FILE)
{
((NDSVFS_FILE *)stream)->eof = HAL_TRUE;
status = HAL_SUCCESS;
}
if (status == HAL_SUCCESS)
((NDSVFS_FILE *)stream)->pos += (INT32)w_size;
else
w_size = 0;
DEBUG(0, 1,"fwrite() 0x%08lx <<\r\n", (UINT32)stream);
if (HAL_SUCCESS != _ndsvfs_unlock())
{
((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_OPERATION;
DEBUG(0, 1,"fwrite() 0x%08lx << unlock fail\r\n", (UINT32)stream);
return 0;
}
return (int)((size_t)w_size / size);
}
__attribute__((used))
int fflush(FILE *stream)
{
if (stream == HAL_NULL)
return (int)NDS_VFSD_INVALID_PARAMETER;
// todo
return (int)HAL_SUCCESS;
}
__attribute__((used))
int fseek(FILE *stream, int offset, int origin)
{
INT32 pos;
if (stream == HAL_NULL)
return (int)NDS_VFSD_INVALID_PARAMETER;
if (HAL_SUCCESS != _ndsvfs_lock())
return (int)HAL_ERR_INVALID_OPERATION;
pos = ((NDSVFS_FILE *)stream)->pos;
//DEBUG(0, 1,"fseek() 0x%08lx >>\r\n", (UINT32)stream);
//DEBUG(0, 1,"pos (cur) : 0x%08lx\r\n", pos);
//DEBUG(0, 1,"offset : 0x%08lx\r\n", offset);
switch (origin)
{
case FSEEK_CUR:
pos += offset;
break;
case FSEEK_END:
pos = (INT32)((NDSVFS_FILE *)stream)->vde->inode->size + offset;
break;
case FSEEK_SET:
pos = offset;
break;
default:
//DEBUG(0, 1,"fseek() 0x%08lx <<\r\n", (UINT32)stream);
_ndsvfs_unlock();
return (int)NDS_VFSD_INVALID_PARAMETER;
}
//DEBUG(0, 1,"pos (new) : 0x%08lx\r\n", pos);
/*
if (pos > ((NDSVFS_FILE *)stream)->vde->inode->size)
{
_ndsvfs_unlock();
return (int)NDS_VFSD_INVALID_PARAMETER; // todo: might be a valid condition for write-mode
}*/
((NDSVFS_FILE *)stream)->pos = pos;
//DEBUG(0, 1,"fseek() 0x%08lx <<\r\n", (UINT32)stream);
if (HAL_SUCCESS != _ndsvfs_unlock())
return (int)HAL_ERR_INVALID_OPERATION;
return (int)HAL_SUCCESS;
}
__attribute__((used))
long ftell(FILE *stream)
{
long pos;
if (stream == HAL_NULL)
return (int)HAL_ERR_INVALID_OPERATION;
if (HAL_SUCCESS != _ndsvfs_lock())
return (int)HAL_ERR_INVALID_OPERATION;
pos = (long)((NDSVFS_FILE *)stream)->pos;
if (HAL_SUCCESS != _ndsvfs_unlock())
return (int)HAL_ERR_INVALID_OPERATION;
return pos;
}
void frewind(FILE *stream)
{
if (stream == HAL_NULL)
return;
if (HAL_SUCCESS != _ndsvfs_lock())
return;
((NDSVFS_FILE *)stream)->pos = 0;
((NDSVFS_FILE *)stream)->err = 0;
((NDSVFS_FILE *)stream)->eof = 0;
if (HAL_SUCCESS != _ndsvfs_unlock())
return;
}
__attribute__((used))
int fgetpos(FILE *stream, fpos_t *position)
{
if (stream == HAL_NULL)
return (int)NDS_VFSD_INVALID_PARAMETER;
if (position == HAL_NULL)
return (int)NDS_VFSD_INVALID_PARAMETER;
if (HAL_SUCCESS != _ndsvfs_lock())
return (int)HAL_ERR_INVALID_OPERATION;
*position = ((NDSVFS_FILE *)stream)->pos;
if (HAL_SUCCESS != _ndsvfs_unlock())
return (int)HAL_ERR_INVALID_OPERATION;
return (int)HAL_SUCCESS;
}
__attribute__((used))
int fsetpos(FILE *stream, const fpos_t *position)
{
if (stream == HAL_NULL)
return (int)NDS_VFSD_INVALID_PARAMETER;
if (position == HAL_NULL)
return (int)NDS_VFSD_INVALID_PARAMETER;
if (HAL_SUCCESS != _ndsvfs_lock())
return (int)HAL_ERR_INVALID_OPERATION;
if (*position > (INT32)((NDSVFS_FILE *)stream)->vde->inode->size)
{
_ndsvfs_unlock();
return (int)NDS_VFSD_INVALID_PARAMETER; // todo: might be a valid condition for write-mode
}
((NDSVFS_FILE *)stream)->pos = *position;
((NDSVFS_FILE *)stream)->eof = 0; // ?? todo: signal eof if position reaches end of file?
if (HAL_SUCCESS != _ndsvfs_unlock())
return (int)HAL_ERR_INVALID_OPERATION;
return (int)HAL_SUCCESS;
}
__attribute__((used))
int feof(FILE *stream)
{
UINT32 eof;
if (HAL_SUCCESS != _ndsvfs_lock())
return (int)HAL_ERR_INVALID_OPERATION;
eof = ((NDSVFS_FILE *)stream)->eof > 0 ? HAL_TRUE : HAL_FALSE;
if (HAL_SUCCESS != _ndsvfs_unlock())
return (int)HAL_ERR_INVALID_OPERATION;
return eof;
}
__attribute__((used))
int ferror(FILE *stream)
{
UINT32 err;
if (HAL_SUCCESS != _ndsvfs_lock())
return (int)HAL_ERR_INVALID_OPERATION;
err = ((NDSVFS_FILE *)stream)->err > 0 ? 1 : 0;
if (HAL_SUCCESS != _ndsvfs_unlock())
return (int)HAL_ERR_INVALID_OPERATION;
return err;
}
void fclearerr(FILE *stream)
{
if (HAL_SUCCESS != _ndsvfs_lock())
return;
((NDSVFS_FILE *)stream)->err = 0;
((NDSVFS_FILE *)stream)->eof = 0;
if (HAL_SUCCESS != _ndsvfs_unlock())
return;
}
extern STATUS _ndsvfs_read_dirs(NDSVFS_DENTRY *vde_parent, NDSVFS_DENTRY **vde_list);
__attribute__((used))
struct dir *opendir(const char *path)
{
NDSVFS_FILE *file = NULL;
struct dir *dirp = NULL;
int status;
file = (NDSVFS_FILE *)fopen(path, "rb");
if (file == NULL) {
// ERROR("fopen path=%s\n",path);
return (void*)0;
}
if (!S_ISDIR(file->vde->inode)){
fclose((FILE *)file);
// ERROR("Not a dir path=%s\n",path);
return (void*)0;
}
if (!file->dirp){
file->dirp = malloc(sizeof(struct dir));
KASSERT(file->dirp);
dirp = (struct dir*)file->dirp;
dirp->d_dirent = malloc(sizeof(struct dirent));
KASSERT(dirp->d_dirent);
dirp->d_file = file;
dirp->d_off = 0;
}
status = _ndsvfs_read_dirs(file->vde, &(dirp->vde_list));
dirp->vde_head = dirp->vde_list;
dirp->vde_list = NULL;
if(status == HAL_FAILURE)
return HAL_NULL;
return dirp;
}
__attribute__((used))
int closedir(struct dir *dirp)
{
NDSVFS_FILE *file = dirp->d_file;
if (dirp == NULL)
return -1;
if (file == NULL)
return -1;
if (dirp->d_dirent != NULL)
free(dirp->d_dirent);
free(dirp);
return fclose((FILE *)file);
}
__attribute__((used))
struct dirent *readdir(struct dir *dirp)
{
/* this is the first time, becasue the vde_list is pointed to null */
if (dirp->vde_list == NULL && dirp->vde_head != NULL) {
strcpy(dirp->d_dirent->d_name, dirp->vde_head->name.utf_name);
dirp->vde_list = NDS_LIST_ENTITY(dirp->vde_head->c_chain.next, NDSVFS_DENTRY, c_chain);
return dirp->d_dirent;
}
/* this is not the first time. */
else if (dirp->vde_list != dirp->vde_head) {
strcpy(dirp->d_dirent->d_name, dirp->vde_list->name.utf_name);
dirp->vde_list = NDS_LIST_ENTITY(dirp->vde_list->c_chain.next, NDSVFS_DENTRY, c_chain);
return dirp->d_dirent;
}
else
return NULL;
}
__attribute__((used))
int fstat(FILE* fd, struct stat *buf)
{
NDSVFS_FILE *file = (NDSVFS_FILE *)fd;
if (file == HAL_NULL)
return -1;
return file->vde->sb->stat_file(file->vde, buf);
}