2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/process/TerminationDeferral.h"
4#include "pedigree/kernel/processor/Processor.h"
5#include "pedigree/kernel/processor/ProcessorInformation.h"
6#include "pedigree/kernel/syscallError.h"
10#include "modules/subsys/posix/FileDescriptor.h"
11#include "modules/subsys/posix/PosixProcess.h"
12#include "modules/subsys/posix/PosixSubsystem.h"
13#include "mqueue-state.h"
15Mutex g_MqueueRegistryLock;
21constexpr size_t MaximumQueues = 64;
22constexpr int AllowedFlags = O_ACCMODE | O_CREAT | O_EXCL | O_NONBLOCK | O_CLOEXEC;
24bool copyName(
const char* userName,
String& name) {
26 if (result != PosixSubsystem::UserStringSuccess) {
27 syscallError(result == PosixSubsystem::UserStringTooLong ? Error::NameTooLong
32 SYSCALL_ERROR(DoesNotExist);
35 for (
size_t n = 0; n < name.length(); ++n) {
37 SYSCALL_ERROR(PermissionDenied);
41 if (name ==
"." || name ==
"..") {
42 SYSCALL_ERROR(PermissionDenied);
49 int forbiddenAccess = -1) {
50 if (!acquireDescriptor(fd, descriptor) || !(queue = descriptor->getMqueueImpl()) ||
52 SYSCALL_ERROR(BadFileDescriptor);
59int posix_mq_open(
const char* userName,
int flags,
unsigned mode,
const LinuxMqAttr* userAttr) {
61 if ((flags & ~AllowedFlags) || (flags & O_ACCMODE) == O_ACCMODE) {
62 SYSCALL_ERROR(InvalidArgument);
66 if (!copyName(userName, name)) {
73 for (
auto it = namedQueues.
begin(); it != namedQueues.
end(); ++it) {
74 if ((*it)->namespaceId() == posix_ipc_namespace_id() && (*it)->name() == name) {
80 if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
81 SYSCALL_ERROR(FileExists);
84 if (!queue->mayOpen(process, flags)) {
85 SYSCALL_ERROR(PermissionDenied);
89 if (!(flags & O_CREAT)) {
90 SYSCALL_ERROR(DoesNotExist);
95 SYSCALL_ERROR(BadAddress);
98 if (attr.maxMessages <= 0 || attr.maxMessages > 128 || attr.messageSize <= 0 ||
99 attr.messageSize > 8192) {
100 SYSCALL_ERROR(InvalidArgument);
103 if (g_Mqueues.count() >= MaximumQueues) {
104 SYSCALL_ERROR(NoSpaceLeftOnDevice);
107 mode &= 0777 & ~static_cast<PosixProcess*>(process)->getMask();
109 name, attr.maxMessages, attr.messageSize, process->getEffectiveUserId(),
110 process->getEffectiveGroupId(), mode));
111 g_Mqueues.pushBack(queue.
get());
118 new FileDescriptor(
nullptr, 0, 0xFFFFFFFF, FD_CLOEXEC, flags & (O_ACCMODE | O_NONBLOCK));
119 descriptor->setMqueueImpl(queue);
121 return static_cast<int>(installDescriptor(descriptor, installed));
124int posix_mq_unlink(
const char* userName) {
127 if (!copyName(userName, name)) {
133 for (
auto it = namedQueues.
begin(); it != namedQueues.
end(); ++it) {
134 if ((*it)->namespaceId() == posix_ipc_namespace_id() && (*it)->name() == name) {
136 SYSCALL_ERROR(PermissionDenied);
140 namedQueues.
erase(it);
145 SYSCALL_ERROR(DoesNotExist);
149int posix_mq_timedsend(
int fd,
const char* data,
size_t length,
unsigned priority,
154 if (!queueDescriptor(fd, descriptor, queue, O_RDONLY)) {
157 return queue->send(data, length, priority, descriptor->
getStatusFlags() & O_NONBLOCK, timeout);
160int posix_mq_timedreceive(
int fd,
char* data,
size_t length,
unsigned* priority,
165 if (!queueDescriptor(fd, descriptor, queue, O_WRONLY)) {
168 return queue->receive(data, length, priority, descriptor->
getStatusFlags() & O_NONBLOCK, timeout);
175 if (!queueDescriptor(fd, descriptor, queue)) {
178 return queue->notify(event);
185 if (!queueDescriptor(fd, descriptor, queue)) {
188 return queue->attributes(*descriptor, requested, previous);
193 queue->cancelNotification(pid);
197void posix_mqueue_process_exit(
size_t pid) {
199 for (
auto it = g_Mqueues.begin(); it != g_Mqueues.end(); ++it) {
200 (*it)->cancelNotification(pid);
204void posix_mqueue_clock_changed() {
206 for (
auto it = g_Mqueues.begin(); it != g_Mqueues.end(); ++it) {
207 (*it)->clockChanged();
211void posix_mqueue_namespace_exit(uint64_t
identity) {
216 for (
auto it = namedQueues.
begin(); it != namedQueues.
end(); ++it) {
217 if ((*it)->namespaceId() ==
identity) {
219 namedQueues.
erase(it);
int getStatusFlags() const
Get current status flags.
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static UserStringResult copyUserString(const char *userString, String ©, size_t maxLength)
static ProcessorInformation & information()
Iterator erase(Iterator &Iter)
void pushBack(const T &value)