mirror of
https://github.com/eledio-devices/thirdparty-littlefs.git
synced 2025-11-01 00:38:29 +01:00
Added tests, cleanup, and fixed a small issue with updating file flags
Related to changes to custom attribute and open file syncing
This commit is contained in:
3
lfs.c
3
lfs.c
@@ -2527,6 +2527,7 @@ static int lfs_file_rawopencfg(lfs_t *lfs, lfs_file_t *file,
|
|||||||
#ifndef LFS_READONLY
|
#ifndef LFS_READONLY
|
||||||
} else if (flags & LFS_O_TRUNC) {
|
} else if (flags & LFS_O_TRUNC) {
|
||||||
// truncate if requested
|
// truncate if requested
|
||||||
|
// always mark dirty in case we have custom attributes
|
||||||
tag = LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0);
|
tag = LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0);
|
||||||
file->flags |= LFS_F_DIRTY;
|
file->flags |= LFS_F_DIRTY;
|
||||||
#endif
|
#endif
|
||||||
@@ -2878,7 +2879,7 @@ static int lfs_file_rawsync(lfs_t *lfs, lfs_file_t *file) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file->flags &= ~(LFS_F_DIRTY | LFS_F_WRITING | LFS_F_READING);
|
f->flags &= ~(LFS_F_DIRTY | LFS_F_WRITING | LFS_F_READING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
lfs.h
8
lfs.h
@@ -294,10 +294,10 @@ struct lfs_file_config {
|
|||||||
void *buffer;
|
void *buffer;
|
||||||
|
|
||||||
// Optional list of custom attributes related to the file. If the file
|
// Optional list of custom attributes related to the file. If the file
|
||||||
// is opened with read access, these attributes will be read from disk
|
// is opened for reading, these attributes will be read from disk during
|
||||||
// during the open call. If the file is opened with write access, the
|
// open. If the file is open for writing, these attribute will be atomically
|
||||||
// attributes will be written to disk every file sync or close. This
|
// written to disk when the file is written to disk. Note that these
|
||||||
// write occurs atomically with update to the file's contents.
|
// attributes are not written unless the file is modified.
|
||||||
//
|
//
|
||||||
// Custom attributes are uniquely identified by an 8-bit type and limited
|
// Custom attributes are uniquely identified by an 8-bit type and limited
|
||||||
// to LFS_ATTR_MAX bytes. If the stored attribute is larger than the
|
// to LFS_ATTR_MAX bytes. If the stored attribute is larger than the
|
||||||
|
|||||||
@@ -242,3 +242,265 @@ code = '''
|
|||||||
|
|
||||||
lfs_unmount(&lfs) => 0;
|
lfs_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
[[case]] # open same file reading from separate file handles
|
||||||
|
define.READERS = 3
|
||||||
|
define.SIZE = [10, 100, 1000, 10000]
|
||||||
|
define.RDMODE = ['LFS_O_RDONLY', 'LFS_O_RDWR']
|
||||||
|
code = '''
|
||||||
|
const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
lfs_format(&lfs, &cfg) => 0;
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_open(&lfs, &file, "shared", LFS_O_CREAT | LFS_O_WRONLY) => 0;
|
||||||
|
for (int j = 0; j < SIZE; j++) {
|
||||||
|
lfs_file_write(&lfs, &file, &alphas[j % 26], 1) => 1;
|
||||||
|
}
|
||||||
|
lfs_file_close(&lfs, &file) => 0;
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
|
||||||
|
// open all files
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_t readers[READERS];
|
||||||
|
for (int i = 0; i < READERS; i++) {
|
||||||
|
lfs_file_open(&lfs, &readers[i], "shared", RDMODE) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform operations while all readers are open
|
||||||
|
for (int i = 0; i < READERS; i++) {
|
||||||
|
for (int j = 0; j < SIZE; j++) {
|
||||||
|
lfs_file_read(&lfs, &readers[i], buffer, 1) => 1;
|
||||||
|
assert(buffer[0] == alphas[j % 26]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < READERS; i++) {
|
||||||
|
lfs_file_close(&lfs, &readers[i]) => 0;
|
||||||
|
}
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
'''
|
||||||
|
|
||||||
|
[[case]] # open same file reading and writing from separate file handles
|
||||||
|
define.READERS = 3
|
||||||
|
define.SIZE = [10, 100, 1000, 10000]
|
||||||
|
define.RDMODE = ['LFS_O_RDONLY', 'LFS_O_RDWR']
|
||||||
|
define.WRMODE = ['LFS_O_WRONLY', 'LFS_O_RDWR']
|
||||||
|
code = '''
|
||||||
|
const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
const char nums[] = "0123456789";
|
||||||
|
lfs_format(&lfs, &cfg) => 0;
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_open(&lfs, &file, "shared", LFS_O_CREAT | LFS_O_WRONLY) => 0;
|
||||||
|
for (int j = 0; j < SIZE; j++) {
|
||||||
|
lfs_file_write(&lfs, &file, &alphas[j % 26], 1) => 1;
|
||||||
|
}
|
||||||
|
lfs_file_close(&lfs, &file) => 0;
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
|
||||||
|
// open all files
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_t writer;
|
||||||
|
lfs_file_t readers[READERS];
|
||||||
|
lfs_file_open(&lfs, &writer, "shared", WRMODE) => 0;
|
||||||
|
for (int i = 0; i < READERS; i++) {
|
||||||
|
lfs_file_open(&lfs, &readers[i], "shared", RDMODE) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform operations while all readers are open
|
||||||
|
for (int j = 0; j < SIZE; j++) {
|
||||||
|
lfs_file_write(&lfs, &writer, &nums[j % 10], 1) => 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < READERS; i++) {
|
||||||
|
for (int j = 0; j < SIZE/2; j++) {
|
||||||
|
lfs_file_read(&lfs, &readers[i], buffer, 1) => 1;
|
||||||
|
assert(buffer[0] == alphas[j % 26]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sync, now write should reflect in all open files
|
||||||
|
lfs_file_sync(&lfs, &writer) => 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < READERS; i++) {
|
||||||
|
for (int j = SIZE/2; j < SIZE; j++) {
|
||||||
|
lfs_file_read(&lfs, &readers[i], buffer, 1) => 1;
|
||||||
|
assert(buffer[0] == nums[j % 10]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// double check our writer reflects its own changes
|
||||||
|
if (WRMODE == LFS_O_RDWR) {
|
||||||
|
lfs_file_rewind(&lfs, &writer) => 0;
|
||||||
|
for (int j = 0; j < SIZE; j++) {
|
||||||
|
lfs_file_read(&lfs, &writer, buffer, 1) => 1;
|
||||||
|
assert(buffer[0] == nums[j % 10]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < READERS; i++) {
|
||||||
|
lfs_file_close(&lfs, &readers[i]) => 0;
|
||||||
|
}
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
'''
|
||||||
|
|
||||||
|
[[case]] # check that attributes are updated in open files
|
||||||
|
define.READERS = 3
|
||||||
|
define.SIZE = 10
|
||||||
|
define.RDMODE = ['LFS_O_RDONLY', 'LFS_O_RDWR']
|
||||||
|
define.WRMODE = ['LFS_O_WRONLY', 'LFS_O_RDWR']
|
||||||
|
code = '''
|
||||||
|
const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
const char nums[] = "0123456789";
|
||||||
|
lfs_format(&lfs, &cfg) => 0;
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
const struct lfs_file_config filecfg = {
|
||||||
|
.attr_count = 3,
|
||||||
|
.attrs = (struct lfs_attr[]){
|
||||||
|
{'A', "a", 1},
|
||||||
|
{'B', "bb", 2},
|
||||||
|
{'C', "ccc", 3},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
lfs_file_opencfg(&lfs, &file, "shared",
|
||||||
|
LFS_O_CREAT | LFS_O_WRONLY, &filecfg) => 0;
|
||||||
|
for (int j = 0; j < SIZE; j++) {
|
||||||
|
lfs_file_write(&lfs, &file, &alphas[j % 26], 1) => 1;
|
||||||
|
}
|
||||||
|
lfs_file_close(&lfs, &file) => 0;
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
|
||||||
|
// open all files
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_t writer;
|
||||||
|
const struct lfs_file_config writercfg = {
|
||||||
|
.attr_count = 3,
|
||||||
|
.attrs = (struct lfs_attr[]){
|
||||||
|
{'A', &(uint8_t[1]){0}, 1},
|
||||||
|
{'B', &(uint8_t[2]){0}, 2},
|
||||||
|
{'C', &(uint8_t[3]){0}, 3}}};
|
||||||
|
lfs_file_t readers[READERS];
|
||||||
|
const struct lfs_file_config readercfgs[READERS] = {
|
||||||
|
{ .attr_count = 3,
|
||||||
|
.attrs = (struct lfs_attr[]){
|
||||||
|
{'A', &(uint8_t[1]){0}, 1},
|
||||||
|
{'B', &(uint8_t[2]){0}, 2},
|
||||||
|
{'C', &(uint8_t[3]){0}, 3}}},
|
||||||
|
{ .attr_count = 3,
|
||||||
|
.attrs = (struct lfs_attr[]){
|
||||||
|
{'A', &(uint8_t[1]){0}, 1},
|
||||||
|
{'B', &(uint8_t[2]){0}, 2},
|
||||||
|
{'C', &(uint8_t[3]){0}, 3}}},
|
||||||
|
{ .attr_count = 3,
|
||||||
|
.attrs = (struct lfs_attr[]){
|
||||||
|
{'A', &(uint8_t[1]){0}, 1},
|
||||||
|
{'B', &(uint8_t[2]){0}, 2},
|
||||||
|
{'C', &(uint8_t[3]){0}, 3}}}};
|
||||||
|
lfs_file_opencfg(&lfs, &writer, "shared",
|
||||||
|
WRMODE, &writercfg) => 0;
|
||||||
|
for (int i = 0; i < READERS; i++) {
|
||||||
|
lfs_file_opencfg(&lfs, &readers[i], "shared",
|
||||||
|
RDMODE, &readercfgs[i]) => 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform operations while all readers are open
|
||||||
|
writercfg.attrs[0].size = 1;
|
||||||
|
memcpy(writercfg.attrs[0].buffer, "0", 1);
|
||||||
|
writercfg.attrs[1].size = 2;
|
||||||
|
memcpy(writercfg.attrs[1].buffer, "11", 2);
|
||||||
|
writercfg.attrs[2].size = 3;
|
||||||
|
memcpy(writercfg.attrs[2].buffer, "222", 3);
|
||||||
|
for (int j = 0; j < SIZE; j++) {
|
||||||
|
lfs_file_write(&lfs, &writer, &nums[j % 10], 1) => 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < READERS; i++) {
|
||||||
|
assert(readercfgs[i].attrs[0].size == 1);
|
||||||
|
assert(memcmp(readercfgs[i].attrs[0].buffer, "a", 1) == 0);
|
||||||
|
assert(readercfgs[i].attrs[1].size == 2);
|
||||||
|
assert(memcmp(readercfgs[i].attrs[1].buffer, "bb", 2) == 0);
|
||||||
|
assert(readercfgs[i].attrs[2].size == 3);
|
||||||
|
assert(memcmp(readercfgs[i].attrs[2].buffer, "ccc", 3) == 0);
|
||||||
|
for (int j = 0; j < SIZE; j++) {
|
||||||
|
lfs_file_read(&lfs, &readers[i], buffer, 1) => 1;
|
||||||
|
assert(buffer[0] == alphas[j % 26]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sync, now write should reflect in all open files
|
||||||
|
lfs_file_sync(&lfs, &writer) => 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < READERS; i++) {
|
||||||
|
assert(readercfgs[i].attrs[0].size == 1);
|
||||||
|
assert(memcmp(readercfgs[i].attrs[0].buffer, "0", 1) == 0);
|
||||||
|
assert(readercfgs[i].attrs[1].size == 2);
|
||||||
|
assert(memcmp(readercfgs[i].attrs[1].buffer, "11", 2) == 0);
|
||||||
|
assert(readercfgs[i].attrs[2].size == 3);
|
||||||
|
assert(memcmp(readercfgs[i].attrs[2].buffer, "222", 3) == 0);
|
||||||
|
lfs_file_rewind(&lfs, &readers[i]) => 0;
|
||||||
|
for (int j = 0; j < SIZE; j++) {
|
||||||
|
lfs_file_read(&lfs, &readers[i], buffer, 1) => 1;
|
||||||
|
assert(buffer[0] == nums[j % 10]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// double check our writer reflects its own changes
|
||||||
|
if (WRMODE == LFS_O_RDWR) {
|
||||||
|
assert(writercfg.attrs[0].size == 1);
|
||||||
|
assert(memcmp(writercfg.attrs[0].buffer, "0", 1) == 0);
|
||||||
|
assert(writercfg.attrs[1].size == 2);
|
||||||
|
assert(memcmp(writercfg.attrs[1].buffer, "11", 2) == 0);
|
||||||
|
assert(writercfg.attrs[2].size == 3);
|
||||||
|
assert(memcmp(writercfg.attrs[2].buffer, "222", 3) == 0);
|
||||||
|
lfs_file_rewind(&lfs, &writer) => 0;
|
||||||
|
for (int j = 0; j < SIZE; j++) {
|
||||||
|
lfs_file_read(&lfs, &writer, buffer, 1) => 1;
|
||||||
|
assert(buffer[0] == nums[j % 10]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now try explicit lfs_setattr calls, this should still update open files
|
||||||
|
lfs_setattr(&lfs, "shared", 'A', "A", 1) => 0;
|
||||||
|
lfs_setattr(&lfs, "shared", 'B', "BB", 2) => 0;
|
||||||
|
lfs_setattr(&lfs, "shared", 'C', "CCC", 3) => 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < READERS; i++) {
|
||||||
|
assert(readercfgs[i].attrs[0].size == 1);
|
||||||
|
assert(memcmp(readercfgs[i].attrs[0].buffer, "A", 1) == 0);
|
||||||
|
assert(readercfgs[i].attrs[1].size == 2);
|
||||||
|
assert(memcmp(readercfgs[i].attrs[1].buffer, "BB", 2) == 0);
|
||||||
|
assert(readercfgs[i].attrs[2].size == 3);
|
||||||
|
assert(memcmp(readercfgs[i].attrs[2].buffer, "CCC", 3) == 0);
|
||||||
|
lfs_file_rewind(&lfs, &readers[i]) => 0;
|
||||||
|
for (int j = 0; j < SIZE; j++) {
|
||||||
|
lfs_file_read(&lfs, &readers[i], buffer, 1) => 1;
|
||||||
|
assert(buffer[0] == nums[j % 10]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WRMODE == LFS_O_RDWR) {
|
||||||
|
assert(writercfg.attrs[0].size == 1);
|
||||||
|
assert(memcmp(writercfg.attrs[0].buffer, "A", 1) == 0);
|
||||||
|
assert(writercfg.attrs[1].size == 2);
|
||||||
|
assert(memcmp(writercfg.attrs[1].buffer, "BB", 2) == 0);
|
||||||
|
assert(writercfg.attrs[2].size == 3);
|
||||||
|
assert(memcmp(writercfg.attrs[2].buffer, "CCC", 3) == 0);
|
||||||
|
lfs_file_rewind(&lfs, &writer) => 0;
|
||||||
|
for (int j = 0; j < SIZE; j++) {
|
||||||
|
lfs_file_read(&lfs, &writer, buffer, 1) => 1;
|
||||||
|
assert(buffer[0] == nums[j % 10]);
|
||||||
|
}
|
||||||
|
} else if (WRMODE == LFS_O_WRONLY) {
|
||||||
|
// this should NOT update wronly attributes, these may be
|
||||||
|
// stored in read-only memory
|
||||||
|
assert(writercfg.attrs[0].size == 1);
|
||||||
|
assert(memcmp(writercfg.attrs[0].buffer, "0", 1) == 0);
|
||||||
|
assert(writercfg.attrs[1].size == 2);
|
||||||
|
assert(memcmp(writercfg.attrs[1].buffer, "11", 2) == 0);
|
||||||
|
assert(writercfg.attrs[2].size == 3);
|
||||||
|
assert(memcmp(writercfg.attrs[2].buffer, "222", 3) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < READERS; i++) {
|
||||||
|
lfs_file_close(&lfs, &readers[i]) => 0;
|
||||||
|
}
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
'''
|
||||||
|
|||||||
Reference in New Issue
Block a user