summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--netfs/daemon/daemonVolume.cpp7
-rw-r--r--netfs/daemon/daemonVolume.h2
-rw-r--r--netfs/fuse/fuseMisc.cpp5
-rw-r--r--netfs/ice/volume.ice2
-rw-r--r--netfs/unittests/testCore.cpp17
5 files changed, 26 insertions, 7 deletions
diff --git a/netfs/daemon/daemonVolume.cpp b/netfs/daemon/daemonVolume.cpp
index bdd899b..6a3c7fe 100644
--- a/netfs/daemon/daemonVolume.cpp
+++ b/netfs/daemon/daemonVolume.cpp
@@ -113,12 +113,15 @@ VolumeServer::link(const NetFS::ReqEnv re, std::string path1, std::string path2,
}
void
-VolumeServer::rename(const NetFS::ReqEnv re, std::string from, std::string to, const Ice::Current &)
+VolumeServer::rename(const NetFS::ReqEnv re, std::string from, std::string to, const Ice::optional<Ice::Int> flags, const Ice::Current &)
{
ModeCheck mc(re, root, userLookup, groupLookup);
errno = 0;
- std::filesystem::path f(resolvePath(std::move(from)));
std::filesystem::path t(resolvePath(std::move(to)));
+ if (flags && *flags == RENAME_NOREPLACE && ::access(t.c_str(), F_OK) == 0) {
+ throw NetFS::SystemError(EEXIST);
+ }
+ std::filesystem::path f(resolvePath(std::move(from)));
mc.AssertWriteParent(f);
mc.AssertWriteParent(t);
if (::rename(f.c_str(), t.c_str()) != 0) {
diff --git a/netfs/daemon/daemonVolume.h b/netfs/daemon/daemonVolume.h
index 770cada..235adf4 100644
--- a/netfs/daemon/daemonVolume.h
+++ b/netfs/daemon/daemonVolume.h
@@ -30,7 +30,7 @@ class VolumeServer : public NetFS::Volume {
virtual void mknod(const NetFS::ReqEnv, std::string path, Ice::Int mode, Ice::Int dev, const Ice::Current&) override;
virtual void symlink(const NetFS::ReqEnv, const std::string path1, const std::string path2, const Ice::Current&) override;
virtual void link(const NetFS::ReqEnv, std::string path1, std::string path2, const Ice::Current&) override;
- virtual void rename(const NetFS::ReqEnv, std::string path1, const std::string path2, const Ice::Current&) override;
+ virtual void rename(const NetFS::ReqEnv, std::string path1, const std::string path2, const Ice::optional<Ice::Int>, const Ice::Current&) override;
virtual std::string readlink(const NetFS::ReqEnv, std::string path, const Ice::Current&) override;
virtual void chmod(const NetFS::ReqEnv, std::string path, Ice::Int mode, const Ice::Current&) override;
virtual void chown(const NetFS::ReqEnv, std::string path, Ice::Int uid, Ice::Int gid, const Ice::Current&) override;
diff --git a/netfs/fuse/fuseMisc.cpp b/netfs/fuse/fuseMisc.cpp
index 6703fa7..c434333 100644
--- a/netfs/fuse/fuseMisc.cpp
+++ b/netfs/fuse/fuseMisc.cpp
@@ -83,11 +83,10 @@ NetFS::FuseApp::readlink(const char * p, char * p2, size_t s)
}
int
-NetFS::FuseApp::rename(const char * p1, const char * p2, unsigned int)
+NetFS::FuseApp::rename(const char * p1, const char * p2, unsigned int flags)
{
try {
- // TODO flags
- volume->rename(reqEnv(), p1, p2);
+ volume->rename(reqEnv(), p1, p2, flags);
return 0;
}
catch (NetFS::SystemError & e) {
diff --git a/netfs/ice/volume.ice b/netfs/ice/volume.ice
index 8d5d9a7..b8fe9ea 100644
--- a/netfs/ice/volume.ice
+++ b/netfs/ice/volume.ice
@@ -28,7 +28,7 @@ module NetFS {
void mknod(ReqEnv env, string path, int mode, int dev) throws AuthError, SystemError;
void symlink(ReqEnv env, string path1, string path2) throws AuthError, SystemError;
void link(ReqEnv env, string path1, string path2) throws AuthError, SystemError;
- void rename(ReqEnv env, string from, string to) throws AuthError, SystemError;
+ void rename(ReqEnv env, string from, string to, optional(0) int flags) throws AuthError, SystemError;
idempotent void chmod(ReqEnv env, string path, int mode) throws AuthError, SystemError;
idempotent void chown(ReqEnv env, string path, int uid, int gid) throws AuthError, SystemError;
idempotent void utimens(ReqEnv env, string path, long atime, long atimens, long mtime, long mtimens) throws AuthError, SystemError;
diff --git a/netfs/unittests/testCore.cpp b/netfs/unittests/testCore.cpp
index 2cc4110..f0f7980 100644
--- a/netfs/unittests/testCore.cpp
+++ b/netfs/unittests/testCore.cpp
@@ -449,6 +449,23 @@ BOOST_AUTO_TEST_CASE( renameToDir )
BOOST_REQUIRE_EQUAL(fuse->rmdir("/dir"), 0);
}
+BOOST_AUTO_TEST_CASE( renameFlags )
+{
+ struct fuse_file_info fi {};
+ BOOST_REQUIRE_EQUAL(fuse->create("/file", 0600, &fi), 0);
+ BOOST_REQUIRE_EQUAL(fuse->release("/file", &fi), 0);
+ BOOST_REQUIRE_EQUAL(fuse->create("/file2", 0600, &fi), 0);
+ BOOST_REQUIRE_EQUAL(fuse->release("/file2", &fi), 0);
+
+ BOOST_REQUIRE_EQUAL(fuse->rename("/file", "/file2", RENAME_NOREPLACE), -EEXIST);
+ BOOST_REQUIRE_EQUAL(fuse->access("/file", F_OK), 0);
+ BOOST_REQUIRE_EQUAL(fuse->access("/file2", F_OK), 0);
+
+ BOOST_REQUIRE_EQUAL(fuse->rename("/file", "/file2", RENAME_EXCHANGE), 0);
+ BOOST_REQUIRE_EQUAL(fuse->access("/file", F_OK), -ENOENT);
+ BOOST_REQUIRE_EQUAL(fuse->access("/file2", F_OK), 0);
+}
+
BOOST_AUTO_TEST_CASE( chown )
{
BOOST_REQUIRE_EQUAL(fuse->mkdir("/dir", 0777), 0);