Beispiel #1
0
// 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
}