Skip to content

Commit 1950758

Browse files
committed
Added 2GiB file size limit and EFBIG reporting
On disk, littlefs uses 32-bit integers to track file size. This sets a theoretical limit of 4GiB for files. However, the API passes file sizes around as signed numbers, with negative values representing error codes. This means that not all of the APIs will work with file sizes > 2GiB. Because of related complications over in FUSE land, I've added the LFS_FILE_MAX constant and proper error reporting if file writes/seeks exceed the 2GiB limit. In v2 this will join the other constants that get stored in the superblock to help portability. Since littlefs is targeting microcontrollers, it's likely this will be a sufficient solution. Note that it's still possible to enable partial-support for 4GiB files by defining LFS_FILE_MAX during compilation. This will work for most of the APIs, except lfs_file_seek, lfs_file_tell, and lfs_file_size. We can also consider improving support for 4GiB files, by making seek a bit more complicated and adding a lfs_file_stat function. I'll leave this for a future improvement if there's interest. Found by cgrozemuller
1 parent 97d8d5e commit 1950758

File tree

2 files changed

+24
-13
lines changed

2 files changed

+24
-13
lines changed

lfs.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1644,6 +1644,11 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
16441644
file->pos = file->size;
16451645
}
16461646

1647+
if (file->pos + size > LFS_FILE_MAX) {
1648+
// larger than file limit?
1649+
return LFS_ERR_FBIG;
1650+
}
1651+
16471652
if (!(file->flags & LFS_F_WRITING) && file->pos > file->size) {
16481653
// fill with zeros
16491654
lfs_off_t pos = file->pos;
@@ -1730,24 +1735,24 @@ lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
17301735
return err;
17311736
}
17321737

1733-
// update pos
1738+
// find new pos
1739+
lfs_soff_t npos = file->pos;
17341740
if (whence == LFS_SEEK_SET) {
1735-
file->pos = off;
1741+
npos = off;
17361742
} else if (whence == LFS_SEEK_CUR) {
1737-
if (off < 0 && (lfs_off_t)-off > file->pos) {
1738-
return LFS_ERR_INVAL;
1739-
}
1740-
1741-
file->pos = file->pos + off;
1743+
npos = file->pos + off;
17421744
} else if (whence == LFS_SEEK_END) {
1743-
if (off < 0 && (lfs_off_t)-off > file->size) {
1744-
return LFS_ERR_INVAL;
1745-
}
1745+
npos = file->size + off;
1746+
}
17461747

1747-
file->pos = file->size + off;
1748+
if (npos < 0 || npos > LFS_FILE_MAX) {
1749+
// file position out of range
1750+
return LFS_ERR_INVAL;
17481751
}
17491752

1750-
return file->pos;
1753+
// update pos
1754+
file->pos = npos;
1755+
return npos;
17511756
}
17521757

17531758
int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {

lfs.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ extern "C"
2121
// Software library version
2222
// Major (top-nibble), incremented on backwards incompatible changes
2323
// Minor (bottom-nibble), incremented on feature additions
24-
#define LFS_VERSION 0x00010006
24+
#define LFS_VERSION 0x00010007
2525
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
2626
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
2727

@@ -49,6 +49,11 @@ typedef uint32_t lfs_block_t;
4949
#define LFS_NAME_MAX 255
5050
#endif
5151

52+
// Max file size in bytes
53+
#ifndef LFS_FILE_MAX
54+
#define LFS_FILE_MAX 2147483647
55+
#endif
56+
5257
// Possible error codes, these are negative to allow
5358
// valid positive return values
5459
enum lfs_error {
@@ -61,6 +66,7 @@ enum lfs_error {
6166
LFS_ERR_ISDIR = -21, // Entry is a dir
6267
LFS_ERR_NOTEMPTY = -39, // Dir is not empty
6368
LFS_ERR_BADF = -9, // Bad file number
69+
LFS_ERR_FBIG = -27, // File too large
6470
LFS_ERR_INVAL = -22, // Invalid parameter
6571
LFS_ERR_NOSPC = -28, // No space left on device
6672
LFS_ERR_NOMEM = -12, // No more memory available

0 commit comments

Comments
 (0)