mirror of
https://gitee.com/openharmony/third_party_littlefs
synced 2024-11-23 06:50:37 +00:00
Added support for renaming dirs/files
This commit is contained in:
parent
3b1bcbe851
commit
bd817abb00
175
lfs.c
175
lfs.c
@ -1337,7 +1337,7 @@ int lfs_remove(lfs_t *lfs, const char *path) {
|
||||
cwd.d.size -= entry.d.len;
|
||||
|
||||
// either shift out the one entry or remove the whole dir block
|
||||
if (cwd.d.size == sizeof(dir.d)) {
|
||||
if (cwd.d.size == sizeof(cwd.d)) {
|
||||
lfs_dir_t pdir;
|
||||
int err = lfs_dir_fetch(lfs, &pdir, lfs->cwd);
|
||||
if (err) {
|
||||
@ -1418,6 +1418,179 @@ int lfs_remove(lfs_t *lfs, const char *path) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
||||
// Find old entry
|
||||
lfs_dir_t oldcwd;
|
||||
int err = lfs_dir_fetch(lfs, &oldcwd, lfs->cwd);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
lfs_entry_t oldentry;
|
||||
err = lfs_dir_find(lfs, &oldcwd, &oldpath, &oldentry);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// Allocate new entry
|
||||
lfs_dir_t newcwd;
|
||||
err = lfs_dir_fetch(lfs, &newcwd, lfs->cwd);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
lfs_entry_t preventry;
|
||||
err = lfs_dir_append(lfs, &newcwd, &newpath, &preventry);
|
||||
if (err && err != LFS_ERROR_EXISTS) {
|
||||
return err;
|
||||
}
|
||||
bool prevexists = (err == LFS_ERROR_EXISTS);
|
||||
|
||||
// must have same type
|
||||
if (prevexists && preventry.d.type != oldentry.d.type) {
|
||||
return LFS_ERROR_INVALID;
|
||||
}
|
||||
|
||||
lfs_dir_t dir;
|
||||
if (prevexists && preventry.d.type == LFS_TYPE_DIR) {
|
||||
// must be empty before removal, checking size
|
||||
// without masking top bit checks for any case where
|
||||
// dir is not empty
|
||||
int err = lfs_dir_fetch(lfs, &dir, preventry.d.u.dir);
|
||||
if (err) {
|
||||
return err;
|
||||
} else if (dir.d.size != sizeof(dir.d)) {
|
||||
return LFS_ERROR_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
// Move to new location
|
||||
lfs_entry_t newentry = preventry;
|
||||
newentry.d = oldentry.d;
|
||||
newentry.d.len = sizeof(newentry.d) + strlen(newpath);
|
||||
|
||||
newcwd.d.rev += 1;
|
||||
if (!prevexists) {
|
||||
newcwd.d.size += newentry.d.len;
|
||||
}
|
||||
|
||||
err = lfs_pair_commit(lfs, newentry.dir,
|
||||
3, (struct lfs_commit_region[3]) {
|
||||
{0, sizeof(newcwd.d), &newcwd.d},
|
||||
{newentry.off,
|
||||
sizeof(newentry.d),
|
||||
&newentry.d},
|
||||
{newentry.off+sizeof(newentry.d),
|
||||
newentry.d.len - sizeof(newentry.d),
|
||||
newpath}
|
||||
});
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// fetch again in case newcwd == oldcwd
|
||||
// TODO handle this better?
|
||||
err = lfs_dir_fetch(lfs, &oldcwd, oldcwd.pair);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = lfs_dir_find(lfs, &oldcwd, &oldpath, &oldentry);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// Remove from old location
|
||||
// TODO abstract this out for rename + remove?
|
||||
oldcwd.d.rev += 1;
|
||||
oldcwd.d.size -= oldentry.d.len;
|
||||
|
||||
// either shift out the one entry or remove the whole dir block
|
||||
if (oldcwd.d.size == sizeof(oldcwd.d)) {
|
||||
lfs_dir_t pdir;
|
||||
int err = lfs_dir_fetch(lfs, &pdir, lfs->cwd);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
while (lfs_paircmp(pdir.d.tail, oldcwd.pair) != 0) {
|
||||
int err = lfs_dir_fetch(lfs, &pdir, pdir.d.tail);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO easier check for head block? (common case)
|
||||
if (!(pdir.d.size & 0x80000000)) {
|
||||
int err = lfs_pair_shift(lfs, oldentry.dir,
|
||||
1, (struct lfs_commit_region[]) {
|
||||
{0, sizeof(oldcwd.d), &oldcwd.d},
|
||||
},
|
||||
oldentry.off, oldentry.d.len);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
pdir.d.tail[0] = oldcwd.d.tail[0];
|
||||
pdir.d.tail[1] = oldcwd.d.tail[1];
|
||||
pdir.d.rev += 1;
|
||||
|
||||
err = lfs_pair_commit(lfs, pdir.pair,
|
||||
1, (struct lfs_commit_region[]) {
|
||||
{0, sizeof(pdir.d), &pdir.d},
|
||||
});
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int err = lfs_pair_shift(lfs, oldentry.dir,
|
||||
1, (struct lfs_commit_region[]) {
|
||||
{0, sizeof(oldcwd.d), &oldcwd.d},
|
||||
},
|
||||
oldentry.off, oldentry.d.len);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO abstract this out for rename + remove?
|
||||
if (prevexists && preventry.d.type == LFS_TYPE_DIR) {
|
||||
// remove dest from the dir list
|
||||
// this may create an orphan, which must be deorphaned
|
||||
lfs_dir_t pdir;
|
||||
int err = lfs_dir_fetch(lfs, &pdir, lfs->root);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
while (pdir.d.tail[0]) {
|
||||
if (lfs_paircmp(pdir.d.tail, preventry.d.u.dir) == 0) {
|
||||
pdir.d.tail[0] = dir.d.tail[0];
|
||||
pdir.d.tail[1] = dir.d.tail[1];
|
||||
pdir.d.rev += 1;
|
||||
|
||||
int err = lfs_pair_commit(lfs, pdir.pair,
|
||||
1, (struct lfs_commit_region[]) {
|
||||
{0, sizeof(pdir.d), &pdir.d},
|
||||
});
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
int err = lfs_dir_fetch(lfs, &pdir, pdir.d.tail);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
|
||||
lfs_dir_t cwd;
|
||||
int err = lfs_dir_fetch(lfs, &cwd, lfs->cwd);
|
||||
|
1
lfs.h
1
lfs.h
@ -138,6 +138,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
|
||||
int lfs_unmount(lfs_t *lfs);
|
||||
|
||||
int lfs_remove(lfs_t *lfs, const char *path);
|
||||
int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
|
||||
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
|
||||
|
||||
int lfs_mkdir(lfs_t *lfs, const char *path);
|
||||
|
@ -123,7 +123,7 @@ tests/test.py << TEST
|
||||
lfs_unmount(&lfs) => 0;
|
||||
TEST
|
||||
|
||||
echo "--- Directory deletion ---"
|
||||
echo "--- Directory remove ---"
|
||||
tests/test.py << TEST
|
||||
lfs_mount(&lfs, &config) => 0;
|
||||
lfs_remove(&lfs, "potato") => LFS_ERROR_INVALID;
|
||||
@ -180,5 +180,107 @@ tests/test.py << TEST
|
||||
lfs_unmount(&lfs) => 0;
|
||||
TEST
|
||||
|
||||
echo "--- Directory rename ---"
|
||||
tests/test.py << TEST
|
||||
lfs_mount(&lfs, &config) => 0;
|
||||
lfs_mkdir(&lfs, "coldpotato") => 0;
|
||||
lfs_mkdir(&lfs, "coldpotato/baked") => 0;
|
||||
lfs_mkdir(&lfs, "coldpotato/sweet") => 0;
|
||||
lfs_mkdir(&lfs, "coldpotato/fried") => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
TEST
|
||||
tests/test.py << TEST
|
||||
lfs_mount(&lfs, &config) => 0;
|
||||
lfs_rename(&lfs, "coldpotato", "hotpotato") => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
TEST
|
||||
tests/test.py << TEST
|
||||
lfs_mount(&lfs, &config) => 0;
|
||||
lfs_dir_open(&lfs, &dir[0], "hotpotato") => 0;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, ".") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, "..") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, "baked") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, "sweet") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, "fried") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 0;
|
||||
lfs_dir_close(&lfs, &dir[0]) => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
TEST
|
||||
tests/test.py << TEST
|
||||
lfs_mount(&lfs, &config) => 0;
|
||||
lfs_mkdir(&lfs, "warmpotato") => 0;
|
||||
lfs_mkdir(&lfs, "warmpotato/mushy") => 0;
|
||||
lfs_rename(&lfs, "hotpotato", "warmpotato") => LFS_ERROR_INVALID;
|
||||
|
||||
lfs_remove(&lfs, "warmpotato/mushy") => 0;
|
||||
lfs_rename(&lfs, "hotpotato", "warmpotato") => 0;
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
TEST
|
||||
tests/test.py << TEST
|
||||
lfs_mount(&lfs, &config) => 0;
|
||||
lfs_dir_open(&lfs, &dir[0], "warmpotato") => 0;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, ".") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, "..") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, "baked") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, "sweet") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, "fried") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 0;
|
||||
lfs_dir_close(&lfs, &dir[0]) => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
TEST
|
||||
tests/test.py << TEST
|
||||
lfs_mount(&lfs, &config) => 0;
|
||||
lfs_mkdir(&lfs, "coldpotato") => 0;
|
||||
lfs_rename(&lfs, "warmpotato/baked", "coldpotato/baked") => 0;
|
||||
lfs_rename(&lfs, "warmpotato/sweet", "coldpotato/sweet") => 0;
|
||||
lfs_rename(&lfs, "warmpotato/fried", "coldpotato/fried") => 0;
|
||||
lfs_remove(&lfs, "coldpotato") => LFS_ERROR_INVALID;
|
||||
lfs_remove(&lfs, "warmpotato") => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
TEST
|
||||
tests/test.py << TEST
|
||||
lfs_mount(&lfs, &config) => 0;
|
||||
lfs_dir_open(&lfs, &dir[0], "coldpotato") => 0;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, ".") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, "..") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, "baked") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, "sweet") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 1;
|
||||
strcmp(info.name, "fried") => 0;
|
||||
info.type => LFS_TYPE_DIR;
|
||||
lfs_dir_read(&lfs, &dir[0], &info) => 0;
|
||||
lfs_dir_close(&lfs, &dir[0]) => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
TEST
|
||||
|
||||
echo "--- Results ---"
|
||||
tests/stats.py
|
||||
|
Loading…
Reference in New Issue
Block a user