Skip to content

Commit

Permalink
cmd/clone: skip trash files (#5109)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhijian-pro authored Sep 2, 2024
1 parent d9fbea1 commit 3528ee7
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 15 deletions.
14 changes: 9 additions & 5 deletions cmd/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@ package cmd

import (
"fmt"
"github.com/juicedata/juicefs/pkg/meta"
"github.com/juicedata/juicefs/pkg/utils"
"github.com/urfave/cli/v2"
"os"
"path"
"path/filepath"
"runtime"
"strings"

"github.com/juicedata/juicefs/pkg/meta"
"github.com/juicedata/juicefs/pkg/utils"
"github.com/urfave/cli/v2"
)

func cmdClone() *cli.Command {
Expand Down Expand Up @@ -71,6 +70,10 @@ func clone(ctx *cli.Context) error {
if err != nil {
return fmt.Errorf("lookup inode for %s: %s", srcPath, err)
}
srcParentIno, err := utils.GetFileInode(filepath.Dir(srcAbsPath))
if err != nil {
return fmt.Errorf("lookup inode for %s: %s", filepath.Dir(srcAbsPath), err)
}
dst := ctx.Args().Get(1)
if strings.HasSuffix(dst, string(filepath.Separator)) {
dst = filepath.Join(dst, filepath.Base(srcPath))
Expand Down Expand Up @@ -112,11 +115,12 @@ func clone(ctx *cli.Context) error {
cmode |= meta.CLONE_MODE_PRESERVE_ATTR
}
headerSize := 4 + 4
contentSize := 8 + 8 + 1 + uint32(len(dstName)) + 2 + 1
contentSize := 8 + 8 + 8 + 1 + uint32(len(dstName)) + 2 + 1
wb := utils.NewBuffer(uint32(headerSize) + contentSize)
wb.Put32(meta.Clone)
wb.Put32(contentSize)
wb.Put64(srcIno)
wb.Put64(srcParentIno)
wb.Put64(dstParentIno)
wb.Put8(uint8(len(dstName)))
wb.Put([]byte(dstName))
Expand Down
9 changes: 4 additions & 5 deletions pkg/meta/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -2436,13 +2436,12 @@ func (m *baseMeta) ScanDeletedObject(ctx Context, tss trashSliceScan, pss pendin
return eg.Wait()
}

func (m *baseMeta) Clone(ctx Context, srcIno, parent Ino, name string, cmode uint8, cumask uint16, count, total *uint64) syscall.Errno {
if isTrash(parent) {
return syscall.EPERM
}
if parent == RootInode && name == TrashName {
func (m *baseMeta) Clone(ctx Context, srcParentIno, srcIno, parent Ino, name string, cmode uint8, cumask uint16, count, total *uint64) syscall.Errno {

if isTrash(srcIno) || isTrash(srcParentIno) || isTrash(parent) || (parent == RootInode && name == TrashName) {
return syscall.EPERM
}

if m.conf.ReadOnly {
return syscall.EROFS
}
Expand Down
12 changes: 9 additions & 3 deletions pkg/meta/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package meta
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"reflect"
Expand Down Expand Up @@ -2663,7 +2664,7 @@ func testClone(t *testing.T, m Meta) {
var count, total uint64
var cmode uint8
cmode |= CLONE_MODE_PRESERVE_ATTR
if eno := m.Clone(Background, dir1, cloneDir, cloneDstName, cmode, 022, &count, &total); eno != 0 {
if eno := m.Clone(Background, cloneDir, dir1, cloneDir, cloneDstName, cmode, 022, &count, &total); eno != 0 {
t.Fatalf("clone: %s", eno)
}
var entries1 []*Entry
Expand Down Expand Up @@ -2711,7 +2712,7 @@ func testClone(t *testing.T, m Meta) {
if iused-iused2 != 8 {
t.Fatalf("added inodes: %d", iused-iused2)
}
if eno := m.Clone(Background, dir1, cloneDir, "no_preserve", 0, 022, &count, &total); eno != 0 {
if eno := m.Clone(Background, RootInode, dir1, cloneDir, "no_preserve", 0, 022, &count, &total); eno != 0 {
t.Fatalf("clone: %s", eno)
}
var d2 Ino
Expand Down Expand Up @@ -2840,7 +2841,12 @@ func testClone(t *testing.T, m Meta) {
if len(nodes) != 2 {
t.Fatalf("find detached nodes error: %v", nodes)
}

if eno := m.Clone(Background, RootInode, TrashInode, cloneDir, "xxx", 0, 022, &count, &total); !errors.Is(eno, syscall.EPERM) {
t.Fatalf("cloning trash files are not supported")
}
if eno := m.Clone(Background, TrashInode+1, 1000, cloneDir, "xxx", 0, 022, &count, &total); !errors.Is(eno, syscall.EPERM) {
t.Fatalf("cloning files in the trash is not supported")
}
}

func checkEntryTree(t *testing.T, m Meta, srcIno, dstIno Ino, walkFunc func(srcEntry, dstEntry *Entry, dstIno Ino)) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/meta/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ type Meta interface {
// GetTreeSummary returns a summary in tree structure
GetTreeSummary(ctx Context, root *TreeSummary, depth, topN uint8, strict bool, updateProgress func(count uint64, bytes uint64)) syscall.Errno
// Clone a file or directory
Clone(ctx Context, srcIno, dstParentIno Ino, dstName string, cmode uint8, cumask uint16, count, total *uint64) syscall.Errno
Clone(ctx Context, srcParentIno, srcIno, dstParentIno Ino, dstName string, cmode uint8, cumask uint16, count, total *uint64) syscall.Errno
// GetPaths returns all paths of an inode
GetPaths(ctx Context, inode Ino) []string
// Check integrity of an absolute path and repair it if asked
Expand Down
3 changes: 2 additions & 1 deletion pkg/vfs/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,14 +316,15 @@ func (v *VFS) handleInternalMsg(ctx meta.Context, cmd uint32, r *utils.Buffer, o
case meta.Clone:
done := make(chan struct{})
srcIno := Ino(r.Get64())
srcParentIno := Ino(r.Get64())
dstParentIno := Ino(r.Get64())
dstName := string(r.Get(int(r.Get8())))
umask := r.Get16()
cmode := r.Get8()
var count, total uint64
var eno syscall.Errno
go func() {
if eno = v.Meta.Clone(ctx, srcIno, dstParentIno, dstName, cmode, umask, &count, &total); eno != 0 {
if eno = v.Meta.Clone(ctx, srcParentIno, srcIno, dstParentIno, dstName, cmode, umask, &count, &total); eno != 0 {
logger.Errorf("clone failed srcIno:%d,dstParentIno:%d,dstName:%s,cmode:%d,umask:%d,eno:%v", srcIno, dstParentIno, dstName, cmode, umask, eno)
}
close(done)
Expand Down

0 comments on commit 3528ee7

Please sign in to comment.