@@ -677,15 +677,14 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir,
677677 return 0 ;
678678}
679679
680- static int lfs_dir_append (lfs_t * lfs , lfs_dir_t * dir ,
681- lfs_entry_t * entry , struct lfs_region * regions ) {
680+ static int lfs_dir_append_ (lfs_t * lfs , lfs_dir_t * dir ,
681+ lfs_off_t * off , lfs_size_t size , struct lfs_region * regions ) {
682682 // check if we fit, if top bit is set we do not and move on
683683 while (true) {
684- if ((0x7fffffff & dir -> d .size ) + lfs_entry_size (entry )
685- <= lfs -> cfg -> block_size ) {
686- entry -> off = dir -> d .size - 4 ;
684+ if ((0x7fffffff & dir -> d .size ) + size <= lfs -> cfg -> block_size ) {
685+ * off = dir -> d .size - 4 ;
687686 for (struct lfs_region * r = regions ; r ; r = r -> next ) {
688- r -> off += entry -> off ;
687+ r -> off += * off ;
689688 }
690689
691690 return lfs_dir_commit (lfs , dir , regions );
@@ -701,9 +700,9 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
701700
702701 dir -> d .tail [0 ] = olddir .d .tail [0 ];
703702 dir -> d .tail [1 ] = olddir .d .tail [1 ];
704- entry -> off = dir -> d .size - 4 ;
703+ * off = dir -> d .size - 4 ;
705704 for (struct lfs_region * r = regions ; r ; r = r -> next ) {
706- r -> off += entry -> off ;
705+ r -> off += * off ;
707706 }
708707
709708 err = lfs_dir_commit (lfs , dir , regions );
@@ -724,9 +723,70 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
724723 }
725724}
726725
726+ static int lfs_dir_remove_ (lfs_t * lfs , lfs_dir_t * dir ,
727+ lfs_off_t off , lfs_size_t size ) {
728+ // check if we should just drop the directory block
729+ if ((dir -> d .size & 0x7fffffff ) == sizeof (dir -> d )+ 4 + size ) {
730+ lfs_dir_t pdir ;
731+ int res = lfs_pred (lfs , dir -> pair , & pdir );
732+ if (res < 0 ) {
733+ return res ;
734+ }
735+
736+ if (pdir .d .size & 0x80000000 ) {
737+ pdir .d .size &= dir -> d .size | 0x7fffffff ;
738+ pdir .d .tail [0 ] = dir -> d .tail [0 ];
739+ pdir .d .tail [1 ] = dir -> d .tail [1 ];
740+ return lfs_dir_commit (lfs , & pdir , NULL );
741+ }
742+ }
743+
744+ // shift out the entry
745+ int err = lfs_dir_commit (lfs , dir ,
746+ & (struct lfs_region ){
747+ off , - size ,
748+ lfs_commit_mem , NULL , 0 });
749+ if (err ) {
750+ return err ;
751+ }
752+
753+ // shift over any files/directories that are affected
754+ for (lfs_file_t * f = lfs -> files ; f ; f = f -> next ) {
755+ if (lfs_paircmp (f -> pair , dir -> pair ) == 0 ) {
756+ if (f -> poff == off ) {
757+ f -> pair [0 ] = 0xffffffff ;
758+ f -> pair [1 ] = 0xffffffff ;
759+ } else if (f -> poff > off ) {
760+ f -> poff -= size ;
761+ }
762+ }
763+ }
764+
765+ for (lfs_dir_t * d = lfs -> dirs ; d ; d = d -> next ) {
766+ if (lfs_paircmp (d -> pair , dir -> pair ) == 0 ) {
767+ if (d -> off > off ) {
768+ d -> off -= size ;
769+ d -> pos -= size ;
770+ }
771+ }
772+ }
773+
774+ return 0 ;
775+ }
776+
777+ static int lfs_dir_append (lfs_t * lfs , lfs_dir_t * dir ,
778+ lfs_entry_t * entry , struct lfs_region * regions ) {
779+ return lfs_dir_append_ (lfs , dir ,
780+ & entry -> off , lfs_entry_size (entry ), regions );
781+ }
782+
783+ static int lfs_dir_remove (lfs_t * lfs , lfs_dir_t * dir , lfs_entry_t * entry ) {
784+ return lfs_dir_remove_ (lfs , dir ,
785+ entry -> off , lfs_entry_size (entry ));
786+ }
787+
727788static int lfs_dir_update (lfs_t * lfs , lfs_dir_t * dir ,
728789 lfs_entry_t * entry , struct lfs_region * regions ) {
729- lfs_off_t oldoff = entry -> off ; // <- TODO rm me?
730790 lfs_ssize_t diff = 0 ;
731791 for (struct lfs_region * r = regions ; r ; r = r -> next ) {
732792 diff += r -> diff ;
@@ -742,6 +802,24 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
742802 if (err ) {
743803 return err ;
744804 }
805+
806+ // shift over any files/directories that are affected
807+ for (lfs_file_t * f = lfs -> files ; f ; f = f -> next ) {
808+ if (lfs_paircmp (f -> pair , dir -> pair ) == 0 ) {
809+ if (f -> poff > entry -> off ) {
810+ f -> poff += diff ;
811+ }
812+ }
813+ }
814+
815+ for (lfs_dir_t * d = lfs -> dirs ; d ; d = d -> next ) {
816+ if (lfs_paircmp (d -> pair , dir -> pair ) == 0 ) {
817+ if (d -> off > entry -> off ) {
818+ d -> off += diff ;
819+ d -> pos += diff ;
820+ }
821+ }
822+ }
745823 } else {
746824 lfs_dir_t olddir = * dir ;
747825 lfs_off_t oldoff = entry -> off ;
@@ -756,9 +834,9 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
756834 if (err ) {
757835 return err ;
758836 }
837+ entry -> d .type &= LFS_STRUCT_MOVED ;
759838
760839 // append updated entry
761- entry -> d .type &= LFS_STRUCT_MOVED ;
762840 err = lfs_dir_append (lfs , dir , entry ,
763841 & (struct lfs_region ){
764842 0 , + lfs_entry_size (entry ),
@@ -769,86 +847,13 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
769847 }
770848
771849 // remove old entry
772- err = lfs_dir_commit (lfs , & olddir ,
773- & (struct lfs_region ){
774- oldoff , - oldsize ,
775- lfs_commit_mem , NULL , 0 });
850+ err = lfs_dir_remove_ (lfs , dir , oldoff , oldsize );
776851 if (err ) {
777852 return err ;
778853 }
779- }
780854
781- // TODO move to dir_commit?
782- // TODO this doesn't work...
783- // shift over any files/directories that are affected
784- for (lfs_file_t * f = lfs -> files ; f ; f = f -> next ) {
785- if (lfs_paircmp (f -> pair , dir -> pair ) == 0 ) {
786- if (f -> poff == oldoff ) {
787- f -> poff = entry -> off ;
788- } else if (f -> poff > entry -> off ) {
789- f -> poff += diff ;
790- }
791- }
792- }
793-
794- for (lfs_dir_t * d = lfs -> dirs ; d ; d = d -> next ) {
795- if (lfs_paircmp (d -> pair , dir -> pair ) == 0 ) {
796- if (d -> off > entry -> off ) {
797- d -> off += diff ;
798- d -> pos += diff ;
799- }
800- }
801- }
802-
803- return 0 ;
804- }
805-
806- static int lfs_dir_remove (lfs_t * lfs , lfs_dir_t * dir , lfs_entry_t * entry ) {
807- // check if we should just drop the directory block
808- if ((dir -> d .size & 0x7fffffff ) == sizeof (dir -> d )+ 4
809- + lfs_entry_size (entry )) {
810- lfs_dir_t pdir ;
811- int res = lfs_pred (lfs , dir -> pair , & pdir );
812- if (res < 0 ) {
813- return res ;
814- }
815-
816- if (pdir .d .size & 0x80000000 ) {
817- pdir .d .size &= dir -> d .size | 0x7fffffff ;
818- pdir .d .tail [0 ] = dir -> d .tail [0 ];
819- pdir .d .tail [1 ] = dir -> d .tail [1 ];
820- return lfs_dir_commit (lfs , & pdir , NULL );
821- }
822- }
823-
824- // shift out the entry
825- int err = lfs_dir_commit (lfs , dir ,
826- & (struct lfs_region ){
827- entry -> off , - lfs_entry_size (entry ),
828- lfs_commit_mem , NULL , 0 });
829- if (err ) {
830- return err ;
831- }
832-
833- // shift over any files/directories that are affected
834- for (lfs_file_t * f = lfs -> files ; f ; f = f -> next ) {
835- if (lfs_paircmp (f -> pair , dir -> pair ) == 0 ) {
836- if (f -> poff == entry -> off ) {
837- f -> pair [0 ] = 0xffffffff ;
838- f -> pair [1 ] = 0xffffffff ;
839- } else if (f -> poff > entry -> off ) {
840- f -> poff -= lfs_entry_size (entry );
841- }
842- }
843- }
844-
845- for (lfs_dir_t * d = lfs -> dirs ; d ; d = d -> next ) {
846- if (lfs_paircmp (d -> pair , dir -> pair ) == 0 ) {
847- if (d -> off > entry -> off ) {
848- d -> off -= lfs_entry_size (entry );
849- d -> pos -= lfs_entry_size (entry );
850- }
851- }
855+ // TODO remove file under file?
856+ // TODO need to shift entries?
852857 }
853858
854859 return 0 ;
0 commit comments