1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "nacl_io/jsfs/js_fs_node.h" 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <assert.h> 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <errno.h> 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <fcntl.h> 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <limits.h> 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <string.h> 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "nacl_io/jsfs/js_fs.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "nacl_io/kernel_handle.h" 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "nacl_io/log.h" 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "nacl_io/osdirent.h" 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "nacl_io/pepper_interface.h" 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "sdk_util/macros.h" 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace nacl_io { 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)JsFsNode::JsFsNode(Filesystem* filesystem, int32_t fd) 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : Node(filesystem), 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ppapi_(filesystem->ppapi()), 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) array_iface_(ppapi_->GetVarArrayInterface()), 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) buffer_iface_(ppapi_->GetVarArrayBufferInterface()), 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var_iface_(ppapi_->GetVarInterface()), 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) fd_(fd) { 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void JsFsNode::Destroy() { 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // TODO(binji): implement 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool JsFsNode::SendRequestAndWait(ScopedVar* out_response, 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* format, 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ...) { 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) va_list args; 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) va_start(args, format); 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool result = filesystem()->VSendRequestAndWait(out_response, format, args); 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) va_end(args); 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return result; 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)int JsFsNode::ScanVar(PP_Var var, const char* format, ...) { 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) va_list args; 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) va_start(args, format); 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int result = filesystem()->VScanVar(var, format, args); 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) va_end(args); 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return result; 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool JsFsNode::CanOpen(int open_flags) { 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) struct stat statbuf; 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error error = GetStat(&statbuf); 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (error) 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // GetStat cached the mode in stat_.st_mode. Forward to Node::CanOpen, 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // which will check this mode against open_flags. 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return Node::CanOpen(open_flags); 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFsNode::GetStat(struct stat* stat) { 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AUTO_LOCK(node_lock_); 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedVar response(ppapi_); 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!SendRequestAndWait(&response, "%s%d", "cmd", "fstat", "fildes", fd_)) { 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Failed to send request."); 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // TODO(binji): find out the size of bionic stat fields. 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(__native_client__) && !defined(__BIONIC__) 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(__GLIBC__) 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char* format = "%d%lld%d%d%d%d%lld%lld%lld%lld%lld%lld%lld"; 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#else 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char* format = "%d%lld%d%d%d%d%lld%lld%d%d%lld%lld%lld"; 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#else 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define FIELD(x) \ 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) assert(sizeof(stat->x) >= sizeof(int32_t)); \ 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) strcat(format, sizeof(stat->x) == sizeof(int64_t) ? "%lld" : "%d"); 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // For host builds, we'll build up the format string at runtime. 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) char format[100] = "%d"; // First field is "error". 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FIELD(st_ino); 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FIELD(st_mode); 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FIELD(st_nlink); 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FIELD(st_uid); 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FIELD(st_gid); 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FIELD(st_rdev); 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FIELD(st_size); 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FIELD(st_blksize); 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FIELD(st_blocks); 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FIELD(st_atime); 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FIELD(st_mtime); 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) FIELD(st_ctime); 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#undef FIELD 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int32_t error; 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int result = ScanVar(response.pp_var(), 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) format, 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "error", &error, 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "st_ino", &stat->st_ino, 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "st_mode", &stat->st_mode, 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "st_nlink", &stat->st_nlink, 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "st_uid", &stat->st_uid, 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "st_gid", &stat->st_gid, 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "st_rdev", &stat->st_rdev, 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "st_size", &stat->st_size, 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "st_blksize", &stat->st_blksize, 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "st_blocks", &stat->st_blocks, 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "st_atime", &stat->st_atime, 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "st_mtime", &stat->st_mtime, 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "st_ctime", &stat->st_ctime); 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (result >= 1 && error) 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return error; 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (result != 13) { 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR( 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "Expected \"st_*\" and \"error\" fields in response (should be 13 " 126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "total)."); 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) stat->st_dev = filesystem()->dev(); 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return 0; 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFsNode::GetSize(off_t* out_size) { 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *out_size = 0; 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) struct stat statbuf; 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error error = GetStat(&statbuf); 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (error) 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return error; 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *out_size = stat_.st_size; 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return 0; 145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFsNode::FSync() { 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AUTO_LOCK(node_lock_); 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedVar response(ppapi_); 151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!SendRequestAndWait(&response, "%s%d", "cmd", "fsync", "fildes", fd_)) { 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Failed to send request."); 153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return filesystem()->ErrorFromResponse(response); 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFsNode::FTruncate(off_t length) { 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AUTO_LOCK(node_lock_); 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedVar response(ppapi_); 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!SendRequestAndWait(&response, 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "%s%d%lld", "cmd", "ftruncate", "fildes", fd_, "length", length)) { 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Failed to send request."); 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return filesystem()->ErrorFromResponse(response); 170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFsNode::Read(const HandleAttr& attr, 173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* buf, 174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t count, 175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int* out_bytes) { 176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AUTO_LOCK(node_lock_); 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *out_bytes = 0; 179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedVar response(ppapi_); 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!SendRequestAndWait(&response, "%s%d%u%lld", 182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "cmd", "pread", 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "fildes", fd_, 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "nbyte", count, 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "offset", attr.offs)) { 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Failed to send request."); 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int32_t error; 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PP_Var buf_var; 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int result = 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScanVar(response.pp_var(), "%d%p", "error", &error, "buf", &buf_var); 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedVar scoped_buf_var(ppapi_, buf_var); 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (result >= 1 && error) 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return error; 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (result != 2) { 201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Expected \"error\" and \"buf\" fields in response."); 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (buf_var.type != PP_VARTYPE_ARRAY_BUFFER) { 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Expected \"buf\" to be an ArrayBuffer."); 207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint32_t src_buf_len; 211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!buffer_iface_->ByteLength(buf_var, &src_buf_len)) { 212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Unable to get byteLength of \"buf\"."); 213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (src_buf_len > count) 217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) src_buf_len = count; 218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* src_buf = buffer_iface_->Map(buf_var); 220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (src_buf == NULL) { 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Unable to map \"buf\"."); 222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) memcpy(buf, src_buf, src_buf_len); 226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *out_bytes = src_buf_len; 227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) buffer_iface_->Unmap(buf_var); 229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return 0; 231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFsNode::Write(const HandleAttr& attr, 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const void* buf, 235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t count, 236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int* out_bytes) { 237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AUTO_LOCK(node_lock_); 238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *out_bytes = 0; 240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PP_Var buf_var = buffer_iface_->Create(count); 242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedVar scoped_buf_var(ppapi_, buf_var); 243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (buf_var.type != PP_VARTYPE_ARRAY_BUFFER) { 245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Unable to create \"buf\" var."); 246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* dst_buf = buffer_iface_->Map(buf_var); 250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (dst_buf == NULL) { 251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Unable to map \"buf\"."); 252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) memcpy(dst_buf, buf, count); 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) buffer_iface_->Unmap(buf_var); 258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedVar response(ppapi_); 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!SendRequestAndWait(&response, "%s%d%p%u%lld", 261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "cmd", "pwrite", 262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "fildes", fd_, 263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "buf", &buf_var, 264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "nbyte", count, 265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "offset", attr.offs)) { 266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Failed to send request."); 267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int error; 271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint32_t nwrote; 272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int result = 273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScanVar(response.pp_var(), "%d%u", "error", &error, "nwrote", &nwrote); 274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (result >= 1 && error) 276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return error; 277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (result != 2) { 279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Expected \"error\" and \"nwrote\" fields in response."); 280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *out_bytes = nwrote; 284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return 0; 285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFsNode::GetDents(size_t offs, 288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) struct dirent* pdir, 289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t count, 290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int* out_bytes) { 291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AUTO_LOCK(node_lock_); 292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *out_bytes = 0; 294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Round to the nearest sizeof(dirent) and ask for that. 296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t first = offs / sizeof(dirent); 297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t last = (offs + count + sizeof(dirent) - 1) / sizeof(dirent); 298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedVar response(ppapi_); 300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!SendRequestAndWait(&response, "%s%d%u%u", 301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "cmd", "getdents", 302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "fildes", fd_, 303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "offs", first, 304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "count", last - first)) { 305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Failed to send request."); 306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int error; 310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PP_Var dirents_var; 311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int result = ScanVar( 312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) response.pp_var(), "%d%p", "error", &error, "dirents", &dirents_var); 313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedVar scoped_dirents_var(ppapi_, dirents_var); 315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (result >= 1 && error) 317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return error; 318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (result != 2) { 320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Expected \"error\" and \"dirents\" fields in response."); 321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (dirents_var.type != PP_VARTYPE_ARRAY) { 325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Expected \"dirents\" to be an Array."); 326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint32_t dirents_len = array_iface_->GetLength(dirents_var); 330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint32_t dirents_byte_len = dirents_len * sizeof(dirent); 331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Allocate enough full dirents to copy from. This makes it easier if, for 333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // some reason, we are reading unaligned dirents. 334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dirent* dirents = static_cast<dirent*>(malloc(dirents_byte_len)); 335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (uint32_t i = 0; i < dirents_len; ++i) { 337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PP_Var dirent_var = array_iface_->Get(dirents_var, i); 338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PP_Var d_name_var; 339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) result = ScanVar(dirent_var, 340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "%lld%p", 341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "d_ino", &dirents[i].d_ino, 342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) "d_name", &d_name_var); 343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedVar scoped_dirent_var(ppapi_, dirent_var); 344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedVar scoped_d_name_var(ppapi_, d_name_var); 345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (result != 2) { 347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Expected dirent[%d] to have \"d_ino\" and \"d_name\".", i); 348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) free(dirents); 349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return EINVAL; 350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uint32_t d_name_len; 353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* d_name = var_iface_->VarToUtf8(d_name_var, &d_name_len); 354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dirents[i].d_off = sizeof(dirent); 356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dirents[i].d_reclen = sizeof(dirent); 357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) strncpy(dirents[i].d_name, d_name, sizeof(dirents[i].d_name)); 358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t dirents_offs = offs - first * sizeof(dirent); 361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (dirents_offs + count > dirents_byte_len) 362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) count = dirents_byte_len - dirents_offs; 363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) memcpy(pdir, reinterpret_cast<const char*>(dirents) + dirents_offs, count); 365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *out_bytes = count; 366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) free(dirents); 368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return 0; 369f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace nacl_io 372