Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ipcset operation #19

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
72 changes: 70 additions & 2 deletions mq.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ typedef struct _sysv_msg {
} sysv_msg;
*/
import "C"
import "errors"
import "runtime"
import (
"errors"
"runtime"
)

// Represents the message queue
type MessageQueue struct {
id int
config *QueueConfig
buffer *C.sysv_msg
stats *QueueStats
}

// Wraps the C structure "struct msgid_ds" (see msgctl(2))
Expand Down Expand Up @@ -51,6 +54,14 @@ type QueueConfig struct {
ProjId int // ProjId for ftok to generate a SysV IPC key if Key is not set
}

// QueueSet is used to modify an instance of the message queue.
type QueueSet struct {
Uid uint32 // unsigned int32, according to bits/typesizes.h
Gid uint32 //
Mode uint16 // unsigned short, according to msgctl(2)
Qbytes uint64 // unsigned long, according to bits/msg.h
}

// NewMessageQueue returns an instance of the message queue given a QueueConfig.
func NewMessageQueue(config *QueueConfig) (*MessageQueue, error) {
mq := new(MessageQueue)
Expand All @@ -67,6 +78,13 @@ func NewMessageQueue(config *QueueConfig) (*MessageQueue, error) {
if err != nil {
return mq, err
}

mq.stats, err = mq.Stat()

if err != nil {
return mq, err
}

runtime.SetFinalizer(mq, func(mq *MessageQueue) {
mq.Close()
})
Expand Down Expand Up @@ -136,6 +154,7 @@ func (mq *MessageQueue) Close() {
}
}

// connect the the message queue
func (mq *MessageQueue) connect() (err error) {
if mq.config.Key == 0 {
mq.config.Key, err = ftok(mq.config.Path, mq.config.ProjId)
Expand All @@ -148,3 +167,52 @@ func (mq *MessageQueue) connect() (err error) {
mq.id, err = msgget(mq.config.Key, mq.config.Mode)
return err
}

// Set modify the message queue
func (mq *MessageQueue) Set(queueSet *QueueSet) error {
return ipcSet(mq.id, queueSet)
}

// SetQbytes modify the qbytes of the message queue
func (mq *MessageQueue) SetQbytes(qbytes uint64) error {
queueSet := &QueueSet{
Uid: mq.stats.Perm.Uid,
Gid: mq.stats.Perm.Gid,
Mode: mq.stats.Perm.Mode,
Qbytes: qbytes,
}
return mq.Set(queueSet)
}

// SetUid modify the uid of the message queue
func (mq *MessageQueue) SetUid(uid uint32) error {
queueSet := &QueueSet{
Uid: uid,
Gid: mq.stats.Perm.Gid,
Mode: mq.stats.Perm.Mode,
Qbytes: mq.stats.Qbytes,
}
return mq.Set(queueSet)
}

// SetGid modify the gid of the message queue
func (mq *MessageQueue) SetGid(gid uint32) error {
queueSet := &QueueSet{
Uid: mq.stats.Perm.Uid,
Gid: gid,
Mode: mq.stats.Perm.Mode,
Qbytes: mq.stats.Qbytes,
}
return mq.Set(queueSet)
}

// SetMode modify the mode of the message queue
func (mq *MessageQueue) SetMode(mode uint16) error {
queueSet := &QueueSet{
Uid: mq.stats.Perm.Uid,
Gid: mq.stats.Perm.Gid,
Mode: mode,
Qbytes: mq.stats.Qbytes,
}
return mq.Set(queueSet)
}
18 changes: 15 additions & 3 deletions wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ typedef struct _sysv_msg {
} sysv_msg;
*/
import "C"
import "unsafe"
import "errors"
import (
"errors"
"unsafe"
)

const (
IPC_CREAT = C.IPC_CREAT
Expand Down Expand Up @@ -101,7 +103,6 @@ func ftok(path string, projId int) (int, error) {
func msgctl(key int, cmd int) (*C.struct_msqid_ds, error) {
info := new(C.struct_msqid_ds)
_, err := C.msgctl(C.int(key), C.int(cmd), info)

return info, err
}

Expand Down Expand Up @@ -160,3 +161,14 @@ func ipcStat(key int) (*QueueStats, error) {

return stat, nil
}

// Wraps msgctl(key, IPC_SET, struct msqid_ds *buf)
func ipcSet(key int, queueSet *QueueSet) error {
info := new(C.struct_msqid_ds)
info.msg_qbytes = C.ulong(queueSet.Qbytes)
info.msg_perm.uid = C.uint(queueSet.Uid)
info.msg_perm.gid = C.uint(queueSet.Gid)
info.msg_perm.mode = C.ushort(queueSet.Mode)
_, err := C.msgctl(C.int(key), C.int(IPC_SET), info)
return err
}