1 /* Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA. */
21 #include <sys/ioctl.h>
24 #include <mach/notify.h>
26 /* Symbol set of ioctl handler lists. If there are user-registered
27 handlers, one of these lists will contain them. The other lists are
28 handlers built into the library. */
32 struct ioctl_handler
*v
[0];
33 } _hurd_ioctl_handler_lists
;
36 /* Perform the I/O control operation specified by REQUEST on FD.
37 The actual type and use of ARG and the return value depend on REQUEST. */
39 DEFUN(__ioctl
, (fd
, request
),
40 int fd AND
unsigned long int request DOTS
)
42 /* Map individual type fields to Mach IPC types. */
43 static const int mach_types
[] =
44 { MACH_MSG_TYPE_CHAR
, MACH_MSG_TYPE_INTEGER_16
, MACH_MSG_TYPE_INTEGER_32
,
48 char msg
[sizeof (mach_msg_header_t
) + /* Header. */
49 sizeof (mach_msg_type_t
) + 4 + /* Return code. */
50 3 * (sizeof (mach_msg_type_t
) + (4 * 32))]; /* Argument data. */
51 mach_msg_header_t
*m
= (mach_msg_header_t
*) msg
;
52 mach_msg_type_t
*t
= (mach_msg_type_t
*) &m
[1];
60 #define io2mach_type(count, type) \
61 ((mach_msg_type_t) { mach_types[type], (type << 1) * 8, count, 1, 0, 0 })
63 /* Pack an argument into the message buffer. */
64 inline void in (unsigned int count
, unsigned int type
)
68 void *const p
= &t
[1];
69 const size_t len
= count
* (type
<< 1);
70 *t
= io2mach_type (count
, type
);
73 t
= p
+ ((len
+ sizeof (*t
) - 1) / sizeof (*t
) * sizeof (*t
));
77 /* Unpack the message buffer into the argument location. */
78 inline int out (unsigned int count
, unsigned int type
,
79 void *store
, void **update
)
83 const size_t len
= count
* (type
<< 1);
84 union { mach_msg_type_t t
; int i
; } ipctype
;
85 ipctype
.t
= io2mach_type (count
, type
);
86 if (*(int *) t
!= ipctype
.i
)
89 memcpy (t
, store
, len
);
92 t
= (void *) t
+ ((len
+ sizeof (*t
) - 1) / sizeof (*t
) * sizeof *t
);
99 va_start (ap
, request
);
100 arg
= va_arg (ap
, void *);
104 /* Check for a registered handler for REQUEST. */
107 const struct ioctl_handler
*h
;
109 for (i
= 0; i
< _hurd_ioctl_handler_lists
.n
; ++i
)
110 for (h
= _hurd_ioctl_handler_lists
.v
[i
]; h
!= NULL
; h
= h
->next
)
111 if (request
>= h
->first_request
&& request
<= h
->last_request
)
112 /* This handler groks REQUEST. Se lo puntamonos. */
113 return (*h
->handler
) (fd
, request
, arg
);
117 /* Pack the argument data. */
120 msgid
= 100000 + ((r
.__s
.group
<< 2) * 1000) + r
.__s
.command
;
122 in (r
.__t
.count0
, r
.__t
.type0
);
123 in (r
.__t
.count1
, r
.__t
.type1
);
124 in (r
.__t
.count2
, r
.__t
.type2
);
126 err
= _HURD_DPORT_USE
129 m
->msgh_size
= (char *) t
- msg
;
130 m
->msgh_remote_port
= port
;
131 m
->msgh_local_port
= __mig_reply_port ();
135 m
->msgh_bits
= ?; /* XXX */
137 _HURD_EINTR_RPC (port
, __mach_msg (m
, MACH_SEND_MSG
|MACH_RCV_MSG
,
138 m
->msgh_size
, sizeof (msg
),
140 MACH_MSG_TIMEOUT_NONE
,
146 case MACH_MSG_SUCCESS
:
148 case MACH_SEND_INVALID_REPLY
:
149 case MACH_RCV_INVALID_NAME
:
150 __mig_dealloc_reply_port ();
152 return __hurd_fail (err
);
155 if (m
->msgh_id
!= msgid
+ 100)
156 return __hurd_fail (m
->msgh_id
== MACH_NOTIFY_SEND_ONCE
?
157 MIG_SERVER_DIED
: MIG_REPLY_MISMATCH
);
159 if ((m
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) || /* XXX ? */
160 m
->msgh_size
!= (char *) t
- msg
)
161 return __hurd_fail (MIG_TYPE_ERROR
);
163 t
= (mach_msg_type_t
*) &m
[1];
164 if (out (1, _IOTS (sizeof (error_t
)), &err
, NULL
) ||
165 out (r
.__t
.count0
, r
.__t
.type0
, arg
, &arg
) ||
166 out (r
.__t
.count1
, r
.__t
.type2
, arg
, &arg
) ||
167 out (r
.__t
.count2
, r
.__t
.type2
, arg
, &arg
))
168 return __hurd_fail (MIG_TYPE_ERROR
);
171 return __hurd_fail (err
);