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

Side by Side Diff: native_client_sdk/src/libraries/nacl_io/httpfs/http_fs.cc

Issue 547713002: [NaCl SDK] nacl_io: Always create directory node in http filesystem root. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/httpfs/http_fs.h" 5 #include "nacl_io/httpfs/http_fs.h"
6 6
7 #include <assert.h> 7 #include <assert.h>
8 #include <ctype.h> 8 #include <ctype.h>
9 #include <errno.h> 9 #include <errno.h>
10 #include <fcntl.h> 10 #include <fcntl.h>
(...skipping 24 matching lines...) Expand all
35 for (size_t i = 0; i < s.length(); ++i) { 35 for (size_t i = 0; i < s.length(); ++i) {
36 char c = s[i]; 36 char c = s[i];
37 result += upper ? toupper(c) : tolower(c); 37 result += upper ? toupper(c) : tolower(c);
38 upper = c == '-'; 38 upper = c == '-';
39 } 39 }
40 40
41 return result; 41 return result;
42 } 42 }
43 43
44 Error HttpFs::Access(const Path& path, int a_mode) { 44 Error HttpFs::Access(const Path& path, int a_mode) {
45 NodeMap_t::iterator iter = node_cache_.find(path.Join()); 45 ScopedNode node = FindExistingNode(path);
46 if (iter == node_cache_.end()) { 46 if (node.get() == NULL) {
47 // If we can't find the node in the cache, fetch it 47 // If we can't find the node in the cache, fetch it
48 std::string url = MakeUrl(path); 48 std::string url = MakeUrl(path);
49 ScopedNode node(new HttpFsNode(this, url, cache_content_)); 49 node.reset(new HttpFsNode(this, url, cache_content_));
50 Error error = node->Init(0); 50 Error error = node->Init(0);
51 if (error) 51 if (error)
52 return error; 52 return error;
53 53
54 error = node->GetStat(NULL); 54 error = node->GetStat(NULL);
55 if (error) 55 if (error)
56 return error; 56 return error;
57 } 57 }
58 58
59 // Don't allow write or execute access. 59 int obj_mode = node->GetMode();
60 if (a_mode & (W_OK | X_OK)) 60 if (((a_mode & R_OK) && !(obj_mode & S_IREAD)) ||
61 ((a_mode & W_OK) && !(obj_mode & S_IWRITE)) ||
62 ((a_mode & X_OK) && !(obj_mode & S_IEXEC))) {
61 return EACCES; 63 return EACCES;
64 }
62 65
63 return 0; 66 return 0;
64 } 67 }
65 68
66 Error HttpFs::Open(const Path& path, int open_flags, ScopedNode* out_node) { 69 Error HttpFs::Open(const Path& path, int open_flags, ScopedNode* out_node) {
67 out_node->reset(NULL); 70 out_node->reset(NULL);
68 71
69 NodeMap_t::iterator iter = node_cache_.find(path.Join()); 72 ScopedNode node = FindExistingNode(path);
70 if (iter != node_cache_.end()) { 73 if (node.get() != NULL) {
71 *out_node = iter->second; 74 *out_node = node;
72 return 0; 75 return 0;
73 } 76 }
74 77
75 // If we can't find the node in the cache, create it 78 // If we can't find the node in the cache, create it
76 std::string url = MakeUrl(path); 79 std::string url = MakeUrl(path);
77 ScopedNode node(new HttpFsNode(this, url, cache_content_)); 80 node.reset(new HttpFsNode(this, url, cache_content_));
78 Error error = node->Init(open_flags); 81 Error error = node->Init(open_flags);
79 if (error) 82 if (error)
80 return error; 83 return error;
81 84
82 error = node->GetStat(NULL); 85 error = node->GetStat(NULL);
83 if (error) 86 if (error)
84 return error; 87 return error;
85 88
86 ScopedNode parent; 89 ScopedNode parent;
87 error = FindOrCreateDir(path.Parent(), &parent); 90 error = FindOrCreateDir(path.Parent(), &parent);
88 if (error) 91 if (error)
89 return error; 92 return error;
90 93
91 error = parent->AddChild(path.Basename(), node); 94 error = parent->AddChild(path.Basename(), node);
92 if (error) 95 if (error)
93 return error; 96 return error;
94 97
95 node_cache_[path.Join()] = node; 98 node_cache_[path.Join()] = node;
96 *out_node = node; 99 *out_node = node;
97 return 0; 100 return 0;
98 } 101 }
99 102
100 Error HttpFs::Unlink(const Path& path) { 103 ScopedNode HttpFs::FindExistingNode(const Path& path) {
101 NodeMap_t::iterator iter = node_cache_.find(path.Join()); 104 NodeMap_t::iterator iter = node_cache_.find(path.Join());
102 if (iter == node_cache_.end()) 105 if (iter == node_cache_.end())
106 return ScopedNode();
107 return iter->second;
108 }
109
110 Error HttpFs::Unlink(const Path& path) {
111 ScopedNode node = FindExistingNode(path);
112 if (node.get() == NULL)
103 return ENOENT; 113 return ENOENT;
104 114
105 if (iter->second->IsaDir()) 115 if (node->IsaDir())
106 return EISDIR; 116 return EISDIR;
107 117
108 return EACCES; 118 return EACCES;
109 } 119 }
110 120
111 Error HttpFs::Mkdir(const Path& path, int permissions) { 121 Error HttpFs::Mkdir(const Path& path, int permissions) {
112 NodeMap_t::iterator iter = node_cache_.find(path.Join()); 122 ScopedNode node = FindExistingNode(path);
113 if (iter != node_cache_.end()) { 123 if (node.get() != NULL && node->IsaDir())
114 if (iter->second->IsaDir()) 124 return EEXIST;
115 return EEXIST; 125
116 }
117 return EACCES; 126 return EACCES;
118 } 127 }
119 128
120 Error HttpFs::Rmdir(const Path& path) { 129 Error HttpFs::Rmdir(const Path& path) {
121 NodeMap_t::iterator iter = node_cache_.find(path.Join()); 130 ScopedNode node = FindExistingNode(path);
122 if (iter == node_cache_.end()) 131 if (node.get() == NULL)
123 return ENOENT; 132 return ENOENT;
124 133
125 if (!iter->second->IsaDir()) 134 if (!node->IsaDir())
126 return ENOTDIR; 135 return ENOTDIR;
127 136
128 return EACCES; 137 return EACCES;
129 } 138 }
130 139
131 Error HttpFs::Remove(const Path& path) { 140 Error HttpFs::Remove(const Path& path) {
132 NodeMap_t::iterator iter = node_cache_.find(path.Join()); 141 ScopedNode node = FindExistingNode(path);
133 if (iter == node_cache_.end()) 142 if (node.get() == NULL)
134 return ENOENT; 143 return ENOENT;
135 144
136 return EACCES; 145 return EACCES;
137 } 146 }
138 147
139 Error HttpFs::Rename(const Path& path, const Path& newpath) { 148 Error HttpFs::Rename(const Path& path, const Path& newpath) {
140 NodeMap_t::iterator iter = node_cache_.find(path.Join()); 149 ScopedNode node = FindExistingNode(path);
141 if (iter == node_cache_.end()) 150 if (node.get() == NULL)
142 return ENOENT; 151 return ENOENT;
143 152
144 return EACCES; 153 return EACCES;
145 } 154 }
146 155
147 PP_Resource HttpFs::MakeUrlRequestInfo(const std::string& url, 156 PP_Resource HttpFs::MakeUrlRequestInfo(const std::string& url,
148 const char* method, 157 const char* method,
149 StringMap_t* additional_headers) { 158 StringMap_t* additional_headers) {
150 URLRequestInfoInterface* interface = ppapi_->GetURLRequestInfoInterface(); 159 URLRequestInfoInterface* interface = ppapi_->GetURLRequestInfoInterface();
151 VarInterface* var_interface = ppapi_->GetVarInterface(); 160 VarInterface* var_interface = ppapi_->GetVarInterface();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 PP_URLREQUESTPROPERTY_HEADERS, 199 PP_URLREQUESTPROPERTY_HEADERS,
191 var_interface->VarFromUtf8(headers.c_str(), headers.length())); 200 var_interface->VarFromUtf8(headers.c_str(), headers.length()));
192 201
193 return request_info; 202 return request_info;
194 } 203 }
195 204
196 HttpFs::HttpFs() 205 HttpFs::HttpFs()
197 : allow_cors_(false), 206 : allow_cors_(false),
198 allow_credentials_(false), 207 allow_credentials_(false),
199 cache_stat_(true), 208 cache_stat_(true),
200 cache_content_(true) { 209 cache_content_(true),
210 is_blob_url_(false) {
201 } 211 }
202 212
203 Error HttpFs::Init(const FsInitArgs& args) { 213 Error HttpFs::Init(const FsInitArgs& args) {
204 Error error = Filesystem::Init(args); 214 Error error = Filesystem::Init(args);
205 if (error) 215 if (error)
206 return error; 216 return error;
207 217
208 // Parse filesystem args. 218 // Parse filesystem args.
209 for (StringMap_t::const_iterator iter = args.string_map.begin(); 219 for (StringMap_t::const_iterator iter = args.string_map.begin();
210 iter != args.string_map.end(); 220 iter != args.string_map.end();
211 ++iter) { 221 ++iter) {
212 if (iter->first == "SOURCE") { 222 if (iter->first == "SOURCE") {
213 url_root_ = iter->second; 223 url_root_ = iter->second;
214 is_blob_url_ = strncmp(url_root_.c_str(), "blob:", 5) == 0; 224 is_blob_url_ = strncmp(url_root_.c_str(), "blob:", 5) == 0;
215 225
216 // Make sure url_root_ ends with a slash, except for blob URLs.
217 if (!is_blob_url_ && !url_root_.empty() &&
218 url_root_[url_root_.length() - 1] != '/') {
219 url_root_ += '/';
220 }
221 } else if (iter->first == "manifest") { 226 } else if (iter->first == "manifest") {
222 char* text; 227 char* text;
223 error = LoadManifest(iter->second, &text); 228 error = LoadManifest(iter->second, &text);
224 if (error) 229 if (error)
225 return error; 230 return error;
226 231
227 error = ParseManifest(text); 232 error = ParseManifest(text);
228 if (error) { 233 if (error) {
229 free(text); 234 free(text);
230 return error; 235 return error;
231 } 236 }
232 237
233 free(text); 238 free(text);
234 } else if (iter->first == "allow_cross_origin_requests") { 239 } else if (iter->first == "allow_cross_origin_requests") {
235 allow_cors_ = iter->second == "true"; 240 allow_cors_ = iter->second == "true";
236 } else if (iter->first == "allow_credentials") { 241 } else if (iter->first == "allow_credentials") {
237 allow_credentials_ = iter->second == "true"; 242 allow_credentials_ = iter->second == "true";
238 } else if (iter->first == "cache_stat") { 243 } else if (iter->first == "cache_stat") {
239 cache_stat_ = iter->second == "true"; 244 cache_stat_ = iter->second == "true";
240 } else if (iter->first == "cache_content") { 245 } else if (iter->first == "cache_content") {
241 cache_content_ = iter->second == "true"; 246 cache_content_ = iter->second == "true";
242 } else { 247 } else {
243 // Assume it is a header to pass to an HTTP request. 248 // Assume it is a header to pass to an HTTP request.
244 headers_[NormalizeHeaderKey(iter->first)] = iter->second; 249 headers_[NormalizeHeaderKey(iter->first)] = iter->second;
245 } 250 }
246 } 251 }
247 252
253 if (!is_blob_url_) {
254 if (!url_root_.empty() && url_root_[url_root_.length() - 1] != '/') {
255 // Make sure url_root_ ends with a slash, except for blob URLs.
256 url_root_ += '/';
257 }
258
259 ScopedNode root;
260 error = FindOrCreateDir(Path("/"), &root);
261 if (error)
262 return error;
263 }
264
248 return 0; 265 return 0;
249 } 266 }
250 267
251 void HttpFs::Destroy() { 268 void HttpFs::Destroy() {
252 } 269 }
253 270
254 Error HttpFs::FindOrCreateDir(const Path& path, ScopedNode* out_node) { 271 Error HttpFs::FindOrCreateDir(const Path& path, ScopedNode* out_node) {
255 out_node->reset(NULL); 272 out_node->reset(NULL);
256 std::string strpath = path.Join(); 273
257 NodeMap_t::iterator iter = node_cache_.find(strpath); 274 ScopedNode node = FindExistingNode(path);
258 if (iter != node_cache_.end()) { 275 if (node.get() != NULL) {
259 *out_node = iter->second; 276 *out_node = node;
260 return 0; 277 return 0;
261 } 278 }
262 279
263 // If the node does not exist, create it. 280 // If the node does not exist, create it.
264 ScopedNode node(new DirNode(this)); 281 node.reset(new DirNode(this));
265 Error error = node->Init(0); 282 Error error = node->Init(0);
266 if (error) 283 if (error)
267 return error; 284 return error;
285 // Directorys in http filesystems are never writable.
286 node->SetMode(node->GetMode() & ~S_IWALL);
268 287
269 // If not the root node, find the parent node and add it to the parent 288 // If not the root node, find the parent node and add it to the parent
270 if (!path.IsRoot()) { 289 if (!path.IsRoot()) {
271 ScopedNode parent; 290 ScopedNode parent;
272 error = FindOrCreateDir(path.Parent(), &parent); 291 error = FindOrCreateDir(path.Parent(), &parent);
273 if (error) 292 if (error)
274 return error; 293 return error;
275 294
276 error = parent->AddChild(path.Basename(), node); 295 error = parent->AddChild(path.Basename(), node);
277 if (error) 296 if (error)
278 return error; 297 return error;
279 } 298 }
280 299
281 // Add it to the node cache. 300 // Add it to the node cache.
282 node_cache_[strpath] = node; 301 node_cache_[path.Join()] = node;
283 *out_node = node; 302 *out_node = node;
284 return 0; 303 return 0;
285 } 304 }
286 305
287 Error HttpFs::ParseManifest(const char* text) { 306 Error HttpFs::ParseManifest(const char* text) {
288 std::vector<std::string> lines; 307 std::vector<std::string> lines;
289 sdk_util::SplitString(text, '\n', &lines); 308 sdk_util::SplitString(text, '\n', &lines);
290 309
291 for (size_t i = 0; i < lines.size(); i++) { 310 for (size_t i = 0; i < lines.size(); i++) {
292 std::vector<std::string> words; 311 std::vector<std::string> words;
(...skipping 11 matching lines...) Expand all
304 if (non_empty_words.size() == 3) { 323 if (non_empty_words.size() == 3) {
305 const std::string& modestr = non_empty_words[0]; 324 const std::string& modestr = non_empty_words[0];
306 const std::string& lenstr = non_empty_words[1]; 325 const std::string& lenstr = non_empty_words[1];
307 const std::string& name = non_empty_words[2]; 326 const std::string& name = non_empty_words[2];
308 327
309 assert(modestr.size() == 4); 328 assert(modestr.size() == 4);
310 assert(name[0] == '/'); 329 assert(name[0] == '/');
311 330
312 // Only support regular and streams for now 331 // Only support regular and streams for now
313 // Ignore EXEC bit 332 // Ignore EXEC bit
314 int mode = S_IFREG; 333 int type = 0;
315 switch (modestr[0]) { 334 switch (modestr[0]) {
316 case '-': 335 case '-':
317 mode = S_IFREG; 336 type = S_IFREG;
318 break; 337 break;
319 case 'c': 338 case 'c':
320 mode = S_IFCHR; 339 type = S_IFCHR;
321 break; 340 break;
322 default: 341 default:
323 LOG_ERROR("Unable to parse type %s for %s.", 342 LOG_ERROR("Unable to parse type %s for %s.",
324 modestr.c_str(), 343 modestr.c_str(),
325 name.c_str()); 344 name.c_str());
326 return EINVAL; 345 return EINVAL;
327 } 346 }
328 347
348 int mode = 0;
329 switch (modestr[1]) { 349 switch (modestr[1]) {
330 case '-': 350 case '-':
331 break; 351 break;
332 case 'r': 352 case 'r':
333 mode |= S_IRUSR | S_IRGRP | S_IROTH; 353 mode |= S_IRUSR | S_IRGRP | S_IROTH;
334 break; 354 break;
335 default: 355 default:
336 LOG_ERROR("Unable to parse read %s for %s.", 356 LOG_ERROR("Unable to parse read %s for %s.",
337 modestr.c_str(), 357 modestr.c_str(),
338 name.c_str()); 358 name.c_str());
(...skipping 10 matching lines...) Expand all
349 LOG_ERROR("Unable to parse write %s for %s.", 369 LOG_ERROR("Unable to parse write %s for %s.",
350 modestr.c_str(), 370 modestr.c_str(),
351 name.c_str()); 371 name.c_str());
352 return EINVAL; 372 return EINVAL;
353 } 373 }
354 374
355 Path path(name); 375 Path path(name);
356 std::string url = MakeUrl(path); 376 std::string url = MakeUrl(path);
357 377
358 HttpFsNode* http_node = new HttpFsNode(this, url, cache_content_); 378 HttpFsNode* http_node = new HttpFsNode(this, url, cache_content_);
359 http_node->SetMode(mode);
360 ScopedNode node(http_node); 379 ScopedNode node(http_node);
380 node->SetMode(mode);
381 node->SetType(type);
361 382
362 Error error = node->Init(0); 383 Error error = node->Init(0);
363 if (error) 384 if (error)
364 return error; 385 return error;
365 http_node->SetCachedSize(atoi(lenstr.c_str())); 386 http_node->SetCachedSize(atoi(lenstr.c_str()));
366 387
367 ScopedNode dir_node; 388 ScopedNode dir_node;
368 error = FindOrCreateDir(path.Parent(), &dir_node); 389 error = FindOrCreateDir(path.Parent(), &dir_node);
369 if (error) 390 if (error)
370 return error; 391 return error;
371 392
372 error = dir_node->AddChild(path.Basename(), node); 393 error = dir_node->AddChild(path.Basename(), node);
373 if (error) 394 if (error)
374 return error; 395 return error;
375 396
376 std::string pname = path.Join(); 397 node_cache_[path.Join()] = node;
377 node_cache_[pname] = node;
378 } 398 }
379 } 399 }
380 400
381 return 0; 401 return 0;
382 } 402 }
383 403
384 Error HttpFs::LoadManifest(const std::string& manifest_name, 404 Error HttpFs::LoadManifest(const std::string& manifest_name,
385 char** out_manifest) { 405 char** out_manifest) {
386 Path manifest_path(manifest_name); 406 Path manifest_path(manifest_name);
387 ScopedNode manifest_node; 407 ScopedNode manifest_node;
(...skipping 21 matching lines...) Expand all
409 *out_manifest = text; 429 *out_manifest = text;
410 return 0; 430 return 0;
411 } 431 }
412 432
413 std::string HttpFs::MakeUrl(const Path& path) { 433 std::string HttpFs::MakeUrl(const Path& path) {
414 return url_root_ + 434 return url_root_ +
415 (path.IsAbsolute() ? path.Range(1, path.Size()) : path.Join()); 435 (path.IsAbsolute() ? path.Range(1, path.Size()) : path.Join());
416 } 436 }
417 437
418 } // namespace nacl_io 438 } // namespace nacl_io
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698