shmctl.c raw

   1  #include <sys/shm.h>
   2  #include <endian.h>
   3  #include "syscall.h"
   4  #include "ipc.h"
   5  
   6  #if __BYTE_ORDER != __BIG_ENDIAN
   7  #undef SYSCALL_IPC_BROKEN_MODE
   8  #endif
   9  
  10  int shmctl(int id, int cmd, struct shmid_ds *buf)
  11  {
  12  #if IPC_TIME64
  13  	struct shmid_ds out, *orig;
  14  	if (cmd&IPC_TIME64) {
  15  		out = (struct shmid_ds){0};
  16  		orig = buf;
  17  		buf = &out;
  18  	}
  19  #endif
  20  #ifdef SYSCALL_IPC_BROKEN_MODE
  21  	struct shmid_ds tmp;
  22  	if (cmd == IPC_SET) {
  23  		tmp = *buf;
  24  		tmp.shm_perm.mode *= 0x10000U;
  25  		buf = &tmp;
  26  	}
  27  #endif
  28  #ifndef SYS_ipc
  29  	int r = __syscall(SYS_shmctl, id, IPC_CMD(cmd), buf);
  30  #else
  31  	int r = __syscall(SYS_ipc, IPCOP_shmctl, id, IPC_CMD(cmd), 0, buf, 0);
  32  #endif
  33  #ifdef SYSCALL_IPC_BROKEN_MODE
  34  	if (r >= 0) switch (cmd | IPC_TIME64) {
  35  	case IPC_STAT:
  36  	case SHM_STAT:
  37  	case SHM_STAT_ANY:
  38  		buf->shm_perm.mode >>= 16;
  39  	}
  40  #endif
  41  #if IPC_TIME64
  42  	if (r >= 0 && (cmd&IPC_TIME64)) {
  43  		buf = orig;
  44  		*buf = out;
  45  		IPC_HILO(buf, shm_atime);
  46  		IPC_HILO(buf, shm_dtime);
  47  		IPC_HILO(buf, shm_ctime);
  48  	}
  49  #endif
  50  	return __syscall_ret(r);
  51  }
  52