// Copyright 2016 Tom Thorogood. All rights reserved. // Use of this source code is governed by a // Modified BSD License license that can be found in // the LICENSE file. // Package shm provides functions to open and unlink shared memory. package shm import ( "os" "golang.org/x/sys/unix" ) const devShm = "/dev/shm/" // Taken from shm_open(3): // shm_open() creates and opens a new, or opens an existing, POSIX shared // memory object. A POSIX shared memory object is in effect a handle which // can be used by unrelated processes to mmap(2) the same region of shared // memory. The shm_unlink() function performs the converse operation, // removing an object previously created by shm_open(). // // The operation of shm_open() is analogous to that of open(2). name // specifies the shared memory object to be created or opened. For // portable use, a shared memory object should be identified by a name of // the form /somename; that is, a null-terminated string of up to NAME_MAX // (i.e., 255) characters consisting of an initial slash, followed by one // or more characters, none of which are slashes. func Open(name string, flag int, perm os.FileMode) (*os.File, error) { fileName := name for len(name) != 0 && name[0] == '/' { name = name[1:] } if len(name) == 0 { return nil, &os.PathError{Op: "open", Path: fileName, Err: unix.EINVAL} } o := uint32(perm.Perm()) if perm&os.ModeSetuid != 0 { o |= unix.S_ISUID } if perm&os.ModeSetgid != 0 { o |= unix.S_ISGID } if perm&os.ModeSticky != 0 { o |= unix.S_ISVTX } fd, err := unix.Open(devShm+name, flag|unix.O_CLOEXEC, o) if err != nil { return nil, &os.PathError{Op: "open", Path: fileName, Err: err} } return os.NewFile(uintptr(fd), fileName), nil } // Taken from shm_unlink(3): // The operation of shm_unlink() is analogous to unlink(2): it removes a // shared memory object name, and, once all processes have unmapped the // object, de-allocates and destroys the contents of the associated memory // region. After a successful shm_unlink(), attempts to shm_open() an // object with the same name will fail (unless O_CREAT was specified, in // which case a new, distinct object is created). func Unlink(name string) error { fileName := name for len(name) != 0 && name[0] == '/' { name = name[1:] } if len(name) == 0 { return &os.PathError{Op: "unlink", Path: fileName, Err: unix.EINVAL} } if err := unix.Unlink(devShm + name); err != nil { return &os.PathError{Op: "unlink", Path: fileName, Err: err} } return nil }