summaryrefslogtreecommitdiff
path: root/src/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipc')
-rw-r--r--src/ipc/ipc.h12
-rw-r--r--src/ipc/msgctl.c25
-rw-r--r--src/ipc/msgget.c2
-rw-r--r--src/ipc/msgrcv.c2
-rw-r--r--src/ipc/msgsnd.c2
-rw-r--r--src/ipc/semctl.c33
-rw-r--r--src/ipc/semget.c2
-rw-r--r--src/ipc/semop.c2
-rw-r--r--src/ipc/semtimedop.c27
-rw-r--r--src/ipc/shmat.c2
-rw-r--r--src/ipc/shmctl.c25
-rw-r--r--src/ipc/shmdt.c2
-rw-r--r--src/ipc/shmget.c2
13 files changed, 113 insertions, 25 deletions
diff --git a/src/ipc/ipc.h b/src/ipc/ipc.h
index 30ab939a..746a905c 100644
--- a/src/ipc/ipc.h
+++ b/src/ipc/ipc.h
@@ -1,3 +1,5 @@
+#include "syscall.h"
+
#define IPCOP_semop 1
#define IPCOP_semget 2
#define IPCOP_semctl 3
@@ -10,3 +12,13 @@
#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/src/ipc/msgctl.c b/src/ipc/msgctl.c
index ea9b2337..9c114406 100644
--- a/src/ipc/msgctl.c
+++ b/src/ipc/msgctl.c
@@ -9,6 +9,14 @@
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) {
@@ -17,18 +25,27 @@ int msgctl(int q, int cmd, struct msqid_ds *buf)
buf = &tmp;
}
#endif
-#ifdef SYS_msgctl
- int r = __syscall(SYS_msgctl, q, cmd | IPC_64, buf);
+#ifndef SYS_ipc
+ int r = __syscall(SYS_msgctl, q, IPC_CMD(cmd), buf);
#else
- int r = __syscall(SYS_ipc, IPCOP_msgctl, q, cmd | IPC_64, 0, buf, 0);
+ 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) {
+ 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/src/ipc/msgget.c b/src/ipc/msgget.c
index 9dfbc4ea..30a4b42b 100644
--- a/src/ipc/msgget.c
+++ b/src/ipc/msgget.c
@@ -4,7 +4,7 @@
int msgget(key_t k, int flag)
{
-#ifdef SYS_msgget
+#ifndef SYS_ipc
return syscall(SYS_msgget, k, flag);
#else
return syscall(SYS_ipc, IPCOP_msgget, k, flag);
diff --git a/src/ipc/msgrcv.c b/src/ipc/msgrcv.c
index 0a344e56..9d1034b1 100644
--- a/src/ipc/msgrcv.c
+++ b/src/ipc/msgrcv.c
@@ -4,7 +4,7 @@
ssize_t msgrcv(int q, void *m, size_t len, long type, int flag)
{
-#ifdef SYS_msgrcv
+#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 }));
diff --git a/src/ipc/msgsnd.c b/src/ipc/msgsnd.c
index e1abde3a..99bb17e9 100644
--- a/src/ipc/msgsnd.c
+++ b/src/ipc/msgsnd.c
@@ -4,7 +4,7 @@
int msgsnd(int q, const void *m, size_t len, int flag)
{
-#ifdef SYS_msgsnd
+#ifndef SYS_ipc
return syscall_cp(SYS_msgsnd, q, m, len, flag);
#else
return syscall_cp(SYS_ipc, IPCOP_msgsnd, q, len, flag, m);
diff --git a/src/ipc/semctl.c b/src/ipc/semctl.c
index 941e2813..bbb97d7a 100644
--- a/src/ipc/semctl.c
+++ b/src/ipc/semctl.c
@@ -18,13 +18,24 @@ int semctl(int id, int num, int cmd, ...)
{
union semun arg = {0};
va_list ap;
- switch (cmd) {
- case SETVAL: case GETALL: case SETALL: case IPC_STAT: case IPC_SET:
- case IPC_INFO: case SEM_INFO: case SEM_STAT:
+ 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) {
@@ -33,18 +44,26 @@ int semctl(int id, int num, int cmd, ...)
arg.buf = &tmp;
}
#endif
-#ifdef SYS_semctl
- int r = __syscall(SYS_semctl, id, num, cmd | IPC_64, arg.buf);
+#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, cmd | IPC_64, &arg.buf);
+ 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) {
+ 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/src/ipc/semget.c b/src/ipc/semget.c
index c4a559db..2cdf626b 100644
--- a/src/ipc/semget.c
+++ b/src/ipc/semget.c
@@ -11,7 +11,7 @@ int semget(key_t key, int n, int fl)
* n fits in the correct (per POSIX) userspace type, so
* we have to check here. */
if (n > USHRT_MAX) return __syscall_ret(-EINVAL);
-#ifdef SYS_semget
+#ifndef SYS_ipc
return syscall(SYS_semget, key, n, fl);
#else
return syscall(SYS_ipc, IPCOP_semget, key, n, fl);
diff --git a/src/ipc/semop.c b/src/ipc/semop.c
index 8046e437..5f0c7dea 100644
--- a/src/ipc/semop.c
+++ b/src/ipc/semop.c
@@ -4,7 +4,7 @@
int semop(int id, struct sembuf *buf, size_t n)
{
-#ifdef SYS_semop
+#ifndef SYS_ipc
return syscall(SYS_semop, id, buf, n);
#else
return syscall(SYS_ipc, IPCOP_semop, id, n, 0, buf);
diff --git a/src/ipc/semtimedop.c b/src/ipc/semtimedop.c
index b0c4cf9f..a104af21 100644
--- a/src/ipc/semtimedop.c
+++ b/src/ipc/semtimedop.c
@@ -1,13 +1,36 @@
#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) || \
+ SYS_semtimedop == SYS_semtimedop_time64
+#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
+#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(SYS_ipc, IPCOP_semtimedop, id, n, 0, buf, ts);
+ return __syscall_ret(-ENOSYS);
#endif
}
diff --git a/src/ipc/shmat.c b/src/ipc/shmat.c
index 38db92f9..8c7407d1 100644
--- a/src/ipc/shmat.c
+++ b/src/ipc/shmat.c
@@ -2,7 +2,7 @@
#include "syscall.h"
#include "ipc.h"
-#ifdef SYS_shmat
+#ifndef SYS_ipc
void *shmat(int id, const void *addr, int flag)
{
return (void *)syscall(SYS_shmat, id, addr, flag);
diff --git a/src/ipc/shmctl.c b/src/ipc/shmctl.c
index c951a581..1c9f78c2 100644
--- a/src/ipc/shmctl.c
+++ b/src/ipc/shmctl.c
@@ -9,6 +9,14 @@
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) {
@@ -17,18 +25,27 @@ int shmctl(int id, int cmd, struct shmid_ds *buf)
buf = &tmp;
}
#endif
-#ifdef SYS_shmctl
- int r = __syscall(SYS_shmctl, id, cmd | IPC_64, buf);
+#ifndef SYS_ipc
+ int r = __syscall(SYS_shmctl, id, IPC_CMD(cmd), buf);
#else
- int r = __syscall(SYS_ipc, IPCOP_shmctl, id, cmd | IPC_64, 0, buf, 0);
+ 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) {
+ 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/src/ipc/shmdt.c b/src/ipc/shmdt.c
index d4fac8f1..57238137 100644
--- a/src/ipc/shmdt.c
+++ b/src/ipc/shmdt.c
@@ -4,7 +4,7 @@
int shmdt(const void *addr)
{
-#ifdef SYS_shmdt
+#ifndef SYS_ipc
return syscall(SYS_shmdt, addr);
#else
return syscall(SYS_ipc, IPCOP_shmdt, 0, 0, 0, addr);
diff --git a/src/ipc/shmget.c b/src/ipc/shmget.c
index b44f9d68..7521b5fa 100644
--- a/src/ipc/shmget.c
+++ b/src/ipc/shmget.c
@@ -6,7 +6,7 @@
int shmget(key_t key, size_t size, int flag)
{
if (size > PTRDIFF_MAX) size = SIZE_MAX;
-#ifdef SYS_shmget
+#ifndef SYS_ipc
return syscall(SYS_shmget, key, size, flag);
#else
return syscall(SYS_ipc, IPCOP_shmget, key, size, flag);