summaryrefslogtreecommitdiffstats
path: root/libc-top-half/musl/src/ipc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libc-top-half/musl/src/ipc/ftok.c10
-rw-r--r--libc-top-half/musl/src/ipc/ipc.h24
-rw-r--r--libc-top-half/musl/src/ipc/msgctl.c51
-rw-r--r--libc-top-half/musl/src/ipc/msgget.c12
-rw-r--r--libc-top-half/musl/src/ipc/msgrcv.c12
-rw-r--r--libc-top-half/musl/src/ipc/msgsnd.c12
-rw-r--r--libc-top-half/musl/src/ipc/semctl.c69
-rw-r--r--libc-top-half/musl/src/ipc/semget.c19
-rw-r--r--libc-top-half/musl/src/ipc/semop.c12
-rw-r--r--libc-top-half/musl/src/ipc/semtimedop.c35
-rw-r--r--libc-top-half/musl/src/ipc/shmat.c17
-rw-r--r--libc-top-half/musl/src/ipc/shmctl.c51
-rw-r--r--libc-top-half/musl/src/ipc/shmdt.c12
-rw-r--r--libc-top-half/musl/src/ipc/shmget.c14
14 files changed, 350 insertions, 0 deletions
diff --git a/libc-top-half/musl/src/ipc/ftok.c b/libc-top-half/musl/src/ipc/ftok.c
new file mode 100644
index 0000000..c36b4b6
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/ftok.c
@@ -0,0 +1,10 @@
+#include <sys/ipc.h>
+#include <sys/stat.h>
+
+key_t ftok(const char *path, int id)
+{
+ struct stat st;
+ if (stat(path, &st) < 0) return -1;
+
+ return ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) | ((id & 0xffu) << 24));
+}
diff --git a/libc-top-half/musl/src/ipc/ipc.h b/libc-top-half/musl/src/ipc/ipc.h
new file mode 100644
index 0000000..746a905
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/ipc.h
@@ -0,0 +1,24 @@
+#include "syscall.h"
+
+#define IPCOP_semop 1
+#define IPCOP_semget 2
+#define IPCOP_semctl 3
+#define IPCOP_semtimedop 4
+#define IPCOP_msgsnd 11
+#define IPCOP_msgrcv 12
+#define IPCOP_msgget 13
+#define IPCOP_msgctl 14
+#define IPCOP_shmat 21
+#define IPCOP_shmdt 22
+#define IPCOP_shmget 23
+#define IPCOP_shmctl 24
+
+#ifndef IPC_64
+#define IPC_64 0x100
+#endif
+
+#define IPC_TIME64 (IPC_STAT & 0x100)
+
+#define IPC_CMD(cmd) (((cmd) & ~IPC_TIME64) | IPC_64)
+
+#define IPC_HILO(b,t) ((b)->t = (b)->__##t##_lo | 0LL+(b)->__##t##_hi<<32)
diff --git a/libc-top-half/musl/src/ipc/msgctl.c b/libc-top-half/musl/src/ipc/msgctl.c
new file mode 100644
index 0000000..9c11440
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/msgctl.c
@@ -0,0 +1,51 @@
+#include <sys/msg.h>
+#include <endian.h>
+#include "syscall.h"
+#include "ipc.h"
+
+#if __BYTE_ORDER != __BIG_ENDIAN
+#undef SYSCALL_IPC_BROKEN_MODE
+#endif
+
+int msgctl(int q, int cmd, struct msqid_ds *buf)
+{
+#if IPC_TIME64
+ struct msqid_ds out, *orig;
+ if (cmd&IPC_TIME64) {
+ out = (struct msqid_ds){0};
+ orig = buf;
+ buf = &out;
+ }
+#endif
+#ifdef SYSCALL_IPC_BROKEN_MODE
+ struct msqid_ds tmp;
+ if (cmd == IPC_SET) {
+ tmp = *buf;
+ tmp.msg_perm.mode *= 0x10000U;
+ buf = &tmp;
+ }
+#endif
+#ifndef SYS_ipc
+ int r = __syscall(SYS_msgctl, q, IPC_CMD(cmd), buf);
+#else
+ int r = __syscall(SYS_ipc, IPCOP_msgctl, q, IPC_CMD(cmd), 0, buf, 0);
+#endif
+#ifdef SYSCALL_IPC_BROKEN_MODE
+ if (r >= 0) switch (cmd | IPC_TIME64) {
+ case IPC_STAT:
+ case MSG_STAT:
+ case MSG_STAT_ANY:
+ buf->msg_perm.mode >>= 16;
+ }
+#endif
+#if IPC_TIME64
+ if (r >= 0 && (cmd&IPC_TIME64)) {
+ buf = orig;
+ *buf = out;
+ IPC_HILO(buf, msg_stime);
+ IPC_HILO(buf, msg_rtime);
+ IPC_HILO(buf, msg_ctime);
+ }
+#endif
+ return __syscall_ret(r);
+}
diff --git a/libc-top-half/musl/src/ipc/msgget.c b/libc-top-half/musl/src/ipc/msgget.c
new file mode 100644
index 0000000..30a4b42
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/msgget.c
@@ -0,0 +1,12 @@
+#include <sys/msg.h>
+#include "syscall.h"
+#include "ipc.h"
+
+int msgget(key_t k, int flag)
+{
+#ifndef SYS_ipc
+ return syscall(SYS_msgget, k, flag);
+#else
+ return syscall(SYS_ipc, IPCOP_msgget, k, flag);
+#endif
+}
diff --git a/libc-top-half/musl/src/ipc/msgrcv.c b/libc-top-half/musl/src/ipc/msgrcv.c
new file mode 100644
index 0000000..9d1034b
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/msgrcv.c
@@ -0,0 +1,12 @@
+#include <sys/msg.h>
+#include "syscall.h"
+#include "ipc.h"
+
+ssize_t msgrcv(int q, void *m, size_t len, long type, int flag)
+{
+#ifndef SYS_ipc
+ return syscall_cp(SYS_msgrcv, q, m, len, type, flag);
+#else
+ return syscall_cp(SYS_ipc, IPCOP_msgrcv, q, len, flag, ((long[]){ (long)m, type }));
+#endif
+}
diff --git a/libc-top-half/musl/src/ipc/msgsnd.c b/libc-top-half/musl/src/ipc/msgsnd.c
new file mode 100644
index 0000000..99bb17e
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/msgsnd.c
@@ -0,0 +1,12 @@
+#include <sys/msg.h>
+#include "syscall.h"
+#include "ipc.h"
+
+int msgsnd(int q, const void *m, size_t len, int flag)
+{
+#ifndef SYS_ipc
+ return syscall_cp(SYS_msgsnd, q, m, len, flag);
+#else
+ return syscall_cp(SYS_ipc, IPCOP_msgsnd, q, len, flag, m);
+#endif
+}
diff --git a/libc-top-half/musl/src/ipc/semctl.c b/libc-top-half/musl/src/ipc/semctl.c
new file mode 100644
index 0000000..bbb97d7
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/semctl.c
@@ -0,0 +1,69 @@
+#include <sys/sem.h>
+#include <stdarg.h>
+#include <endian.h>
+#include "syscall.h"
+#include "ipc.h"
+
+#if __BYTE_ORDER != __BIG_ENDIAN
+#undef SYSCALL_IPC_BROKEN_MODE
+#endif
+
+union semun {
+ int val;
+ struct semid_ds *buf;
+ unsigned short *array;
+};
+
+int semctl(int id, int num, int cmd, ...)
+{
+ union semun arg = {0};
+ va_list ap;
+ switch (cmd & ~IPC_TIME64) {
+ case SETVAL: case GETALL: case SETALL: case IPC_SET:
+ case IPC_INFO: case SEM_INFO:
+ case IPC_STAT & ~IPC_TIME64:
+ case SEM_STAT & ~IPC_TIME64:
+ case SEM_STAT_ANY & ~IPC_TIME64:
+ va_start(ap, cmd);
+ arg = va_arg(ap, union semun);
+ va_end(ap);
+ }
+#if IPC_TIME64
+ struct semid_ds out, *orig;
+ if (cmd&IPC_TIME64) {
+ out = (struct semid_ds){0};
+ orig = arg.buf;
+ arg.buf = &out;
+ }
+#endif
+#ifdef SYSCALL_IPC_BROKEN_MODE
+ struct semid_ds tmp;
+ if (cmd == IPC_SET) {
+ tmp = *arg.buf;
+ tmp.sem_perm.mode *= 0x10000U;
+ arg.buf = &tmp;
+ }
+#endif
+#ifndef SYS_ipc
+ int r = __syscall(SYS_semctl, id, num, IPC_CMD(cmd), arg.buf);
+#else
+ int r = __syscall(SYS_ipc, IPCOP_semctl, id, num, IPC_CMD(cmd), &arg.buf);
+#endif
+#ifdef SYSCALL_IPC_BROKEN_MODE
+ if (r >= 0) switch (cmd | IPC_TIME64) {
+ case IPC_STAT:
+ case SEM_STAT:
+ case SEM_STAT_ANY:
+ arg.buf->sem_perm.mode >>= 16;
+ }
+#endif
+#if IPC_TIME64
+ if (r >= 0 && (cmd&IPC_TIME64)) {
+ arg.buf = orig;
+ *arg.buf = out;
+ IPC_HILO(arg.buf, sem_otime);
+ IPC_HILO(arg.buf, sem_ctime);
+ }
+#endif
+ return __syscall_ret(r);
+}
diff --git a/libc-top-half/musl/src/ipc/semget.c b/libc-top-half/musl/src/ipc/semget.c
new file mode 100644
index 0000000..2cdf626
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/semget.c
@@ -0,0 +1,19 @@
+#include <sys/sem.h>
+#include <limits.h>
+#include <errno.h>
+#include "syscall.h"
+#include "ipc.h"
+
+int semget(key_t key, int n, int fl)
+{
+ /* The kernel uses the wrong type for the sem_nsems member
+ * of struct semid_ds, and thus might not check that the
+ * n fits in the correct (per POSIX) userspace type, so
+ * we have to check here. */
+ if (n > USHRT_MAX) return __syscall_ret(-EINVAL);
+#ifndef SYS_ipc
+ return syscall(SYS_semget, key, n, fl);
+#else
+ return syscall(SYS_ipc, IPCOP_semget, key, n, fl);
+#endif
+}
diff --git a/libc-top-half/musl/src/ipc/semop.c b/libc-top-half/musl/src/ipc/semop.c
new file mode 100644
index 0000000..5f0c7de
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/semop.c
@@ -0,0 +1,12 @@
+#include <sys/sem.h>
+#include "syscall.h"
+#include "ipc.h"
+
+int semop(int id, struct sembuf *buf, size_t n)
+{
+#ifndef SYS_ipc
+ return syscall(SYS_semop, id, buf, n);
+#else
+ return syscall(SYS_ipc, IPCOP_semop, id, n, 0, buf);
+#endif
+}
diff --git a/libc-top-half/musl/src/ipc/semtimedop.c b/libc-top-half/musl/src/ipc/semtimedop.c
new file mode 100644
index 0000000..1632e7b
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/semtimedop.c
@@ -0,0 +1,35 @@
+#define _GNU_SOURCE
+#include <sys/sem.h>
+#include <errno.h>
+#include "syscall.h"
+#include "ipc.h"
+
+#define IS32BIT(x) !((x)+0x80000000ULL>>32)
+#define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63))
+
+#if !defined(SYS_semtimedop) && !defined(SYS_ipc)
+#define NO_TIME32 1
+#else
+#define NO_TIME32 0
+#endif
+
+int semtimedop(int id, struct sembuf *buf, size_t n, const struct timespec *ts)
+{
+#ifdef SYS_semtimedop_time64
+ time_t s = ts ? ts->tv_sec : 0;
+ long ns = ts ? ts->tv_nsec : 0;
+ int r = -ENOSYS;
+ if (NO_TIME32 || !IS32BIT(s))
+ r = __syscall(SYS_semtimedop_time64, id, buf, n,
+ ts ? ((long long[]){s, ns}) : 0);
+ if (NO_TIME32 || r!=-ENOSYS) return __syscall_ret(r);
+ ts = ts ? (void *)(long[]){CLAMP(s), ns} : 0;
+#endif
+#if defined(SYS_ipc)
+ return syscall(SYS_ipc, IPCOP_semtimedop, id, n, 0, buf, ts);
+#elif defined(SYS_semtimedop)
+ return syscall(SYS_semtimedop, id, buf, n, ts);
+#else
+ return __syscall_ret(-ENOSYS);
+#endif
+}
diff --git a/libc-top-half/musl/src/ipc/shmat.c b/libc-top-half/musl/src/ipc/shmat.c
new file mode 100644
index 0000000..8c7407d
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/shmat.c
@@ -0,0 +1,17 @@
+#include <sys/shm.h>
+#include "syscall.h"
+#include "ipc.h"
+
+#ifndef SYS_ipc
+void *shmat(int id, const void *addr, int flag)
+{
+ return (void *)syscall(SYS_shmat, id, addr, flag);
+}
+#else
+void *shmat(int id, const void *addr, int flag)
+{
+ unsigned long ret;
+ ret = syscall(SYS_ipc, IPCOP_shmat, id, flag, &addr, addr);
+ return (ret > -(unsigned long)SHMLBA) ? (void *)ret : (void *)addr;
+}
+#endif
diff --git a/libc-top-half/musl/src/ipc/shmctl.c b/libc-top-half/musl/src/ipc/shmctl.c
new file mode 100644
index 0000000..1c9f78c
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/shmctl.c
@@ -0,0 +1,51 @@
+#include <sys/shm.h>
+#include <endian.h>
+#include "syscall.h"
+#include "ipc.h"
+
+#if __BYTE_ORDER != __BIG_ENDIAN
+#undef SYSCALL_IPC_BROKEN_MODE
+#endif
+
+int shmctl(int id, int cmd, struct shmid_ds *buf)
+{
+#if IPC_TIME64
+ struct shmid_ds out, *orig;
+ if (cmd&IPC_TIME64) {
+ out = (struct shmid_ds){0};
+ orig = buf;
+ buf = &out;
+ }
+#endif
+#ifdef SYSCALL_IPC_BROKEN_MODE
+ struct shmid_ds tmp;
+ if (cmd == IPC_SET) {
+ tmp = *buf;
+ tmp.shm_perm.mode *= 0x10000U;
+ buf = &tmp;
+ }
+#endif
+#ifndef SYS_ipc
+ int r = __syscall(SYS_shmctl, id, IPC_CMD(cmd), buf);
+#else
+ int r = __syscall(SYS_ipc, IPCOP_shmctl, id, IPC_CMD(cmd), 0, buf, 0);
+#endif
+#ifdef SYSCALL_IPC_BROKEN_MODE
+ if (r >= 0) switch (cmd | IPC_TIME64) {
+ case IPC_STAT:
+ case SHM_STAT:
+ case SHM_STAT_ANY:
+ buf->shm_perm.mode >>= 16;
+ }
+#endif
+#if IPC_TIME64
+ if (r >= 0 && (cmd&IPC_TIME64)) {
+ buf = orig;
+ *buf = out;
+ IPC_HILO(buf, shm_atime);
+ IPC_HILO(buf, shm_dtime);
+ IPC_HILO(buf, shm_ctime);
+ }
+#endif
+ return __syscall_ret(r);
+}
diff --git a/libc-top-half/musl/src/ipc/shmdt.c b/libc-top-half/musl/src/ipc/shmdt.c
new file mode 100644
index 0000000..5723813
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/shmdt.c
@@ -0,0 +1,12 @@
+#include <sys/shm.h>
+#include "syscall.h"
+#include "ipc.h"
+
+int shmdt(const void *addr)
+{
+#ifndef SYS_ipc
+ return syscall(SYS_shmdt, addr);
+#else
+ return syscall(SYS_ipc, IPCOP_shmdt, 0, 0, 0, addr);
+#endif
+}
diff --git a/libc-top-half/musl/src/ipc/shmget.c b/libc-top-half/musl/src/ipc/shmget.c
new file mode 100644
index 0000000..7521b5f
--- /dev/null
+++ b/libc-top-half/musl/src/ipc/shmget.c
@@ -0,0 +1,14 @@
+#include <sys/shm.h>
+#include <stdint.h>
+#include "syscall.h"
+#include "ipc.h"
+
+int shmget(key_t key, size_t size, int flag)
+{
+ if (size > PTRDIFF_MAX) size = SIZE_MAX;
+#ifndef SYS_ipc
+ return syscall(SYS_shmget, key, size, flag);
+#else
+ return syscall(SYS_ipc, IPCOP_shmget, key, size, flag);
+#endif
+}