- add sources.
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / libraries / nacl_io / mount_node.cc
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.h"
6
7 #include <assert.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <poll.h>
11 #include <string.h>
12 #include <sys/stat.h>
13
14 #include <algorithm>
15 #include <string>
16
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"
22
23 namespace nacl_io {
24
25 static const int USR_ID = 1001;
26 static const int GRP_ID = 1002;
27
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;
33
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.
36   if (mount_)
37     mount_->OnNodeCreated(this);
38   else
39     stat_.st_ino = 1;
40 }
41
42 MountNode::~MountNode() {}
43
44 Error MountNode::Init(int open_flags) {
45   return 0;
46 }
47
48 void MountNode::Destroy() {
49   if (mount_) {
50     mount_->OnNodeDestroyed(this);
51   }
52 }
53
54 EventEmitter* MountNode::GetEventEmitter() { return NULL; }
55
56 uint32_t MountNode::GetEventStatus() {
57   if (GetEventEmitter())
58     return GetEventEmitter()->GetEventStatus();
59
60   return POLLIN | POLLOUT;
61 }
62
63 bool MountNode::CanOpen(int open_flags) {
64   switch (open_flags & 3) {
65     case O_RDONLY:
66       return (stat_.st_mode & S_IRALL) != 0;
67     case O_WRONLY:
68       return (stat_.st_mode & S_IWALL) != 0;
69     case O_RDWR:
70       return (stat_.st_mode & S_IRALL) != 0 && (stat_.st_mode & S_IWALL) != 0;
71   }
72
73   return false;
74 }
75
76 Error MountNode::FSync() { return 0; }
77
78 Error MountNode::FTruncate(off_t length) { return EINVAL; }
79
80 Error MountNode::GetDents(size_t offs,
81                           struct dirent* pdir,
82                           size_t count,
83                           int* out_bytes) {
84   *out_bytes = 0;
85   return ENOTDIR;
86 }
87
88 Error MountNode::GetStat(struct stat* pstat) {
89   AUTO_LOCK(node_lock_);
90   memcpy(pstat, &stat_, sizeof(stat_));
91   return 0;
92 }
93
94 Error MountNode::Ioctl(int request, ...) {
95   va_list ap;
96   va_start(ap, request);
97   Error rtn = VIoctl(request, ap);
98   va_end(ap);
99   return rtn;
100 }
101
102 Error MountNode::VIoctl(int request, va_list args) { return EINVAL; }
103
104 Error MountNode::Read(const HandleAttr& attr,
105                       void* buf,
106                       size_t count,
107                       int* out_bytes) {
108   *out_bytes = 0;
109   return EINVAL;
110 }
111
112 Error MountNode::Write(const HandleAttr& attr,
113                        const void* buf,
114                        size_t count,
115                        int* out_bytes) {
116   *out_bytes = 0;
117   return EINVAL;
118 }
119
120 Error MountNode::MMap(void* addr,
121                       size_t length,
122                       int prot,
123                       int flags,
124                       size_t offset,
125                       void** out_addr) {
126   *out_addr = NULL;
127
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
130   // continue to work.
131   if (prot & PROT_EXEC)
132     return EPERM;
133
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);
141     return mmap_error;
142   }
143
144   HandleAttr data;
145   data.offs = offset;
146   data.flags = 0;
147   int bytes_read;
148   Error read_error = Read(data, new_addr, length, &bytes_read);
149   if (read_error) {
150     _real_munmap(new_addr, length);
151     return read_error;
152   }
153
154   *out_addr = new_addr;
155   return 0;
156 }
157
158 Error MountNode::Tcflush(int queue_selector) {
159   return EINVAL;
160 }
161
162 Error MountNode::Tcgetattr(struct termios* termios_p) {
163   return EINVAL;
164 }
165
166 Error MountNode::Tcsetattr(int optional_actions,
167                            const struct termios *termios_p) {
168   return EINVAL;
169 }
170
171 int MountNode::GetLinks() { return stat_.st_nlink; }
172
173 int MountNode::GetMode() { return stat_.st_mode & ~S_IFMT; }
174
175 Error MountNode::GetSize(size_t* out_size) {
176   *out_size = stat_.st_size;
177   return 0;
178 }
179
180 int MountNode::GetType() { return stat_.st_mode & S_IFMT; }
181
182 void MountNode::SetType(int type) {
183   assert((type & ~S_IFMT) == 0);
184   stat_.st_mode &= ~S_IFMT;
185   stat_.st_mode |= type;
186 }
187
188 bool MountNode::IsaDir() { return (stat_.st_mode & S_IFDIR) != 0; }
189
190 bool MountNode::IsaFile() { return (stat_.st_mode & S_IFREG) != 0; }
191
192 bool MountNode::IsaSock() { return (stat_.st_mode & S_IFSOCK) != 0; }
193
194 bool MountNode::IsaTTY() { return (stat_.st_mode & S_IFCHR) != 0; }
195
196 Error MountNode::AddChild(const std::string& name,
197                           const ScopedMountNode& node) {
198   return ENOTDIR;
199 }
200
201 Error MountNode::RemoveChild(const std::string& name) { return ENOTDIR; }
202
203 Error MountNode::FindChild(const std::string& name, ScopedMountNode* out_node) {
204   out_node->reset(NULL);
205   return ENOTDIR;
206 }
207
208 int MountNode::ChildCount() { return 0; }
209
210 void MountNode::Link() { stat_.st_nlink++; }
211
212 void MountNode::Unlink() { stat_.st_nlink--; }
213
214 }  // namespace nacl_io