]>
Commit | Line | Data |
---|---|---|
0ecb606c | 1 | /* Copyright (C) 1995,1997,1998,2000,2003,2006 Free Software Foundation, Inc. |
d6c5fe3a 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 | |
41bdb6e2 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. | |
d6c5fe3a 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 | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
d6c5fe3a | 14 | |
41bdb6e2 AJ |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, write to the Free | |
17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
18 | 02111-1307 USA. */ | |
d6c5fe3a UD |
19 | |
20 | #include <errno.h> | |
21 | #include <sys/msg.h> | |
22 | #include <ipc_priv.h> | |
23 | ||
24 | #include <sysdep.h> | |
25 | #include <string.h> | |
26 | #include <sys/syscall.h> | |
d25c879d | 27 | #include <bp-checks.h> |
d6c5fe3a | 28 | |
0ecb606c | 29 | #include <kernel-features.h> |
d6c5fe3a UD |
30 | |
31 | struct __old_msqid_ds | |
32 | { | |
33 | struct __old_ipc_perm msg_perm; /* structure describing operation permission */ | |
d25c879d GM |
34 | struct msg *__unbounded __msg_first; /* pointer to first message on queue */ |
35 | struct msg *__unbounded __msg_last; /* pointer to last message on queue */ | |
d6c5fe3a UD |
36 | __time_t msg_stime; /* time of last msgsnd command */ |
37 | __time_t msg_rtime; /* time of last msgrcv command */ | |
38 | __time_t msg_ctime; /* time of last change */ | |
d25c879d GM |
39 | struct wait_queue *__unbounded __wwait; /* ??? */ |
40 | struct wait_queue *__unbounded __rwait; /* ??? */ | |
d6c5fe3a UD |
41 | unsigned short int __msg_cbytes; /* current number of bytes on queue */ |
42 | unsigned short int msg_qnum; /* number of messages currently on queue */ | |
43 | unsigned short int msg_qbytes; /* max number of bytes allowed on queue */ | |
44 | __ipc_pid_t msg_lspid; /* pid of last msgsnd() */ | |
45 | __ipc_pid_t msg_lrpid; /* pid of last msgrcv() */ | |
46 | }; | |
47 | ||
48 | /* Allows to control internal state and destruction of message queue | |
49 | objects. */ | |
50 | int __new_msgctl (int, int, struct msqid_ds *); | |
51 | ||
52 | int | |
53 | __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) | |
54 | { | |
c7e41631 UD |
55 | /* This is a misnomer -- Alpha had 32-bit uids at the beginning |
56 | of time. However, msg_qnum and msg_qbytes changed size at | |
57 | the same time the size of uid changed elsewhere. */ | |
d6c5fe3a | 58 | #if __ASSUME_32BITUIDS > 0 |
d25c879d | 59 | return INLINE_SYSCALL (msgctl, 3, msqid, cmd | __IPC_64, CHECK_1 (buf)); |
d6c5fe3a UD |
60 | #else |
61 | switch (cmd) { | |
62 | case MSG_STAT: | |
63 | case IPC_STAT: | |
64 | case IPC_SET: | |
65 | break; | |
66 | default: | |
d25c879d | 67 | return INLINE_SYSCALL (msgctl, 3, msqid, cmd, CHECK_1 (buf)); |
d6c5fe3a UD |
68 | } |
69 | ||
70 | { | |
71 | int save_errno = errno, result; | |
72 | struct __old_msqid_ds old; | |
73 | ||
74 | /* Unfortunately there is no way how to find out for sure whether | |
75 | we should use old or new msgctl. */ | |
d25c879d | 76 | result = INLINE_SYSCALL (msgctl, 3, msqid, cmd | __IPC_64, CHECK_1 (buf)); |
d6c5fe3a UD |
77 | if (result != -1 || errno != EINVAL) |
78 | return result; | |
79 | ||
80 | __set_errno(save_errno); | |
81 | if (cmd == IPC_SET) | |
82 | { | |
83 | old.msg_perm.uid = buf->msg_perm.uid; | |
84 | old.msg_perm.gid = buf->msg_perm.gid; | |
85 | old.msg_perm.mode = buf->msg_perm.mode; | |
86 | old.msg_qbytes = buf->msg_qbytes; | |
87 | if (old.msg_perm.uid != buf->msg_perm.uid || | |
88 | old.msg_perm.gid != buf->msg_perm.gid || | |
89 | old.msg_qbytes != buf->msg_qbytes) | |
90 | { | |
91 | __set_errno (EINVAL); | |
92 | return -1; | |
93 | } | |
94 | } | |
d25c879d | 95 | result = INLINE_SYSCALL (msgctl, 3, msqid, cmd, __ptrvalue (&old)); |
d6c5fe3a UD |
96 | if (result != -1 && cmd != IPC_SET) |
97 | { | |
98 | memset(buf, 0, sizeof(*buf)); | |
99 | buf->msg_perm.__key = old.msg_perm.__key; | |
100 | buf->msg_perm.uid = old.msg_perm.uid; | |
101 | buf->msg_perm.gid = old.msg_perm.gid; | |
102 | buf->msg_perm.cuid = old.msg_perm.cuid; | |
103 | buf->msg_perm.cgid = old.msg_perm.cgid; | |
104 | buf->msg_perm.mode = old.msg_perm.mode; | |
105 | buf->msg_perm.__seq = old.msg_perm.__seq; | |
106 | buf->msg_stime = old.msg_stime; | |
107 | buf->msg_rtime = old.msg_rtime; | |
108 | buf->msg_ctime = old.msg_ctime; | |
109 | buf->__msg_cbytes = old.__msg_cbytes; | |
110 | buf->msg_qnum = old.msg_qnum; | |
111 | buf->msg_qbytes = old.msg_qbytes; | |
112 | buf->msg_lspid = old.msg_lspid; | |
113 | buf->msg_lrpid = old.msg_lrpid; | |
114 | } | |
115 | return result; | |
116 | } | |
117 | #endif | |
118 | } | |
119 | ||
b5567b2a UD |
120 | #include <shlib-compat.h> |
121 | versioned_symbol (libc, __new_msgctl, msgctl, GLIBC_2_2); |