Index: native_client_sdk/src/libraries/nacl_io/httpfs/http_fs.cc |
diff --git a/native_client_sdk/src/libraries/nacl_io/httpfs/http_fs.cc b/native_client_sdk/src/libraries/nacl_io/httpfs/http_fs.cc |
index cc44cfa0ba20959a22108b812f4e42867127bb2e..67dcc489f0faa18c37dc2d9036755f07275a98a8 100644 |
--- a/native_client_sdk/src/libraries/nacl_io/httpfs/http_fs.cc |
+++ b/native_client_sdk/src/libraries/nacl_io/httpfs/http_fs.cc |
@@ -42,11 +42,11 @@ std::string NormalizeHeaderKey(const std::string& s) { |
} |
Error HttpFs::Access(const Path& path, int a_mode) { |
- NodeMap_t::iterator iter = node_cache_.find(path.Join()); |
- if (iter == node_cache_.end()) { |
+ ScopedNode node = FindExistingNode(path); |
+ if (node.get() == NULL) { |
// If we can't find the node in the cache, fetch it |
std::string url = MakeUrl(path); |
- ScopedNode node(new HttpFsNode(this, url, cache_content_)); |
+ node.reset(new HttpFsNode(this, url, cache_content_)); |
Error error = node->Init(0); |
if (error) |
return error; |
@@ -56,9 +56,12 @@ Error HttpFs::Access(const Path& path, int a_mode) { |
return error; |
} |
- // Don't allow write or execute access. |
- if (a_mode & (W_OK | X_OK)) |
+ int obj_mode = node->GetMode(); |
+ if (((a_mode & R_OK) && !(obj_mode & S_IREAD)) || |
+ ((a_mode & W_OK) && !(obj_mode & S_IWRITE)) || |
+ ((a_mode & X_OK) && !(obj_mode & S_IEXEC))) { |
return EACCES; |
+ } |
return 0; |
} |
@@ -66,15 +69,15 @@ Error HttpFs::Access(const Path& path, int a_mode) { |
Error HttpFs::Open(const Path& path, int open_flags, ScopedNode* out_node) { |
out_node->reset(NULL); |
- NodeMap_t::iterator iter = node_cache_.find(path.Join()); |
- if (iter != node_cache_.end()) { |
- *out_node = iter->second; |
+ ScopedNode node = FindExistingNode(path); |
+ if (node.get() != NULL) { |
+ *out_node = node; |
return 0; |
} |
// If we can't find the node in the cache, create it |
std::string url = MakeUrl(path); |
- ScopedNode node(new HttpFsNode(this, url, cache_content_)); |
+ node.reset(new HttpFsNode(this, url, cache_content_)); |
Error error = node->Init(open_flags); |
if (error) |
return error; |
@@ -97,48 +100,54 @@ Error HttpFs::Open(const Path& path, int open_flags, ScopedNode* out_node) { |
return 0; |
} |
-Error HttpFs::Unlink(const Path& path) { |
+ScopedNode HttpFs::FindExistingNode(const Path& path) { |
NodeMap_t::iterator iter = node_cache_.find(path.Join()); |
if (iter == node_cache_.end()) |
+ return ScopedNode(); |
+ return iter->second; |
+} |
+ |
+Error HttpFs::Unlink(const Path& path) { |
+ ScopedNode node = FindExistingNode(path); |
+ if (node.get() == NULL) |
return ENOENT; |
- if (iter->second->IsaDir()) |
+ if (node->IsaDir()) |
return EISDIR; |
return EACCES; |
} |
Error HttpFs::Mkdir(const Path& path, int permissions) { |
- NodeMap_t::iterator iter = node_cache_.find(path.Join()); |
- if (iter != node_cache_.end()) { |
- if (iter->second->IsaDir()) |
- return EEXIST; |
- } |
+ ScopedNode node = FindExistingNode(path); |
+ if (node.get() != NULL && node->IsaDir()) |
+ return EEXIST; |
+ |
return EACCES; |
} |
Error HttpFs::Rmdir(const Path& path) { |
- NodeMap_t::iterator iter = node_cache_.find(path.Join()); |
- if (iter == node_cache_.end()) |
+ ScopedNode node = FindExistingNode(path); |
+ if (node.get() == NULL) |
return ENOENT; |
- if (!iter->second->IsaDir()) |
+ if (!node->IsaDir()) |
return ENOTDIR; |
return EACCES; |
} |
Error HttpFs::Remove(const Path& path) { |
- NodeMap_t::iterator iter = node_cache_.find(path.Join()); |
- if (iter == node_cache_.end()) |
+ ScopedNode node = FindExistingNode(path); |
+ if (node.get() == NULL) |
return ENOENT; |
return EACCES; |
} |
Error HttpFs::Rename(const Path& path, const Path& newpath) { |
- NodeMap_t::iterator iter = node_cache_.find(path.Join()); |
- if (iter == node_cache_.end()) |
+ ScopedNode node = FindExistingNode(path); |
+ if (node.get() == NULL) |
return ENOENT; |
return EACCES; |
@@ -197,7 +206,8 @@ HttpFs::HttpFs() |
: allow_cors_(false), |
allow_credentials_(false), |
cache_stat_(true), |
- cache_content_(true) { |
+ cache_content_(true), |
+ is_blob_url_(false) { |
} |
Error HttpFs::Init(const FsInitArgs& args) { |
@@ -213,11 +223,6 @@ Error HttpFs::Init(const FsInitArgs& args) { |
url_root_ = iter->second; |
is_blob_url_ = strncmp(url_root_.c_str(), "blob:", 5) == 0; |
- // Make sure url_root_ ends with a slash, except for blob URLs. |
- if (!is_blob_url_ && !url_root_.empty() && |
- url_root_[url_root_.length() - 1] != '/') { |
- url_root_ += '/'; |
- } |
} else if (iter->first == "manifest") { |
char* text; |
error = LoadManifest(iter->second, &text); |
@@ -245,6 +250,18 @@ Error HttpFs::Init(const FsInitArgs& args) { |
} |
} |
+ if (!is_blob_url_) { |
+ if (!url_root_.empty() && url_root_[url_root_.length() - 1] != '/') { |
+ // Make sure url_root_ ends with a slash, except for blob URLs. |
+ url_root_ += '/'; |
+ } |
+ |
+ ScopedNode root; |
+ error = FindOrCreateDir(Path("/"), &root); |
+ if (error) |
+ return error; |
+ } |
+ |
return 0; |
} |
@@ -253,18 +270,20 @@ void HttpFs::Destroy() { |
Error HttpFs::FindOrCreateDir(const Path& path, ScopedNode* out_node) { |
out_node->reset(NULL); |
- std::string strpath = path.Join(); |
- NodeMap_t::iterator iter = node_cache_.find(strpath); |
- if (iter != node_cache_.end()) { |
- *out_node = iter->second; |
+ |
+ ScopedNode node = FindExistingNode(path); |
+ if (node.get() != NULL) { |
+ *out_node = node; |
return 0; |
} |
// If the node does not exist, create it. |
- ScopedNode node(new DirNode(this)); |
+ node.reset(new DirNode(this)); |
Error error = node->Init(0); |
if (error) |
return error; |
+ // Directorys in http filesystems are never writable. |
+ node->SetMode(node->GetMode() & ~S_IWALL); |
// If not the root node, find the parent node and add it to the parent |
if (!path.IsRoot()) { |
@@ -279,7 +298,7 @@ Error HttpFs::FindOrCreateDir(const Path& path, ScopedNode* out_node) { |
} |
// Add it to the node cache. |
- node_cache_[strpath] = node; |
+ node_cache_[path.Join()] = node; |
*out_node = node; |
return 0; |
} |
@@ -311,13 +330,13 @@ Error HttpFs::ParseManifest(const char* text) { |
// Only support regular and streams for now |
// Ignore EXEC bit |
- int mode = S_IFREG; |
+ int type = 0; |
switch (modestr[0]) { |
case '-': |
- mode = S_IFREG; |
+ type = S_IFREG; |
break; |
case 'c': |
- mode = S_IFCHR; |
+ type = S_IFCHR; |
break; |
default: |
LOG_ERROR("Unable to parse type %s for %s.", |
@@ -326,6 +345,7 @@ Error HttpFs::ParseManifest(const char* text) { |
return EINVAL; |
} |
+ int mode = 0; |
switch (modestr[1]) { |
case '-': |
break; |
@@ -356,8 +376,9 @@ Error HttpFs::ParseManifest(const char* text) { |
std::string url = MakeUrl(path); |
HttpFsNode* http_node = new HttpFsNode(this, url, cache_content_); |
- http_node->SetMode(mode); |
ScopedNode node(http_node); |
+ node->SetMode(mode); |
+ node->SetType(type); |
Error error = node->Init(0); |
if (error) |
@@ -373,8 +394,7 @@ Error HttpFs::ParseManifest(const char* text) { |
if (error) |
return error; |
- std::string pname = path.Join(); |
- node_cache_[pname] = node; |
+ node_cache_[path.Join()] = node; |
} |
} |