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 #include "nacl_io/node.h"
17 #include "nacl_io/filesystem.h"
18 #include "nacl_io/kernel_handle.h"
19 #include "nacl_io/kernel_wrap_real.h"
20 #include "nacl_io/osmman.h"
21 #include "sdk_util/auto_lock.h"
25 static const int USR_ID = 1001;
26 static const int GRP_ID = 1002;
28 Node::Node(Filesystem* filesystem) : filesystem_(filesystem) {
29 memset(&stat_, 0, sizeof(stat_));
30 stat_.st_gid = GRP_ID;
31 stat_.st_uid = USR_ID;
32 stat_.st_mode = S_IRALL | S_IWALL;
34 // Filesystem should normally never be NULL, but may be null in tests.
35 // If NULL, at least set the inode to a valid (nonzero) value.
37 filesystem_->OnNodeCreated(this);
44 Error Node::Init(int open_flags) { return 0; }
46 void Node::Destroy() {
48 filesystem_->OnNodeDestroyed(this);
52 EventEmitter* Node::GetEventEmitter() { return NULL; }
54 uint32_t Node::GetEventStatus() {
55 if (GetEventEmitter())
56 return GetEventEmitter()->GetEventStatus();
58 return POLLIN | POLLOUT;
61 bool Node::CanOpen(int open_flags) {
62 switch (open_flags & 3) {
64 return (stat_.st_mode & S_IRALL) != 0;
66 return (stat_.st_mode & S_IWALL) != 0;
68 return (stat_.st_mode & S_IRALL) != 0 && (stat_.st_mode & S_IWALL) != 0;
74 Error Node::FSync() { return 0; }
76 Error Node::FTruncate(off_t length) { return EINVAL; }
78 Error Node::GetDents(size_t offs,
86 Error Node::GetStat(struct stat* pstat) {
87 AUTO_LOCK(node_lock_);
88 memcpy(pstat, &stat_, sizeof(stat_));
92 Error Node::Ioctl(int request, ...) {
94 va_start(ap, request);
95 Error rtn = VIoctl(request, ap);
100 Error Node::VIoctl(int request, va_list args) { return EINVAL; }
102 Error Node::Read(const HandleAttr& attr,
110 Error Node::Write(const HandleAttr& attr,
118 Error Node::MMap(void* addr,
126 // Never allow mmap'ing PROT_EXEC. The passthrough node supports this, but we
127 // don't. Fortunately, glibc will fallback if this fails, so dlopen will
129 if (prot & PROT_EXEC)
132 // This default mmap support is just enough to make dlopen work. This
133 // implementation just reads from the filesystem into the mmap'd memory area.
134 void* new_addr = addr;
135 int mmap_error = _real_mmap(
136 &new_addr, length, prot | PROT_WRITE, flags | MAP_ANONYMOUS, -1, 0);
137 if (new_addr == MAP_FAILED) {
138 _real_munmap(new_addr, length);
146 Error read_error = Read(data, new_addr, length, &bytes_read);
148 _real_munmap(new_addr, length);
152 *out_addr = new_addr;
156 Error Node::Tcflush(int queue_selector) { return EINVAL; }
158 Error Node::Tcgetattr(struct termios* termios_p) { return EINVAL; }
160 Error Node::Tcsetattr(int optional_actions, const struct termios* termios_p) {
164 int Node::GetLinks() { return stat_.st_nlink; }
166 int Node::GetMode() { return stat_.st_mode & ~S_IFMT; }
168 Error Node::GetSize(off_t* out_size) {
169 *out_size = stat_.st_size;
173 int Node::GetType() { return stat_.st_mode & S_IFMT; }
175 void Node::SetType(int type) {
176 assert((type & ~S_IFMT) == 0);
177 stat_.st_mode &= ~S_IFMT;
178 stat_.st_mode |= type;
181 bool Node::IsaDir() { return (stat_.st_mode & S_IFDIR) != 0; }
183 bool Node::IsaFile() { return (stat_.st_mode & S_IFREG) != 0; }
185 bool Node::IsaSock() { return (stat_.st_mode & S_IFSOCK) != 0; }
187 Error Node::Isatty() {
191 Error Node::AddChild(const std::string& name, const ScopedNode& node) {
195 Error Node::RemoveChild(const std::string& name) { return ENOTDIR; }
197 Error Node::FindChild(const std::string& name, ScopedNode* out_node) {
198 out_node->reset(NULL);
202 int Node::ChildCount() { return 0; }
204 void Node::Link() { stat_.st_nlink++; }
206 void Node::Unlink() { stat_.st_nlink--; }
208 } // namespace nacl_io