15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 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 56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#ifndef __STDC_LIMIT_MACROS 66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#define __STDC_LIMIT_MACROS 76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif 86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/memfs/mem_fs_node.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <assert.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <algorithm> 16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "nacl_io/kernel_handle.h" 186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "nacl_io/osinttypes.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osstat.h" 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/auto_lock.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace nacl_io { 23ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace { 25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// The maximum size to reserve in addition to the requested size. Resize() will 27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// allocate twice as much as requested, up to this value. 28424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const size_t kMaxResizeIncrement = 16 * 1024 * 1024; 29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} // namespace 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)MemFsNode::MemFsNode(Filesystem* filesystem) 336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) : Node(filesystem), 346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) data_(NULL), 356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) data_capacity_(0) { 368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) SetType(S_IFREG); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)MemFsNode::~MemFsNode() { 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci free(data_); 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error MemFsNode::Read(const HandleAttr& attr, 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void* buf, 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t count, 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int* out_bytes) { 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *out_bytes = 0; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AUTO_LOCK(node_lock_); 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (count == 0) 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return 0; 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t size = stat_.st_size; 54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (attr.offs + count > size) { 564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) count = size - attr.offs; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) memcpy(buf, data_ + attr.offs, count); 60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *out_bytes = static_cast<int>(count); 61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return 0; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error MemFsNode::Write(const HandleAttr& attr, 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const void* buf, 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t count, 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int* out_bytes) { 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *out_bytes = 0; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (count == 0) 71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return 0; 72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) AUTO_LOCK(node_lock_); 746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) off_t new_size = attr.offs + count; 756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (new_size > stat_.st_size) { 766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Error error = Resize(new_size); 776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (error) { 786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) LOG_ERROR("memfs: resize (%" PRIoff ") failed: %s", new_size, 796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) strerror(error)); 806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return error; 816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) memcpy(data_ + attr.offs, buf, count); 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *out_bytes = static_cast<int>(count); 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return 0; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error MemFsNode::FTruncate(off_t new_size) { 90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) AUTO_LOCK(node_lock_); 916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return Resize(new_size); 92424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)Error MemFsNode::Resize(off_t new_length) { 956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (new_length < 0) 966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return EINVAL; 976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) size_t new_size = static_cast<size_t>(new_length); 986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t new_capacity = data_capacity_; 1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (new_size > data_capacity_) { 101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // While the node size is small, grow exponentially. When it starts to get 102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // larger, grow linearly. 1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) size_t extra = std::min(new_size, kMaxResizeIncrement); 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new_capacity = new_size + extra; 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (new_length < stat_.st_size) { 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Shrinking capacity 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new_capacity = new_size; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (new_capacity != data_capacity_) { 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci data_ = (char*)realloc(data_, new_capacity); 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (new_capacity != 0) { 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci assert(data_ != NULL); 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (data_ == NULL) 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return ENOMEM; 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci data_capacity_ = new_capacity; 1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (new_length > stat_.st_size) 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci memset(data_ + stat_.st_size, 0, new_length - stat_.st_size); 1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) stat_.st_size = new_length; 1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return 0; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciError MemFsNode::Fchmod(mode_t mode) { 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AUTO_LOCK(node_lock_); 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetMode(mode); 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return 0; 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} // namespace nacl_io 133