mirror of
https://github.com/rclone/rclone.git
synced 2024-12-02 13:25:51 +01:00
87 lines
2.4 KiB
Go
87 lines
2.4 KiB
Go
// +build linux
|
|
|
|
// Copyright 2019 the Go-FUSE Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package fs
|
|
|
|
import (
|
|
"context"
|
|
"syscall"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
func (n *loopbackNode) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) {
|
|
sz, err := syscall.Getxattr(n.path(), attr, dest)
|
|
return uint32(sz), ToErrno(err)
|
|
}
|
|
|
|
func (n *loopbackNode) Setxattr(ctx context.Context, attr string, data []byte, flags uint32) syscall.Errno {
|
|
err := syscall.Setxattr(n.path(), attr, data, int(flags))
|
|
return ToErrno(err)
|
|
}
|
|
|
|
func (n *loopbackNode) Removexattr(ctx context.Context, attr string) syscall.Errno {
|
|
err := syscall.Removexattr(n.path(), attr)
|
|
return ToErrno(err)
|
|
}
|
|
|
|
func (n *loopbackNode) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) {
|
|
sz, err := syscall.Listxattr(n.path(), dest)
|
|
return uint32(sz), ToErrno(err)
|
|
}
|
|
|
|
func (n *loopbackNode) renameExchange(name string, newparent *loopbackNode, newName string) syscall.Errno {
|
|
fd1, err := syscall.Open(n.path(), syscall.O_DIRECTORY, 0)
|
|
if err != nil {
|
|
return ToErrno(err)
|
|
}
|
|
defer syscall.Close(fd1)
|
|
fd2, err := syscall.Open(newparent.path(), syscall.O_DIRECTORY, 0)
|
|
defer syscall.Close(fd2)
|
|
if err != nil {
|
|
return ToErrno(err)
|
|
}
|
|
|
|
var st syscall.Stat_t
|
|
if err := syscall.Fstat(fd1, &st); err != nil {
|
|
return ToErrno(err)
|
|
}
|
|
|
|
// Double check that nodes didn't change from under us.
|
|
inode := &n.Inode
|
|
if inode.Root() != inode && inode.StableAttr().Ino != n.root().idFromStat(&st).Ino {
|
|
return syscall.EBUSY
|
|
}
|
|
if err := syscall.Fstat(fd2, &st); err != nil {
|
|
return ToErrno(err)
|
|
}
|
|
|
|
newinode := &newparent.Inode
|
|
if newinode.Root() != newinode && newinode.StableAttr().Ino != n.root().idFromStat(&st).Ino {
|
|
return syscall.EBUSY
|
|
}
|
|
|
|
return ToErrno(unix.Renameat2(fd1, name, fd2, newName, unix.RENAME_EXCHANGE))
|
|
}
|
|
|
|
func (n *loopbackNode) CopyFileRange(ctx context.Context, fhIn FileHandle,
|
|
offIn uint64, out *Inode, fhOut FileHandle, offOut uint64,
|
|
len uint64, flags uint64) (uint32, syscall.Errno) {
|
|
lfIn, ok := fhIn.(*loopbackFile)
|
|
if !ok {
|
|
return 0, syscall.ENOTSUP
|
|
}
|
|
lfOut, ok := fhOut.(*loopbackFile)
|
|
if !ok {
|
|
return 0, syscall.ENOTSUP
|
|
}
|
|
|
|
signedOffIn := int64(offIn)
|
|
signedOffOut := int64(offOut)
|
|
count, err := unix.CopyFileRange(lfIn.fd, &signedOffIn, lfOut.fd, &signedOffOut, int(len), int(flags))
|
|
return uint32(count), ToErrno(err)
|
|
}
|