@@ -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