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 /* -------------------------------------------------------------------------------------------------------------------*/