You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
2.3 KiB
126 lines
2.3 KiB
//go:build unix
|
|
|
|
package fuse
|
|
|
|
import (
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
// Vectored I/O support for Unix-like systems
|
|
|
|
// IOVec represents an I/O vector for readv/writev operations
|
|
type IOVec struct {
|
|
Base *byte
|
|
Len uint64
|
|
}
|
|
|
|
func readvFile(fd int, iovs []IOVec) (int, error) {
|
|
if len(iovs) == 0 {
|
|
return 0, nil
|
|
}
|
|
|
|
n, _, errno := syscall.Syscall(syscall.SYS_READV,
|
|
uintptr(fd),
|
|
uintptr(unsafe.Pointer(&iovs[0])),
|
|
uintptr(len(iovs)))
|
|
|
|
if errno != 0 {
|
|
return 0, errno
|
|
}
|
|
return int(n), nil
|
|
}
|
|
|
|
func writevFile(fd int, iovs []IOVec) (int, error) {
|
|
if len(iovs) == 0 {
|
|
return 0, nil
|
|
}
|
|
|
|
n, _, errno := syscall.Syscall(syscall.SYS_WRITEV,
|
|
uintptr(fd),
|
|
uintptr(unsafe.Pointer(&iovs[0])),
|
|
uintptr(len(iovs)))
|
|
|
|
if errno != 0 {
|
|
return 0, errno
|
|
}
|
|
return int(n), nil
|
|
}
|
|
|
|
func preadvFile(fd int, iovs []IOVec, offset int64) (int, error) {
|
|
if len(iovs) == 0 {
|
|
return 0, nil
|
|
}
|
|
|
|
// preadv/pwritev may not be available on all Unix systems
|
|
// Fall back to individual pread calls
|
|
totalRead := 0
|
|
currentOffset := offset
|
|
|
|
for _, iov := range iovs {
|
|
if iov.Len == 0 {
|
|
continue
|
|
}
|
|
|
|
buf := (*[1 << 30]byte)(unsafe.Pointer(iov.Base))[:iov.Len:iov.Len]
|
|
n, err := syscall.Pread(fd, buf, currentOffset)
|
|
if err != nil {
|
|
return totalRead, err
|
|
}
|
|
totalRead += n
|
|
currentOffset += int64(n)
|
|
|
|
if n < int(iov.Len) {
|
|
break // EOF or partial read
|
|
}
|
|
}
|
|
|
|
return totalRead, nil
|
|
}
|
|
|
|
func pwritevFile(fd int, iovs []IOVec, offset int64) (int, error) {
|
|
if len(iovs) == 0 {
|
|
return 0, nil
|
|
}
|
|
|
|
// preadv/pwritev may not be available on all Unix systems
|
|
// Fall back to individual pwrite calls
|
|
totalWritten := 0
|
|
currentOffset := offset
|
|
|
|
for _, iov := range iovs {
|
|
if iov.Len == 0 {
|
|
continue
|
|
}
|
|
|
|
buf := (*[1 << 30]byte)(unsafe.Pointer(iov.Base))[:iov.Len:iov.Len]
|
|
n, err := syscall.Pwrite(fd, buf, currentOffset)
|
|
if err != nil {
|
|
return totalWritten, err
|
|
}
|
|
totalWritten += n
|
|
currentOffset += int64(n)
|
|
|
|
if n < int(iov.Len) {
|
|
break // Partial write
|
|
}
|
|
}
|
|
|
|
return totalWritten, nil
|
|
}
|
|
|
|
// Helper function to create IOVec from byte slices
|
|
func makeIOVecs(buffers [][]byte) []IOVec {
|
|
iovs := make([]IOVec, len(buffers))
|
|
for i, buf := range buffers {
|
|
if len(buf) > 0 {
|
|
iovs[i].Base = &buf[0]
|
|
iovs[i].Len = uint64(len(buf))
|
|
}
|
|
}
|
|
return iovs
|
|
}
|
|
|
|
func isVectoredIOSupported() bool {
|
|
return true
|
|
}
|