]> git.saurik.com Git - apple/libc.git/blob - sys/semctl.c
Libc-1081.1.3.tar.gz
[apple/libc.git] / sys / semctl.c
1 /*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 #include <unistd.h>
24 #include <stdarg.h>
25 #include <sys/sem.h>
26
27 #include <errno.h>
28 /*
29 * Because KERNEL is defined, including errno.h doesn't define errno, so
30 * we have to do it ourselves.
31 */
32 extern int * __error(void);
33 #define errno (*__error())
34
35 /*
36 * Legacy stub to account for the differences in the ipc_perm structure,
37 * while maintaining binary backward compatibility.
38 */
39 extern int __semctl(int semid, int semnum, int cmd, void *);
40
41 int
42 semctl(int semid, int semnum, int cmd, ...)
43 {
44 va_list ap;
45 int rv;
46 int val = 0;
47 struct __semid_ds_new ds;
48 struct __semid_ds_new *ds_new = &ds;
49 struct __semid_ds_old *ds_old = NULL;
50
51 va_start(ap, cmd);
52 if (cmd == SETVAL)
53 val = va_arg(ap, int);
54 else
55 ds_old = va_arg(ap, struct __semid_ds_old *);
56 va_end(ap);
57
58 #define _UP_CVT(x) ds_new-> x = ds_old-> x
59 #define _DN_CVT(x) ds_old-> x = ds_new-> x
60
61 if ((cmd == IPC_SET || cmd == IPC_STAT) && ds_old == NULL) {
62 /* Return EFAULT if ds_old is NULL (like the kernel would do) */
63 errno = EFAULT;
64 return -1;
65 }
66 if (cmd == IPC_SET) {
67 /* convert before call */
68 _UP_CVT(sem_perm.uid);
69 _UP_CVT(sem_perm.gid);
70 _UP_CVT(sem_perm.cuid);
71 _UP_CVT(sem_perm.cgid);
72 _UP_CVT(sem_perm.mode);
73 ds_new->sem_perm._seq = ds_old->sem_perm.seq;
74 ds_new->sem_perm._key = ds_old->sem_perm.key;
75 _UP_CVT(sem_base);
76 _UP_CVT(sem_nsems);
77 _UP_CVT(sem_otime);
78 _UP_CVT(sem_pad1); /* binary compatibility */
79 _UP_CVT(sem_ctime);
80 _UP_CVT(sem_pad2); /* binary compatibility */
81 _UP_CVT(sem_pad3[0]); /* binary compatibility */
82 _UP_CVT(sem_pad3[1]); /* binary compatibility */
83 _UP_CVT(sem_pad3[2]); /* binary compatibility */
84 _UP_CVT(sem_pad3[3]); /* binary compatibility */
85 }
86 switch (cmd) {
87 case SETVAL:
88 /* syscall must use LP64 quantities */
89 rv = __semctl(semid, semnum, cmd, (void *)val);
90 break;
91 case IPC_SET:
92 case IPC_STAT:
93 rv = __semctl(semid, semnum, cmd, ds_new);
94 break;
95 default:
96 rv = __semctl(semid, semnum, cmd, ds_old);
97 break;
98 }
99
100 if (cmd == IPC_STAT) {
101 /* convert after call */
102 _DN_CVT(sem_perm.uid); /* warning! precision loss! */
103 _DN_CVT(sem_perm.gid); /* warning! precision loss! */
104 _DN_CVT(sem_perm.cuid); /* warning! precision loss! */
105 _DN_CVT(sem_perm.cgid); /* warning! precision loss! */
106 _DN_CVT(sem_perm.mode);
107 ds_old->sem_perm.seq = ds_new->sem_perm._seq;
108 ds_old->sem_perm.key = ds_new->sem_perm._key;
109 _DN_CVT(sem_base);
110 _DN_CVT(sem_nsems);
111 _DN_CVT(sem_otime);
112 _DN_CVT(sem_pad1); /* binary compatibility */
113 _DN_CVT(sem_ctime);
114 _DN_CVT(sem_pad2); /* binary compatibility */
115 _DN_CVT(sem_pad3[0]); /* binary compatibility */
116 _DN_CVT(sem_pad3[1]); /* binary compatibility */
117 _DN_CVT(sem_pad3[2]); /* binary compatibility */
118 _DN_CVT(sem_pad3[3]); /* binary compatibility */
119 }
120
121 return (rv);
122 }