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
3 // found in the LICENSE file.
5 #include "nacl_io/mount_html5fs.h"
9 #include <ppapi/c/pp_completion_callback.h>
10 #include <ppapi/c/pp_errors.h>
14 #include "nacl_io/mount_node_html5fs.h"
15 #include "sdk_util/auto_lock.h"
22 int64_t strtoull(const char* nptr, char** endptr, int base) {
23 return _strtoui64(nptr, endptr, base);
29 Error MountHtml5Fs::Access(const Path& path, int a_mode) {
30 // a_mode is unused, since all files are readable, writable and executable.
32 return Open(path, O_RDONLY, &node);
35 Error MountHtml5Fs::Open(const Path& path,
37 ScopedMountNode* out_node) {
38 out_node->reset(NULL);
39 Error error = BlockUntilFilesystemOpen();
43 PP_Resource fileref = ppapi()->GetFileRefInterface()
44 ->Create(filesystem_resource_, path.Join().c_str());
48 ScopedMountNode node(new MountNodeHtml5Fs(this, fileref));
49 error = node->Init(open_flags);
57 Error MountHtml5Fs::Unlink(const Path& path) { return Remove(path); }
59 Error MountHtml5Fs::Mkdir(const Path& path, int permissions) {
60 Error error = BlockUntilFilesystemOpen();
64 // FileRef returns PP_ERROR_NOACCESS which is translated to EACCES if you
65 // try to create the root directory. EEXIST is a better errno here.
69 ScopedResource fileref_resource(
71 ppapi()->GetFileRefInterface()->Create(filesystem_resource_,
72 path.Join().c_str()));
73 if (!fileref_resource.pp_resource())
76 int32_t result = ppapi()->GetFileRefInterface()->MakeDirectory(
77 fileref_resource.pp_resource(), PP_FALSE, PP_BlockUntilComplete());
79 return PPErrorToErrno(result);
84 Error MountHtml5Fs::Rmdir(const Path& path) { return Remove(path); }
86 Error MountHtml5Fs::Remove(const Path& path) {
87 Error error = BlockUntilFilesystemOpen();
91 ScopedResource fileref_resource(
93 ppapi()->GetFileRefInterface()->Create(filesystem_resource_,
94 path.Join().c_str()));
95 if (!fileref_resource.pp_resource())
98 int32_t result = ppapi()->GetFileRefInterface()
99 ->Delete(fileref_resource.pp_resource(), PP_BlockUntilComplete());
101 return PPErrorToErrno(result);
106 MountHtml5Fs::MountHtml5Fs()
107 : filesystem_resource_(0),
108 filesystem_open_has_result_(false),
109 filesystem_open_error_(0) {}
111 Error MountHtml5Fs::Init(int dev, StringMap_t& args, PepperInterface* ppapi) {
112 Error error = Mount::Init(dev, args, ppapi);
119 pthread_cond_init(&filesystem_open_cond_, NULL);
122 PP_FileSystemType filesystem_type = PP_FILESYSTEMTYPE_LOCALPERSISTENT;
123 int64_t expected_size = 0;
124 for (StringMap_t::iterator iter = args.begin(), end = args.end(); iter != end;
126 if (iter->first == "type") {
127 if (iter->second == "PERSISTENT") {
128 filesystem_type = PP_FILESYSTEMTYPE_LOCALPERSISTENT;
129 } else if (iter->second == "TEMPORARY") {
130 filesystem_type = PP_FILESYSTEMTYPE_LOCALTEMPORARY;
132 } else if (iter->first == "expected_size") {
133 expected_size = strtoull(iter->second.c_str(), NULL, 10);
137 // Initialize filesystem.
138 filesystem_resource_ = ppapi->GetFileSystemInterface()
139 ->Create(ppapi_->GetInstance(), filesystem_type);
140 if (filesystem_resource_ == 0)
143 // We can't block the main thread, so make an asynchronous call if on main
144 // thread. If we are off-main-thread, then don't make an asynchronous call;
145 // otherwise we require a message loop.
146 bool main_thread = ppapi->GetCoreInterface()->IsMainThread();
147 PP_CompletionCallback cc =
148 main_thread ? PP_MakeCompletionCallback(
149 &MountHtml5Fs::FilesystemOpenCallbackThunk, this)
150 : PP_BlockUntilComplete();
152 int32_t result = ppapi->GetFileSystemInterface()
153 ->Open(filesystem_resource_, expected_size, cc);
156 filesystem_open_has_result_ = true;
157 filesystem_open_error_ = PPErrorToErrno(result);
159 return filesystem_open_error_;
162 // We have to assume the call to Open will succeed; there is no better
163 // result to return here.
167 void MountHtml5Fs::Destroy() {
168 ppapi_->ReleaseResource(filesystem_resource_);
169 pthread_cond_destroy(&filesystem_open_cond_);
172 Error MountHtml5Fs::BlockUntilFilesystemOpen() {
173 AUTO_LOCK(filesysem_open_lock_);
174 while (!filesystem_open_has_result_) {
175 pthread_cond_wait(&filesystem_open_cond_, filesysem_open_lock_.mutex());
177 return filesystem_open_error_;
181 void MountHtml5Fs::FilesystemOpenCallbackThunk(void* user_data,
183 MountHtml5Fs* self = static_cast<MountHtml5Fs*>(user_data);
184 self->FilesystemOpenCallback(result);
187 void MountHtml5Fs::FilesystemOpenCallback(int32_t result) {
188 AUTO_LOCK(filesysem_open_lock_);
189 filesystem_open_has_result_ = true;
190 filesystem_open_error_ = PPErrorToErrno(result);
191 pthread_cond_signal(&filesystem_open_cond_);
194 } // namespace nacl_io