Os: add ReceiveDatagram

Add a wrapper for recv(), which reads one datagram
from a socket. Add unit tests for the same.

While there:
- add NONNULL annotation to the |buf| argument of
  Os::Write()
- add some more tests for Os::Write()
- replace an instance of EBADFD with EBADF
  (the two errors are not necessarily the same,
  and the documentation for write() talks about
  EBADF, not EBADFD.)
- remove unnecessary ON_CALL in a test
  (in WriteWithOverlyLargeBufferCausesDeath,
  we expect to abort before calling RawOs::Write())

Bug: 32447384
Test: ./runtests.sh (on angler)
Change-Id: I1a8b7e94d415d5f63a2ccc842d292c6c65b85b09
diff --git a/os.cpp b/os.cpp
index d437066..ae8caca 100644
--- a/os.cpp
+++ b/os.cpp
@@ -58,6 +58,25 @@
   return now_timestamp;
 }
 
+std::tuple<size_t, Os::Errno> Os::ReceiveDatagram(int fd, void* buf,
+                                                  size_t buflen) {
+  // recv() takes a size_t, but returns an ssize_t. That means that the largest
+  // successful read that recv() can report is the maximal ssize_t. Passing a
+  // larger |buflen| risks mistakenly reporting a truncated read.
+  CHECK(buflen <= GetMaxVal<ssize_t>());
+
+  const ssize_t res = raw_os_->Recv(fd, buf, buflen, MSG_TRUNC);
+  if (res < 0) {
+    return {0, errno};
+  }
+
+  // Due to the MSG_TRUNC flag, |res| may reasonably be larger than
+  // |buflen|. In such cases, |res| indicates the full size of the datagram,
+  // before being truncated to fit our buffer. Hence, we omit the
+  // buffer-overflow CHECK that exists in Write().
+  return {res, 0};
+}
+
 std::tuple<size_t, Os::Errno> Os::Write(int fd, const void* buf,
                                         size_t buflen) {
   // write() takes a size_t, but returns an ssize_t. That means that the