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