go-tg-screenshot-bot
137 строк · 3.4 Кб
1// +build darwin dragonfly freebsd linux netbsd openbsd
2
3// Package shm implements System V shared memory functions (shmctl, shmget, shmat, shmdt).
4package shm5
6import (7"syscall"8"unsafe"9)
10
11// Constants.
12const (13// Mode bits for `shmget`.14
15// Create key if key does not exist.16IPC_CREAT = 0100017// Fail if key exists.18IPC_EXCL = 0200019// Return error on wait.20IPC_NOWAIT = 0400021
22// Special key values.23
24// Private key.25IPC_PRIVATE = 026
27// Flags for `shmat`.28
29// Attach read-only access.30SHM_RDONLY = 01000031// Round attach address to SHMLBA.32SHM_RND = 02000033// Take-over region on attach.34SHM_REMAP = 04000035// Execution access.36SHM_EXEC = 010000037
38// Commands for `shmctl`.39
40// Lock segment (root only).41SHM_LOCK = 142// Unlock segment (root only).43SHM_UNLOCK = 1244
45// Control commands for `shmctl`.46
47// Remove identifier.48IPC_RMID = 049// Set `ipc_perm` options.50IPC_SET = 151// Get `ipc_perm' options.52IPC_STAT = 253)
54
55// Get allocates a shared memory segment.
56//
57// Get() returns the identifier of the shared memory segment associated with the value of the argument key.
58// A new shared memory segment is created if key has the value IPC_PRIVATE or key isn't IPC_PRIVATE,
59// no shared memory segment corresponding to key exists, and IPC_CREAT is specified in shmFlg.
60//
61// If shmFlg specifies both IPC_CREAT and IPC_EXCL and a shared memory segment already exists for key,
62// then Get() fails with errno set to EEXIST.
63func Get(key int, size int, shmFlg int) (shmId int, err error) {64id, _, errno := syscall.Syscall(sysShmGet, uintptr(int32(key)), uintptr(int32(size)), uintptr(int32(shmFlg)))65if int(id) == -1 {66return -1, errno67}68
69return int(id), nil70}
71
72// At attaches the shared memory segment identified by shmId.
73//
74// Using At() with shmAddr equal to NULL is the preferred, portable way of attaching a shared memory segment.
75func At(shmId int, shmAddr uintptr, shmFlg int) (data []byte, err error) {76addr, _, errno := syscall.Syscall(sysShmAt, uintptr(int32(shmId)), shmAddr, uintptr(int32(shmFlg)))77if int(addr) == -1 {78return nil, errno79}80
81length, err := Size(shmId)82if err != nil {83syscall.Syscall(sysShmDt, addr, 0, 0)84return nil, err85}86
87var b = struct {88addr uintptr89len int90cap int91}{addr, int(length), int(length)}92
93data = *(*[]byte)(unsafe.Pointer(&b))94return data, nil95}
96
97// Dt detaches the shared memory segment.
98//
99// The to-be-detached segment must be currently attached with shmAddr equal to the value returned by the attaching At() call.
100func Dt(data []byte) error {101result, _, errno := syscall.Syscall(sysShmDt, uintptr(unsafe.Pointer(&data[0])), 0, 0)102if int(result) == -1 {103return errno104}105
106return nil107}
108
109// Ctl performs the control operation specified by cmd on the shared memory segment whose identifier is given in shmId.
110//
111// The buf argument is a pointer to a IdDs structure.
112func Ctl(shmId int, cmd int, buf *IdDs) (int, error) {113result, _, errno := syscall.Syscall(sysShmCtl, uintptr(int32(shmId)), uintptr(int32(cmd)), uintptr(unsafe.Pointer(buf)))114if int(result) == -1 {115return -1, errno116}117
118return int(result), nil119}
120
121// Rm removes the shared memory segment.
122func Rm(shmId int) error {123_, err := Ctl(shmId, IPC_RMID, nil)124return err125}
126
127// Size returns size of shared memory segment.
128func Size(shmId int) (int64, error) {129var idDs IdDs130
131_, err := Ctl(shmId, IPC_STAT, &idDs)132if err != nil {133return 0, err134}135
136return int64(idDs.SegSz), nil137}
138