gopkg.in/ro-ag/posix.v1@v1.0.6/shm_open_darwin.go (about)

     1  package posix
     2  
     3  import (
     4  	"crypto/md5"
     5  	"encoding/hex"
     6  	"fmt"
     7  	"syscall"
     8  	"time"
     9  	"unsafe"
    10  )
    11  
    12  /* -------------------------------------------------------------------------------------------------------------------*/
    13  
    14  func newName(name string) string {
    15  	unique := ""
    16  	n := fmt.Sprintf("%d.%s", time.Now().UnixNano(), name)
    17  	x := md5.Sum([]byte(n))
    18  	s := hex.EncodeToString(x[:])
    19  	unique = _MFD_NAME_PREFIX + s[len(_MFD_NAME_PREFIX)+1:]
    20  	return unique
    21  }
    22  
    23  func memfdCreate(name string, flags int) (fd int, err error) {
    24  
    25  	fd = -1
    26  	if flags&MFD_HUGETLB == 0 {
    27  		if flags & ^_MFD_ALL_FLAGS != 0 {
    28  			return fd, EINVAL
    29  		}
    30  	} else {
    31  		/* Allow huge page size encoding in flags. */
    32  		if flags & ^(_MFD_ALL_FLAGS|(_MFD_HUGE_MASK<<_MFD_HUGE_SHIFT)) != 0 {
    33  			return fd, EINVAL
    34  		}
    35  	}
    36  
    37  	/* length includes terminating zero */
    38  	nameLen := len(name)
    39  	if nameLen <= 0 {
    40  		return fd, EFAULT
    41  	}
    42  	if nameLen > _MFD_NAME_MAX_LEN {
    43  		return fd, EINVAL
    44  	}
    45  
    46  	unique := newName(name)
    47  	for {
    48  		if fd, err = shmOpen(unique, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, S_IRUSR|S_IWUSR|S_IRGRP); err != nil {
    49  			if err != syscall.EEXIST {
    50  				return -1, err
    51  			} else {
    52  				unique = newName(name)
    53  			}
    54  		} else {
    55  			break
    56  		}
    57  	}
    58  
    59  	if flags&MFD_CLOEXEC == 0 {
    60  		/* Remove Flag FD_CLOEXEC which deletes the file if it needs to be passed to another process */
    61  		if err = remCloseOnExec(fd); err != nil {
    62  			goto unlinking
    63  		}
    64  	}
    65  
    66  	/* Delete shmName but keep the file descriptor */
    67  	if err = shmUnlink(unique); err != nil {
    68  		goto closing
    69  	}
    70  
    71  	return
    72  unlinking:
    73  	_ = shmUnlink(unique)
    74  closing:
    75  	_ = Close(fd)
    76  	fd = -1
    77  	return
    78  }
    79  
    80  //goland:noinspection GoSnakeCaseUsage
    81  const (
    82  	_MFD_NAME_PREFIX           = "memfd:"
    83  	_MFD_NAME_PREFIX_LEN       = 10
    84  	_MFD_NAME_MAX_LEN          = syscall.NAME_MAX - _MFD_NAME_PREFIX_LEN
    85  	_MFD_ALL_FLAGS             = MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB
    86  	_HUGETLB_FLAG_ENCODE_SHIFT = 26
    87  	_HUGETLB_FLAG_ENCODE_MASK  = 0x3
    88  	_MFD_HUGE_SHIFT            = _HUGETLB_FLAG_ENCODE_SHIFT
    89  	_MFD_HUGE_MASK             = _HUGETLB_FLAG_ENCODE_MASK
    90  )
    91  
    92  /* -------------------------------------------------------------------------------------------------------------------*/
    93  
    94  func ShmAnonymous() (fd int, err error) {
    95  
    96  	fd = -1
    97  
    98  	name := "shm_anon"
    99  	unique := newName(name)
   100  	for {
   101  		if fd, err = shmOpen(unique, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, S_IRUSR|S_IWUSR|S_IRGRP); err != nil {
   102  			if err != syscall.EEXIST {
   103  				return -1, err
   104  			} else {
   105  				unique = newName(name)
   106  			}
   107  		} else {
   108  			break
   109  		}
   110  	}
   111  
   112  	if err != nil {
   113  		return
   114  	}
   115  
   116  	/* Delete shmName but keep the file descriptor */
   117  	if err = shmUnlink(unique); err != nil {
   118  		goto closing
   119  	}
   120  
   121  	/* Remove Flag FD_CLOEXEC which deletes the file if it needs to be passed to another process */
   122  	if err = remCloseOnExec(fd); err != nil {
   123  		goto closing
   124  	}
   125  
   126  	return
   127  closing:
   128  	Close(fd)
   129  	fd = -1
   130  	return
   131  }
   132  
   133  /* -------------------------------------------------------------------------------------------------------------------*/
   134  func remCloseOnExec(fd int) (err error) {
   135  	var arg int
   136  	if arg, err = Fcntl(fd, F_GETFD, 0); err != nil {
   137  		_ = Close(fd)
   138  		return
   139  	}
   140  
   141  	arg &^= FD_CLOEXEC // Clear the close-on-exec flag.
   142  
   143  	if arg, err = Fcntl(fd, F_SETFD, arg); err != nil {
   144  		_ = Close(fd)
   145  		return
   146  	}
   147  	return
   148  }
   149  
   150  /* -------------------------------------------------------------------------------------------------------------------*/
   151  func shmOpen(path string, oflag int, mode uint32) (fd int, err error) {
   152  	var _p0 *byte
   153  	_p0, err = syscall.BytePtrFromString(path)
   154  	if err != nil {
   155  		return
   156  	}
   157  	r0, _, e1 := syscall_syscall(libc_shm_open_trampoline_addr,
   158  		uintptr(unsafe.Pointer(_p0)), uintptr(oflag), uintptr(mode))
   159  	fd = int(r0)
   160  	if e1 != 0 {
   161  		err = errnoErr(e1)
   162  	}
   163  	return
   164  }
   165  
   166  var libc_shm_open_trampoline_addr uintptr
   167  
   168  //go:cgo_import_dynamic libc_shm_open shm_open "/usr/lib/libSystem.B.dylib"
   169  
   170  /* -------------------------------------------------------------------------------------------------------------------*/
   171  
   172  func shmUnlink(path string) (err error) {
   173  	var _p0 *byte
   174  	_p0, err = syscall.BytePtrFromString(path)
   175  	if err != nil {
   176  		return
   177  	}
   178  	_, _, e1 := syscall_syscall(libc_shm_unlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0)
   179  	if e1 != 0 {
   180  		err = errnoErr(e1)
   181  	}
   182  	return
   183  }
   184  
   185  var libc_shm_unlink_trampoline_addr uintptr
   186  
   187  //go:cgo_import_dynamic libc_shm_unlink shm_unlink "/usr/lib/libSystem.B.dylib"
   188  
   189  /* -------------------------------------------------------------------------------------------------------------------*/