Pārlūkot izejas kodu

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.
Christopher Haster 8 gadi atpakaļ
vecāks
revīzija
472ccc4203
2 mainītis faili ar 30 papildinājumiem un 2 dzēšanām
  1. 3 0
      lfs.c
  2. 27 2
      tests/test_files.sh

+ 3 - 0
lfs.c

@@ -1261,6 +1261,9 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
     file->pos = 0;
 
     if (flags & LFS_O_TRUNC) {
+        if (file->size != 0) {
+            file->flags |= LFS_F_DIRTY;
+        }
         file->head = 0xffffffff;
         file->size = 0;
     }

+ 27 - 2
tests/test_files.sh

@@ -34,7 +34,8 @@ tests/test.py << TEST
     lfs_size_t chunk = 31;
     srand(0);
     lfs_mount(&lfs, &cfg) => 0;
-    lfs_file_open(&lfs, &file[0], "$2", LFS_O_WRONLY | LFS_O_CREAT) => 0;
+    lfs_file_open(&lfs, &file[0], "$2",
+        ${3:-LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC}) => 0;
     for (lfs_size_t i = 0; i < size; i += chunk) {
         chunk = (chunk < size - i) ? chunk : size - i;
         for (lfs_size_t b = 0; b < chunk; b++) {
@@ -53,7 +54,10 @@ tests/test.py << TEST
     lfs_size_t chunk = 29;
     srand(0);
     lfs_mount(&lfs, &cfg) => 0;
-    lfs_file_open(&lfs, &file[0], "$2", LFS_O_RDONLY) => 0;
+    lfs_stat(&lfs, "$2", &info) => 0;
+    info.type => LFS_TYPE_REG;
+    info.size => size;
+    lfs_file_open(&lfs, &file[0], "$2", ${3:-LFS_O_RDONLY}) => 0;
     for (lfs_size_t i = 0; i < size; i += chunk) {
         chunk = (chunk < size - i) ? chunk : size - i;
         lfs_file_read(&lfs, &file[0], buffer, chunk) => chunk;
@@ -78,10 +82,27 @@ echo "--- Large file test ---"
 w_test $LARGESIZE largeavacado
 r_test $LARGESIZE largeavacado
 
+echo "--- Zero file test ---"
+w_test 0 noavacado
+r_test 0 noavacado
+
+echo "--- Truncate small test ---"
+w_test $SMALLSIZE mediumavacado
+r_test $SMALLSIZE mediumavacado
+w_test $MEDIUMSIZE mediumavacado
+r_test $MEDIUMSIZE mediumavacado
+
+echo "--- Truncate zero test ---"
+w_test $SMALLSIZE noavacado
+r_test $SMALLSIZE noavacado
+w_test 0 noavacado
+r_test 0 noavacado
+
 echo "--- Non-overlap check ---"
 r_test $SMALLSIZE smallavacado
 r_test $MEDIUMSIZE mediumavacado
 r_test $LARGESIZE largeavacado
+r_test 0 noavacado
 
 echo "--- Dir check ---"
 tests/test.py << TEST
@@ -105,6 +126,10 @@ tests/test.py << TEST
     strcmp(info.name, "largeavacado") => 0;
     info.type => LFS_TYPE_REG;
     info.size => $LARGESIZE;
+    lfs_dir_read(&lfs, &dir[0], &info) => 1;
+    strcmp(info.name, "noavacado") => 0;
+    info.type => LFS_TYPE_REG;
+    info.size => 0;
     lfs_dir_read(&lfs, &dir[0], &info) => 0;
     lfs_dir_close(&lfs, &dir[0]) => 0;
     lfs_unmount(&lfs) => 0;