From a757587ea29b3c337633d8493c7e2c178520c943 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 22 Dec 2022 16:17:21 +0530 Subject: [PATCH] Fix SHM on OpenBSD --- tools/utils/shm/shm.go | 54 ------------- tools/utils/shm/shm_fs.go | 105 +++++++++++++++++++++++--- tools/utils/shm/specific_dragonfly.go | 4 - tools/utils/shm/specific_linux.go | 4 - tools/utils/shm/specific_netbsd.go | 4 - tools/utils/shm/specific_openbsd.go | 10 --- 6 files changed, 96 insertions(+), 85 deletions(-) diff --git a/tools/utils/shm/shm.go b/tools/utils/shm/shm.go index 40a6291a1..cd6e4d655 100644 --- a/tools/utils/shm/shm.go +++ b/tools/utils/shm/shm.go @@ -7,7 +7,6 @@ import ( "fmt" "math/rand" "os" - "path/filepath" "strconv" "strings" @@ -86,59 +85,6 @@ func munmap(s []byte) error { return unix.Munmap(s) } -type file_based_mmap struct { - f *os.File - region []byte - unlinked bool -} - -func file_mmap(f *os.File, size uint64, access AccessFlags, truncate bool) (MMap, error) { - if truncate { - err := truncate_or_unlink(f, size) - if err != nil { - return nil, err - } - } - region, err := mmap(int(size), access, int(f.Fd()), 0) - if err != nil { - f.Close() - os.Remove(f.Name()) - return nil, err - } - return &file_based_mmap{f: f, region: region}, nil -} - -func (self *file_based_mmap) Name() string { - return filepath.Base(self.f.Name()) -} - -func (self *file_based_mmap) FileSystemName() string { - return self.f.Name() -} - -func (self *file_based_mmap) Slice() []byte { - return self.region -} - -func (self *file_based_mmap) Close() (err error) { - if self.region != nil { - self.f.Close() - err = munmap(self.region) - self.region = nil - } - return err -} - -func (self *file_based_mmap) Unlink() (err error) { - if self.unlinked { - return nil - } - self.unlinked = true - return os.Remove(self.f.Name()) -} - -func (self *file_based_mmap) IsFileSystemBacked() bool { return true } - func CreateTemp(pattern string, size uint64) (MMap, error) { return create_temp(pattern, size) } diff --git a/tools/utils/shm/shm_fs.go b/tools/utils/shm/shm_fs.go index 50836b847..b895f7d7c 100644 --- a/tools/utils/shm/shm_fs.go +++ b/tools/utils/shm/shm_fs.go @@ -4,29 +4,116 @@ package shm import ( + "crypto/sha256" + "errors" "fmt" + "io/fs" + "kitty/tools/utils" "os" "path/filepath" + "runtime" ) var _ = fmt.Print -func create_temp(pattern string, size uint64) (MMap, error) { - pattern = modify_pattern(pattern) - ans, err := os.CreateTemp(SHM_DIR, pattern) +type file_based_mmap struct { + f *os.File + region []byte + unlinked bool + special_name string +} + +func file_mmap(f *os.File, size uint64, access AccessFlags, truncate bool, special_name string) (MMap, error) { + if truncate { + err := truncate_or_unlink(f, size) + if err != nil { + return nil, err + } + } + region, err := mmap(int(size), access, int(f.Fd()), 0) if err != nil { + f.Close() + os.Remove(f.Name()) return nil, err } - return file_mmap(ans, size, WRITE, true) + return &file_based_mmap{f: f, region: region, special_name: special_name}, nil +} + +func (self *file_based_mmap) Name() string { + if self.special_name != "" { + return self.special_name + } + return filepath.Base(self.f.Name()) +} + +func (self *file_based_mmap) FileSystemName() string { + return self.f.Name() +} + +func (self *file_based_mmap) Slice() []byte { + return self.region +} + +func (self *file_based_mmap) Close() (err error) { + if self.region != nil { + self.f.Close() + err = munmap(self.region) + self.region = nil + } + return err +} + +func (self *file_based_mmap) Unlink() (err error) { + if self.unlinked { + return nil + } + self.unlinked = true + return os.Remove(self.f.Name()) +} + +func (self *file_based_mmap) IsFileSystemBacked() bool { return true } + +func file_path_from_name(name string) string { + // See https://github.com/openbsd/src/blob/master/lib/libc/gen/shm_open.c + if runtime.GOOS == "openbsd" { + hash := sha256.Sum256(utils.UnsafeStringToBytes(name)) + return filepath.Join(SHM_DIR, utils.UnsafeBytesToString(hash[:])+".shm") + } + return filepath.Join(SHM_DIR, name) +} + +func create_temp(pattern string, size uint64) (ans MMap, err error) { + special_name := "" + var prefix, suffix string + prefix, suffix, err = prefix_and_suffix(pattern) + if err != nil { + return + } + var f *os.File + try := 0 + for { + name := prefix + next_random() + suffix + path := file_path_from_name(name) + f, err = os.OpenFile(path, os.O_EXCL|os.O_CREATE|os.O_RDWR, 0600) + if err != nil { + if errors.Is(err, fs.ErrExist) { + try += 1 + if try > 10000 { + return nil, &os.PathError{Op: "createtemp", Path: prefix + "*" + suffix, Err: fs.ErrExist} + } + continue + } + return + } + break + } + return file_mmap(f, size, WRITE, true, special_name) } func Open(name string, size uint64) (MMap, error) { - if !filepath.IsAbs(name) { - name = filepath.Join(SHM_DIR, name) - } - ans, err := os.OpenFile(name, os.O_RDONLY, 0) + ans, err := os.OpenFile(file_path_from_name(name), os.O_RDONLY, 0) if err != nil { return nil, err } - return file_mmap(ans, size, READ, false) + return file_mmap(ans, size, READ, false, name) } diff --git a/tools/utils/shm/specific_dragonfly.go b/tools/utils/shm/specific_dragonfly.go index 2b8fdb22c..7e5bdcd36 100644 --- a/tools/utils/shm/specific_dragonfly.go +++ b/tools/utils/shm/specific_dragonfly.go @@ -10,7 +10,3 @@ var _ = fmt.Print // https://www.dragonflybsd.org/cgi/web-man?command=shm_open§ion=3 const SHM_DIR = "/var/run/shm" - -func modify_pattern(pattern string) string { - return pattern -} diff --git a/tools/utils/shm/specific_linux.go b/tools/utils/shm/specific_linux.go index bc9e94dcf..cab8901e7 100644 --- a/tools/utils/shm/specific_linux.go +++ b/tools/utils/shm/specific_linux.go @@ -9,7 +9,3 @@ import ( var _ = fmt.Print const SHM_DIR = "/dev/shm" - -func modify_pattern(pattern string) string { - return pattern -} diff --git a/tools/utils/shm/specific_netbsd.go b/tools/utils/shm/specific_netbsd.go index e8bd8d2c4..209095a2e 100644 --- a/tools/utils/shm/specific_netbsd.go +++ b/tools/utils/shm/specific_netbsd.go @@ -9,7 +9,3 @@ import ( var _ = fmt.Print const SHM_DIR = "/var/shm" - -func modify_pattern(pattern string) string { - return pattern -} diff --git a/tools/utils/shm/specific_openbsd.go b/tools/utils/shm/specific_openbsd.go index b571b593f..e1b604e62 100644 --- a/tools/utils/shm/specific_openbsd.go +++ b/tools/utils/shm/specific_openbsd.go @@ -9,13 +9,3 @@ import ( var _ = fmt.Print const SHM_DIR = "/tmp" - -func modify_pattern(pattern string) string { - // https://github.com/openbsd/src/blob/master/lib/libc/gen/shm_open.c - if strings.Contains(pattern, "*") { - pattern += ".shm" - } else { - pattern += "*.shm" - } - return pattern -}