@@ -82,7 +82,6 @@ static int lfs_bd_read(lfs_t *lfs, lfs_block_t block,
8282 // load to cache, first condition can no longer fail
8383 lfs -> rcache .block = block ;
8484 lfs -> rcache .off = off - (off % lfs -> cfg -> read_size );
85- // TODO remove reading, should be unnecessary
8685 err = lfs -> cfg -> read (lfs -> cfg , lfs -> rcache .block ,
8786 lfs -> rcache .off , lfs -> cfg -> read_size ,
8887 lfs -> rcache .buffer );
@@ -141,12 +140,6 @@ static int lfs_bd_prog(lfs_t *lfs, lfs_block_t block,
141140 // prepare cache, first condition can no longer fail
142141 lfs -> pcache .block = block ;
143142 lfs -> pcache .off = off - (off % lfs -> cfg -> prog_size );
144- err = lfs -> cfg -> read (lfs -> cfg , lfs -> pcache .block ,
145- lfs -> pcache .off , lfs -> cfg -> prog_size ,
146- lfs -> pcache .buffer );
147- if (err ) {
148- return err ;
149- }
150143 }
151144
152145 return 0 ;
@@ -810,7 +803,7 @@ static int lfs_index_find(lfs_t *lfs, lfs_block_t head, lfs_size_t size,
810803 lfs_off_t current = lfs_index (lfs , & (lfs_off_t ){size - 1 });
811804 lfs_off_t target = lfs_index (lfs , & pos );
812805
813- while (current != target ) {
806+ while (current > target ) {
814807 lfs_size_t skip = lfs_min (
815808 lfs_npw2 (current - target + 1 ) - 1 ,
816809 lfs_min (lfs_ctz (current )+ 1 , lfs -> words - 1 ) - 1 );
@@ -831,6 +824,7 @@ static int lfs_index_find(lfs_t *lfs, lfs_block_t head, lfs_size_t size,
831824static int lfs_index_extend (lfs_t * lfs ,
832825 lfs_block_t head , lfs_size_t size ,
833826 lfs_off_t * block , lfs_block_t * off ) {
827+ // go ahead and grab a block
834828 int err = lfs_alloc (lfs , block );
835829 if (err ) {
836830 return err ;
@@ -846,11 +840,35 @@ static int lfs_index_extend(lfs_t *lfs,
846840 return 0 ;
847841 }
848842
849- lfs_off_t index = lfs_index (lfs , & (lfs_off_t ){size - 1 }) + 1 ;
843+ size -= 1 ;
844+ lfs_off_t index = lfs_index (lfs , & size );
845+ size += 1 ;
846+
847+ // just copy out the last block if it is incomplete
848+ if (size != lfs -> cfg -> block_size ) {
849+ for (lfs_off_t i = 0 ; i < size ; i ++ ) {
850+ uint8_t data ;
851+ int err = lfs_bd_read (lfs , head , i , 1 , & data );
852+ if (err ) {
853+ return err ;
854+ }
855+
856+ err = lfs_bd_prog (lfs , * block , i , 1 , & data );
857+ if (err ) {
858+ return err ;
859+ }
860+ }
861+
862+ * off = size ;
863+ return 0 ;
864+ }
865+
866+ // append block
867+ index += 1 ;
850868 lfs_size_t skips = lfs_min (lfs_ctz (index )+ 1 , lfs -> words - 1 );
851869
852870 for (lfs_off_t i = 0 ; i < skips ; i ++ ) {
853- err = lfs_bd_prog (lfs , * block , 4 * i , 4 , & head );
871+ int err = lfs_bd_prog (lfs , * block , 4 * i , 4 , & head );
854872 if (err ) {
855873 return err ;
856874 }
@@ -936,27 +954,68 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
936954 return LFS_ERROR_EXISTS ;
937955 }
938956
939- file -> head = file -> entry .d .u .file .head ;
940- file -> size = file -> entry .d .u .file .size ;
941- file -> wpos = file -> entry .d .u .file .size ;
957+ file -> wpos = 0 ;
942958 file -> wblock = 0 ;
943959 file -> rpos = 0 ;
944960 file -> rblock = 0 ;
945961
962+ if (flags & LFS_O_TRUNC ) {
963+ file -> entry .d .u .file .head = 0 ;
964+ file -> entry .d .u .file .size = 0 ;
965+ }
966+
967+ if (flags & LFS_O_APPEND ) {
968+ file -> wpos = file -> entry .d .u .file .size ;
969+ }
970+
946971 return 0 ;
947972}
948973
949974int lfs_file_close (lfs_t * lfs , lfs_file_t * file ) {
950- // Store file
975+ return lfs_file_sync (lfs , file );
976+ }
977+
978+ int lfs_file_sync (lfs_t * lfs , lfs_file_t * file ) {
979+ if (file -> wblock == 0 ) {
980+ // already in sync, may be rdonly
981+ return 0 ;
982+ }
983+
984+ // copy over anything after the file
985+ lfs_off_t oldrpos = file -> rpos ;
986+ lfs_off_t oldwpos = file -> wpos ;
987+ file -> rpos = file -> wpos ;
988+ file -> rblock = 0 ;
989+
990+ while (file -> wpos < file -> entry .d .u .file .size ) {
991+ uint8_t data ;
992+ lfs_ssize_t res = lfs_file_read (lfs , file , & data , 1 );
993+ if (res < 0 ) {
994+ return res ;
995+ }
996+
997+ res = lfs_file_write (lfs , file , & data , 1 );
998+ if (res < 0 ) {
999+ return res ;
1000+ }
1001+ }
1002+
1003+ // actual file updates
1004+ file -> entry .d .u .file .head = file -> wblock ;
1005+ file -> entry .d .u .file .size = file -> wpos ;
1006+
1007+ file -> rpos = oldrpos ;
1008+ file -> rblock = 0 ;
1009+ file -> wpos = oldwpos ;
1010+ file -> wblock = 0 ;
1011+
1012+ // update dir entry
9511013 lfs_dir_t cwd ;
9521014 int err = lfs_dir_fetch (lfs , & cwd , file -> entry .pair );
9531015 if (err ) {
9541016 return err ;
9551017 }
9561018
957- file -> entry .d .u .file .head = file -> head ;
958- file -> entry .d .u .file .size = file -> size ;
959-
9601019 return lfs_dir_commit (lfs , & cwd , & file -> entry , NULL );
9611020}
9621021
@@ -966,14 +1025,16 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
9661025 lfs_size_t nsize = size ;
9671026
9681027 while (nsize > 0 ) {
1028+ // check if we need a new block
9691029 if (!file -> wblock || file -> woff == lfs -> cfg -> block_size ) {
970- int err = lfs_index_extend (lfs , file -> head , file -> wpos ,
1030+ int err = lfs_index_extend (lfs , file -> wblock , file -> wpos ,
9711031 & file -> wblock , & file -> woff );
9721032 if (err ) {
9731033 return err ;
9741034 }
9751035 }
9761036
1037+ // program as much as we can in current block
9771038 lfs_size_t diff = lfs_min (nsize , lfs -> cfg -> block_size - file -> woff );
9781039 int err = lfs_bd_prog (lfs , file -> wblock , file -> woff , diff , data );
9791040 if (err ) {
@@ -985,9 +1046,16 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
9851046 data += diff ;
9861047 nsize -= diff ;
9871048
988- if (file -> wpos > file -> size ) {
989- file -> size = file -> wpos ;
990- file -> head = file -> wblock ;
1049+ if (file -> flags & LFS_O_APPEND ) {
1050+ file -> entry .d .u .file .head = file -> wblock ;
1051+ file -> entry .d .u .file .size = file -> wpos ;
1052+ }
1053+ }
1054+
1055+ if (file -> flags & LFS_O_SYNC ) {
1056+ int err = lfs_file_sync (lfs , file );
1057+ if (err ) {
1058+ return err ;
9911059 }
9921060 }
9931061
@@ -997,18 +1065,21 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
9971065lfs_ssize_t lfs_file_read (lfs_t * lfs , lfs_file_t * file ,
9981066 void * buffer , lfs_size_t size ) {
9991067 uint8_t * data = buffer ;
1000- size = lfs_min (size , file -> size - file -> rpos );
1068+ size = lfs_min (size , file -> entry . d . u . file . size - file -> rpos );
10011069 lfs_size_t nsize = size ;
10021070
10031071 while (nsize > 0 ) {
1072+ // check if we need a new block
10041073 if (!file -> rblock || file -> roff == lfs -> cfg -> block_size ) {
1005- int err = lfs_index_find (lfs , file -> head , file -> size , file -> rpos ,
1006- & file -> rblock , & file -> roff );
1074+ int err = lfs_index_find (lfs ,
1075+ file -> entry .d .u .file .head , file -> entry .d .u .file .size ,
1076+ file -> rpos , & file -> rblock , & file -> roff );
10071077 if (err ) {
10081078 return err ;
10091079 }
10101080 }
10111081
1082+ // read as much as we can in current block
10121083 lfs_size_t diff = lfs_min (nsize , lfs -> cfg -> block_size - file -> roff );
10131084 int err = lfs_bd_read (lfs , file -> rblock , file -> roff , diff , data );
10141085 if (err ) {
0 commit comments