Files
scoutfs-go/syscall.go
2020-03-15 09:04:08 -07:00

81 lines
1.8 KiB
Go

package scoutfs
import (
"os"
"syscall"
"unsafe"
)
const (
// sysOpenByHandleAt linux system call
sysOpenByHandleAt = 304
// fileIDScoutfs for scoutfs file handle
fileIDScoutfs = 0x81
)
type fileID struct {
Ino uint64
ParentIno uint64
}
type fileHandle struct {
FidSize uint32
HandleType int32
FID fileID
}
// OpenByHandle is similar to OpenByID, but returns just the file descriptor
// and does not have the added overhead of getting the filename
// An open file within scoutfs is supplied for ioctls
// (usually just the base mount point directory)
func OpenByHandle(dirfd *os.File, ino uint64, flags int) (uintptr, error) {
h := &fileHandle{
FidSize: uint32(unsafe.Sizeof(fileID{})),
HandleType: fileIDScoutfs,
FID: fileID{Ino: ino},
}
return openbyhandleat(dirfd, h, flags)
}
func openbyhandleat(dirfd *os.File, handle *fileHandle, flags int) (uintptr, error) {
fd, _, e1 := syscall.Syscall6(sysOpenByHandleAt, uintptr(dirfd.Fd()), uintptr(unsafe.Pointer(handle)), uintptr(flags), 0, 0, 0)
var err error
if e1 != 0 {
err = errnoErr(e1)
}
return fd, err
}
func scoutfsctl(f *os.File, cmd int, ptr unsafe.Pointer) (int, error) {
count, _, e1 := syscall.Syscall(syscall.SYS_IOCTL, uintptr(f.Fd()), uintptr(cmd), uintptr(ptr))
var err error
if e1 != 0 {
err = errnoErr(e1)
}
return int(count), err
}
// Do the interface allocations only once for common
// Errno values.
var (
errEAGAIN error = syscall.EAGAIN
errEINVAL error = syscall.EINVAL
errENOENT error = syscall.ENOENT
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return nil
case syscall.EAGAIN:
return errEAGAIN
case syscall.EINVAL:
return errEINVAL
case syscall.ENOENT:
return errENOENT
}
return e
}