@@ -82,7 +82,6 @@ static int lfs_bd_read(lfs_t *lfs, lfs_block_t block,
82
82
// load to cache, first condition can no longer fail
83
83
lfs -> rcache .block = block ;
84
84
lfs -> rcache .off = off - (off % lfs -> cfg -> read_size );
85
- // TODO remove reading, should be unnecessary
86
85
err = lfs -> cfg -> read (lfs -> cfg , lfs -> rcache .block ,
87
86
lfs -> rcache .off , lfs -> cfg -> read_size ,
88
87
lfs -> rcache .buffer );
@@ -141,12 +140,6 @@ static int lfs_bd_prog(lfs_t *lfs, lfs_block_t block,
141
140
// prepare cache, first condition can no longer fail
142
141
lfs -> pcache .block = block ;
143
142
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
- }
150
143
}
151
144
152
145
return 0 ;
@@ -810,7 +803,7 @@ static int lfs_index_find(lfs_t *lfs, lfs_block_t head, lfs_size_t size,
810
803
lfs_off_t current = lfs_index (lfs , & (lfs_off_t ){size - 1 });
811
804
lfs_off_t target = lfs_index (lfs , & pos );
812
805
813
- while (current != target ) {
806
+ while (current > target ) {
814
807
lfs_size_t skip = lfs_min (
815
808
lfs_npw2 (current - target + 1 ) - 1 ,
816
809
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,
831
824
static int lfs_index_extend (lfs_t * lfs ,
832
825
lfs_block_t head , lfs_size_t size ,
833
826
lfs_off_t * block , lfs_block_t * off ) {
827
+ // go ahead and grab a block
834
828
int err = lfs_alloc (lfs , block );
835
829
if (err ) {
836
830
return err ;
@@ -846,11 +840,35 @@ static int lfs_index_extend(lfs_t *lfs,
846
840
return 0 ;
847
841
}
848
842
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 ;
850
868
lfs_size_t skips = lfs_min (lfs_ctz (index )+ 1 , lfs -> words - 1 );
851
869
852
870
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 );
854
872
if (err ) {
855
873
return err ;
856
874
}
@@ -936,27 +954,68 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
936
954
return LFS_ERROR_EXISTS ;
937
955
}
938
956
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 ;
942
958
file -> wblock = 0 ;
943
959
file -> rpos = 0 ;
944
960
file -> rblock = 0 ;
945
961
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
+
946
971
return 0 ;
947
972
}
948
973
949
974
int 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
951
1013
lfs_dir_t cwd ;
952
1014
int err = lfs_dir_fetch (lfs , & cwd , file -> entry .pair );
953
1015
if (err ) {
954
1016
return err ;
955
1017
}
956
1018
957
- file -> entry .d .u .file .head = file -> head ;
958
- file -> entry .d .u .file .size = file -> size ;
959
-
960
1019
return lfs_dir_commit (lfs , & cwd , & file -> entry , NULL );
961
1020
}
962
1021
@@ -966,14 +1025,16 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
966
1025
lfs_size_t nsize = size ;
967
1026
968
1027
while (nsize > 0 ) {
1028
+ // check if we need a new block
969
1029
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 ,
971
1031
& file -> wblock , & file -> woff );
972
1032
if (err ) {
973
1033
return err ;
974
1034
}
975
1035
}
976
1036
1037
+ // program as much as we can in current block
977
1038
lfs_size_t diff = lfs_min (nsize , lfs -> cfg -> block_size - file -> woff );
978
1039
int err = lfs_bd_prog (lfs , file -> wblock , file -> woff , diff , data );
979
1040
if (err ) {
@@ -985,9 +1046,16 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
985
1046
data += diff ;
986
1047
nsize -= diff ;
987
1048
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 ;
991
1059
}
992
1060
}
993
1061
@@ -997,18 +1065,21 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
997
1065
lfs_ssize_t lfs_file_read (lfs_t * lfs , lfs_file_t * file ,
998
1066
void * buffer , lfs_size_t size ) {
999
1067
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 );
1001
1069
lfs_size_t nsize = size ;
1002
1070
1003
1071
while (nsize > 0 ) {
1072
+ // check if we need a new block
1004
1073
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 );
1007
1077
if (err ) {
1008
1078
return err ;
1009
1079
}
1010
1080
}
1011
1081
1082
+ // read as much as we can in current block
1012
1083
lfs_size_t diff = lfs_min (nsize , lfs -> cfg -> block_size - file -> roff );
1013
1084
int err = lfs_bd_read (lfs , file -> rblock , file -> roff , diff , data );
1014
1085
if (err ) {
0 commit comments