Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(624)

Side by Side Diff: native_client_sdk/src/libraries/nacl_mounts/mount_mem.cc

Issue 9956156: Add mount sources for a MountNode (inode) (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file. 3 * found in the LICENSE file.
4 */ 4 */
5
6 #include <assert.h>
7 #include <dirent.h> 5 #include <dirent.h>
8 #include <errno.h> 6 #include <errno.h>
9 #include <fcntl.h> 7 #include <fcntl.h>
10 #include <sys/stat.h> 8 #include <sys/stat.h>
11 #include <string> 9 #include <string>
12 10
13 #include <vector> 11 #include "mount.h"
14
15 #include "mount_mem.h" 12 #include "mount_mem.h"
13 #include "mount_node.h"
14 #include "mount_node_dir.h"
15 #include "mount_node_mem.h"
16 #include "path.h" 16 #include "path.h"
17 #include "util/simple_auto_lock.h" 17
18 18 #include "auto_lock.h"
19 static const size_t s_blksize = 1024; 19 #include "ref_object.h"
20 20
21 class MountNodeMem { 21 MountMem::MountMem(int dev) :
binji 2012/04/16 22:43:05 nit: move : to next line, indent 4
noelallen1 2012/04/21 18:09:53 Done.
22 public: 22 Mount(dev),
23 MountNodeMem(int ino) { 23 root_(NULL),
24 ino_ = ino; 24 max_ino_(0) {
25 ref_count_ = 0; 25 }
26 data_ = NULL; 26
27 memset(&stat_, 0, sizeof(stat_)); 27 bool MountMem::Init(const std::string& args) {
28 Resize(s_blksize); 28 root_ = AllocatePath(_S_IREAD | _S_IWRITE);
29 }; 29 return (bool) (root_ != NULL);
30 30 }
31 size_t Size() const { 31
32 return stat_.st_size; 32 void MountMem::Destroy() {
33 } 33 if (root_)
34 34 root_->Release();
binji 2012/04/16 22:43:05 set root_ to NULL
noelallen1 2012/04/21 18:09:53 Done.
35 void Resize(size_t size) { 35 }
36 size_t cap = blocks_; 36
37 size_t req = (size + s_blksize - 1) / s_blksize; 37 MountNode *MountMem::AllocatePath(int mode) {
binji 2012/04/16 22:43:05 nit: swap * side
noelallen1 2012/04/21 18:09:53 Done.
38 38 ino_t ino = AllocateINO();
39 if ((req > cap) || (req < (cap / 2))) { 39
40 char *newdata = (char *) malloc(req * s_blksize); 40 // If we fail to initialize, let the smart pointer delete it
binji 2012/04/16 22:43:05 Where is the smart pointer?
noelallen1 2012/04/21 18:09:53 Done.
41 memcpy(newdata, data_, size); 41 MountNode *ptr = new MountNodeDir(this, ino, dev_);
binji 2012/04/16 22:43:05 nit: swap * side
noelallen1 2012/04/21 18:09:53 Done.
42 free(data_); 42 if (!ptr->Init(mode, 1002, 1003)) {
binji 2012/04/16 22:43:05 what are 1002, 1003?
noelallen1 2012/04/21 18:09:53 Done.
43 stat_.st_size = size; 43 ptr->Release();
44 data_ = newdata; 44 FreeINO(ino);
45 blocks_ = req; 45 return NULL;
46 }
47 return ptr;
48 }
49
50 MountNode *MountMem::AllocateData(int mode) {
binji 2012/04/16 22:43:05 nit: swap * side
noelallen1 2012/04/21 18:09:53 Done.
51 ino_t ino = AllocateINO();
52
53 // If we fail to initialize, let the smart pointer delete it
54 MountNode *ptr = new MountNodeMem(this, ino, dev_);
binji 2012/04/16 22:43:05 nit: swap * side
noelallen1 2012/04/21 18:09:53 Done.
55 if (!ptr->Init(mode, 1002, 1003)) {
56 ptr->Release();
57 FreeINO(ino);
58 return NULL;
59 }
60 return ptr;
61 }
62
63 void MountMem::ReleaseNode(MountNode* node) {
64 node->Release();
65 }
66
67 int MountMem::AllocateINO() {
68 if (inos_.size() == 0) {
69 max_ino_ += 8;
70 for (int a=0; a < 7; a++) {
binji 2012/04/16 22:43:05 nit: spaces around =
noelallen1 2012/04/21 18:09:53 Done.
71 inos_.push_back(max_ino_ - a);
46 } 72 }
47 } 73 }
48 74 return max_ino_ - 8;
binji 2012/04/16 22:43:05 How does this work? It doesn't look like anything
noelallen1 2012/04/21 18:09:53 Whoops. Fixed.
49 int ino_; 75 }
50 int ref_count_; 76
51 struct stat stat_; 77 void MountMem::FreeINO(int ino) {
52 void *data_; 78 inos_.push_back(ino);
53 size_t blocks_; 79 }
54 pthread_mutex_t lock_; 80
55 }; 81 MountNode *MountMem::FindNode(const Path& path, int type) {
binji 2012/04/16 22:43:05 Can we assert in debug versions that the lock is h
noelallen1 2012/04/21 18:09:53 Unless we specialize the lock, it won't tell us if
56 82 MountNode *node = root_;
binji 2012/04/16 22:43:05 nit: swap * side
noelallen1 2012/04/21 18:09:53 Done.
57 MountMem::MountMem() {} 83
58 MountMem::~MountMem() {} 84 // If there is no root there, we have an error
59 85 if (node == NULL) {
60 int MountMem::AddDirEntry(MountMemNode* dir_node, MountMemNode* obj_node, const char *name) { 86 errno = ENOTDIR;
61 if (strlen(name > 255)) { 87 return NULL;
88 }
89
90 // We are expecting an "absolute" path from this mount point
91 if (!path.IsAbsolute()) {
62 errno = EINVAL; 92 errno = EINVAL;
63 return -1; 93 return NULL;
64 } 94 }
65 95
66 struct dirent* d = (struct dirent *) dir_node->data_; 96 for (size_t index = 1; node && index < path.Size(); index++) {
67 size_t cnt = dir_node->Size() / sizeof(struct dirent); 97 // If not a directory, then we have an error so return.
68 size_t off; 98 if (!node->IsaDir()) {
69 99 errno = ENOTDIR;
70 // Find a free location 100 return NULL;
71 for (off = 0; off < cnt; off++) {
72 if (d->d_name[0] == 0) break;
73 d++;
74 }
75
76 // Otherwise regrow and take the last spot.
77 if (off == cnt) {
78 dir_node->Resize(dir_node->Size() + sizeof(struct dirent));
79 d = &((struct dirent *) dir_node->data_)[off];
80 }
81
82 strcpy(d->d_name, name);
83 d->d_ino = obj_node->ino_;
84 d->d_reclen = sizeof(dirent);
85 d->d_off = off * sizeof(dirent);
86
87 // Add a ref_count_ and link count for the directory
88 obj_node->Acquire();
89 obj_node->stat_.st_nlink++;
90 return 0;
91 }
92
93
94
95
96 int MountMem::DelDirEntry_locked(int dir_ino, const char *name) {
97 MountMemNode* dir_node = inodes_.At(dir_ino);
98 struct dirent* d = (struct dirent *) dir_node->data_;
99 size_t cnt = dir_node->Size() / sizeof(struct dirent);
100 size_t off = 0;
101
102 // Find a free location
103 for (off = 0; off < cnt; off++) {
104 if (!strcmp(d->d_name, name)) {
105 d->d_name[0] = 0;
106 obj_node->stat_.st_nlink--;
107 if (0 == --obj_node->ref_count_) FreeNode(obj_node->ino_);
108 dir_node->ref_count_--;
109 return 0;
110 } 101 }
111 } 102
112 103 // Find the child node
113 errno = ENOENT; 104 node = node->FindChild(path.Part(index));
114 return -1; 105 }
115 } 106
116 107 // If we can't find it, fail
117 MountNodeMem* MountMem::AcquireNode(int ino) { 108 if (NULL == node) return NULL;
118 SimpleAutoLock lock(&lock_); 109
119 MountNodeMem *node = inodes_.At(ino); 110 // If a directory is expected, but it's not a directory, then fail
120 if (node) node->ref_count_++; 111 if ((type & _S_IFDIR) && !node->IsaDir()) {
112 errno = ENOTDIR;
113 return NULL;
114 }
115
116 // If a file is expected, but it's not a file, then fail
117 if ((type & _S_IFREG) && node->IsaDir()) {
118 errno = EISDIR;
119 return NULL;
120 }
121
122 // We now have a valid directory object, so increment the ref count
binji 2012/04/16 22:43:05 Where do we increment a refcount?
noelallen1 2012/04/21 18:09:53 Bad comment, fixed.
123 // and return it.
121 return node; 124 return node;
122 } 125 }
123 126
124 void MountMem::ReleaseNode(MountMemNode* node) { 127 MountNode *MountMem::Open(const Path& path, int mode) {
binji 2012/04/16 22:43:05 nit: swap * side
noelallen1 2012/04/21 18:09:53 Done.
125 if (node) { 128 AutoLock lock(&lock_);
126 SimpleAutoLock lock(&lock_); 129 MountNode* node = FindNode(path);
127 if (--node->ref_count_) inodes_.Free(node->ino_);
128 }
129 }
130
131 void MountMem::Init(void) {
132 int root = inodes_.Alloc();
133
134 assert(root == 0);
135 AddDirEntry(root, root, "/");
136 }
137
138 int MountMem::Mkdir(const std::string& path, mode_t mode, struct stat *buf) {
139 SimpleAutoLock lock(&lock_);
140
141 int ino = AcquireNode(path);
142
143 // Make sure it doesn't already exist.
144 child = GetMemNode(path);
145 if (child) {
146 errno = EEXIST;
147 return -1;
148 }
149 // Get the parent node.
150 int parent_slot = GetParentSlot(path);
151 if (parent_slot == -1) {
152 errno = ENOENT;
153 return -1;
154 }
155 parent = slots_.At(parent_slot);
156 if (!parent->is_dir()) {
157 errno = ENOTDIR;
158 return -1;
159 }
160
161 // Create a new node
162 int slot = slots_.Alloc();
163 child = slots_.At(slot);
164 child->set_slot(slot);
165 child->set_mount(this);
166 child->set_is_dir(true);
167 Path p(path);
168 child->set_name(p.Last());
169 child->set_parent(parent_slot);
170 parent->AddChild(slot);
171 if (!buf) {
172 return 0;
173 }
174
175 return Stat(slot, buf);
176 }
177
178 int MountMem::Rmdir(int node) {
179 }
180
181 int MountMem::Chmod(int ino, int mode) {
182 MountMemNode* node = AcquireNode(ino);
183 130
184 if (NULL == node) { 131 if (NULL == node) {
185 errno = BADF; 132 // Now first find the parent directory to see if we can add it
186 return -1; 133 MountNode* parent = FindNode(path.Parent(), _S_IFDIR);
187 } 134 if (NULL == parent) return NULL;
188 135
189 node->stat_.st_mode = mode; 136 // If the node does not exist and we can't create it, fail
137 if ((mode & O_CREAT) == 0) return NULL;
138
139 // Otherwise, create it with a single refernece
140 mode = OpenModeToPermission(mode);
binji 2012/04/16 22:43:05 Is OpenModeToPermission new? I can't find it.
noelallen1 2012/04/21 18:09:53 A public static defined in the parent class.
141 node = AllocateData(mode);
142 if (NULL == node) return NULL;
143
binji 2012/04/16 22:43:05 nit: remove extra blank line
noelallen1 2012/04/21 18:09:53 Done.
144
145 if (parent->AddChild(path.Filename(), node) == -1) {
146 // Or if it fails, release it
147 node->Release();
148 return NULL;
149 }
150 return node;
151 }
152
153 // If we were expected to create it exclusively, fail
154 if (mode & O_EXCL) {
155 errno = EEXIST;
156 return NULL;
157 }
158
159 // Verify we got the requested permisions.
160 int req_mode = OpenModeToPermission(mode);
161 int obj_mode = node->GetMode() & OpenModeToPermission(_O_RDWR);
162 if ((obj_mode & req_mode) != req_mode) {
163 errno = EACCES;
164 return NULL;
165 }
166
167 // We opened it, so ref count it before passing it back.
168 node->Acquire();
169 return node;
170 }
171
172 int MountMem::Close(MountNode* node) {
173 AutoLock lock(&lock_);
174 node->Close();
190 ReleaseNode(node); 175 ReleaseNode(node);
191 return 0; 176 return 0;
192 } 177 }
193 178
194 int MountMem::Stat(int ino, struct stat *buf) { 179 int MountMem::Unlink(const Path& path) {
195 MountMemNode* node = AcquireNode(ino); 180 AutoLock lock(&lock_);
196 181 MountNode* parent = FindNode(path.Parent(), _S_IFDIR);
182
183 if (NULL == parent) return -1;
184
185 MountNode* child = parent->FindChild(path.Filename());
186 if (NULL == child) {
187 errno = ENOENT;
188 return -1;
189 }
190 if (child->IsaDir()) {
191 errno = EISDIR;
192 return -1;
193 }
194 return parent->RemoveChild(path.Filename());
195 }
196
197 int MountMem::Mkdir(const Path& path, int mode) {
198 AutoLock lock(&lock_);
199
200 // We expect a Mount "absolute" path
201 if (!path.IsAbsolute()) {
202 errno = ENOENT;
203 return -1;
204 }
205
206 // The root of the mount is already created by the mount
207 if (path.Size() == 1) {
208 errno = EEXIST;
209 return -1;
210 }
211
212 MountNode* parent = FindNode(path.Parent(), _S_IFDIR);
213 MountNode* node;
214
215 // If we failed to find the parent, the error code is already set.
216 if (NULL == parent) return -1;
217
218 node = parent->FindChild(path.Filename());
219 if (NULL != node) {
220 errno = EEXIST;
221 return -1;
222 }
223
224 // Otherwise, create a new node and attempt to add it
225 mode = OpenModeToPermission(mode);
226 node = AllocatePath(_S_IREAD | _S_IWRITE);
227 if (NULL == node) return -1;
228
229 if (parent->AddChild(path.Filename(), node) == -1) {
230 node->Release();
231 return -1;
232 }
233
234 node->Release();
binji 2012/04/16 22:43:05 Document this release
noelallen1 2012/04/21 18:09:53 Done.
235 return 0;
236 }
237
238 int MountMem::Rmdir(const Path& path) {
239 AutoLock lock(&lock_);
240
241 // We expect a Mount "absolute" path
242 if (!path.IsAbsolute()) {
243 errno = ENOENT;
244 return -1;
245 }
246
247 // The root of the mount is already created by the mount
248 if (path.Size() == 1) {
249 errno = EEXIST;
250 return -1;
251 }
252
253 MountNode* parent = FindNode(path.Parent(), _S_IFDIR);
254 MountNode* node;
255
256 // If we failed to find the parent, the error code is already set.
257 if (NULL == parent) return -1;
258
259 // Verify we find a child which is also a directory
260 node = parent->FindChild(path.Filename());
197 if (NULL == node) { 261 if (NULL == node) {
198 errno = BADF; 262 errno = ENOENT;
199 return -1; 263 return -1;
200 } 264 }
201 265 if (!node->IsaDir()) {
202 memcpy(buf, node->stat_, sizeof(struct stat)); 266 errno = ENOTDIR;
203 ReleaseNode(node); 267 return -1;
204 return 0; 268 }
205 } 269 if (node->ChildCount() > 0) {
206 270 errno = ENOTEMPTY;
207 int MountMem::Fsync(int ino) { 271 return -1;
208 // Acquire the node in case he node 272 }
209 MountMemNode* node = AcquireNode(ino); 273 return parent->RemoveChild(path.Filename());
210 if (node) { 274 }
211 ReleaseNode(node);
212 return 0
213 }
214
215 errno = BADF;
216 return -1;
217 }
218
219 int MountMem::Getdents(int ino, off_t offset, struct dirent *dirp, unsigned int count) {
220 MountMemNode* node = AcquireNode(ino);
221 if ((NULL == node) == 0) {
222 errno = EBADF;
223 return -1;
224 }
225
226 if ((node->stat_.st_mode & S_IFDIR) == 0) {
227 errno =ENOTDIR;
228 return -1;
229 }
230
231 if (offset + count > node->Size()) {
232 count = node->Size() - offset;
233 }
234
235 memcpy(dirp, &node->data_[offset], count);
236 return count;
237 }
238
239 ssize_t MountMem::Write(int ino, off_t offset, const void *buf, size_t count) {
240 MountMemNode* node = AcquireNode(ino);
241
242 if (NULL == node || (node->stat_.st_mode & S_IWUSER) == 0) {
243 errno = EBADF;
244 return -1;
245 }
246
247 if (offset + count > node->Size()) {
248 int err = node->Resize();
249 if (err) {
250 errno = err;
251 ReleaseNode(node);
252 return -1;
253 }
254 }
255
256 mempcy(&node->data_[offset], buf, count);
257 ReleaseNode(node);
258 return count;
259 }
260
261 ssize_t MountMem::Read(int ino, off_t offset, const void *buf, size_t count) {
262 MountMemNode* node = AcquireNode(ino);
263
264 if (NULL == node || (node->stat_.st_mode & S_IRUSER) == 0) {
265 errno = EBADF;
266 return -1;
267 }
268
269 if (offset + count > node->Size()) {
270 count = node->Size() - offset;
271 }
272
273 mempcy(buf, &node->data_[offset], count);
274 ReleaseNode(node);
275 return count;
276 }
277
278 int MountMem::Isatty(int ino) {
279 // Acquire the node in case he node array is in flux
280 MountMemNode* node = AcquireNode(ino);
281
282 if (node) {
283 errno = ENOTTY;
284 ReleaseNode(node);
285 }
286 else {
287 errno = BADF;
288 }
289 return 0;
290 }
291
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698