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.
5 #include "nacl_io/mount_node.h"
17 #include "nacl_io/kernel_handle.h"
18 #include "nacl_io/kernel_wrap_real.h"
19 #include "nacl_io/mount.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 MountNode::MountNode(Mount* mount) : mount_(mount) {
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 // Mount 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 mount_->OnNodeCreated(this);
42 MountNode::~MountNode() {}
44 Error MountNode::Init(int open_flags) {
48 void MountNode::Destroy() {
50 mount_->OnNodeDestroyed(this);
54 EventEmitter* MountNode::GetEventEmitter() { return NULL; }
56 uint32_t MountNode::GetEventStatus() {
57 if (GetEventEmitter())
58 return GetEventEmitter()->GetEventStatus();
60 return POLLIN | POLLOUT;
63 bool MountNode::CanOpen(int open_flags) {
64 switch (open_flags & 3) {
66 return (stat_.st_mode & S_IRALL) != 0;
68 return (stat_.st_mode & S_IWALL) != 0;
70 return (stat_.st_mode & S_IRALL) != 0 && (stat_.st_mode & S_IWALL) != 0;
76 Error MountNode::FSync() { return 0; }
78 Error MountNode::FTruncate(off_t length) { return EINVAL; }
80 Error MountNode::GetDents(size_t offs,
88 Error MountNode::GetStat(struct stat* pstat) {
89 AUTO_LOCK(node_lock_);
90 memcpy(pstat, &stat_, sizeof(stat_));
94 Error MountNode::Ioctl(int request, ...) {
96 va_start(ap, request);
97 Error rtn = VIoctl(request, ap);
102 Error MountNode::VIoctl(int request, va_list args) { return EINVAL; }
104 Error MountNode::Read(const HandleAttr& attr,
112 Error MountNode::Write(const HandleAttr& attr,
120 Error MountNode::MMap(void* addr,
128 // Never allow mmap'ing PROT_EXEC. The passthrough node supports this, but we
129 // don't. Fortunately, glibc will fallback if this fails, so dlopen will
131 if (prot & PROT_EXEC)
134 // This default mmap support is just enough to make dlopen work.
135 // This implementation just reads from the mount into the mmap'd memory area.
136 void* new_addr = addr;
137 int mmap_error = _real_mmap(
138 &new_addr, length, prot | PROT_WRITE, flags | MAP_ANONYMOUS, -1, 0);
139 if (new_addr == MAP_FAILED) {
140 _real_munmap(new_addr, length);
148 Error read_error = Read(data, new_addr, length, &bytes_read);
150 _real_munmap(new_addr, length);
154 *out_addr = new_addr;
158 Error MountNode::Tcflush(int queue_selector) {
162 Error MountNode::Tcgetattr(struct termios* termios_p) {
166 Error MountNode::Tcsetattr(int optional_actions,
167 const struct termios *termios_p) {
171 int MountNode::GetLinks() { return stat_.st_nlink; }
173 int MountNode::GetMode() { return stat_.st_mode & ~S_IFMT; }
175 Error MountNode::GetSize(size_t* out_size) {
176 *out_size = stat_.st_size;
180 int MountNode::GetType() { return stat_.st_mode & S_IFMT; }
182 void MountNode::SetType(int type) {
183 assert((type & ~S_IFMT) == 0);
184 stat_.st_mode &= ~S_IFMT;
185 stat_.st_mode |= type;
188 bool MountNode::IsaDir() { return (stat_.st_mode & S_IFDIR) != 0; }
190 bool MountNode::IsaFile() { return (stat_.st_mode & S_IFREG) != 0; }
192 bool MountNode::IsaSock() { return (stat_.st_mode & S_IFSOCK) != 0; }
194 bool MountNode::IsaTTY() { return (stat_.st_mode & S_IFCHR) != 0; }
196 Error MountNode::AddChild(const std::string& name,
197 const ScopedMountNode& node) {
201 Error MountNode::RemoveChild(const std::string& name) { return ENOTDIR; }
203 Error MountNode::FindChild(const std::string& name, ScopedMountNode* out_node) {
204 out_node->reset(NULL);
208 int MountNode::ChildCount() { return 0; }
210 void MountNode::Link() { stat_.st_nlink++; }
212 void MountNode::Unlink() { stat_.st_nlink--; }
214 } // namespace nacl_io