2024-02-25 15:15:36 +08:00

227 lines
5.6 KiB
C

#include "PikaObj.h"
#include "ff.h"
typedef FIL _INNER_FILE;
/* private prototypes */
int __fmodeflags(const char* mode);
/* public prototypes */
#ifndef PIKA_FATFS_ENABLE
#define PIKA_FATFS_ENABLE 1
#endif
#if PIKA_FATFS_ENABLE
FILE* pika_platform_fopen(const char* filename, const char* modes) {
FRESULT res;
int flags;
/* Check for valid initial mode character */
if (!strchr("rwa", *modes)) {
return 0;
}
/* Compute the flags to pass to open() */
flags = __fmodeflags(modes);
_INNER_FILE *_f = pika_platform_malloc(sizeof(*_f));
if(NULL == _f){
return NULL;
}
res = f_open(_f, filename, flags);
if (res) {
pika_platform_free(_f);
return NULL;
}
return (FILE *)_f;
}
size_t pika_platform_fwrite(const void* ptr, size_t size, size_t n, FILE* stream) {
_INNER_FILE* _f = (_INNER_FILE*)stream;
size_t len = 0;
f_write(_f, ptr, n * size, &len);
return len;
}
size_t pika_platform_fread(void* ptr, size_t size, size_t n, FILE* stream) {
_INNER_FILE* _f = (_INNER_FILE*)stream;
size_t len = 0;
f_read(_f, ptr, n * size, &len);
return len;
}
int pika_platform_fclose(FILE* stream) {
_INNER_FILE* _f = (_INNER_FILE*)stream;
f_close(_f);
pika_platform_free(_f);
return 0;
}
int pika_platform_fseek(FILE* stream, long offset, int whence) {
_INNER_FILE* _f = (_INNER_FILE*)stream;
DWORD fatfs_offset;
switch (whence) {
case SEEK_SET:
fatfs_offset = offset;
break;
case SEEK_CUR:
fatfs_offset = f_tell(_f) + offset;
break;
case SEEK_END:
fatfs_offset = f_size(_f) + offset;
break;
default:
return -1; // Invalid argument
}
if (f_lseek(_f, fatfs_offset) == FR_OK) {
return 0;
} else {
return -1;
}
}
long pika_platform_ftell(FILE* stream) {
_INNER_FILE* _f = (_INNER_FILE*)stream;
return f_tell(_f);
}
int __fmodeflags(const char* mode) {
int flags = 0;
if (strchr(mode, '+')) {
flags = FA_WRITE | FA_READ;
}
if (*mode == 'r') {
if (!(flags & FA_WRITE)) {
flags |= FA_READ;
}
} else if (*mode == 'w') {
flags |= FA_CREATE_ALWAYS | FA_WRITE;
} else if (*mode == 'a') {
flags |= FA_OPEN_APPEND | FA_WRITE;
}
return flags;
}
char* pika_platform_getcwd(char* buf, size_t size) {
// FatFS doesn't directly provide a getcwd function. You might need
// to manage the current directory yourself or return a default if it's
// not crucial for your application.
strncpy(buf, "/", size);
return buf;
}
int pika_platform_chdir(const char* path) {
// FatFS doesn't directly provide a chdir function. You might need
// to manage the current directory yourself.
return -1; // Not implemented
}
int pika_platform_rmdir(const char* pathname) {
return f_unlink(pathname);
}
int pika_platform_mkdir(const char* pathname, int mode) {
return f_mkdir(pathname);
}
int pika_platform_remove(const char* pathname) {
return f_unlink(pathname);
}
int pika_platform_rename(const char* oldpath, const char* newpath) {
return f_rename(oldpath, newpath);
}
char** pika_platform_listdir(const char* path, int* count) {
DIR dir;
static FILINFO fno;
FRESULT res;
char **filelist = NULL;
int idx = 0, capacity = 10; // start with a capacity of 10, then grow if necessary
res = f_opendir(&dir, path); // Open the directory
if (res == FR_OK) {
filelist = pika_platform_malloc(capacity * sizeof(char*));
if(!filelist) return NULL; // Failed to allocate memory
for (;;) {
res = f_readdir(&dir, &fno); // Read a directory item
if (res != FR_OK || fno.fname[0] == 0) break; // Break on error or end of dir
if (idx == capacity) { // Grow the list if necessary
capacity *= 2;
char **newlist = pika_platform_realloc(filelist, capacity * sizeof(char*));
if(!newlist) {
// Free any previously allocated memory
for(int i = 0; i < idx; i++)
pika_platform_free(filelist[i]);
pika_platform_free(filelist);
*count = 0;
return NULL; // Failed to allocate more memory
}
filelist = newlist;
}
filelist[idx] = pika_platform_strdup(fno.fname);
if(!filelist[idx]) {
// Free any previously allocated memory
for(int i = 0; i < idx; i++)
pika_platform_free(filelist[i]);
pika_platform_free(filelist);
*count = 0;
return NULL; // Failed to allocate memory for filename
}
idx++;
}
f_closedir(&dir);
}
*count = idx;
return filelist;
}
int pika_platform_path_exists(const char *path){
FRESULT res;
FILINFO fno;
res = f_stat(path, &fno);
if (res != FR_OK) {
return 0; // Path does not exist
}
return 1;
}
int pika_platform_path_isdir(const char *path){
int is_dir = 0;
FRESULT res;
FILINFO fno;
res = f_stat(path, &fno);
if (res == FR_OK) {
is_dir = (fno.fattrib & AM_DIR) ? 1 : 0;
}else{
return 0;
}
return is_dir;
}
int pika_platform_path_isfile(const char *path){
int is_file = 0;
FRESULT res;
FILINFO fno;
res = f_stat(path, &fno);
if (res == FR_OK) {
is_file = (fno.fattrib & AM_DIR) == 0 ? 1 : 0;
}else{
return 0;
}
return is_file;
}
#endif