@@ -3894,6 +3894,63 @@ struct lfs_remove_state
38943894};
38953895#endif
38963896
3897+ #ifndef LFS_READONLY
3898+ static int lfs_dir_prep_removal (lfs_t * lfs , struct lfs_remove_state * p ) {
3899+ lfs_stag_t res = lfs_dir_get (lfs , & p -> cwd , LFS_MKTAG (0x700 , 0x3ff , 0 ),
3900+ LFS_MKTAG (LFS_TYPE_STRUCT , lfs_tag_id (p -> tag ), 8 ), p -> dir_head );
3901+ if (res < 0 ) {
3902+ return (int )res ;
3903+ }
3904+ lfs_pair_fromle32 (p -> dir_head );
3905+
3906+ int err = lfs_dir_fetch (lfs , & p -> dir .m , p -> dir_head );
3907+ if (err ) {
3908+ return err ;
3909+ }
3910+
3911+ if (p -> dir .m .count > 0 || p -> dir .m .split ) {
3912+ return LFS_ERR_NOTEMPTY ;
3913+ }
3914+
3915+ // mark fs as orphaned
3916+ err = lfs_fs_preporphans (lfs , +1 );
3917+ if (err ) {
3918+ return err ;
3919+ }
3920+
3921+ // I know it's crazy but yes, dir can be changed by our parent's
3922+ // commit (if predecessor is child)
3923+ p -> dir .type = 0 ;
3924+ p -> dir .id = 0 ;
3925+ lfs -> mlist = & p -> dir ;
3926+
3927+ return 0 ;
3928+ }
3929+ #endif
3930+
3931+ #ifndef LFS_READONLY
3932+ static int lfs_dir_finish_removal (lfs_t * lfs , struct lfs_remove_state * p )
3933+ {
3934+ // fix orphan
3935+ int err = lfs_fs_preporphans (lfs , -1 );
3936+ if (err ) {
3937+ return err ;
3938+ }
3939+
3940+ err = lfs_fs_pred (lfs , p -> dir .m .pair , & p -> cwd );
3941+ if (err ) {
3942+ return err ;
3943+ }
3944+
3945+ err = lfs_dir_drop (lfs , & p -> cwd , & p -> dir .m );
3946+ if (err ) {
3947+ return err ;
3948+ }
3949+
3950+ return 0 ;
3951+ }
3952+ #endif
3953+
38973954#ifndef LFS_READONLY
38983955static int lfs_remove_ (lfs_t * lfs , const char * path ) {
38993956 // deorphan if we haven't yet, needed at most once after poweron
@@ -3910,34 +3967,10 @@ static int lfs_remove_(lfs_t *lfs, const char *path) {
39103967
39113968 s .dir .next = lfs -> mlist ;
39123969 if (lfs_tag_type3 (s .tag ) == LFS_TYPE_DIR ) {
3913- // must be empty before removal
3914- lfs_stag_t res = lfs_dir_get (lfs , & s .cwd , LFS_MKTAG (0x700 , 0x3ff , 0 ),
3915- LFS_MKTAG (LFS_TYPE_STRUCT , lfs_tag_id (s .tag ), 8 ), s .dir_head );
3916- if (res < 0 ) {
3917- return (int )res ;
3918- }
3919- lfs_pair_fromle32 (s .dir_head );
3920-
3921- err = lfs_dir_fetch (lfs , & s .dir .m , s .dir_head );
3922- if (err ) {
3923- return err ;
3924- }
3925-
3926- if (s .dir .m .count > 0 || s .dir .m .split ) {
3927- return LFS_ERR_NOTEMPTY ;
3928- }
3929-
3930- // mark fs as orphaned
3931- err = lfs_fs_preporphans (lfs , +1 );
3932- if (err ) {
3970+ err = lfs_dir_prep_removal (lfs , & s );
3971+ if (err < 0 ) {
39333972 return err ;
39343973 }
3935-
3936- // I know it's crazy but yes, dir can be changed by our parent's
3937- // commit (if predecessor is child)
3938- s .dir .type = 0 ;
3939- s .dir .id = 0 ;
3940- lfs -> mlist = & s .dir ;
39413974 }
39423975
39433976 // delete the entry
@@ -3950,18 +3983,7 @@ static int lfs_remove_(lfs_t *lfs, const char *path) {
39503983
39513984 lfs -> mlist = s .dir .next ;
39523985 if (lfs_tag_type3 (s .tag ) == LFS_TYPE_DIR ) {
3953- // fix orphan
3954- err = lfs_fs_preporphans (lfs , -1 );
3955- if (err ) {
3956- return err ;
3957- }
3958-
3959- err = lfs_fs_pred (lfs , s .dir .m .pair , & s .cwd );
3960- if (err ) {
3961- return err ;
3962- }
3963-
3964- err = lfs_dir_drop (lfs , & s .cwd , & s .dir .m );
3986+ err = lfs_dir_finish_removal (lfs , & s );
39653987 if (err ) {
39663988 return err ;
39673989 }
@@ -4027,34 +4049,10 @@ static int lfs_rename_(lfs_t *lfs, const char *oldpath, const char *newpath) {
40274049 // we're renaming to ourselves??
40284050 return 0 ;
40294051 } else if (lfs_tag_type3 (n .tag ) == LFS_TYPE_DIR ) {
4030- lfs_stag_t res = lfs_dir_get (lfs , & n .cwd , LFS_MKTAG (0x700 , 0x3ff , 0 ),
4031- LFS_MKTAG (LFS_TYPE_STRUCT , newid , 8 ), n .dir_head );
4032- if (res < 0 ) {
4033- return (int )res ;
4034- }
4035- lfs_pair_fromle32 (n .dir_head );
4036-
4037- // must be empty before removal
4038- err = lfs_dir_fetch (lfs , & n .dir .m , n .dir_head );
4039- if (err ) {
4040- return err ;
4041- }
4042-
4043- if (n .dir .m .count > 0 || n .dir .m .split ) {
4044- return LFS_ERR_NOTEMPTY ;
4045- }
4046-
4047- // mark fs as orphaned
4048- err = lfs_fs_preporphans (lfs , +1 );
4052+ err = lfs_dir_prep_removal (lfs , & n );
40494053 if (err ) {
40504054 return err ;
40514055 }
4052-
4053- // I know it's crazy but yes, dir can be changed by our parent's
4054- // commit (if predecessor is child)
4055- n .dir .type = 0 ;
4056- n .dir .id = 0 ;
4057- lfs -> mlist = & n .dir ;
40584056 }
40594057
40604058 if (!samepair ) {
@@ -4092,18 +4090,7 @@ static int lfs_rename_(lfs_t *lfs, const char *oldpath, const char *newpath) {
40924090 lfs -> mlist = n .dir .next ;
40934091 if (n .tag != LFS_ERR_NOENT
40944092 && lfs_tag_type3 (n .tag ) == LFS_TYPE_DIR ) {
4095- // fix orphan
4096- err = lfs_fs_preporphans (lfs , -1 );
4097- if (err ) {
4098- return err ;
4099- }
4100-
4101- err = lfs_fs_pred (lfs , n .dir .m .pair , & n .cwd );
4102- if (err ) {
4103- return err ;
4104- }
4105-
4106- err = lfs_dir_drop (lfs , & n .cwd , & n .dir .m );
4093+ err = lfs_dir_finish_removal (lfs , & n );
41074094 if (err ) {
41084095 return err ;
41094096 }
0 commit comments