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