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

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

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

Powered by Google App Engine
This is Rietveld 408576698