+ 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;
+ }
+ }
+ }