101 lines
1.5 KiB
Go
101 lines
1.5 KiB
Go
|
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
|
||
|
}
|