[fs][minfs][memfs] Add support for renaming to self
ZX-1729 #done
Change-Id: I6f780d6403b5e0bc97c8f3d33659acd1f81d4ea8
diff --git a/system/ulib/memfs/directory.cpp b/system/ulib/memfs/directory.cpp
index 12f94b2..81d8714 100644
--- a/system/ulib/memfs/directory.cpp
+++ b/system/ulib/memfs/directory.cpp
@@ -162,6 +162,10 @@
if (!olddn->IsDirectory() && (src_must_be_dir || dst_must_be_dir)) {
return ZX_ERR_NOT_DIR;
+ } else if ((newdir->ino() == ino_) && (oldname == newname)) {
+ // Renaming a file or directory to itself?
+ // Shortcut success case
+ return ZX_OK;
}
// Verify that the destination is not a subdirectory of the source (if
diff --git a/system/ulib/memfs/include/memfs/vnode.h b/system/ulib/memfs/include/memfs/vnode.h
index 607f8be..ed84ae4 100644
--- a/system/ulib/memfs/include/memfs/vnode.h
+++ b/system/ulib/memfs/include/memfs/vnode.h
@@ -46,6 +46,7 @@
virtual ~VnodeMemfs();
Vfs* vfs() const { return vfs_; }
+ uint64_t ino() const { return ino_; }
fbl::RefPtr<Dnode> dnode_;
uint32_t link_count_;
diff --git a/system/ulib/minfs/vnode.cpp b/system/ulib/minfs/vnode.cpp
index 22b164c..fef0acf 100644
--- a/system/ulib/minfs/vnode.cpp
+++ b/system/ulib/minfs/vnode.cpp
@@ -1824,6 +1824,10 @@
// If either the 'src' or 'dst' must be directories, BOTH of them must be directories.
if (!oldvn->IsDirectory() && (src_must_be_dir || dst_must_be_dir)) {
return ZX_ERR_NOT_DIR;
+ } else if ((newdir->ino_ == ino_) && (oldname == newname)) {
+ // Renaming a file or directory to itself?
+ // Shortcut success case.
+ return ZX_OK;
}
// if the entry for 'newname' exists, make sure it can be replaced by
diff --git a/system/utest/fs/test-rename.c b/system/utest/fs/test-rename.c
index f2326b0..3617794 100644
--- a/system/utest/fs/test-rename.c
+++ b/system/utest/fs/test-rename.c
@@ -22,9 +22,14 @@
// Cannot rename when src does not exist
ASSERT_EQ(rename("::alpha", "::bravo"), -1, "");
- // Cannot rename to self
+ // Renaming to self is fine
ASSERT_EQ(mkdir("::alpha", 0755), 0, "");
- ASSERT_EQ(rename("::alpha", "::alpha"), -1, "");
+ ASSERT_EQ(rename("::alpha", "::alpha"), 0, "");
+ ASSERT_EQ(rename("::alpha/.", "::alpha/."), 0, "");
+ ASSERT_EQ(rename("::alpha/", "::alpha"), 0, "");
+ ASSERT_EQ(rename("::alpha", "::alpha/"), 0, "");
+ ASSERT_EQ(rename("::alpha/", "::alpha/"), 0, "");
+ ASSERT_EQ(rename("::alpha/./../alpha", "::alpha/./../alpha"), 0, "");
// Cannot rename dir to file
int fd = open("::bravo", O_RDWR | O_CREAT | O_EXCL, 0644);
@@ -43,6 +48,12 @@
fd = open("::alpha/charlie", O_RDWR | O_CREAT | O_EXCL, 0644);
ASSERT_GT(fd, 0, "");
ASSERT_EQ(rename("::alpha/charlie", "::alpha/delta"), 0, "");
+ // File rename to self
+ ASSERT_EQ(rename("::alpha/delta", "::alpha/delta"), 0, "");
+ // Not permitted with trailing '/'
+ ASSERT_EQ(rename("::alpha/delta", "::alpha/delta/"), -1, "");
+ ASSERT_EQ(rename("::alpha/delta/", "::alpha/delta"), -1, "");
+ ASSERT_EQ(rename("::alpha/delta/", "::alpha/delta/"), -1, "");
ASSERT_EQ(close(fd), 0, "");
// Rename file (dst does not exist)