// Rename implements the fs.NodeRenamer interface for Dir. func (d *Dir) Rename(ctx context.Context, req *fuse.RenameRequest, newDir fs.Node) (err error) { d.folder.fs.log.CDebugf(ctx, "Dir Rename %s -> %s", req.OldName, req.NewName) defer func() { d.folder.reportErr(ctx, libkbfs.WriteMode, err) }() var realNewDir *Dir switch newDir := newDir.(type) { case *Dir: realNewDir = newDir case *TLF: var err error realNewDir, err = newDir.loadDir(ctx) if err != nil { return err } default: // The destination is not a TLF instance, probably // because it's Root (or some other node type added // later). The kernel won't let a rename newDir point // to a non-directory. // // We have no cheap atomic rename across folders, so // we can't serve this. EXDEV makes `mv` do a // copy+delete, and the Lookup on the destination path // will decide whether it's legal. return fuse.Errno(syscall.EXDEV) } if d.folder != realNewDir.folder { // Check this explicitly, not just trusting KBFSOps.Rename to // return an error, because we rely on it for locking // correctness. return fuse.Errno(syscall.EXDEV) } // overwritten node, if any, will be removed from Folder.nodes, if // it is there in the first place, by its Forget if err := d.folder.fs.config.KBFSOps().Rename( ctx, d.node, req.OldName, realNewDir.node, req.NewName); err != nil { return err } return nil }
func isDir(node fs.Node) bool { return (node.Attr().Mode & os.ModeDir) != 0 }