Consolidate some of the logic for removals of folders

This routine checks that the folder is empty before removing and is
found in two places.  We can consolidate this for changes to the logic.
This commit is contained in:
Tim Nordell
2021-05-12 14:06:39 -05:00
parent 1863dc7883
commit 8c1931ac55

95
lfs.c
View File

@@ -3189,6 +3189,42 @@ static int lfs_rawstat(lfs_t *lfs, const char *path, struct lfs_info *info) {
return lfs_dir_getinfo(lfs, &cwd, lfs_tag_id(tag), info); return lfs_dir_getinfo(lfs, &cwd, lfs_tag_id(tag), info);
} }
#ifndef LFS_READONLY
static int lfs_dir_prep_dirremoval(lfs_t *lfs, struct lfs_mlist *dir, lfs_mdir_t *newcwd, uint16_t newid)
{
lfs_block_t pair[2];
lfs_stag_t res = lfs_dir_get(lfs, newcwd, LFS_MKTAG(0x700, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_STRUCT, newid, 8), pair);
if (res < 0) {
return (int)res;
}
lfs_pair_fromle32(pair);
int err = lfs_dir_fetch(lfs, &dir->m, pair);
if (err) {
return err;
}
if (dir->m.count > 0 || dir->m.split) {
return LFS_ERR_NOTEMPTY;
}
// mark fs as orphaned
err = lfs_fs_preporphans(lfs, +1);
if (err) {
return err;
}
// I know it's crazy but yes, dir can be changed by our parent's
// commit (if predecessor is child)
dir->type = 0;
dir->id = 0;
lfs->mlist = dir;
return 0;
}
#endif
#ifndef LFS_READONLY #ifndef LFS_READONLY
static int lfs_rawremove(lfs_t *lfs, const char *path) { static int lfs_rawremove(lfs_t *lfs, const char *path) {
// deorphan if we haven't yet, needed at most once after poweron // deorphan if we haven't yet, needed at most once after poweron
@@ -3206,35 +3242,11 @@ static int lfs_rawremove(lfs_t *lfs, const char *path) {
struct lfs_mlist dir; struct lfs_mlist dir;
dir.next = lfs->mlist; dir.next = lfs->mlist;
if (lfs_tag_type3(tag) == LFS_TYPE_DIR) { if (lfs_tag_type3(tag) == LFS_TYPE_DIR) {
// must be empty before removal // must be empty before removal to prevent orphans
lfs_block_t pair[2]; err = lfs_dir_prep_dirremoval(lfs, &dir, &cwd, lfs_tag_id(tag));
lfs_stag_t res = lfs_dir_get(lfs, &cwd, LFS_MKTAG(0x700, 0x3ff, 0), if (err < 0) {
LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tag_id(tag), 8), pair);
if (res < 0) {
return (int)res;
}
lfs_pair_fromle32(pair);
err = lfs_dir_fetch(lfs, &dir.m, pair);
if (err) {
return err; return err;
} }
if (dir.m.count > 0 || dir.m.split) {
return LFS_ERR_NOTEMPTY;
}
// mark fs as orphaned
err = lfs_fs_preporphans(lfs, +1);
if (err) {
return err;
}
// I know it's crazy but yes, dir can be changed by our parent's
// commit (if predecessor is child)
dir.type = 0;
dir.id = 0;
lfs->mlist = &dir;
} }
// delete the entry // delete the entry
@@ -3317,36 +3329,11 @@ static int lfs_rawrename(lfs_t *lfs, const char *oldpath, const char *newpath) {
// we're renaming to ourselves?? // we're renaming to ourselves??
return 0; return 0;
} else if (lfs_tag_type3(prevtag) == LFS_TYPE_DIR) { } else if (lfs_tag_type3(prevtag) == LFS_TYPE_DIR) {
// must be empty before removal // must be empty before removal to prevent orphans
lfs_block_t prevpair[2]; err = lfs_dir_prep_dirremoval(lfs, &prevdir, &newcwd, newid);
lfs_stag_t res = lfs_dir_get(lfs, &newcwd, LFS_MKTAG(0x700, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_STRUCT, newid, 8), prevpair);
if (res < 0) {
return (int)res;
}
lfs_pair_fromle32(prevpair);
// must be empty before removal
err = lfs_dir_fetch(lfs, &prevdir.m, prevpair);
if (err) { if (err) {
return err; return err;
} }
if (prevdir.m.count > 0 || prevdir.m.split) {
return LFS_ERR_NOTEMPTY;
}
// mark fs as orphaned
err = lfs_fs_preporphans(lfs, +1);
if (err) {
return err;
}
// I know it's crazy but yes, dir can be changed by our parent's
// commit (if predecessor is child)
prevdir.type = 0;
prevdir.id = 0;
lfs->mlist = &prevdir;
} }
if (!samepair) { if (!samepair) {