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
9 #include "nacl_io/memfs/mem_fs_node.h"
17 #include "nacl_io/kernel_handle.h"
18 #include "nacl_io/osinttypes.h"
19 #include "nacl_io/osstat.h"
20 #include "nacl_io/ostime.h"
21 #include "sdk_util/auto_lock.h"
27 // The maximum size to reserve in addition to the requested size. Resize() will
28 // allocate twice as much as requested, up to this value.
29 const size_t kMaxResizeIncrement
= 16 * 1024 * 1024;
33 MemFsNode::MemFsNode(Filesystem
* filesystem
)
38 UpdateTime(UPDATE_ATIME
| UPDATE_MTIME
| UPDATE_CTIME
);
41 MemFsNode::~MemFsNode() {
45 Error
MemFsNode::Read(const HandleAttr
& attr
,
51 AUTO_LOCK(node_lock_
);
55 size_t size
= stat_
.st_size
;
57 if (attr
.offs
+ count
> size
) {
58 count
= size
- attr
.offs
;
62 UpdateTime(UPDATE_ATIME
);
65 memcpy(buf
, data_
+ attr
.offs
, count
);
66 *out_bytes
= static_cast<int>(count
);
70 Error
MemFsNode::Write(const HandleAttr
& attr
,
79 AUTO_LOCK(node_lock_
);
80 off_t new_size
= attr
.offs
+ count
;
81 if (new_size
> stat_
.st_size
) {
82 Error error
= Resize(new_size
);
84 LOG_ERROR("memfs: resize (%" PRIoff
") failed: %s", new_size
,
91 UpdateTime(UPDATE_MTIME
| UPDATE_CTIME
);
94 memcpy(data_
+ attr
.offs
, buf
, count
);
95 *out_bytes
= static_cast<int>(count
);
99 Error
MemFsNode::FTruncate(off_t new_size
) {
100 AUTO_LOCK(node_lock_
);
101 Error error
= Resize(new_size
);
103 UpdateTime(UPDATE_MTIME
| UPDATE_CTIME
);
108 Error
MemFsNode::Resize(off_t new_length
) {
111 size_t new_size
= static_cast<size_t>(new_length
);
113 size_t new_capacity
= data_capacity_
;
114 if (new_size
> data_capacity_
) {
115 // While the node size is small, grow exponentially. When it starts to get
116 // larger, grow linearly.
117 size_t extra
= std::min(new_size
, kMaxResizeIncrement
);
118 new_capacity
= new_size
+ extra
;
119 } else if (new_length
< stat_
.st_size
) {
120 // Shrinking capacity
121 new_capacity
= new_size
;
124 if (new_capacity
!= data_capacity_
) {
125 data_
= (char*)realloc(data_
, new_capacity
);
126 if (new_capacity
!= 0) {
127 assert(data_
!= NULL
);
131 data_capacity_
= new_capacity
;
134 if (new_length
> stat_
.st_size
)
135 memset(data_
+ stat_
.st_size
, 0, new_length
- stat_
.st_size
);
136 stat_
.st_size
= new_length
;
140 Error
MemFsNode::Futimens(const struct timespec times
[2]) {
141 AUTO_LOCK(node_lock_
);
142 stat_
.st_atime
= times
[0].tv_sec
;
143 stat_
.st_atimensec
= times
[0].tv_nsec
;
144 stat_
.st_mtime
= times
[1].tv_sec
;
145 stat_
.st_mtimensec
= times
[1].tv_nsec
;
149 Error
MemFsNode::Fchmod(mode_t mode
) {
150 AUTO_LOCK(node_lock_
);
152 UpdateTime(UPDATE_CTIME
);
156 } // namespace nacl_io