Skip to content

Commit 472ccc4

Browse files
committed
Fixed file truncation without writes
In the open call, the LFS_O_TRUNC flag was correctly zeroing the file, but it wasn't actually writing the change out to disk. This went unnoticed because in the cases where the truncate was followed by a file write, the updated contents would be written out correctly. Marking the file as dirty if the file isn't already truncated fixes the problem with the least impact. Also added better test cases around truncating files.
1 parent aea3d3d commit 472ccc4

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

lfs.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,9 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
12611261
file->pos = 0;
12621262

12631263
if (flags & LFS_O_TRUNC) {
1264+
if (file->size != 0) {
1265+
file->flags |= LFS_F_DIRTY;
1266+
}
12641267
file->head = 0xffffffff;
12651268
file->size = 0;
12661269
}

tests/test_files.sh

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ tests/test.py << TEST
3434
lfs_size_t chunk = 31;
3535
srand(0);
3636
lfs_mount(&lfs, &cfg) => 0;
37-
lfs_file_open(&lfs, &file[0], "$2", LFS_O_WRONLY | LFS_O_CREAT) => 0;
37+
lfs_file_open(&lfs, &file[0], "$2",
38+
${3:-LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC}) => 0;
3839
for (lfs_size_t i = 0; i < size; i += chunk) {
3940
chunk = (chunk < size - i) ? chunk : size - i;
4041
for (lfs_size_t b = 0; b < chunk; b++) {
@@ -53,7 +54,10 @@ tests/test.py << TEST
5354
lfs_size_t chunk = 29;
5455
srand(0);
5556
lfs_mount(&lfs, &cfg) => 0;
56-
lfs_file_open(&lfs, &file[0], "$2", LFS_O_RDONLY) => 0;
57+
lfs_stat(&lfs, "$2", &info) => 0;
58+
info.type => LFS_TYPE_REG;
59+
info.size => size;
60+
lfs_file_open(&lfs, &file[0], "$2", ${3:-LFS_O_RDONLY}) => 0;
5761
for (lfs_size_t i = 0; i < size; i += chunk) {
5862
chunk = (chunk < size - i) ? chunk : size - i;
5963
lfs_file_read(&lfs, &file[0], buffer, chunk) => chunk;
@@ -78,10 +82,27 @@ echo "--- Large file test ---"
7882
w_test $LARGESIZE largeavacado
7983
r_test $LARGESIZE largeavacado
8084

85+
echo "--- Zero file test ---"
86+
w_test 0 noavacado
87+
r_test 0 noavacado
88+
89+
echo "--- Truncate small test ---"
90+
w_test $SMALLSIZE mediumavacado
91+
r_test $SMALLSIZE mediumavacado
92+
w_test $MEDIUMSIZE mediumavacado
93+
r_test $MEDIUMSIZE mediumavacado
94+
95+
echo "--- Truncate zero test ---"
96+
w_test $SMALLSIZE noavacado
97+
r_test $SMALLSIZE noavacado
98+
w_test 0 noavacado
99+
r_test 0 noavacado
100+
81101
echo "--- Non-overlap check ---"
82102
r_test $SMALLSIZE smallavacado
83103
r_test $MEDIUMSIZE mediumavacado
84104
r_test $LARGESIZE largeavacado
105+
r_test 0 noavacado
85106

86107
echo "--- Dir check ---"
87108
tests/test.py << TEST
@@ -105,6 +126,10 @@ tests/test.py << TEST
105126
strcmp(info.name, "largeavacado") => 0;
106127
info.type => LFS_TYPE_REG;
107128
info.size => $LARGESIZE;
129+
lfs_dir_read(&lfs, &dir[0], &info) => 1;
130+
strcmp(info.name, "noavacado") => 0;
131+
info.type => LFS_TYPE_REG;
132+
info.size => 0;
108133
lfs_dir_read(&lfs, &dir[0], &info) => 0;
109134
lfs_dir_close(&lfs, &dir[0]) => 0;
110135
lfs_unmount(&lfs) => 0;

0 commit comments

Comments
 (0)