185 lines
4.2 KiB
C
185 lines
4.2 KiB
C
/******************************************************************************
|
|
* MiniFFS : Mini Flat File System
|
|
* miniffs.c: Shared code for all platforms.
|
|
*
|
|
* Copyright (c) 2008-2022 986-Studio. All rights reserved.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define __miniffs_internal
|
|
#include <miniffs.h>
|
|
|
|
static miniffs_error_t last_error = MINIFFS_NOERROR;
|
|
|
|
/* Public API */
|
|
|
|
file_t *miniffs_open(miniffs_t *fs, const char *filename)
|
|
{
|
|
file_t *ret = (file_t *)calloc(1, sizeof(file_t));
|
|
if (ret == NULL)
|
|
{
|
|
miniffs_seterror(MINIFFS_ALLOCATION_ERROR);
|
|
goto exit;
|
|
}
|
|
|
|
ret->private_data = fs;
|
|
ret->fent = miniffs_findfile(fs, filename);
|
|
if (!ret->fent)
|
|
{
|
|
miniffs_seterror(MINIFFS_FILE_NOT_FOUND);
|
|
goto free_and_exit;
|
|
}
|
|
|
|
ret->offset = 0;
|
|
goto exit;
|
|
|
|
free_and_exit:
|
|
free(ret);
|
|
ret = NULL;
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
int miniffs_close(file_t *file)
|
|
{
|
|
/* Let's poison the struct */
|
|
file->private_data = NULL;
|
|
file->offset = 0;
|
|
file->fent = NULL;
|
|
|
|
free(file);
|
|
}
|
|
|
|
void *miniffs_map(file_t *file)
|
|
{
|
|
miniffs_t *fs = (miniffs_t *)file->private_data;
|
|
return miniffs_getfileaddr(fs, file->fent);
|
|
}
|
|
|
|
uint8_t miniffs_read(file_t *file)
|
|
{
|
|
miniffs_t *fs = (miniffs_t *) file->private_data;
|
|
uint8_t *filePtr = miniffs_getfileaddr(fs, file->fent);
|
|
uint8_t ret = filePtr[file->offset];
|
|
|
|
file->offset++;
|
|
|
|
if (file->offset >= file->fent->size)
|
|
{
|
|
miniffs_seterror(MINIFFS_END_OF_FILE);
|
|
file->offset = file->fent->size - 1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int miniffs_read_blocks(void *ptr, size_t size, size_t nmemb, file_t *file)
|
|
{
|
|
int i;
|
|
miniffs_t *fs = (miniffs_t *) file->private_data;
|
|
uint8_t *filePtr = miniffs_getfileaddr(fs, file->fent);
|
|
size_t fileOffset = file->offset;
|
|
size_t bufferOffset = 0;
|
|
int blockCount = 0;
|
|
|
|
for(i = 0; i < nmemb; i++)
|
|
{
|
|
if (file->fent->size > (fileOffset + size))
|
|
{
|
|
memcpy(ptr + bufferOffset, &filePtr[fileOffset], size);
|
|
bufferOffset += size;
|
|
fileOffset += size;
|
|
blockCount++;
|
|
}
|
|
}
|
|
file->offset = fileOffset;
|
|
return blockCount;
|
|
}
|
|
|
|
int miniffs_seek(file_t *file, size_t offset, int whence)
|
|
{
|
|
switch(whence)
|
|
{
|
|
default:
|
|
miniffs_seterror(MINIFFS_INVALID_PARAMS);
|
|
return -1;
|
|
|
|
case MFFS_SEEK_SET:
|
|
file->offset = offset;
|
|
break;
|
|
case MFFS_SEEK_CUR:
|
|
file->offset += offset;
|
|
break;
|
|
case MFFS_SEEK_END:
|
|
file->offset = file->fent->size - offset;
|
|
break;
|
|
}
|
|
}
|
|
|
|
size_t miniffs_tell(file_t *file)
|
|
{
|
|
return file->offset;
|
|
}
|
|
|
|
miniffs_error_t miniffs_geterror()
|
|
{
|
|
return last_error;
|
|
}
|
|
|
|
/* Private API */
|
|
bool miniffs_isvalidfs(miniffs_t *fs)
|
|
{
|
|
return (fs->header->magic == MINIFFS_MAGIC) &&
|
|
(fs->header->fs_version_major == MINIFFS_VERSION_MAJOR) &&
|
|
(fs->header->fs_version_minor == MINIFFS_VERSION_MINOR) &&
|
|
(fs->header->fs_filename_len == MINIFFS_FILENAME_LENGTH) &&
|
|
(fs->header->fs_extention_len == MINIFFS_EXTENSION_LENGTH);
|
|
}
|
|
|
|
static void make_fullname(char *name, char *ext, char *out)
|
|
{
|
|
uint8_t nameLen = strnlen(name, MINIFFS_FILENAME_LENGTH);
|
|
uint8_t extLen = strnlen(ext, MINIFFS_EXTENSION_LENGTH);
|
|
|
|
memcpy(out, name, nameLen);
|
|
memcpy(out + nameLen, ".", 1);
|
|
memcpy(out + nameLen + 1, ext, extLen);
|
|
}
|
|
|
|
fileentry_t *miniffs_findfile(miniffs_t *fs, const char *filename)
|
|
{
|
|
int i;
|
|
char entryFullName[MINIFFS_FULLNAME_LENGTH];
|
|
uint8_t filenameLength = strlen(filename);
|
|
fileentry_t *ret = NULL;
|
|
if (filenameLength > MINIFFS_FULLNAME_LENGTH)
|
|
{
|
|
miniffs_seterror(MINIFFS_INVALID_NAME);
|
|
goto exit;
|
|
}
|
|
|
|
for(i = 0; i < fs->header->entry_count; i++)
|
|
{
|
|
fileentry_t *cur = &fs->header->fent[i];
|
|
make_fullname(cur->name, cur->ext, entryFullName);
|
|
|
|
if (memcmp(filename, entryFullName, filenameLength) == 0)
|
|
{
|
|
/* File found! */
|
|
ret = cur;
|
|
break;
|
|
}
|
|
}
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
void miniffs_seterror(miniffs_error_t err)
|
|
{
|
|
last_error = err;
|
|
} |