7b330d67eb
Note this includes both the lfs3_config -> lfs3_cfg structs as well as the LFS3_CONFIG -> LFS3_CFG include define: - LFS3_CONFIG -> LFS3_CFG - struct lfs3_config -> struct lfs3_cfg - struct lfs3_file_config -> struct lfs3_file_cfg - struct lfs3_*bd_config -> struct lfs3_*bd_cfg - cfg -> cfg We were already using cfg as the variable name everywhere. The fact that these names were different was an inconsistency that should be fixed since we're committing to an API break. LFS3_CFG is already out-of-date from upstream, and there's plans for a config rework, but I figured I'd go ahead and change it as well to lower the chances it gets overlooked. --- Note this does _not_ affect LFS3_TAG_CONFIG. Having the on-disk vs driver-level config take slightly different names is not a bad thing.
163 lines
4.7 KiB
C
163 lines
4.7 KiB
C
/*
|
|
* Block device emulated in a file
|
|
*
|
|
* Copyright (c) 2022, The littlefs authors.
|
|
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
#include "bd/lfs3_filebd.h"
|
|
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
int lfs3_filebd_create(const struct lfs3_cfg *cfg, const char *path) {
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_create(%p {.context=%p, "
|
|
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
|
|
".read_size=%"PRIu32", .prog_size=%"PRIu32", "
|
|
".block_size=%"PRIu32", .block_count=%"PRIu32"}, "
|
|
"\"%s\")",
|
|
(void*)cfg, cfg->context,
|
|
(void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
|
|
(void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
|
|
cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
|
|
path, (void*)bdcfg, bdcfg->erase_value);
|
|
lfs3_filebd_t *bd = cfg->context;
|
|
|
|
// open file
|
|
#ifdef _WIN32
|
|
bd->fd = open(path, O_RDWR | O_CREAT | O_BINARY, 0666);
|
|
#else
|
|
bd->fd = open(path, O_RDWR | O_CREAT, 0666);
|
|
#endif
|
|
|
|
if (bd->fd < 0) {
|
|
int err = -errno;
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_create -> %d", err);
|
|
return err;
|
|
}
|
|
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_create -> %d", 0);
|
|
return 0;
|
|
}
|
|
|
|
int lfs3_filebd_destroy(const struct lfs3_cfg *cfg) {
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_destroy(%p)", (void*)cfg);
|
|
lfs3_filebd_t *bd = cfg->context;
|
|
int err = close(bd->fd);
|
|
if (err < 0) {
|
|
err = -errno;
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_destroy -> %d", err);
|
|
return err;
|
|
}
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_destroy -> %d", 0);
|
|
return 0;
|
|
}
|
|
|
|
int lfs3_filebd_read(const struct lfs3_cfg *cfg, lfs3_block_t block,
|
|
lfs3_off_t off, void *buffer, lfs3_size_t size) {
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_read(%p, "
|
|
"0x%"PRIx32", %"PRIu32", %p, %"PRIu32")",
|
|
(void*)cfg, block, off, buffer, size);
|
|
lfs3_filebd_t *bd = cfg->context;
|
|
|
|
// check if read is valid
|
|
LFS3_ASSERT(block < cfg->block_count);
|
|
LFS3_ASSERT(off % cfg->read_size == 0);
|
|
LFS3_ASSERT(size % cfg->read_size == 0);
|
|
LFS3_ASSERT(off+size <= cfg->block_size);
|
|
|
|
// zero for reproducibility (in case file is truncated)
|
|
memset(buffer, 0, size);
|
|
|
|
// read
|
|
off_t res1 = lseek(bd->fd,
|
|
(off_t)block*cfg->block_size + (off_t)off, SEEK_SET);
|
|
if (res1 < 0) {
|
|
int err = -errno;
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_read -> %d", err);
|
|
return err;
|
|
}
|
|
|
|
ssize_t res2 = read(bd->fd, buffer, size);
|
|
if (res2 < 0) {
|
|
int err = -errno;
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_read -> %d", err);
|
|
return err;
|
|
}
|
|
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_read -> %d", 0);
|
|
return 0;
|
|
}
|
|
|
|
int lfs3_filebd_prog(const struct lfs3_cfg *cfg, lfs3_block_t block,
|
|
lfs3_off_t off, const void *buffer, lfs3_size_t size) {
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_prog(%p, "
|
|
"0x%"PRIx32", %"PRIu32", %p, %"PRIu32")",
|
|
(void*)cfg, block, off, buffer, size);
|
|
lfs3_filebd_t *bd = cfg->context;
|
|
|
|
// check if write is valid
|
|
LFS3_ASSERT(block < cfg->block_count);
|
|
LFS3_ASSERT(off % cfg->prog_size == 0);
|
|
LFS3_ASSERT(size % cfg->prog_size == 0);
|
|
LFS3_ASSERT(off+size <= cfg->block_size);
|
|
|
|
// program data
|
|
off_t res1 = lseek(bd->fd,
|
|
(off_t)block*cfg->block_size + (off_t)off, SEEK_SET);
|
|
if (res1 < 0) {
|
|
int err = -errno;
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_prog -> %d", err);
|
|
return err;
|
|
}
|
|
|
|
ssize_t res2 = write(bd->fd, buffer, size);
|
|
if (res2 < 0) {
|
|
int err = -errno;
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_prog -> %d", err);
|
|
return err;
|
|
}
|
|
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_prog -> %d", 0);
|
|
return 0;
|
|
}
|
|
|
|
int lfs3_filebd_erase(const struct lfs3_cfg *cfg, lfs3_block_t block) {
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_erase(%p, 0x%"PRIx32" (%"PRIu32"))",
|
|
(void*)cfg, block, cfg->block_size);
|
|
|
|
// check if erase is valid
|
|
LFS3_ASSERT(block < cfg->block_count);
|
|
|
|
// erase is a noop
|
|
(void)block;
|
|
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_erase -> %d", 0);
|
|
return 0;
|
|
}
|
|
|
|
int lfs3_filebd_sync(const struct lfs3_cfg *cfg) {
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_sync(%p)", (void*)cfg);
|
|
|
|
// file sync
|
|
lfs3_filebd_t *bd = cfg->context;
|
|
#ifdef _WIN32
|
|
int err = FlushFileBuffers((HANDLE) _get_osfhandle(bd->fd)) ? 0 : -1;
|
|
#else
|
|
int err = fsync(bd->fd);
|
|
#endif
|
|
if (err) {
|
|
err = -errno;
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_sync -> %d", 0);
|
|
return err;
|
|
}
|
|
|
|
LFS3_FILEBD_TRACE("lfs3_filebd_sync -> %d", 0);
|
|
return 0;
|
|
}
|