- if (mr == MACH_RCV_TOO_LARGE ) {
- if (option & MACH_RCV_LARGE) {
- /*
- * We need to inform the user-level code that it needs more
- * space. The value for how much space was returned in the
- * msize save area instead of the message (which was left on
- * the queue).
- */
- if (option & MACH_RCV_LARGE_IDENTITY) {
- if (copyout((char *) &self->ith_receiver_name,
- msg_addr + offsetof(mach_msg_user_header_t, msgh_local_port),
- sizeof(mach_port_name_t)))
- mr = MACH_RCV_INVALID_DATA;
- }
- if (copyout((char *) &self->ith_msize,
- msg_addr + offsetof(mach_msg_user_header_t, msgh_size),
- sizeof(mach_msg_size_t)))
- mr = MACH_RCV_INVALID_DATA;
- } else {
-
- /* discard importance in message */
- ipc_importance_clean(kmsg);
-
- if (msg_receive_error(kmsg, msg_addr, option, seqno, space)
- == MACH_RCV_INVALID_DATA)
- mr = MACH_RCV_INVALID_DATA;
- }
- }
- return mr;
+ if (mr == MACH_RCV_TOO_LARGE) {
+
+ /*
+ * If the receive operation occurs with MACH_RCV_LARGE set
+ * then no message was extracted from the queue, and the size
+ * and (optionally) receiver names were the only thing captured.
+ * Just copyout the size (and optional port name) in a fake
+ * header.
+ */
+ if (option & MACH_RCV_LARGE) {
+
+ if ((option & MACH_RCV_STACK) == 0 &&
+ rcv_size >= offsetof(mach_msg_user_header_t, msgh_reserved)) {
+
+ /*
+ * We need to inform the user-level code that it needs more
+ * space. The value for how much space was returned in the
+ * msize save area instead of the message (which was left on
+ * the queue).
+ */
+ if (option & MACH_RCV_LARGE_IDENTITY) {
+ if (copyout((char *) &self->ith_receiver_name,
+ rcv_addr + offsetof(mach_msg_user_header_t, msgh_local_port),
+ sizeof(mach_port_name_t)))
+ mr = MACH_RCV_INVALID_DATA;
+ }
+ if (copyout((char *) &self->ith_msize,
+ rcv_addr + offsetof(mach_msg_user_header_t, msgh_size),
+ sizeof(mach_msg_size_t)))
+ mr = MACH_RCV_INVALID_DATA;
+ }
+ } else {
+
+ /* discard importance in message */
+ ipc_importance_clean(kmsg);
+
+ if (msg_receive_error(kmsg, option, rcv_addr, rcv_size, seqno, space, &size)
+ == MACH_RCV_INVALID_DATA)
+ mr = MACH_RCV_INVALID_DATA;
+ }
+ }
+
+ if (sizep)
+ *sizep = size;
+ return mr;