]> git.saurik.com Git - apple/libc.git/blobdiff - sys/semctl.c
Libc-1081.1.3.tar.gz
[apple/libc.git] / sys / semctl.c
index d6d599b0ace09dd153b1d1ec794f0f4c1adc30f6..494f3e01a8d78ad53ad967c5a184609724720a1b 100644 (file)
 #include <unistd.h>
 #include <stdarg.h>
 #include <sys/sem.h>
-#include <sys/syscall.h>
 
+#include <errno.h>
 /*
- * Stub function to account for the differences in the ipc_perm structure,
+ * 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())
+
+/*
+ * Legacy stub 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;
-       struct __semid_ds_new   *ds;
-
-       va_start(ap, cmd);
-       ds = va_arg(ap, struct __semid_ds_new *);
-       va_end(ap);
-
-       return syscall(SYS_semctl, semid, semnum, cmd, ds);
-#else  /* !__DARWIN_UNIX03 */
        va_list                 ap;
-       struct __semid_ds_old   *ds_old;
+       int                     rv;
+       int                     val = 0;
        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 +83,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 +104,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);
@@ -100,5 +119,4 @@ semctl(int semid, int semnum, int cmd, ...)
        }
 
        return (rv);
-#endif /* !__DARWIN_UNIX03 */
 }