ipc_helper.cpp revision f0a7bd033941e26e380232a0515e903cf8e678e5
1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "uds/ipc_helper.h"
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <alloca.h>
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <errno.h>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <log/log.h>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <poll.h>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <string.h>
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/inotify.h>
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/param.h>
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/socket.h>
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <algorithm>
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/service.h>
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/utility.h>
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace pdx {
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace uds {
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkouint32_t kMagicPreamble = 0x7564736d;  // 'udsm'.
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostruct MessagePreamble {
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  uint32_t magic{0};
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  uint32_t data_size{0};
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  uint32_t fd_count{0};
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> SendPayload::Send(int socket_fd) {
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return Send(socket_fd, nullptr);
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> SendPayload::Send(int socket_fd, const ucred* cred) {
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  MessagePreamble preamble;
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  preamble.magic = kMagicPreamble;
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  preamble.data_size = buffer_.size();
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  preamble.fd_count = file_handles_.size();
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ssize_t ret =
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      RETRY_EINTR(send(socket_fd, &preamble, sizeof(preamble), MSG_NOSIGNAL));
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (ret < 0)
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (ret != sizeof(preamble))
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(EIO);
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msghdr msg = {};
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  iovec recv_vect = {buffer_.data(), buffer_.size()};
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iov = &recv_vect;
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iovlen = 1;
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (cred || !file_handles_.empty()) {
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const size_t fd_bytes = file_handles_.size() * sizeof(int);
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    msg.msg_controllen = (cred ? CMSG_SPACE(sizeof(ucred)) : 0) +
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                         (fd_bytes == 0 ? 0 : CMSG_SPACE(fd_bytes));
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    msg.msg_control = alloca(msg.msg_controllen);
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    cmsghdr* control = CMSG_FIRSTHDR(&msg);
58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (cred) {
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control->cmsg_level = SOL_SOCKET;
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control->cmsg_type = SCM_CREDENTIALS;
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control->cmsg_len = CMSG_LEN(sizeof(ucred));
62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      memcpy(CMSG_DATA(control), cred, sizeof(ucred));
63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control = CMSG_NXTHDR(&msg, control);
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (fd_bytes) {
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control->cmsg_level = SOL_SOCKET;
68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control->cmsg_type = SCM_RIGHTS;
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      control->cmsg_len = CMSG_LEN(fd_bytes);
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      memcpy(CMSG_DATA(control), file_handles_.data(), fd_bytes);
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ret = RETRY_EINTR(sendmsg(socket_fd, &msg, MSG_NOSIGNAL));
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (ret < 0)
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (static_cast<size_t>(ret) != buffer_.size())
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(EIO);
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return {};
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// MessageWriter
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid* SendPayload::GetNextWriteBufferSection(size_t size) {
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return buffer_.grow_by(size);
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoOutputResourceMapper* SendPayload::GetOutputResourceMapper() { return this; }
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// OutputResourceMapper
90f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<FileReference> SendPayload::PushFileHandle(const LocalHandle& handle) {
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (handle) {
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const int ref = file_handles_.size();
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    file_handles_.push_back(handle.Get());
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ref;
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return handle.Get();
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
98e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
99e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
100f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<FileReference> SendPayload::PushFileHandle(
101f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    const BorrowedHandle& handle) {
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (handle) {
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const int ref = file_handles_.size();
104e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    file_handles_.push_back(handle.Get());
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ref;
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return handle.Get();
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
111f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<FileReference> SendPayload::PushFileHandle(const RemoteHandle& handle) {
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return handle.Get();
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
115f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<ChannelReference> SendPayload::PushChannelHandle(
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const LocalChannelHandle& /*handle*/) {
117f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return ErrorStatus{EOPNOTSUPP};
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
119f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<ChannelReference> SendPayload::PushChannelHandle(
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const BorrowedChannelHandle& /*handle*/) {
121f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return ErrorStatus{EOPNOTSUPP};
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
123f0a7bd033941e26e380232a0515e903cf8e678e5Alex VakulenkoStatus<ChannelReference> SendPayload::PushChannelHandle(
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const RemoteChannelHandle& /*handle*/) {
125f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  return ErrorStatus{EOPNOTSUPP};
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> ReceivePayload::Receive(int socket_fd) {
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return Receive(socket_fd, nullptr);
130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
132e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> ReceivePayload::Receive(int socket_fd, ucred* cred) {
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  MessagePreamble preamble;
134e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ssize_t ret =
135e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      RETRY_EINTR(recv(socket_fd, &preamble, sizeof(preamble), MSG_WAITALL));
136e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (ret < 0)
137e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
1386890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  else if (ret == 0)
1396890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    return ErrorStatus(ESHUTDOWN);
1406890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  else if (ret != sizeof(preamble) || preamble.magic != kMagicPreamble)
141e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(EIO);
142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
143e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  buffer_.resize(preamble.data_size);
144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  file_handles_.clear();
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  read_pos_ = 0;
146e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msghdr msg = {};
148e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  iovec recv_vect = {buffer_.data(), buffer_.size()};
149e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iov = &recv_vect;
150e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iovlen = 1;
151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (cred || preamble.fd_count) {
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const size_t receive_fd_bytes = preamble.fd_count * sizeof(int);
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    msg.msg_controllen =
155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        (cred ? CMSG_SPACE(sizeof(ucred)) : 0) +
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        (receive_fd_bytes == 0 ? 0 : CMSG_SPACE(receive_fd_bytes));
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    msg.msg_control = alloca(msg.msg_controllen);
158e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
159e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
160e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ret = RETRY_EINTR(recvmsg(socket_fd, &msg, MSG_WAITALL));
161e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (ret < 0)
162e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
1636890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  else if (ret == 0)
1646890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    return ErrorStatus(ESHUTDOWN);
1656890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  else if (static_cast<uint32_t>(ret) != preamble.data_size)
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(EIO);
167e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool cred_available = false;
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  file_handles_.reserve(preamble.fd_count);
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  while (cmsg) {
172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS &&
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        cred && cmsg->cmsg_len == CMSG_LEN(sizeof(ucred))) {
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      cred_available = true;
175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      memcpy(cred, CMSG_DATA(cmsg), sizeof(ucred));
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    } else if (cmsg->cmsg_level == SOL_SOCKET &&
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko               cmsg->cmsg_type == SCM_RIGHTS) {
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      socklen_t payload_len = cmsg->cmsg_len - CMSG_LEN(0);
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const int* fds = reinterpret_cast<const int*>(CMSG_DATA(cmsg));
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      size_t fd_count = payload_len / sizeof(int);
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      std::transform(fds, fds + fd_count, std::back_inserter(file_handles_),
182e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                     [](int fd) { return LocalHandle{fd}; });
183e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
184e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    cmsg = CMSG_NXTHDR(&msg, cmsg);
185e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (cred && !cred_available) {
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(EIO);
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return {};
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
194e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// MessageReader
195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoMessageReader::BufferSection ReceivePayload::GetNextReadBufferSection() {
196e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return {buffer_.data() + read_pos_, &*buffer_.end()};
197e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
198e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid ReceivePayload::ConsumeReadBufferSectionData(const void* new_start) {
200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  read_pos_ = PointerDistance(new_start, buffer_.data());
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoInputResourceMapper* ReceivePayload::GetInputResourceMapper() { return this; }
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// InputResourceMapper
206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool ReceivePayload::GetFileHandle(FileReference ref, LocalHandle* handle) {
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (ref < 0) {
208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    *handle = LocalHandle{ref};
209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return true;
210e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (static_cast<size_t>(ref) > file_handles_.size())
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return false;
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  *handle = std::move(file_handles_[ref]);
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return true;
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
217e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool ReceivePayload::GetChannelHandle(ChannelReference /*ref*/,
218e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                      LocalChannelHandle* /*handle*/) {
219e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return false;
220e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
222e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> SendData(int socket_fd, const void* data, size_t size) {
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ssize_t size_written = RETRY_EINTR(send(socket_fd, data, size, MSG_NOSIGNAL));
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (size_written < 0)
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (static_cast<size_t>(size_written) != size)
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(EIO);
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return {};
229e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
231e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> SendDataVector(int socket_fd, const iovec* data, size_t count) {
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msghdr msg = {};
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iov = const_cast<iovec*>(data);
234e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iovlen = count;
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ssize_t size_written = RETRY_EINTR(sendmsg(socket_fd, &msg, MSG_NOSIGNAL));
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (size_written < 0)
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
238e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (static_cast<size_t>(size_written) != CountVectorSize(data, count))
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(EIO);
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return {};
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
242e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
243e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> ReceiveData(int socket_fd, void* data, size_t size) {
244e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ssize_t size_read = RETRY_EINTR(recv(socket_fd, data, size, MSG_WAITALL));
245e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (size_read < 0)
246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
2476890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  else if (size_read == 0)
2486890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    return ErrorStatus(ESHUTDOWN);
2496890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  else if (static_cast<size_t>(size_read) != size)
250e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(EIO);
251e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return {};
252e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
253e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
254e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> ReceiveDataVector(int socket_fd, const iovec* data, size_t count) {
255e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msghdr msg = {};
256e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iov = const_cast<iovec*>(data);
257e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  msg.msg_iovlen = count;
258e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ssize_t size_read = RETRY_EINTR(recvmsg(socket_fd, &msg, MSG_WAITALL));
259e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (size_read < 0)
260e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
2616890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  else if (size_read == 0)
2626890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka    return ErrorStatus(ESHUTDOWN);
2636890d95ec8b96970202518b439bfa8ab2d9dbf77Corey Tabaka  else if (static_cast<size_t>(size_read) != CountVectorSize(data, count))
264e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(EIO);
265e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return {};
266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkosize_t CountVectorSize(const iovec* vector, size_t count) {
269e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return std::accumulate(
270e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      vector, vector + count, size_t{0},
271e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      [](size_t size, const iovec& vec) { return size + vec.iov_len; });
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
273e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
274e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid InitRequest(android::pdx::uds::RequestHeader<BorrowedHandle>* request,
275e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                 int opcode, uint32_t send_len, uint32_t max_recv_len,
276e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                 bool is_impulse) {
277e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->op = opcode;
278e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->cred.pid = getpid();
279e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->cred.uid = geteuid();
280e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->cred.gid = getegid();
281e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->send_len = send_len;
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->max_recv_len = max_recv_len;
283e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  request->is_impulse = is_impulse;
284e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
285e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoStatus<void> WaitForEndpoint(const std::string& endpoint_path,
287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                             int64_t timeout_ms) {
288e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Endpoint path must be absolute.
289e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (endpoint_path.empty() || endpoint_path.front() != '/')
290e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(EINVAL);
291e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create inotify fd.
293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle fd{inotify_init()};
294e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!fd)
295e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ErrorStatus(errno);
296e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
297e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Set the inotify fd to non-blocking.
298e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int ret = fcntl(fd.Get(), F_GETFL);
299e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  fcntl(fd.Get(), F_SETFL, ret | O_NONBLOCK);
300e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
301e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Setup the pollfd.
302e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  pollfd pfd = {fd.Get(), POLLIN, 0};
303e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
304e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Find locations of each path separator.
305e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<size_t> separators{0};  // The path is absolute, so '/' is at #0.
306e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t pos = endpoint_path.find('/', 1);
307e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  while (pos != std::string::npos) {
308e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    separators.push_back(pos);
309e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    pos = endpoint_path.find('/', pos + 1);
310e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
311e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  separators.push_back(endpoint_path.size());
312e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
313e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Walk down the path, checking for existence and waiting if needed.
314e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  pos = 1;
315e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t links = 0;
316e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::string current;
317e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  while (pos < separators.size() && links <= MAXSYMLINKS) {
318e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::string previous = current;
319e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    current = endpoint_path.substr(0, separators[pos]);
320e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
321e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Check for existence; proceed to setup a watch if not.
322e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (access(current.c_str(), F_OK) < 0) {
323e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (errno != ENOENT)
324e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        return ErrorStatus(errno);
325e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
326e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // Extract the name of the path component to wait for.
327e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      std::string next = current.substr(
328e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          separators[pos - 1] + 1, separators[pos] - separators[pos - 1] - 1);
329e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
330e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // Add a watch on the last existing directory we reach.
331e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      int wd = inotify_add_watch(
332e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          fd.Get(), previous.c_str(),
333e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          IN_CREATE | IN_DELETE_SELF | IN_MOVE_SELF | IN_MOVED_TO);
334e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (wd < 0) {
335e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (errno != ENOENT)
336e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          return ErrorStatus(errno);
337e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        // Restart at the beginning if previous was deleted.
338e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        links = 0;
339e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        current.clear();
340e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        pos = 1;
341e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        continue;
342e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
343e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
344e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // Make sure current didn't get created before the watch was added.
345e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ret = access(current.c_str(), F_OK);
346e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (ret < 0) {
347e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (errno != ENOENT)
348e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          return ErrorStatus(errno);
349e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
350e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        bool exit_poll = false;
351e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        while (!exit_poll) {
352e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          // Wait for an event or timeout.
353e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          ret = poll(&pfd, 1, timeout_ms);
354e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          if (ret <= 0)
355e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            return ErrorStatus(ret == 0 ? ETIMEDOUT : errno);
356e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
357e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          // Read events.
358e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          char buffer[sizeof(inotify_event) + NAME_MAX + 1];
359e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
360e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          ret = read(fd.Get(), buffer, sizeof(buffer));
361e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          if (ret < 0) {
362e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            if (errno == EAGAIN || errno == EWOULDBLOCK)
363e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              continue;
364e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            else
365e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              return ErrorStatus(errno);
366e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          } else if (static_cast<size_t>(ret) < sizeof(struct inotify_event)) {
367e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            return ErrorStatus(EIO);
368e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          }
369e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
370e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          auto* event = reinterpret_cast<const inotify_event*>(buffer);
371e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          auto* end = reinterpret_cast<const inotify_event*>(buffer + ret);
372e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          while (event < end) {
373e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            std::string event_for;
374e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            if (event->len > 0)
375e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              event_for = event->name;
376e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
377e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            if (event->mask & (IN_CREATE | IN_MOVED_TO)) {
378e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              // See if this is the droid we're looking for.
379e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              if (next == event_for) {
380e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                exit_poll = true;
381e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                break;
382e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              }
383e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            } else if (event->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) {
384e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              // Restart at the beginning if our watch dir is deleted.
385e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              links = 0;
386e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              current.clear();
387e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              pos = 0;
388e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              exit_poll = true;
389e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              break;
390e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            }
391e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
392e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            event = reinterpret_cast<const inotify_event*>(AdvancePointer(
393e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                event, sizeof(struct inotify_event) + event->len));
394e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          }  // while (event < end)
395e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        }    // while (!exit_poll)
396e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }      // Current dir doesn't exist.
397e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ret = inotify_rm_watch(fd.Get(), wd);
398e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (ret < 0 && errno != EINVAL)
399e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        return ErrorStatus(errno);
400e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }  // if (access(current.c_str(), F_OK) < 0)
401e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
402e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Check for symbolic link and update link count.
403e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    struct stat stat_buf;
404e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ret = lstat(current.c_str(), &stat_buf);
405e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (ret < 0 && errno != ENOENT)
406e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return ErrorStatus(errno);
407e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    else if (ret == 0 && S_ISLNK(stat_buf.st_mode))
408e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      links++;
409e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    pos++;
410e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }  // while (pos < separators.size() && links <= MAXSYMLINKS)
411e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
412e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return {};
413e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
414e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
415e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace uds
416e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace pdx
417e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
418