github.com/pachyderm/pachyderm@v1.13.4/src/server/pfs/fuse/loopback_linux.go (about) 1 package fuse 2 3 import ( 4 "context" 5 "syscall" 6 7 "github.com/hanwen/go-fuse/v2/fs" 8 "golang.org/x/sys/unix" 9 ) 10 11 func (n *loopbackNode) renameExchange(name string, newparent *loopbackNode, newName string) syscall.Errno { 12 fd1, err := syscall.Open(n.path(), syscall.O_DIRECTORY, 0) 13 if err != nil { 14 return fs.ToErrno(err) 15 } 16 defer syscall.Close(fd1) 17 fd2, err := syscall.Open(newparent.path(), syscall.O_DIRECTORY, 0) 18 defer syscall.Close(fd2) 19 if err != nil { 20 return fs.ToErrno(err) 21 } 22 23 var st syscall.Stat_t 24 if err := syscall.Fstat(fd1, &st); err != nil { 25 return fs.ToErrno(err) 26 } 27 28 // Double check that nodes didn't change from under us. 29 inode := &n.Inode 30 if inode.Root() != inode && inode.StableAttr().Ino != n.root().idFromStat(&st).Ino { 31 return syscall.EBUSY 32 } 33 if err := syscall.Fstat(fd2, &st); err != nil { 34 return fs.ToErrno(err) 35 } 36 37 newinode := &newparent.Inode 38 if newinode.Root() != newinode && newinode.StableAttr().Ino != n.root().idFromStat(&st).Ino { 39 return syscall.EBUSY 40 } 41 42 return fs.ToErrno(unix.Renameat2(fd1, name, fd2, newName, unix.RENAME_EXCHANGE)) 43 } 44 45 func (n *loopbackNode) CopyFileRange(ctx context.Context, fhIn fs.FileHandle, 46 offIn uint64, out *fs.Inode, fhOut fs.FileHandle, offOut uint64, 47 len uint64, flags uint64) (uint32, syscall.Errno) { 48 lfIn, ok := fhIn.(*loopbackFile) 49 if !ok { 50 return 0, syscall.ENOTSUP 51 } 52 lfOut, ok := fhOut.(*loopbackFile) 53 if !ok { 54 return 0, syscall.ENOTSUP 55 } 56 57 signedOffIn := int64(offIn) 58 signedOffOut := int64(offOut) 59 count, err := unix.CopyFileRange(lfIn.fd, &signedOffIn, lfOut.fd, &signedOffOut, int(len), int(flags)) 60 return uint32(count), fs.ToErrno(err) 61 }