Cygwin: AF_UNIX: adapt grab_admin_pkt to mqueues

Use peek_mqueue instead of peek_pipe, and remove the latter.  Use
mq_receive instead of NtReadFile.
This commit is contained in:
Ken Brown 2021-05-08 10:38:22 -04:00
parent 92a7d6b532
commit 9e3a04efb6
2 changed files with 49 additions and 80 deletions

View File

@ -1095,7 +1095,7 @@ class fhandler_socket_unix : public fhandler_socket
char get_type_char ();
void set_pipe_non_blocking (bool nonblocking);
int send_sock_info (bool from_bind);
int grab_admin_pkt ();
int grab_admin_pkt (bool peek = true);
int recv_peer_info ();
static NTSTATUS npfs_handle (HANDLE &nph);
int create_mqueue (bool listener = false);
@ -1107,7 +1107,6 @@ class fhandler_socket_unix : public fhandler_socket
int connect_pipe (PUNICODE_STRING pipe_name);
int listen_pipe ();
ssize_t peek_mqueue (char *buf, size_t buflen, bool nonblocking = true);
ULONG peek_pipe (PFILE_PIPE_PEEK_BUFFER pbuf, ULONG psize, HANDLE evt);
int disconnect_pipe (HANDLE ph);
/* The NULL pointer check is required for FS methods like fstat. When
called via stat or lstat, there's no shared memory, just a path in pc. */

View File

@ -673,72 +673,63 @@ fhandler_socket_unix::send_sock_info (bool from_bind)
return 0;
}
/* Checks if the next packet in the pipe is an administrative packet.
If so, it reads it from the pipe, handles it. Returns an error code. */
/* Reads an administrative packet from the pipe and handles it. If
PEEK is true, checks first to see if the next packet in the pipe is
an administrative packet; otherwise the caller must set io_lock and
check this. Returns an error code, but callers ignore it. */
int
fhandler_socket_unix::grab_admin_pkt ()
fhandler_socket_unix::grab_admin_pkt (bool peek)
{
HANDLE evt;
NTSTATUS status;
IO_STATUS_BLOCK io;
/* MAX_PATH is more than sufficient for admin packets. */
PFILE_PIPE_PEEK_BUFFER pbuf = (PFILE_PIPE_PEEK_BUFFER) alloca (MAX_PATH);
if (!(evt = create_event ()))
return 0;
io_lock ();
ULONG ret_len = peek_pipe (pbuf, MAX_PATH, evt);
if (pbuf->NumberOfMessages == 0 || ret_len < sizeof (af_unix_pkt_hdr_t))
af_unix_pkt_hdr_t *packet = (af_unix_pkt_hdr_t *) alloca (MAX_PATH);
ssize_t nr;
if (peek)
{
io_unlock ();
NtClose (evt);
return 0;
}
af_unix_pkt_hdr_t *packet = (af_unix_pkt_hdr_t *) pbuf->Data;
if (!packet->admin_pkt)
io_unlock ();
else
{
packet = (af_unix_pkt_hdr_t *) pbuf;
status = NtReadFile (get_handle (), evt, NULL, NULL, &io, packet,
MAX_PATH, NULL, NULL);
if (status == STATUS_PENDING)
io_lock ();
nr = peek_mqueue ((char *) packet, MAX_PATH);
if (nr < 0)
{
/* Very short-lived */
status = NtWaitForSingleObject (evt, FALSE, NULL);
if (NT_SUCCESS (status))
status = io.Status;
io_unlock ();
if (get_errno () == EAGAIN)
return 0;
return get_errno ();
}
io_unlock ();
if (NT_SUCCESS (status))
if (!packet->admin_pkt)
{
state_lock ();
if (packet->shut_info)
{
/* Peer's shutdown sends the SHUT flags as used by the peer.
They have to be reversed for our side. */
int shut_info = saw_shutdown ();
if (packet->shut_info & _SHUT_RECV)
shut_info |= _SHUT_SEND;
if (packet->shut_info & _SHUT_SEND)
shut_info |= _SHUT_RECV;
saw_shutdown (shut_info);
/* FIXME: anything else here? */
}
if (packet->name_len > 0)
peer_sun_path (AF_UNIX_PKT_NAME (packet), packet->name_len);
if (packet->cmsg_len > 0)
{
struct cmsghdr *cmsg = (struct cmsghdr *)
alloca (packet->cmsg_len);
memcpy (cmsg, AF_UNIX_PKT_CMSG (packet), packet->cmsg_len);
if (cmsg->cmsg_level == SOL_SOCKET
&& cmsg->cmsg_type == SCM_CREDENTIALS)
peer_cred ((struct ucred *) CMSG_DATA(cmsg));
}
state_unlock ();
io_unlock ();
return 0;
}
}
NtClose (evt);
nr = _mq_recv (get_mqd_in (), (char *) packet, MAX_PATH, 0);
io_unlock ();
if (nr < 0)
return get_errno ();
state_lock ();
if (packet->shut_info)
{
/* Peer's shutdown sends the SHUT flags as used by the peer.
They have to be reversed for our side. */
int shut_info = saw_shutdown ();
if (packet->shut_info & _SHUT_RECV)
shut_info |= _SHUT_SEND;
if (packet->shut_info & _SHUT_SEND)
shut_info |= _SHUT_RECV;
saw_shutdown (shut_info);
/* FIXME: anything else here? */
}
if (packet->name_len > 0)
peer_sun_path (AF_UNIX_PKT_NAME (packet), packet->name_len);
if (packet->cmsg_len > 0)
{
struct cmsghdr *cmsg = (struct cmsghdr *)
alloca (packet->cmsg_len);
memcpy (cmsg, AF_UNIX_PKT_CMSG (packet), packet->cmsg_len);
if (cmsg->cmsg_level == SOL_SOCKET
&& cmsg->cmsg_type == SCM_CREDENTIALS)
peer_cred ((struct ucred *) CMSG_DATA(cmsg));
}
state_unlock ();
return 0;
}
@ -1116,27 +1107,6 @@ fhandler_socket_unix::peek_mqueue (char *buf, size_t buflen, bool nonblocking)
return _mq_peek (get_mqd_in (), buf, buflen, nonblocking);
}
ULONG
fhandler_socket_unix::peek_pipe (PFILE_PIPE_PEEK_BUFFER pbuf, ULONG psize,
HANDLE evt)
{
NTSTATUS status;
IO_STATUS_BLOCK io;
status = NtFsControlFile (get_handle (), evt, NULL, NULL, &io,
FSCTL_PIPE_PEEK, NULL, 0, pbuf, psize);
if (status == STATUS_PENDING)
{
/* Very short-lived */
status = NtWaitForSingleObject (evt ?: get_handle (), FALSE, NULL);
if (NT_SUCCESS (status))
status = io.Status;
}
return NT_SUCCESS (status) ? (io.Information
- offsetof (FILE_PIPE_PEEK_BUFFER, Data))
: 0;
}
int
fhandler_socket_unix::disconnect_pipe (HANDLE ph)
{