Skip to content

Commit 140beb4

Browse files
committed
fuse: implement rename within directory boundary
1 parent 8f643d2 commit 140beb4

File tree

1 file changed

+50
-11
lines changed

1 file changed

+50
-11
lines changed

fuse/fuse_ll.cpp

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -598,11 +598,6 @@ namespace
598598
FUSE_CALL(fuse_reply_err(req, 0));
599599
}
600600

601-
void Rename(fuse_req_t req, FuseId parent, const char *name, FuseId newparent, const char *newname)
602-
{
603-
fuse_reply_err(req, EXDEV); //return cross-device link, so user space should re-create file and copy it
604-
}
605-
606601
void SetAttr(fuse_req_t req, FuseId inode, struct stat *attr, int to_set, struct fuse_file_info *fi)
607602
{
608603
mtp::scoped_mutex_lock l(_mutex);
@@ -623,11 +618,46 @@ namespace
623618
entry.ReplyError(ENOENT);
624619
}
625620

621+
void UnlinkImpl(FuseId inode)
622+
{
623+
mtp::debug(" unlinking inode ", inode.Inode);
624+
mtp::ObjectId id = FromFuse(inode);
625+
_session->DeleteObject(id);
626+
_openedFiles.erase(inode);
627+
_objectAttrs.erase(id);
628+
}
629+
630+
void Unlink(fuse_req_t req, FuseId parent, const char *name)
631+
{
632+
mtp::scoped_mutex_lock l(_mutex);
633+
ChildrenObjects &children = GetChildren(parent);
634+
auto i = children.find(name);
635+
if (i == children.end())
636+
{
637+
FUSE_CALL(fuse_reply_err(req, ENOENT));
638+
return;
639+
}
640+
641+
FuseId inode = i->second;
642+
UnlinkImpl(inode);
643+
_directoryCache.erase(parent);
644+
children.erase(i);
645+
646+
FUSE_CALL(fuse_reply_err(req, 0));
647+
}
648+
626649
void RemoveDir (fuse_req_t req, FuseId parent, const char *name)
627650
{ Unlink(req, parent, name); }
628651

629-
void Unlink(fuse_req_t req, FuseId parent, const char *name)
652+
void Rename(fuse_req_t req, FuseId parent, const char *name, FuseId newparent, const char *newName)
630653
{
654+
if (parent != newparent) {
655+
//no renames across directory boundary, sorry
656+
//return cross-device link, so user space should re-create file and copy it
657+
FUSE_CALL(fuse_reply_err(req, EXDEV));
658+
return;
659+
}
660+
631661
mtp::scoped_mutex_lock l(_mutex);
632662
ChildrenObjects &children = GetChildren(parent);
633663
auto i = children.find(name);
@@ -638,14 +668,23 @@ namespace
638668
}
639669

640670
FuseId inode = i->second;
641-
mtp::debug(" unlinking inode ", inode.Inode);
671+
mtp::debug(" renaming inode ", inode.Inode, " to ", newName);
672+
673+
auto old = children.find(newName);
674+
if (old != children.end())
675+
{
676+
mtp::debug(" unlinking target inode ", old->second.Inode);
677+
UnlinkImpl(old->second);
678+
children.erase(old);
679+
}
680+
642681
mtp::ObjectId id = FromFuse(inode);
643-
_directoryCache.erase(parent);
644-
_openedFiles.erase(inode);
645-
_objectAttrs.erase(id);
682+
_session->SetObjectProperty(id, mtp::ObjectProperty::ObjectFilename, std::string(newName));
683+
646684
children.erase(i);
685+
children.emplace(newName, inode);
686+
_directoryCache.erase(parent);
647687

648-
_session->DeleteObject(id);
649688
FUSE_CALL(fuse_reply_err(req, 0));
650689
}
651690

0 commit comments

Comments
 (0)