X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fipc%2Fsemctl.c;h=ce1fb164fa8114bee5511c554b12ab0edd557aa3;hb=22276671d031639f1bd55d7dbf817290c321c7bf;hp=392a4aac2cfbbdfe94c529a96cb95d0470d9e014;hpb=aa398f56fa398f2202b04e82c67f822f3233786f;p=musl diff --git a/src/ipc/semctl.c b/src/ipc/semctl.c index 392a4aac..ce1fb164 100644 --- a/src/ipc/semctl.c +++ b/src/ipc/semctl.c @@ -1,18 +1,50 @@ #include #include +#include #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, ...) { - long arg; + union semun arg = {0}; va_list ap; - va_start(ap, cmd); - arg = va_arg(ap, long); - va_end(ap); -#ifdef __NR_semctl - return syscall(SYS_semctl, id, num, cmd, arg); + switch (cmd) { + case SETVAL: case GETALL: case SETALL: case IPC_STAT: case IPC_SET: + case IPC_INFO: case SEM_INFO: case SEM_STAT: + va_start(ap, cmd); + arg = va_arg(ap, union semun); + va_end(ap); + } +#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, cmd | IPC_64, arg.buf); #else - return syscall(SYS_ipc, IPCOP_semctl, id, num, cmd | 0x100, &arg); + int r = __syscall(SYS_ipc, IPCOP_semctl, id, num, cmd | IPC_64, &arg.buf); +#endif +#ifdef SYSCALL_IPC_BROKEN_MODE + if (r >= 0) switch (cmd) { + case IPC_STAT: + case SEM_STAT: + case SEM_STAT_ANY: + arg.buf->sem_perm.mode >>= 16; + } #endif + return __syscall_ret(r); }