Compare commits

..

15 Commits

Author SHA1 Message Date
Christopher Haster
80494b0bda Added thread-safe build+size reporting to CI 2020-11-28 12:41:36 -06:00
Christopher Haster
f507a5c483 Moved LFS_TRACE calls to API wrapper functions
This removes quite a bit of extra code needed to entertwine the
LFS_TRACE calls into the original funcions.

Also changed temporary return type to match API declaration where
necessary.
2020-11-28 12:37:01 -06:00
Christopher Haster
1c5081adb8 Tweaked thread-safe implementation
- Stayed on non-system include for lfs_util.h for now
- Named internal functions "lfs_functionraw"
- Merged lfs_fs_traverseraw
- Added LFS_LOCK/UNLOCK macros
- Changed LFS_THREADSAFE from 1/0 to defined/undefined to
  match LFS_READONLY
2020-11-28 11:15:23 -06:00
Bill Gesner
aab8df756f make the raw functions static 2020-11-20 20:34:54 +00:00
Bill Gesner
a15a060d90 make raw functions static. formatting tweaks 2020-11-20 17:01:04 +00:00
Bill Gesner
d46cefc71c review comments 2020-11-19 19:39:09 +00:00
Bill Gesner
3964e4e1c7 minor cleanup 2020-11-19 19:34:30 +00:00
Bill Gesner
def0228266 minor cleanup 2020-11-19 19:23:47 +00:00
Bill Gesner
1f831e234a address review comments 2020-11-19 19:17:42 +00:00
Bill Gesner
b477e0d8e8 use the global config file 2020-11-12 23:04:41 +00:00
Bill Gesner
be364e8721 fix ac6 linker issue 2020-11-09 16:07:40 +00:00
Bill Gesner
1ecef83c7a use global include 2020-11-06 20:12:15 +00:00
Bill Gesner
f195ffe74c fix locking issue in format and mount 2020-10-28 00:46:01 +00:00
Bill Gesner
16e48ca21b rename functions 2020-10-28 00:42:10 +00:00
Bill Gesner
b4ab86ee3a expand functions
add comment
2020-10-01 01:48:29 +00:00
9 changed files with 376 additions and 1370 deletions

View File

@@ -208,22 +208,6 @@ jobs:
script: script:
- make test TFLAGS+="-k --valgrind" - make test TFLAGS+="-k --valgrind"
# test compilation in read-only mode
- stage: test
env:
- NAME=littlefs-readonly
- CC="arm-linux-gnueabi-gcc --static -mthumb"
- CFLAGS="-Werror -DLFS_READONLY"
if: branch !~ -prefix$
install:
- *install-common
- sudo apt-get install
gcc-arm-linux-gnueabi
libc6-dev-armel-cross
- arm-linux-gnueabi-gcc --version
# report-size will compile littlefs and report the size
script: [*report-size]
# test compilation in thread-safe mode # test compilation in thread-safe mode
- stage: test - stage: test
env: env:

View File

@@ -221,11 +221,6 @@ License Identifiers that are here available: http://spdx.org/licenses/
- [littlefs-js] - A javascript wrapper for littlefs. I'm not sure why you would - [littlefs-js] - A javascript wrapper for littlefs. I'm not sure why you would
want this, but it is handy for demos. You can see it in action want this, but it is handy for demos. You can see it in action
[here][littlefs-js-demo]. [here][littlefs-js-demo].
- [littlefs-python] - A Python wrapper for littlefs. The project allows you
to create images of the filesystem on your PC. Check if littlefs will fit
your needs, create images for a later download to the target memory or
inspect the content of a binary image of the target memory.
- [mklfs] - A command line tool built by the [Lua RTOS] guys for making - [mklfs] - A command line tool built by the [Lua RTOS] guys for making
littlefs images from a host PC. Supports Windows, Mac OS, and Linux. littlefs images from a host PC. Supports Windows, Mac OS, and Linux.
@@ -255,4 +250,3 @@ License Identifiers that are here available: http://spdx.org/licenses/
[LittleFileSystem]: https://os.mbed.com/docs/mbed-os/v5.12/apis/littlefilesystem.html [LittleFileSystem]: https://os.mbed.com/docs/mbed-os/v5.12/apis/littlefilesystem.html
[SPIFFS]: https://github.com/pellepl/spiffs [SPIFFS]: https://github.com/pellepl/spiffs
[Dhara]: https://github.com/dlbeer/dhara [Dhara]: https://github.com/dlbeer/dhara
[littlefs-python]: https://pypi.org/project/littlefs-python/

View File

@@ -207,7 +207,7 @@ int lfs_testbd_prog(const struct lfs_config *cfg, lfs_block_t block,
bd->power_cycles -= 1; bd->power_cycles -= 1;
if (bd->power_cycles == 0) { if (bd->power_cycles == 0) {
// sync to make sure we persist the last changes // sync to make sure we persist the last changes
LFS_ASSERT(lfs_testbd_rawsync(cfg) == 0); assert(lfs_testbd_rawsync(cfg) == 0);
// simulate power loss // simulate power loss
exit(33); exit(33);
} }
@@ -254,7 +254,7 @@ int lfs_testbd_erase(const struct lfs_config *cfg, lfs_block_t block) {
bd->power_cycles -= 1; bd->power_cycles -= 1;
if (bd->power_cycles == 0) { if (bd->power_cycles == 0) {
// sync to make sure we persist the last changes // sync to make sure we persist the last changes
LFS_ASSERT(lfs_testbd_rawsync(cfg) == 0); assert(lfs_testbd_rawsync(cfg) == 0);
// simulate power loss // simulate power loss
exit(33); exit(33);
} }

800
lfs.c

File diff suppressed because it is too large Load Diff

77
lfs.h
View File

@@ -22,7 +22,7 @@ extern "C"
// Software library version // Software library version
// Major (top-nibble), incremented on backwards incompatible changes // Major (top-nibble), incremented on backwards incompatible changes
// Minor (bottom-nibble), incremented on feature additions // Minor (bottom-nibble), incremented on feature additions
#define LFS_VERSION 0x00020003 #define LFS_VERSION 0x00020002
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16)) #define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0)) #define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
@@ -123,30 +123,21 @@ enum lfs_type {
// File open flags // File open flags
enum lfs_open_flags { enum lfs_open_flags {
// open flags // open flags
LFS_O_RDONLY = 1, // Open a file as read only LFS_O_RDONLY = 1, // Open a file as read only
#ifndef LFS_READONLY LFS_O_WRONLY = 2, // Open a file as write only
LFS_O_WRONLY = 2, // Open a file as write only LFS_O_RDWR = 3, // Open a file as read and write
LFS_O_RDWR = 3, // Open a file as read and write LFS_O_CREAT = 0x0100, // Create a file if it does not exist
#endif LFS_O_EXCL = 0x0200, // Fail if a file already exists
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
#ifndef LFS_READONLY LFS_O_APPEND = 0x0800, // Move to end of file on every write
LFS_O_CREAT = 0x0100, // Create a file if it does not exist
LFS_O_EXCL = 0x0200, // Fail if a file already exists
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
LFS_O_APPEND = 0x0800, // Move to end of file on every write
LFS_O_SNAPSHOT = 0x1000, // Open a temporary snapshot, ignore changes
#endif
// internally used flags // internally used flags
#ifndef LFS_READONLY LFS_F_DIRTY = 0x010000, // File does not match storage
LFS_F_DIRTY = 0x010000, // File does not match storage LFS_F_WRITING = 0x020000, // File has been written since last flush
#endif LFS_F_READING = 0x040000, // File has been read since last flush
LFS_F_READING = 0x020000, // File has been read since last flush LFS_F_ERRED = 0x080000, // An error occured during write
#ifndef LFS_READONLY LFS_F_INLINE = 0x100000, // Currently inlined in directory entry
LFS_F_WRITING = 0x040000, // File has been written since last flush LFS_F_OPENED = 0x200000, // File has been opened
LFS_F_ZOMBIE = 0x080000, // An error occurred during write
#endif
LFS_F_INLINE = 0x100000, // Currently inlined in directory entry
}; };
// File seek flags // File seek flags
@@ -298,15 +289,16 @@ 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 for reading, these attributes will be read from disk during // is opened with read access, these attributes will be read from disk
// open. If the file is open for writing, these attribute will be atomically // during the open call. If the file is opened with write access, the
// written to disk when the file is written to disk. Note that these // attributes will be written to disk every file sync or close. This
// attributes are not written unless the file is modified. // write occurs atomically with update to the file's contents.
// //
// 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. When read, if the stored attribute is smaller
// provided buffer, it will be silently truncated. If no attribute is // than the buffer, it will be padded with zeros. If the stored attribute
// found, and the file is open for writing, it will be created implicitly. // is larger, then it will be silently truncated. If the attribute is not
// found, it will be created implicitly.
struct lfs_attr *attrs; struct lfs_attr *attrs;
// Number of custom attributes in the list // Number of custom attributes in the list
@@ -418,7 +410,6 @@ typedef struct lfs {
/// Filesystem functions /// /// Filesystem functions ///
#ifndef LFS_READONLY
// Format a block device with the littlefs // Format a block device with the littlefs
// //
// Requires a littlefs object and config struct. This clobbers the littlefs // Requires a littlefs object and config struct. This clobbers the littlefs
@@ -427,7 +418,6 @@ typedef struct lfs {
// //
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_format(lfs_t *lfs, const struct lfs_config *config); int lfs_format(lfs_t *lfs, const struct lfs_config *config);
#endif
// Mounts a littlefs // Mounts a littlefs
// //
@@ -447,15 +437,12 @@ int lfs_unmount(lfs_t *lfs);
/// General operations /// /// General operations ///
#ifndef LFS_READONLY
// Removes a file or directory // Removes a file or directory
// //
// If removing a directory, the directory must be empty. // If removing a directory, the directory must be empty.
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_remove(lfs_t *lfs, const char *path); int lfs_remove(lfs_t *lfs, const char *path);
#endif
#ifndef LFS_READONLY
// Rename or move a file or directory // Rename or move a file or directory
// //
// If the destination exists, it must match the source in type. // If the destination exists, it must match the source in type.
@@ -463,7 +450,6 @@ int lfs_remove(lfs_t *lfs, const char *path);
// //
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath); int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
#endif
// Find info about a file or directory // Find info about a file or directory
// //
@@ -474,9 +460,10 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
// Get a custom attribute // Get a custom attribute
// //
// 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. When read, if the stored attribute is smaller than
// provided buffer, it will be silently truncated. If no attribute is found, // the buffer, it will be padded with zeros. If the stored attribute is larger,
// the error LFS_ERR_NOATTR is returned and the buffer is filled with zeros. // then it will be silently truncated. If no attribute is found, the error
// LFS_ERR_NOATTR is returned and the buffer is filled with zeros.
// //
// Returns the size of the attribute, or a negative error code on failure. // Returns the size of the attribute, or a negative error code on failure.
// Note, the returned size is the size of the attribute on disk, irrespective // Note, the returned size is the size of the attribute on disk, irrespective
@@ -485,7 +472,6 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path, lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
uint8_t type, void *buffer, lfs_size_t size); uint8_t type, void *buffer, lfs_size_t size);
#ifndef LFS_READONLY
// Set custom attributes // Set custom attributes
// //
// Custom attributes are uniquely identified by an 8-bit type and limited // Custom attributes are uniquely identified by an 8-bit type and limited
@@ -495,16 +481,13 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_setattr(lfs_t *lfs, const char *path, int lfs_setattr(lfs_t *lfs, const char *path,
uint8_t type, const void *buffer, lfs_size_t size); uint8_t type, const void *buffer, lfs_size_t size);
#endif
#ifndef LFS_READONLY
// Removes a custom attribute // Removes a custom attribute
// //
// If an attribute is not found, nothing happens. // If an attribute is not found, nothing happens.
// //
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type); int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type);
#endif
/// File operations /// /// File operations ///
@@ -553,7 +536,6 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file);
lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
void *buffer, lfs_size_t size); void *buffer, lfs_size_t size);
#ifndef LFS_READONLY
// Write data to file // Write data to file
// //
// Takes a buffer and size indicating the data to write. The file will not // Takes a buffer and size indicating the data to write. The file will not
@@ -562,7 +544,6 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
// Returns the number of bytes written, or a negative error code on failure. // Returns the number of bytes written, or a negative error code on failure.
lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
const void *buffer, lfs_size_t size); const void *buffer, lfs_size_t size);
#endif
// Change the position of the file // Change the position of the file
// //
@@ -571,12 +552,10 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
lfs_soff_t off, int whence); lfs_soff_t off, int whence);
#ifndef LFS_READONLY
// Truncates the size of the file to the specified size // Truncates the size of the file to the specified size
// //
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size); int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size);
#endif
// Return the position of the file // Return the position of the file
// //
@@ -599,12 +578,10 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);
/// Directory operations /// /// Directory operations ///
#ifndef LFS_READONLY
// Create a directory // Create a directory
// //
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_mkdir(lfs_t *lfs, const char *path); int lfs_mkdir(lfs_t *lfs, const char *path);
#endif
// Open a directory // Open a directory
// //
@@ -666,7 +643,6 @@ lfs_ssize_t lfs_fs_size(lfs_t *lfs);
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
#ifndef LFS_READONLY
#ifdef LFS_MIGRATE #ifdef LFS_MIGRATE
// Attempts to migrate a previous version of littlefs // Attempts to migrate a previous version of littlefs
// //
@@ -681,7 +657,6 @@ int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
// Returns a negative error code on failure. // Returns a negative error code on failure.
int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg); int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg);
#endif #endif
#endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -106,7 +106,7 @@ def main(args):
struct.unpack('<HH', superblock[1].data[0:4].ljust(4, b'\xff')))) struct.unpack('<HH', superblock[1].data[0:4].ljust(4, b'\xff'))))
print("%-47s%s" % ("littlefs v%s.%s" % version, print("%-47s%s" % ("littlefs v%s.%s" % version,
"data (truncated, if it fits)" "data (truncated, if it fits)"
if not any([args.no_truncate, args.log, args.all]) else "")) if not any([args.no_truncate, args.tags, args.log, args.all]) else ""))
# print gstate # print gstate
print("gstate 0x%s" % ''.join('%02x' % c for c in gstate)) print("gstate 0x%s" % ''.join('%02x' % c for c in gstate))

View File

@@ -16,39 +16,41 @@ code = '''
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 6; lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 6;
lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5; lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+4, "bbbbbb", 6) == 0); memcmp(buffer+4, "bbbbbb", 6) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+10, "ccccc", 5) => 0;
lfs_setattr(&lfs, "hello", 'B', "", 0) => 0; lfs_setattr(&lfs, "hello", 'B', "", 0) => 0;
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 0; lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 0;
lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5; lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
memcmp(buffer+10, "ccccc", 5) => 0;
lfs_removeattr(&lfs, "hello", 'B') => 0; lfs_removeattr(&lfs, "hello", 'B') => 0;
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => LFS_ERR_NOATTR; lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => LFS_ERR_NOATTR;
lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5; lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
memcmp(buffer+10, "ccccc", 5) => 0;
lfs_setattr(&lfs, "hello", 'B', "dddddd", 6) => 0; lfs_setattr(&lfs, "hello", 'B', "dddddd", 6) => 0;
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 6; lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 6;
lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5; lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+4, "dddddd", 6) == 0); memcmp(buffer+4, "dddddd", 6) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+10, "ccccc", 5) => 0;
lfs_setattr(&lfs, "hello", 'B', "eee", 3) => 0; lfs_setattr(&lfs, "hello", 'B', "eee", 3) => 0;
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 3; lfs_getattr(&lfs, "hello", 'B', buffer+4, 6) => 3;
lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5; lfs_getattr(&lfs, "hello", 'C', buffer+10, 5) => 5;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+4, "eee", 3) == 0); memcmp(buffer+4, "eee\0\0\0", 6) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+10, "ccccc", 5) => 0;
lfs_setattr(&lfs, "hello", 'A', buffer, LFS_ATTR_MAX+1) => LFS_ERR_NOSPC; lfs_setattr(&lfs, "hello", 'A', buffer, LFS_ATTR_MAX+1) => LFS_ERR_NOSPC;
lfs_setattr(&lfs, "hello", 'B', "fffffffff", 9) => 0; lfs_setattr(&lfs, "hello", 'B', "fffffffff", 9) => 0;
@@ -63,13 +65,13 @@ code = '''
lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "hello", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "hello", 'B', buffer+4, 9) => 9; lfs_getattr(&lfs, "hello", 'B', buffer+4, 9) => 9;
lfs_getattr(&lfs, "hello", 'C', buffer+13, 5) => 5; lfs_getattr(&lfs, "hello", 'C', buffer+13, 5) => 5;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+4, "fffffffff", 9) == 0); memcmp(buffer+4, "fffffffff", 9) => 0;
assert(memcmp(buffer+13, "ccccc", 5) == 0); memcmp(buffer+13, "ccccc", 5) => 0;
lfs_file_open(&lfs, &file, "hello/hello", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "hello/hello", LFS_O_RDONLY) => 0;
lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => strlen("hello"); lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => strlen("hello");
assert(memcmp(buffer, "hello", strlen("hello")) == 0); memcmp(buffer, "hello", strlen("hello")) => 0;
lfs_file_close(&lfs, &file); lfs_file_close(&lfs, &file);
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''
@@ -92,39 +94,41 @@ code = '''
lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 6; lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 6;
lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5; lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+4, "bbbbbb", 6) == 0); memcmp(buffer+4, "bbbbbb", 6) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+10, "ccccc", 5) => 0;
lfs_setattr(&lfs, "/", 'B', "", 0) => 0; lfs_setattr(&lfs, "/", 'B', "", 0) => 0;
lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 0; lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 0;
lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5; lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
memcmp(buffer+10, "ccccc", 5) => 0;
lfs_removeattr(&lfs, "/", 'B') => 0; lfs_removeattr(&lfs, "/", 'B') => 0;
lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => LFS_ERR_NOATTR; lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => LFS_ERR_NOATTR;
lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5; lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
memcmp(buffer+10, "ccccc", 5) => 0;
lfs_setattr(&lfs, "/", 'B', "dddddd", 6) => 0; lfs_setattr(&lfs, "/", 'B', "dddddd", 6) => 0;
lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 6; lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 6;
lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5; lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+4, "dddddd", 6) == 0); memcmp(buffer+4, "dddddd", 6) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+10, "ccccc", 5) => 0;
lfs_setattr(&lfs, "/", 'B', "eee", 3) => 0; lfs_setattr(&lfs, "/", 'B', "eee", 3) => 0;
lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 3; lfs_getattr(&lfs, "/", 'B', buffer+4, 6) => 3;
lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5; lfs_getattr(&lfs, "/", 'C', buffer+10, 5) => 5;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+4, "eee", 3) == 0); memcmp(buffer+4, "eee\0\0\0", 6) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+10, "ccccc", 5) => 0;
lfs_setattr(&lfs, "/", 'A', buffer, LFS_ATTR_MAX+1) => LFS_ERR_NOSPC; lfs_setattr(&lfs, "/", 'A', buffer, LFS_ATTR_MAX+1) => LFS_ERR_NOSPC;
lfs_setattr(&lfs, "/", 'B', "fffffffff", 9) => 0; lfs_setattr(&lfs, "/", 'B', "fffffffff", 9) => 0;
@@ -138,13 +142,13 @@ code = '''
lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4; lfs_getattr(&lfs, "/", 'A', buffer, 4) => 4;
lfs_getattr(&lfs, "/", 'B', buffer+4, 9) => 9; lfs_getattr(&lfs, "/", 'B', buffer+4, 9) => 9;
lfs_getattr(&lfs, "/", 'C', buffer+13, 5) => 5; lfs_getattr(&lfs, "/", 'C', buffer+13, 5) => 5;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+4, "fffffffff", 9) == 0); memcmp(buffer+4, "fffffffff", 9) => 0;
assert(memcmp(buffer+13, "ccccc", 5) == 0); memcmp(buffer+13, "ccccc", 5) => 0;
lfs_file_open(&lfs, &file, "hello/hello", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "hello/hello", LFS_O_RDONLY) => 0;
lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => strlen("hello"); lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => strlen("hello");
assert(memcmp(buffer, "hello", strlen("hello")) == 0); memcmp(buffer, "hello", strlen("hello")) => 0;
lfs_file_close(&lfs, &file); lfs_file_close(&lfs, &file);
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''
@@ -172,55 +176,52 @@ code = '''
memcpy(buffer, "aaaa", 4); memcpy(buffer, "aaaa", 4);
memcpy(buffer+4, "bbbbbb", 6); memcpy(buffer+4, "bbbbbb", 6);
memcpy(buffer+10, "ccccc", 5); memcpy(buffer+10, "ccccc", 5);
lfs_file_write(&lfs, &file, "hi", 2) => 2;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
memset(buffer, 0, 15); memset(buffer, 0, 15);
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+4, "bbbbbb", 6) == 0); memcmp(buffer+4, "bbbbbb", 6) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+10, "ccccc", 5) => 0;
attrs1[1].size = 0; attrs1[1].size = 0;
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
lfs_file_write(&lfs, &file, "hi", 2) => 2;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
memset(buffer, 0, 15); memset(buffer, 0, 15);
attrs1[1].size = 6; attrs1[1].size = 6;
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+4, "\0\0\0\0\0\0", 6) => 0;
memcmp(buffer+10, "ccccc", 5) => 0;
attrs1[1].size = 6; attrs1[1].size = 6;
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
memcpy(buffer+4, "dddddd", 6); memcpy(buffer+4, "dddddd", 6);
lfs_file_write(&lfs, &file, "hi", 2) => 2;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
memset(buffer, 0, 15); memset(buffer, 0, 15);
attrs1[1].size = 6; attrs1[1].size = 6;
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+4, "dddddd", 6) == 0); memcmp(buffer+4, "dddddd", 6) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+10, "ccccc", 5) => 0;
attrs1[1].size = 3; attrs1[1].size = 3;
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1) => 0;
memcpy(buffer+4, "eee", 3); memcpy(buffer+4, "eee", 3);
lfs_file_write(&lfs, &file, "hi", 2) => 2;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
memset(buffer, 0, 15); memset(buffer, 0, 15);
attrs1[1].size = 6; attrs1[1].size = 6;
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+4, "eee", 3) == 0); memcmp(buffer+4, "eee\0\0\0", 6) => 0;
assert(memcmp(buffer+10, "ccccc", 5) == 0); memcmp(buffer+10, "ccccc", 5) => 0;
attrs1[0].size = LFS_ATTR_MAX+1; attrs1[0].size = LFS_ATTR_MAX+1;
lfs_file_opencfg(&lfs, &file, "hello/hello2", lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_WRONLY, &cfg1)
LFS_O_WRONLY | LFS_O_CREAT, &cfg1) => LFS_ERR_NOSPC; => LFS_ERR_NOSPC;
struct lfs_attr attrs2[] = { struct lfs_attr attrs2[] = {
{'A', buffer, 4}, {'A', buffer, 4},
@@ -230,7 +231,6 @@ code = '''
struct lfs_file_config cfg2 = {.attrs=attrs2, .attr_count=3}; struct lfs_file_config cfg2 = {.attrs=attrs2, .attr_count=3};
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDWR, &cfg2) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDWR, &cfg2) => 0;
memcpy(buffer+4, "fffffffff", 9); memcpy(buffer+4, "fffffffff", 9);
lfs_file_write(&lfs, &file, "hi", 2) => 2;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
attrs1[0].size = 4; attrs1[0].size = 4;
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg1) => 0;
@@ -249,13 +249,13 @@ code = '''
lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg3) => 0; lfs_file_opencfg(&lfs, &file, "hello/hello", LFS_O_RDONLY, &cfg3) => 0;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
assert(memcmp(buffer, "aaaa", 4) == 0); memcmp(buffer, "aaaa", 4) => 0;
assert(memcmp(buffer+4, "fffffffff", 9) == 0); memcmp(buffer+4, "fffffffff", 9) => 0;
assert(memcmp(buffer+13, "ccccc", 5) == 0); memcmp(buffer+13, "ccccc", 5) => 0;
lfs_file_open(&lfs, &file, "hello/hello", LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file, "hello/hello", LFS_O_RDONLY) => 0;
lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => strlen("hello"); lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => strlen("hello");
assert(memcmp(buffer, "hillo", strlen("hello")) == 0); memcmp(buffer, "hello", strlen("hello")) => 0;
lfs_file_close(&lfs, &file); lfs_file_close(&lfs, &file);
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''
@@ -287,16 +287,17 @@ code = '''
lfs_getattr(&lfs, "hello/hello", 'B', buffer, 9) => 9; lfs_getattr(&lfs, "hello/hello", 'B', buffer, 9) => 9;
lfs_getattr(&lfs, "hello/hello", 'C', buffer+9, 9) => 5; lfs_getattr(&lfs, "hello/hello", 'C', buffer+9, 9) => 5;
lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => LFS_ERR_NOATTR; lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => LFS_ERR_NOATTR;
assert(memcmp(buffer, "fffffffff", 9) == 0); memcmp(buffer, "fffffffff", 9) => 0;
assert(memcmp(buffer+9, "ccccc", 5) == 0); memcmp(buffer+9, "ccccc\0\0\0\0", 9) => 0;
memcmp(buffer+18, "\0\0\0\0\0\0\0\0\0", 9) => 0;
lfs_file_write(&lfs, &file, "hi", 2) => 2;
lfs_file_sync(&lfs, &file) => 0; lfs_file_sync(&lfs, &file) => 0;
lfs_getattr(&lfs, "hello/hello", 'B', buffer, 9) => 4; lfs_getattr(&lfs, "hello/hello", 'B', buffer, 9) => 4;
lfs_getattr(&lfs, "hello/hello", 'C', buffer+9, 9) => 0; lfs_getattr(&lfs, "hello/hello", 'C', buffer+9, 9) => 0;
lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => 4; lfs_getattr(&lfs, "hello/hello", 'D', buffer+18, 9) => 4;
assert(memcmp(buffer, "gggg", 4) == 0); memcmp(buffer, "gggg\0\0\0\0\0", 9) => 0;
assert(memcmp(buffer+18, "hhhh", 4) == 0); memcmp(buffer+9, "\0\0\0\0\0\0\0\0\0", 9) => 0;
memcmp(buffer+18, "hhhh\0\0\0\0\0", 9) => 0;
lfs_file_close(&lfs, &file) => 0; lfs_file_close(&lfs, &file) => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;

View File

@@ -1,7 +1,7 @@
[[case]] # interspersed file test [[case]] # interspersed file test
define.SIZE = [10, 100] define.SIZE = [10, 100]
define.FILES = [4, 10, 26] define.FILES = [4, 10, 26]
code = ''' code = '''
lfs_file_t files[FILES]; lfs_file_t files[FILES];
const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
@@ -55,7 +55,7 @@ code = '''
for (int j = 0; j < FILES; j++) { for (int j = 0; j < FILES; j++) {
lfs_file_close(&lfs, &files[j]); lfs_file_close(&lfs, &files[j]);
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''
@@ -108,7 +108,7 @@ code = '''
assert(buffer[0] == '~'); assert(buffer[0] == '~');
} }
lfs_file_close(&lfs, &file); lfs_file_close(&lfs, &file);
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''
@@ -168,13 +168,13 @@ code = '''
} }
lfs_file_close(&lfs, &files[0]); lfs_file_close(&lfs, &files[0]);
lfs_file_close(&lfs, &files[1]); lfs_file_close(&lfs, &files[1]);
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''
[[case]] # reentrant interspersed file test [[case]] # reentrant interspersed file test
define.SIZE = [10, 100] define.SIZE = [10, 100]
define.FILES = [4, 10, 26] define.FILES = [4, 10, 26]
reentrant = true reentrant = true
code = ''' code = '''
lfs_file_t files[FILES]; lfs_file_t files[FILES];
@@ -239,698 +239,6 @@ code = '''
for (int j = 0; j < FILES; j++) { for (int j = 0; j < FILES; j++) {
lfs_file_close(&lfs, &files[j]); lfs_file_close(&lfs, &files[j]);
} }
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;
'''
[[case]] # simple snapshot for reading
define.SIZE = [10, 100, 1000, 10000]
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 = 1,
.attrs = (struct lfs_attr[]){
{'A', "abcd", 4},
},
};
lfs_file_opencfg(&lfs, &file, "open_me",
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 reader/writer/snapshot
lfs_mount(&lfs, &cfg) => 0;
lfs_file_t reader;
const struct lfs_file_config readercfg = {
.attr_count = 1,
.attrs = (struct lfs_attr[]){
{'A', &(uint8_t[4]){0}, 4}
},
};
lfs_file_t writer;
const struct lfs_file_config writercfg = {
.attr_count = 1,
.attrs = (struct lfs_attr[]){
{'A', &(uint8_t[4]){0}, 4}
},
};
lfs_file_t snapshot;
const struct lfs_file_config snapshotcfg = {
.attr_count = 1,
.attrs = (struct lfs_attr[]){
{'A', &(uint8_t[4]){0}, 4}
},
};
lfs_file_opencfg(&lfs, &reader, "open_me",
LFS_O_RDONLY, &readercfg) => 0;
lfs_file_opencfg(&lfs, &writer, "open_me",
LFS_O_WRONLY, &writercfg) => 0;
lfs_file_opencfg(&lfs, &snapshot, "open_me",
LFS_O_RDONLY | LFS_O_SNAPSHOT, &snapshotcfg) => 0;
assert(memcmp(readercfg.attrs[0].buffer, "abcd", 4) == 0);
for (int j = 0; j < SIZE/2; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == alphas[j % 26]);
}
assert(memcmp(snapshotcfg.attrs[0].buffer, "abcd", 4) == 0);
for (int j = 0; j < SIZE/2; j++) {
lfs_file_read(&lfs, &snapshot, buffer, 1) => 1;
assert(buffer[0] == alphas[j % 26]);
}
// write file
for (int j = 0; j < SIZE; j++) {
lfs_file_write(&lfs, &writer, &nums[j % 10], 1) => 1;
}
memcpy(writercfg.attrs[0].buffer, "0123", 4);
lfs_file_sync(&lfs, &writer) => 0;
// reader should change
assert(memcmp(readercfg.attrs[0].buffer, "0123", 4) == 0);
for (int j = SIZE/2; j < SIZE; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == nums[j % 10]);
}
// snapshot should remain unchanged
assert(memcmp(snapshotcfg.attrs[0].buffer, "abcd", 4) == 0);
for (int j = SIZE/2; j < SIZE; j++) {
lfs_file_read(&lfs, &snapshot, buffer, 1) => 1;
assert(buffer[0] == alphas[j % 26]);
}
lfs_file_close(&lfs, &reader) => 0;
lfs_file_close(&lfs, &writer) => 0;
lfs_file_close(&lfs, &snapshot) => 0;
// disk should change
lfs_file_opencfg(&lfs, &reader, "open_me",
LFS_O_RDONLY, &readercfg) => 0;
assert(memcmp(readercfg.attrs[0].buffer, "0123", 4) == 0);
for (int j = 0; j < SIZE; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == nums[j % 10]);
}
lfs_file_close(&lfs, &reader) => 0;
lfs_unmount(&lfs) => 0;
lfs_mount(&lfs, &cfg) => 0;
lfs_file_opencfg(&lfs, &reader, "open_me",
LFS_O_RDONLY, &readercfg) => 0;
assert(memcmp(readercfg.attrs[0].buffer, "0123", 4) == 0);
for (int j = 0; j < SIZE; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == nums[j % 10]);
}
lfs_file_close(&lfs, &reader) => 0;
lfs_unmount(&lfs) => 0;
'''
[[case]] # simple snapshot for writing
define.SIZE = [10, 100, 1000, 10000]
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 = 1,
.attrs = (struct lfs_attr[]){
{'A', "abcd", 4},
},
};
lfs_file_opencfg(&lfs, &file, "open_me",
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 reader/snapshot
lfs_mount(&lfs, &cfg) => 0;
lfs_file_t reader;
const struct lfs_file_config readercfg = {
.attr_count = 1,
.attrs = (struct lfs_attr[]){
{'A', &(uint8_t[4]){0}, 4}
},
};
lfs_file_t snapshot;
const struct lfs_file_config snapshotcfg = {
.attr_count = 1,
.attrs = (struct lfs_attr[]){
{'A', &(uint8_t[4]){0}, 4}
},
};
lfs_file_opencfg(&lfs, &reader, "open_me",
LFS_O_RDONLY, &readercfg) => 0;
lfs_file_opencfg(&lfs, &snapshot, "open_me",
LFS_O_RDWR | LFS_O_SNAPSHOT, &snapshotcfg) => 0;
assert(memcmp(readercfg.attrs[0].buffer, "abcd", 4) == 0);
for (int j = 0; j < SIZE/2; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == alphas[j % 26]);
}
assert(memcmp(snapshotcfg.attrs[0].buffer, "abcd", 4) == 0);
for (int j = 0; j < SIZE; j++) {
lfs_file_read(&lfs, &snapshot, buffer, 1) => 1;
assert(buffer[0] == alphas[j % 26]);
}
// modify snapshot
lfs_file_rewind(&lfs, &snapshot) => 0;
for (int j = 0; j < SIZE; j++) {
lfs_file_write(&lfs, &snapshot, &nums[j % 10], 1) => 1;
}
memcpy(snapshotcfg.attrs[0].buffer, "0123", 4);
lfs_file_rewind(&lfs, &snapshot) => 0;
for (int j = 0; j < SIZE; j++) {
lfs_file_read(&lfs, &snapshot, buffer, 1) => 1;
assert(buffer[0] == nums[j % 10]);
}
lfs_file_sync(&lfs, &snapshot) => 0;
// reader should not change
assert(memcmp(readercfg.attrs[0].buffer, "abcd", 4) == 0);
for (int j = SIZE/2; j < SIZE; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == alphas[j % 26]);
}
// snapshot should changed
assert(memcmp(snapshotcfg.attrs[0].buffer, "0123", 4) == 0);
lfs_file_rewind(&lfs, &snapshot) => 0;
for (int j = 0; j < SIZE; j++) {
lfs_file_read(&lfs, &snapshot, buffer, 1) => 1;
assert(buffer[0] == nums[j % 10]);
}
lfs_file_close(&lfs, &reader) => 0;
lfs_file_close(&lfs, &snapshot) => 0;
// disk should not change
lfs_file_opencfg(&lfs, &reader, "open_me",
LFS_O_RDONLY, &readercfg) => 0;
assert(memcmp(readercfg.attrs[0].buffer, "abcd", 4) == 0);
for (int j = 0; j < SIZE; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == alphas[j % 26]);
}
lfs_file_close(&lfs, &reader) => 0;
lfs_unmount(&lfs) => 0;
lfs_mount(&lfs, &cfg) => 0;
lfs_file_opencfg(&lfs, &reader, "open_me",
LFS_O_RDONLY, &readercfg) => 0;
assert(memcmp(readercfg.attrs[0].buffer, "abcd", 4) == 0);
for (int j = 0; j < SIZE; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == alphas[j % 26]);
}
lfs_file_close(&lfs, &reader) => 0;
lfs_unmount(&lfs) => 0;
'''
[[case]] # temporary files
define.SIZE = [10, 100, 1000, 10000]
define.TMP_PATH = 'range(4)'
code = '''
const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
const char nums[] = "0123456789";
const char caps[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
lfs_format(&lfs, &cfg) => 0;
lfs_mount(&lfs, &cfg) => 0;
const struct lfs_file_config filecfg = {
.attr_count = 1,
.attrs = (struct lfs_attr[]){
{'A', "abcd", 4},
},
};
lfs_file_opencfg(&lfs, &file, "open_me",
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_file_opencfg(&lfs, &file, "dont_open_me",
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 reader/writer/temp
lfs_mount(&lfs, &cfg) => 0;
lfs_file_t reader;
const struct lfs_file_config readercfg = {
.attr_count = 1,
.attrs = (struct lfs_attr[]){
{'A', &(uint8_t[4]){0}, 4}
},
};
lfs_file_t writer;
const struct lfs_file_config writercfg = {
.attr_count = 1,
.attrs = (struct lfs_attr[]){
{'A', &(uint8_t[4]){0}, 4}
},
};
lfs_file_t tmp;
const struct lfs_file_config tmpcfg = {
.attr_count = 1,
.attrs = (struct lfs_attr[]){
{'A', &(uint8_t[4]){0}, 4}
},
};
lfs_file_opencfg(&lfs, &reader, "open_me",
LFS_O_RDONLY, &readercfg) => 0;
lfs_file_opencfg(&lfs, &writer, "open_me",
LFS_O_WRONLY, &writercfg) => 0;
const char *tmp_paths[] = {NULL, "/", "/tmp", "/open_me.tmp"};
lfs_file_opencfg(&lfs, &tmp, tmp_paths[TMP_PATH],
LFS_O_RDWR | LFS_O_CREAT | LFS_O_SNAPSHOT, &tmpcfg) => 0;
assert(memcmp(readercfg.attrs[0].buffer, "abcd", 4) == 0);
for (int j = 0; j < SIZE/3; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == alphas[j % 26]);
}
assert(memcmp(tmpcfg.attrs[0].buffer, "\0\0\0\0", 4) == 0);
assert(lfs_file_size(&lfs, &tmp) == 0);
// write to tmp
for (int j = 0; j < SIZE; j++) {
lfs_file_write(&lfs, &tmp, &nums[j % 10], 1) => 1;
}
memcpy(tmpcfg.attrs[0].buffer, "0123", 4);
lfs_file_rewind(&lfs, &tmp) => 0;
for (int j = 0; j < SIZE; j++) {
lfs_file_read(&lfs, &tmp, buffer, 1) => 1;
assert(buffer[0] == nums[j % 10]);
}
lfs_file_sync(&lfs, &tmp) => 0;
// reader should not change
assert(memcmp(readercfg.attrs[0].buffer, "abcd", 4) == 0);
for (int j = SIZE/3; j < 2*SIZE/3; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == alphas[j % 26]);
}
// tmp should change
assert(memcmp(tmpcfg.attrs[0].buffer, "0123", 4) == 0);
lfs_file_rewind(&lfs, &tmp) => 0;
for (int j = 0; j < SIZE/2; j++) {
lfs_file_read(&lfs, &tmp, buffer, 1) => 1;
assert(buffer[0] == nums[j % 10]);
}
// write to file
for (int j = 0; j < SIZE; j++) {
lfs_file_write(&lfs, &writer, &caps[j % 26], 1) => 1;
}
memcpy(writercfg.attrs[0].buffer, "ABCD", 4);
lfs_file_sync(&lfs, &writer) => 0;
// reader should change
assert(memcmp(readercfg.attrs[0].buffer, "ABCD", 4) == 0);
for (int j = 2*SIZE/3; j < SIZE; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == caps[j % 26]);
}
// tmp should not change
assert(memcmp(tmpcfg.attrs[0].buffer, "0123", 4) == 0);
for (int j = SIZE/2; j < SIZE; j++) {
lfs_file_read(&lfs, &tmp, buffer, 1) => 1;
assert(buffer[0] == nums[j % 10]);
}
lfs_file_close(&lfs, &reader) => 0;
lfs_file_close(&lfs, &writer) => 0;
lfs_file_close(&lfs, &tmp) => 0;
// tmp should not appear on disk
lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR);
assert(strcmp(info.name, ".") == 0);
lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR);
assert(strcmp(info.name, "..") == 0);
lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_REG);
assert(strcmp(info.name, "dont_open_me") == 0);
lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_REG);
assert(strcmp(info.name, "open_me") == 0);
lfs_dir_read(&lfs, &dir, &info) => 0;
lfs_dir_close(&lfs, &dir) => 0;
lfs_file_opencfg(&lfs, &reader, "open_me",
LFS_O_RDONLY, &readercfg) => 0;
assert(memcmp(readercfg.attrs[0].buffer, "ABCD", 4) == 0);
for (int j = 0; j < SIZE; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == caps[j % 26]);
}
lfs_file_close(&lfs, &reader) => 0;
lfs_file_opencfg(&lfs, &reader, "dont_open_me",
LFS_O_RDONLY, &readercfg) => 0;
assert(memcmp(readercfg.attrs[0].buffer, "abcd", 4) == 0);
for (int j = 0; j < SIZE; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == alphas[j % 26]);
}
lfs_file_close(&lfs, &reader) => 0;
lfs_unmount(&lfs) => 0;
lfs_mount(&lfs, &cfg) => 0;
lfs_dir_open(&lfs, &dir, "/") => 0;
lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR);
assert(strcmp(info.name, ".") == 0);
lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_DIR);
assert(strcmp(info.name, "..") == 0);
lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_REG);
assert(strcmp(info.name, "dont_open_me") == 0);
lfs_dir_read(&lfs, &dir, &info) => 1;
assert(info.type == LFS_TYPE_REG);
assert(strcmp(info.name, "open_me") == 0);
lfs_dir_read(&lfs, &dir, &info) => 0;
lfs_dir_close(&lfs, &dir) => 0;
lfs_file_opencfg(&lfs, &reader, "open_me",
LFS_O_RDONLY, &readercfg) => 0;
assert(memcmp(readercfg.attrs[0].buffer, "ABCD", 4) == 0);
for (int j = 0; j < SIZE; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == caps[j % 26]);
}
lfs_file_close(&lfs, &reader) => 0;
lfs_file_opencfg(&lfs, &reader, "dont_open_me",
LFS_O_RDONLY, &readercfg) => 0;
assert(memcmp(readercfg.attrs[0].buffer, "abcd", 4) == 0);
for (int j = 0; j < SIZE; j++) {
lfs_file_read(&lfs, &reader, buffer, 1) => 1;
assert(buffer[0] == alphas[j % 26]);
}
lfs_file_close(&lfs, &reader) => 0;
lfs_unmount(&lfs) => 0;
'''
[[case]] # test snapshot open errors
code = '''
lfs_format(&lfs, &cfg) => 0;
lfs_mount(&lfs, &cfg) => 0;
lfs_file_open(&lfs, &file, NULL,
LFS_O_RDWR | LFS_O_SNAPSHOT) => LFS_ERR_ISDIR;
lfs_file_open(&lfs, &file, "/",
LFS_O_RDWR | LFS_O_SNAPSHOT) => LFS_ERR_ISDIR;
lfs_file_open(&lfs, &file, "/tmp",
LFS_O_RDWR | LFS_O_SNAPSHOT) => LFS_ERR_NOENT;
lfs_file_open(&lfs, &file, "/tmp/",
LFS_O_RDWR | LFS_O_CREAT | LFS_O_SNAPSHOT) => LFS_ERR_NOENT;
lfs_file_open(&lfs, &file, "/tmp/tmp",
LFS_O_RDWR | LFS_O_CREAT | LFS_O_SNAPSHOT) => LFS_ERR_NOENT;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''

View File

@@ -95,9 +95,9 @@ code = '''
lfs_mkdir(&lfs, "coffee/../milk") => 0; lfs_mkdir(&lfs, "coffee/../milk") => 0;
lfs_stat(&lfs, "coffee/../milk", &info) => 0; lfs_stat(&lfs, "coffee/../milk", &info) => 0;
assert(strcmp(info.name, "milk") == 0); strcmp(info.name, "milk") => 0;
lfs_stat(&lfs, "milk", &info) => 0; lfs_stat(&lfs, "milk", &info) => 0;
assert(strcmp(info.name, "milk") == 0); strcmp(info.name, "milk") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''
@@ -129,9 +129,9 @@ code = '''
lfs_mount(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
lfs_mkdir(&lfs, ".milk") => 0; lfs_mkdir(&lfs, ".milk") => 0;
lfs_stat(&lfs, ".milk", &info) => 0; lfs_stat(&lfs, ".milk", &info) => 0;
assert(strcmp(info.name, ".milk") == 0); strcmp(info.name, ".milk") => 0;
lfs_stat(&lfs, "tea/.././.milk", &info) => 0; lfs_stat(&lfs, "tea/.././.milk", &info) => 0;
assert(strcmp(info.name, ".milk") == 0); strcmp(info.name, ".milk") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''
@@ -149,13 +149,13 @@ code = '''
lfs_mkdir(&lfs, "coffee/coldcoffee") => 0; lfs_mkdir(&lfs, "coffee/coldcoffee") => 0;
lfs_stat(&lfs, "coffee/../../../../../../tea/hottea", &info) => 0; lfs_stat(&lfs, "coffee/../../../../../../tea/hottea", &info) => 0;
assert(strcmp(info.name, "hottea") == 0); strcmp(info.name, "hottea") => 0;
lfs_mkdir(&lfs, "coffee/../../../../../../milk") => 0; lfs_mkdir(&lfs, "coffee/../../../../../../milk") => 0;
lfs_stat(&lfs, "coffee/../../../../../../milk", &info) => 0; lfs_stat(&lfs, "coffee/../../../../../../milk", &info) => 0;
assert(strcmp(info.name, "milk") == 0); strcmp(info.name, "milk") => 0;
lfs_stat(&lfs, "milk", &info) => 0; lfs_stat(&lfs, "milk", &info) => 0;
assert(strcmp(info.name, "milk") == 0); strcmp(info.name, "milk") => 0;
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
''' '''