Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / native_client_sdk / src / libraries / nacl_io / memfs / mem_fs_node.cc
blob0040df3faeb8bb7203d737870fdc853e7798bd40
1 // Copyright 2013 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.
5 #ifndef __STDC_LIMIT_MACROS
6 #define __STDC_LIMIT_MACROS
7 #endif
9 #include "nacl_io/memfs/mem_fs_node.h"
11 #include <assert.h>
12 #include <errno.h>
13 #include <string.h>
15 #include <algorithm>
17 #include "nacl_io/kernel_handle.h"
18 #include "nacl_io/osinttypes.h"
19 #include "nacl_io/osstat.h"
20 #include "sdk_util/auto_lock.h"
22 namespace nacl_io {
24 namespace {
26 // The maximum size to reserve in addition to the requested size. Resize() will
27 // allocate twice as much as requested, up to this value.
28 const size_t kMaxResizeIncrement = 16 * 1024 * 1024;
30 } // namespace
32 MemFsNode::MemFsNode(Filesystem* filesystem)
33 : Node(filesystem),
34 data_(NULL),
35 data_capacity_(0) {
36 SetType(S_IFREG);
39 MemFsNode::~MemFsNode() {
42 Error MemFsNode::Read(const HandleAttr& attr,
43 void* buf,
44 size_t count,
45 int* out_bytes) {
46 *out_bytes = 0;
48 AUTO_LOCK(node_lock_);
49 if (count == 0)
50 return 0;
52 size_t size = stat_.st_size;
54 if (attr.offs + count > size) {
55 count = size - attr.offs;
58 memcpy(buf, data_ + attr.offs, count);
59 *out_bytes = static_cast<int>(count);
60 return 0;
63 Error MemFsNode::Write(const HandleAttr& attr,
64 const void* buf,
65 size_t count,
66 int* out_bytes) {
67 *out_bytes = 0;
69 if (count == 0)
70 return 0;
72 AUTO_LOCK(node_lock_);
73 off_t new_size = attr.offs + count;
74 if (new_size > stat_.st_size) {
75 Error error = Resize(new_size);
76 if (error) {
77 LOG_ERROR("memfs: resize (%" PRIoff ") failed: %s", new_size,
78 strerror(error));
79 return error;
83 memcpy(data_ + attr.offs, buf, count);
84 *out_bytes = static_cast<int>(count);
85 return 0;
88 Error MemFsNode::FTruncate(off_t new_size) {
89 AUTO_LOCK(node_lock_);
90 return Resize(new_size);
93 Error MemFsNode::Resize(off_t new_length) {
94 if (new_length < 0)
95 return EINVAL;
96 size_t new_size = static_cast<size_t>(new_length);
98 if (new_size > data_capacity_) {
99 // While the node size is small, grow exponentially. When it starts to get
100 // larger, grow linearly.
101 size_t extra = std::min(new_size, kMaxResizeIncrement);
102 data_capacity_ = new_size + extra;
103 } else {
104 data_capacity_ = new_size;
107 data_ = (char*)realloc(data_, data_capacity_);
108 if (data_capacity_ != 0) {
109 assert(data_ != NULL);
110 if (data_ == NULL)
111 return ENOMEM;
112 if (new_length > stat_.st_size)
113 memset(data_ + stat_.st_size, 0, new_length - stat_.st_size);
116 stat_.st_size = new_length;
117 return 0;
120 } // namespace nacl_io