X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/3d9156a7a519a5e3aa1b92e9d9d4b991f1aed7ff..b5d655f7532a546b54809da387f7467d128a756b:/sys/semctl.c diff --git a/sys/semctl.c b/sys/semctl.c index d6d599b..77d5ab0 100644 --- a/sys/semctl.c +++ b/sys/semctl.c @@ -23,38 +23,63 @@ #include #include #include -#include + +#if !__DARWIN_UNIX03 +#include +/* + * Because KERNEL is defined, including errno.h doesn't define errno, so + * we have to do it ourselves. + */ +extern int * __error(void); +#define errno (*__error()) +#endif /* !__DARWIN_UNIX03 */ /* * Stub function to account for the differences in the ipc_perm structure, * while maintaining binary backward compatibility. */ +extern int __semctl(int semid, int semnum, int cmd, void *); + int semctl(int semid, int semnum, int cmd, ...) { -#ifdef __DARWIN_UNIX03 va_list ap; + int rv; + int val = 0; +#if __DARWIN_UNIX03 struct __semid_ds_new *ds; va_start(ap, cmd); - ds = va_arg(ap, struct __semid_ds_new *); + if (cmd == SETVAL) { + val = va_arg(ap, int); + rv = __semctl(semid, semnum, cmd, (void *)val); + } else { + ds = va_arg(ap, struct __semid_ds_new *); + rv = __semctl(semid, semnum, cmd, (void *)ds); + } va_end(ap); - return syscall(SYS_semctl, semid, semnum, cmd, ds); + return rv; #else /* !__DARWIN_UNIX03 */ - va_list ap; - struct __semid_ds_old *ds_old; struct __semid_ds_new ds; struct __semid_ds_new *ds_new = &ds; - int rv; + struct __semid_ds_old *ds_old = NULL; va_start(ap, cmd); - ds_old = va_arg(ap, struct __semid_ds_old *); + if (cmd == SETVAL) + val = va_arg(ap, int); + else + ds_old = va_arg(ap, struct __semid_ds_old *); va_end(ap); #define _UP_CVT(x) ds_new-> x = ds_old-> x #define _DN_CVT(x) ds_old-> x = ds_new-> x + if ((cmd == IPC_SET || cmd == IPC_STAT) && ds_old == NULL) { + /* Return EFAULT if ds_old is NULL (like the kernel would do) */ + errno = EFAULT; + return -1; + } if (cmd == IPC_SET) { /* convert before call */ _UP_CVT(sem_perm.uid); @@ -75,8 +100,19 @@ semctl(int semid, int semnum, int cmd, ...) _UP_CVT(sem_pad3[2]); /* binary compatibility */ _UP_CVT(sem_pad3[3]); /* binary compatibility */ } - - rv = syscall(SYS_semctl, semid, semnum, cmd, &ds); + switch (cmd) { + case SETVAL: + /* syscall must use LP64 quantities */ + rv = __semctl(semid, semnum, cmd, (void *)val); + break; + case IPC_SET: + case IPC_STAT: + rv = __semctl(semid, semnum, cmd, ds_new); + break; + default: + rv = __semctl(semid, semnum, cmd, ds_old); + break; + } if (cmd == IPC_STAT) { /* convert after call */ @@ -85,8 +121,8 @@ semctl(int semid, int semnum, int cmd, ...) _DN_CVT(sem_perm.cuid); /* warning! precision loss! */ _DN_CVT(sem_perm.cgid); /* warning! precision loss! */ _DN_CVT(sem_perm.mode); - ds_new->sem_perm.seq = ds_old->sem_perm._seq; - ds_new->sem_perm.key = ds_old->sem_perm._key; + ds_old->sem_perm.seq = ds_new->sem_perm._seq; + ds_old->sem_perm.key = ds_new->sem_perm._key; _DN_CVT(sem_base); _DN_CVT(sem_nsems); _DN_CVT(sem_otime);