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 */ 32extern 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 */ 39extern int __semctl(int semid, int semnum, int cmd, void *); 40 41int 42semctl(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} 123