| 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;
|
| }
|
| }
|
|
|
|
|