-
Notifications
You must be signed in to change notification settings - Fork 568
/
loopback_linux.go
61 lines (52 loc) · 1.61 KB
/
loopback_linux.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package fuse
import (
"context"
"syscall"
"github.com/hanwen/go-fuse/v2/fs"
"golang.org/x/sys/unix"
)
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 fs.ToErrno(err)
}
defer syscall.Close(fd1)
fd2, err := syscall.Open(newparent.path(), syscall.O_DIRECTORY, 0)
defer syscall.Close(fd2)
if err != nil {
return fs.ToErrno(err)
}
var st syscall.Stat_t
if err := syscall.Fstat(fd1, &st); err != nil {
return fs.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 fs.ToErrno(err)
}
newinode := &newparent.Inode
if newinode.Root() != newinode && newinode.StableAttr().Ino != n.root().idFromStat(&st).Ino {
return syscall.EBUSY
}
return fs.ToErrno(unix.Renameat2(fd1, name, fd2, newName, unix.RENAME_EXCHANGE))
}
func (n *loopbackNode) CopyFileRange(ctx context.Context, fhIn fs.FileHandle,
offIn uint64, out *fs.Inode, fhOut fs.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), fs.ToErrno(err)
}