OLD | NEW |
| (Empty) |
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_mounts/mount_mem.h" | |
6 | |
7 #include <errno.h> | |
8 #include <fcntl.h> | |
9 #include <string> | |
10 | |
11 #include "nacl_mounts/mount.h" | |
12 #include "nacl_mounts/mount_node.h" | |
13 #include "nacl_mounts/mount_node_dir.h" | |
14 #include "nacl_mounts/mount_node_mem.h" | |
15 #include "nacl_mounts/osstat.h" | |
16 #include "nacl_mounts/path.h" | |
17 #include "utils/auto_lock.h" | |
18 #include "utils/ref_object.h" | |
19 | |
20 // TODO(noelallen) : Grab/Redefine these in the kernel object once available. | |
21 #define USR_ID 1002 | |
22 #define GRP_ID 1003 | |
23 | |
24 MountMem::MountMem() | |
25 : root_(NULL), | |
26 max_ino_(0) { | |
27 } | |
28 | |
29 bool MountMem::Init(int dev, StringMap_t& args, PepperInterface* ppapi) { | |
30 Mount::Init(dev, args, ppapi); | |
31 root_ = AllocatePath(S_IREAD | S_IWRITE); | |
32 return (bool) (root_ != NULL); | |
33 } | |
34 | |
35 void MountMem::Destroy() { | |
36 if (root_) | |
37 root_->Release(); | |
38 root_ = NULL; | |
39 } | |
40 | |
41 MountNode* MountMem::AllocatePath(int mode) { | |
42 MountNode *ptr = new MountNodeDir(this); | |
43 if (!ptr->Init(mode)) { | |
44 ptr->Release(); | |
45 return NULL; | |
46 } | |
47 return ptr; | |
48 } | |
49 | |
50 MountNode* MountMem::AllocateData(int mode) { | |
51 MountNode* ptr = new MountNodeMem(this); | |
52 if (!ptr->Init(mode)) { | |
53 ptr->Release(); | |
54 return NULL; | |
55 } | |
56 return ptr; | |
57 } | |
58 | |
59 MountNode* MountMem::FindNode(const Path& path, int type) { | |
60 MountNode* node = root_; | |
61 | |
62 // If there is no root there, we have an error. | |
63 if (node == NULL) { | |
64 errno = ENOTDIR; | |
65 return NULL; | |
66 } | |
67 | |
68 // We are expecting an "absolute" path from this mount point. | |
69 if (!path.IsAbsolute()) { | |
70 errno = EINVAL; | |
71 return NULL; | |
72 } | |
73 | |
74 // Starting at the root, traverse the path parts. | |
75 for (size_t index = 1; node && index < path.Size(); index++) { | |
76 // If not a directory, then we have an error so return. | |
77 if (!node->IsaDir()) { | |
78 errno = ENOTDIR; | |
79 return NULL; | |
80 } | |
81 | |
82 // Find the child node | |
83 node = node->FindChild(path.Part(index)); | |
84 } | |
85 | |
86 // node should be root, a found child, or a failed 'FindChild' | |
87 // which already has the correct errno set. | |
88 if (NULL == node) return NULL; | |
89 | |
90 // If a directory is expected, but it's not a directory, then fail. | |
91 if ((type & S_IFDIR) && !node->IsaDir()) { | |
92 errno = ENOTDIR; | |
93 return NULL; | |
94 } | |
95 | |
96 // If a file is expected, but it's not a file, then fail. | |
97 if ((type & S_IFREG) && node->IsaDir()) { | |
98 errno = EISDIR; | |
99 return NULL; | |
100 } | |
101 | |
102 // We now have a valid object of the expected type, so return it. | |
103 return node; | |
104 } | |
105 | |
106 MountNode* MountMem::Open(const Path& path, int mode) { | |
107 AutoLock lock(&lock_); | |
108 MountNode* node = FindNode(path); | |
109 | |
110 if (NULL == node) { | |
111 // Now first find the parent directory to see if we can add it | |
112 MountNode* parent = FindNode(path.Parent(), S_IFDIR); | |
113 if (NULL == parent) return NULL; | |
114 | |
115 // If the node does not exist and we can't create it, fail | |
116 if ((mode & O_CREAT) == 0) return NULL; | |
117 | |
118 // Otherwise, create it with a single refernece | |
119 mode = OpenModeToPermission(mode); | |
120 node = AllocateData(mode); | |
121 if (NULL == node) return NULL; | |
122 | |
123 if (parent->AddChild(path.Basename(), node) == -1) { | |
124 // Or if it fails, release it | |
125 node->Release(); | |
126 return NULL; | |
127 } | |
128 return node; | |
129 } | |
130 | |
131 // If we were expected to create it exclusively, fail | |
132 if (mode & O_EXCL) { | |
133 errno = EEXIST; | |
134 return NULL; | |
135 } | |
136 | |
137 // Verify we got the requested permisions. | |
138 int req_mode = OpenModeToPermission(mode); | |
139 int obj_mode = node->GetMode() & OpenModeToPermission(O_RDWR); | |
140 if ((obj_mode & req_mode) != req_mode) { | |
141 errno = EACCES; | |
142 return NULL; | |
143 } | |
144 | |
145 // We opened it, so ref count it before passing it back. | |
146 node->Acquire(); | |
147 return node; | |
148 } | |
149 | |
150 int MountMem::Mkdir(const Path& path, int mode) { | |
151 AutoLock lock(&lock_); | |
152 | |
153 // We expect a Mount "absolute" path | |
154 if (!path.IsAbsolute()) { | |
155 errno = ENOENT; | |
156 return -1; | |
157 } | |
158 | |
159 // The root of the mount is already created by the mount | |
160 if (path.Size() == 1) { | |
161 errno = EEXIST; | |
162 return -1; | |
163 } | |
164 | |
165 MountNode* parent = FindNode(path.Parent(), S_IFDIR); | |
166 MountNode* node; | |
167 | |
168 // If we failed to find the parent, the error code is already set. | |
169 if (NULL == parent) return -1; | |
170 | |
171 node = parent->FindChild(path.Basename()); | |
172 if (NULL != node) { | |
173 errno = EEXIST; | |
174 return -1; | |
175 } | |
176 | |
177 // Otherwise, create a new node and attempt to add it | |
178 mode = OpenModeToPermission(mode); | |
179 | |
180 // Allocate a node, with a RefCount of 1. If added to the parent | |
181 // it will get ref counted again. In either case, release the | |
182 // recount we have on exit. | |
183 node = AllocatePath(S_IREAD | S_IWRITE); | |
184 if (NULL == node) return -1; | |
185 | |
186 if (parent->AddChild(path.Basename(), node) == -1) { | |
187 node->Release(); | |
188 return -1; | |
189 } | |
190 | |
191 node->Release(); | |
192 return 0; | |
193 } | |
194 | |
195 int MountMem::Unlink(const Path& path) { | |
196 return RemoveInternal(path, REMOVE_FILE); | |
197 } | |
198 | |
199 int MountMem::Rmdir(const Path& path) { | |
200 return RemoveInternal(path, REMOVE_DIR); | |
201 } | |
202 | |
203 int MountMem::Remove(const Path& path) { | |
204 return RemoveInternal(path, REMOVE_ALL); | |
205 } | |
206 | |
207 int MountMem::RemoveInternal(const Path& path, int remove_type) { | |
208 AutoLock lock(&lock_); | |
209 bool dir_only = remove_type == REMOVE_DIR; | |
210 bool file_only = remove_type == REMOVE_FILE; | |
211 bool remove_dir = (remove_type & REMOVE_DIR) != 0; | |
212 | |
213 if (dir_only) { | |
214 // We expect a Mount "absolute" path | |
215 if (!path.IsAbsolute()) { | |
216 errno = ENOENT; | |
217 return -1; | |
218 } | |
219 | |
220 // The root of the mount is already created by the mount | |
221 if (path.Size() == 1) { | |
222 errno = EEXIST; | |
223 return -1; | |
224 } | |
225 } | |
226 | |
227 MountNode* parent = FindNode(path.Parent(), S_IFDIR); | |
228 | |
229 // If we failed to find the parent, the error code is already set. | |
230 if (NULL == parent) return -1; | |
231 | |
232 // Verify we find a child which is a directory. | |
233 MountNode* child = parent->FindChild(path.Basename()); | |
234 if (NULL == child) { | |
235 errno = ENOENT; | |
236 return -1; | |
237 } | |
238 if (dir_only && !child->IsaDir()) { | |
239 errno = ENOTDIR; | |
240 return -1; | |
241 } | |
242 if (file_only && child->IsaDir()) { | |
243 errno = EISDIR; | |
244 return -1; | |
245 } | |
246 if (remove_dir && child->ChildCount() > 0) { | |
247 errno = ENOTEMPTY; | |
248 return -1; | |
249 } | |
250 return parent->RemoveChild(path.Basename()); | |
251 } | |
OLD | NEW |