1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file.
4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_handle.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pthread.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/filesystem.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/node.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "nacl_io/osunistd.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/socket/socket_node.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "sdk_util/auto_lock.h"
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace nacl_io {
18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is only legal to construct a handle while the kernel lock is held.
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)KernelHandle::KernelHandle() : filesystem_(NULL), node_(NULL) {
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)KernelHandle::KernelHandle(const ScopedFilesystem& fs, const ScopedNode& node)
2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : filesystem_(fs), node_(node) {
2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochKernelHandle::~KernelHandle() {
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Force release order for cases where filesystem_ is not ref'd by mounting.
29ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  node_.reset(NULL);
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  filesystem_.reset(NULL);
31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
32ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns the SocketNode* if this node is a socket.
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SocketNode* KernelHandle::socket_node() {
353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (node_.get() && node_->IsaSock())
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return reinterpret_cast<SocketNode*>(node_.get());
373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return NULL;
383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)Error KernelHandle::Init(int open_flags) {
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  handle_attr_.flags = open_flags;
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!node_->CanOpen(open_flags)) {
448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return EACCES;
458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (open_flags & O_APPEND) {
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    Error error = node_->GetSize(&handle_attr_.offs);
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (error)
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return error;
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Error KernelHandle::Seek(off_t offset, int whence, off_t* out_offset) {
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // By default, don't move the offset.
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *out_offset = offset;
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  off_t base;
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  off_t node_size;
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AUTO_LOCK(handle_lock_);
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = node_->GetSize(&node_size);
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error)
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return error;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (whence) {
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case SEEK_SET:
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base = 0;
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case SEEK_CUR:
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base = handle_attr_.offs;
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case SEEK_END:
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base = node_size;
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    default:
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return -1;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (base + offset < 0)
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return EINVAL;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  off_t new_offset = base + offset;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Seeking past the end of the file will zero out the space between the old
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // end and the new end.
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_offset > node_size) {
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    error = node_->FTruncate(new_offset);
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (error)
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return EINVAL;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *out_offset = handle_attr_.offs = new_offset;
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochError KernelHandle::Read(void* buf, size_t nbytes, int* cnt) {
994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AUTO_LOCK(handle_lock_);
1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (OpenMode() == O_WRONLY)
1018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return EACCES;
1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = node_->Read(handle_attr_, buf, nbytes, cnt);
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (0 == error)
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    handle_attr_.offs += *cnt;
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return error;
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochError KernelHandle::Write(const void* buf, size_t nbytes, int* cnt) {
1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AUTO_LOCK(handle_lock_);
1108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (OpenMode() == O_RDONLY)
1118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return EACCES;
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = node_->Write(handle_attr_, buf, nbytes, cnt);
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (0 == error)
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    handle_attr_.offs += *cnt;
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return error;
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochError KernelHandle::GetDents(struct dirent* pdir, size_t nbytes, int* cnt) {
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AUTO_LOCK(handle_lock_);
1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error error = node_->GetDents(handle_attr_.offs, pdir, nbytes, cnt);
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (0 == error)
1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    handle_attr_.offs += *cnt;
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return error;
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)Error KernelHandle::Fcntl(int request, int* result, ...) {
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  va_list ap;
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  va_start(ap, result);
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Error rtn = VFcntl(request, result, ap);
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  va_end(ap);
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return rtn;
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)Error KernelHandle::VFcntl(int request, int* result, va_list args) {
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  switch (request) {
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case F_GETFL: {
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      *result = handle_attr_.flags;
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return 0;
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case F_SETFL: {
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      AUTO_LOCK(handle_lock_);
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      int flags = va_arg(args, int);
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (!(flags & O_APPEND) && (handle_attr_.flags & O_APPEND)) {
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        // Attempt to clear O_APPEND.
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return EPERM;
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Only certain flags are mutable
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const int mutable_flags = O_ASYNC | O_NONBLOCK;
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      flags &= mutable_flags;
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      handle_attr_.flags &= ~mutable_flags;
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      handle_attr_.flags |= flags;
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return 0;
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    default:
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      LOG_ERROR("Unsupported fcntl: %#x", request);
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      break;
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return ENOSYS;
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Error KernelHandle::Accept(PP_Resource* new_sock,
16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                           struct sockaddr* addr,
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           socklen_t* len) {
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SocketNode* sock = socket_node();
1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!sock)
1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return ENOTSOCK;
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AUTO_LOCK(handle_lock_);
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return sock->Accept(handle_attr_, new_sock, addr, len);
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)Error KernelHandle::Connect(const struct sockaddr* addr, socklen_t len) {
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SocketNode* sock = socket_node();
1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!sock)
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return ENOTSOCK;
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AUTO_LOCK(handle_lock_);
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return sock->Connect(handle_attr_, addr, len);
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)Error KernelHandle::Recv(void* buf, size_t len, int flags, int* out_len) {
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SocketNode* sock = socket_node();
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!sock)
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return ENOTSOCK;
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (OpenMode() == O_WRONLY)
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return EACCES;
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AUTO_LOCK(handle_lock_);
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return sock->Recv(handle_attr_, buf, len, flags, out_len);
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)Error KernelHandle::RecvFrom(void* buf,
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             size_t len,
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             int flags,
1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             struct sockaddr* src_addr,
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             socklen_t* addrlen,
1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             int* out_len) {
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SocketNode* sock = socket_node();
1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!sock)
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return ENOTSOCK;
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (OpenMode() == O_WRONLY)
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return EACCES;
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AUTO_LOCK(handle_lock_);
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return sock->RecvFrom(handle_attr_, buf, len, flags, src_addr, addrlen,
2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                        out_len);
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Error KernelHandle::Send(const void* buf, size_t len, int flags, int* out_len) {
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SocketNode* sock = socket_node();
2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!sock)
2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return ENOTSOCK;
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (OpenMode() == O_RDONLY)
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return EACCES;
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AUTO_LOCK(handle_lock_);
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return sock->Send(handle_attr_, buf, len, flags, out_len);
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)Error KernelHandle::SendTo(const void* buf,
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           size_t len,
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           int flags,
2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           const struct sockaddr* dest_addr,
2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           socklen_t addrlen,
2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           int* out_len) {
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SocketNode* sock = socket_node();
2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!sock)
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return ENOTSOCK;
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (OpenMode() == O_RDONLY)
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return EACCES;
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AUTO_LOCK(handle_lock_);
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return sock->SendTo(handle_attr_, buf, len, flags, dest_addr, addrlen,
2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                      out_len);
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
237ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}  // namespace nacl_io
238