This commit is contained in:
jdl
2024-11-11 06:36:55 +01:00
parent d0587cc585
commit c5419d662e
102 changed files with 4181 additions and 0 deletions

2
mmap/README.md Normal file
View File

@@ -0,0 +1,2 @@
# mmap

100
mmap/file.go Normal file
View File

@@ -0,0 +1,100 @@
package mmap
import "os"
type File struct {
f *os.File
Map []byte
}
func Create(path string, size int64) (*File, error) {
f, err := os.Create(path)
if err != nil {
return nil, err
}
if err := f.Truncate(size); err != nil {
f.Close()
return nil, err
}
m, err := Map(f, PROT_READ|PROT_WRITE)
if err != nil {
f.Close()
return nil, err
}
return &File{f, m}, nil
}
// Opens a mapped file in read-only mode.
func Open(path string) (*File, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
m, err := Map(f, PROT_READ)
if err != nil {
f.Close()
return nil, err
}
return &File{f, m}, nil
}
func OpenFile(
path string,
fileFlags int,
perm os.FileMode,
size int64, // -1 for file size.
) (*File, error) {
f, err := os.OpenFile(path, fileFlags, perm)
if err != nil {
return nil, err
}
writable := fileFlags|os.O_RDWR != 0 || fileFlags|os.O_WRONLY != 0
fi, err := f.Stat()
if err != nil {
f.Close()
return nil, err
}
if writable && size > 0 && size != fi.Size() {
if err := f.Truncate(size); err != nil {
f.Close()
return nil, err
}
}
mapFlags := PROT_READ
if writable {
mapFlags |= PROT_WRITE
}
m, err := Map(f, mapFlags)
if err != nil {
f.Close()
return nil, err
}
return &File{f, m}, nil
}
func (f *File) Sync() error {
return Sync(f.Map)
}
func (f *File) Close() error {
if f.Map != nil {
if err := Unmap(f.Map); err != nil {
return err
}
f.Map = nil
}
if f.f != nil {
if err := f.f.Close(); err != nil {
return err
}
f.f = nil
}
return nil
}

3
mmap/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module git.crumpington.com/lib/mmap
go 1.23.2

0
mmap/go.sum Normal file
View File

59
mmap/mmap.go Normal file
View File

@@ -0,0 +1,59 @@
package mmap
import (
"os"
"syscall"
"unsafe"
)
const (
PROT_READ = syscall.PROT_READ
PROT_WRITE = syscall.PROT_WRITE
)
// Mmap creates a memory map of the given file. The flags argument should be a
// combination of PROT_READ and PROT_WRITE. The size of the map will be the
// file's size.
func Map(f *os.File, flags int) ([]byte, error) {
fi, err := f.Stat()
if err != nil {
return nil, err
}
size := fi.Size()
addr, _, errno := syscall.Syscall6(
syscall.SYS_MMAP,
0, // addr: 0 => allow kernel to choose
uintptr(size),
uintptr(flags),
uintptr(syscall.MAP_SHARED),
f.Fd(),
0) // offset: 0 => start of file
if errno != 0 {
return nil, syscall.Errno(errno)
}
return unsafe.Slice((*byte)(unsafe.Pointer(addr)), size), nil
}
// Munmap unmaps the data obtained by Map.
func Unmap(data []byte) error {
_, _, errno := syscall.Syscall(
syscall.SYS_MUNMAP,
uintptr(unsafe.Pointer(&data[:1][0])),
uintptr(cap(data)),
0)
if errno != 0 {
return syscall.Errno(errno)
}
return nil
}
func Sync(b []byte) (err error) {
_p0 := unsafe.Pointer(&b[0])
_, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(_p0), uintptr(len(b)), uintptr(syscall.MS_SYNC))
if errno != 0 {
err = syscall.Errno(errno)
}
return
}