1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "nacl_io/mount_node_mem.h" 6 7 #include <errno.h> 8 #include <string.h> 9 10 #include "nacl_io/osstat.h" 11 #include "sdk_util/auto_lock.h" 12 13 namespace nacl_io { 14 15 #define BLOCK_SIZE (1 << 16) 16 #define BLOCK_MASK (BLOCK_SIZE - 1) 17 18 MountNodeMem::MountNodeMem(Mount* mount) 19 : MountNode(mount), data_(NULL), capacity_(0) { 20 stat_.st_mode |= S_IFREG; 21 } 22 23 MountNodeMem::~MountNodeMem() { free(data_); } 24 25 Error MountNodeMem::Read(size_t offs, void* buf, size_t count, int* out_bytes) { 26 *out_bytes = 0; 27 28 AUTO_LOCK(node_lock_); 29 if (count == 0) 30 return 0; 31 32 size_t size = stat_.st_size; 33 34 if (offs + count > size) { 35 count = size - offs; 36 } 37 38 memcpy(buf, &data_[offs], count); 39 *out_bytes = static_cast<int>(count); 40 return 0; 41 } 42 43 Error MountNodeMem::Write(size_t offs, 44 const void* buf, 45 size_t count, 46 int* out_bytes) { 47 *out_bytes = 0; 48 AUTO_LOCK(node_lock_); 49 50 if (count == 0) 51 return 0; 52 53 if (count + offs > stat_.st_size) { 54 Error error = FTruncate(count + offs); 55 if (error) 56 return error; 57 58 count = stat_.st_size - offs; 59 } 60 61 memcpy(&data_[offs], buf, count); 62 *out_bytes = static_cast<int>(count); 63 return 0; 64 } 65 66 Error MountNodeMem::FTruncate(off_t new_size) { 67 size_t need = (new_size + BLOCK_MASK) & ~BLOCK_MASK; 68 size_t old_size = stat_.st_size; 69 70 // If the current capacity is correct, just adjust and return 71 if (need == capacity_) { 72 stat_.st_size = static_cast<off_t>(new_size); 73 return 0; 74 } 75 76 // Attempt to realloc the block 77 char* newdata = static_cast<char*>(realloc(data_, need)); 78 if (newdata != NULL) { 79 // Zero out new space. 80 if (new_size > old_size) 81 memset(newdata + old_size, 0, need - old_size); 82 83 data_ = newdata; 84 capacity_ = need; 85 stat_.st_size = static_cast<off_t>(new_size); 86 return 0; 87 } 88 89 // If we failed, then adjust size according to what we keep 90 if (new_size > capacity_) 91 new_size = capacity_; 92 93 // Update the size and return the new size 94 stat_.st_size = static_cast<off_t>(new_size); 95 return EIO; 96 } 97 98 } // namespace nacl_io 99 100