]>
Commit | Line | Data |
---|---|---|
44422d11 | 1 | /* Copyright (C) 1995,1997,1998,2000,2003,2006 Free Software Foundation, Inc. |
f8d5da29 UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995. | |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
3214b89b AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
f8d5da29 UD |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
3214b89b | 13 | Lesser General Public License for more details. |
f8d5da29 | 14 | |
3214b89b | 15 | You should have received a copy of the GNU Lesser General Public |
ab84e3ff PE |
16 | License along with the GNU C Library. If not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
f8d5da29 UD |
18 | |
19 | #include <errno.h> | |
20 | #include <sys/shm.h> | |
21 | #include <ipc_priv.h> | |
22 | ||
23 | #include <sysdep.h> | |
24 | #include <string.h> | |
25 | #include <sys/syscall.h> | |
26 | #include <bits/wordsize.h> | |
1e431627 | 27 | #include <bp-checks.h> |
f8d5da29 | 28 | |
44422d11 | 29 | #include <kernel-features.h> |
f8d5da29 UD |
30 | |
31 | struct __old_shmid_ds | |
32 | { | |
33 | struct __old_ipc_perm shm_perm; /* operation permission struct */ | |
34 | int shm_segsz; /* size of segment in bytes */ | |
35 | __time_t shm_atime; /* time of last shmat() */ | |
36 | __time_t shm_dtime; /* time of last shmdt() */ | |
37 | __time_t shm_ctime; /* time of last change by shmctl() */ | |
38 | __ipc_pid_t shm_cpid; /* pid of creator */ | |
39 | __ipc_pid_t shm_lpid; /* pid of last shmop */ | |
40 | unsigned short int shm_nattch; /* number of current attaches */ | |
41 | unsigned short int __shm_npages; /* size of segment (pages) */ | |
1e431627 GM |
42 | unsigned long int *__unbounded __shm_pages; /* array of ptrs to frames -> SHMMAX */ |
43 | struct vm_area_struct *__unbounded __attaches; /* descriptors for attaches */ | |
f8d5da29 UD |
44 | }; |
45 | ||
46 | struct __old_shminfo | |
47 | { | |
48 | int shmmax; | |
49 | int shmmin; | |
50 | int shmmni; | |
51 | int shmseg; | |
52 | int shmall; | |
53 | }; | |
54 | ||
55 | /* Provide operations to control over shared memory segments. */ | |
56 | int __new_shmctl (int, int, struct shmid_ds *); | |
57 | ||
58 | int | |
59 | __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) | |
60 | { | |
61 | #if __ASSUME_32BITUIDS > 0 | |
1e431627 | 62 | return INLINE_SYSCALL (shmctl, 3, shmid, cmd | __IPC_64, CHECK_1 (buf)); |
f8d5da29 UD |
63 | #else |
64 | switch (cmd) { | |
65 | case SHM_STAT: | |
66 | case IPC_STAT: | |
67 | case IPC_SET: | |
68 | case IPC_INFO: | |
69 | break; | |
70 | default: | |
1e431627 | 71 | return INLINE_SYSCALL (shmctl, 3, shmid, cmd, CHECK_1 (buf)); |
f8d5da29 UD |
72 | } |
73 | ||
74 | { | |
75 | int save_errno = errno, result; | |
76 | struct __old_shmid_ds old; | |
77 | ||
78 | /* Unfortunately there is no way how to find out for sure whether | |
79 | we should use old or new shmctl. */ | |
1e431627 | 80 | result = INLINE_SYSCALL (shmctl, 3, shmid, cmd | __IPC_64, CHECK_1 (buf)); |
f8d5da29 UD |
81 | if (result != -1 || errno != EINVAL) |
82 | return result; | |
83 | ||
84 | __set_errno(save_errno); | |
85 | if (cmd == IPC_SET) | |
86 | { | |
87 | old.shm_perm.uid = buf->shm_perm.uid; | |
88 | old.shm_perm.gid = buf->shm_perm.gid; | |
89 | old.shm_perm.mode = buf->shm_perm.mode; | |
90 | if (old.shm_perm.uid != buf->shm_perm.uid || | |
91 | old.shm_perm.gid != buf->shm_perm.gid) | |
92 | { | |
93 | __set_errno (EINVAL); | |
94 | return -1; | |
95 | } | |
96 | } | |
1e431627 | 97 | result = INLINE_SYSCALL (shmctl, 3, shmid, cmd, __ptrvalue (&old)); |
f8d5da29 UD |
98 | if (result != -1 && (cmd == SHM_STAT || cmd == IPC_STAT)) |
99 | { | |
100 | memset(buf, 0, sizeof(*buf)); | |
101 | buf->shm_perm.__key = old.shm_perm.__key; | |
102 | buf->shm_perm.uid = old.shm_perm.uid; | |
103 | buf->shm_perm.gid = old.shm_perm.gid; | |
104 | buf->shm_perm.cuid = old.shm_perm.cuid; | |
105 | buf->shm_perm.cgid = old.shm_perm.cgid; | |
106 | buf->shm_perm.mode = old.shm_perm.mode; | |
107 | buf->shm_perm.__seq = old.shm_perm.__seq; | |
108 | buf->shm_atime = old.shm_atime; | |
109 | buf->shm_dtime = old.shm_dtime; | |
110 | buf->shm_ctime = old.shm_ctime; | |
111 | buf->shm_segsz = old.shm_segsz; | |
112 | buf->shm_nattch = old.shm_nattch; | |
113 | buf->shm_cpid = old.shm_cpid; | |
114 | buf->shm_lpid = old.shm_lpid; | |
115 | } | |
116 | else if (result != -1 && cmd == IPC_INFO) | |
117 | { | |
cfbf1a2f | 118 | struct __old_shminfo *oldi = (void *)&old; |
f8d5da29 UD |
119 | struct shminfo *i = (struct shminfo *)buf; |
120 | ||
121 | memset(i, 0, sizeof(*i)); | |
122 | i->shmmax = oldi->shmmax; | |
123 | i->shmmin = oldi->shmmin; | |
124 | i->shmmni = oldi->shmmni; | |
125 | i->shmseg = oldi->shmseg; | |
126 | i->shmall = oldi->shmall; | |
127 | } | |
128 | return result; | |
129 | } | |
130 | #endif | |
131 | } | |
132 | ||
0772663d UD |
133 | #include <shlib-compat.h> |
134 | versioned_symbol (libc, __new_shmctl, shmctl, GLIBC_2_2); |