| OLD | NEW |
| 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 | 5 |
| 6 #include "nacl_io/mount_html5fs.h" | 6 #include "nacl_io/mount_html5fs.h" |
| 7 | 7 |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <ppapi/c/pp_completion_callback.h> | 9 #include <ppapi/c/pp_completion_callback.h> |
| 10 #include <ppapi/c/pp_errors.h> | 10 #include <ppapi/c/pp_errors.h> |
| 11 #include <stdlib.h> | 11 #include <stdlib.h> |
| 12 #include <string.h> | 12 #include <string.h> |
| 13 #include <algorithm> | 13 #include <algorithm> |
| 14 #include "nacl_io/mount_node_html5fs.h" | 14 #include "nacl_io/mount_node_html5fs.h" |
| 15 #include "utils/auto_lock.h" | 15 #include "utils/auto_lock.h" |
| 16 | 16 |
| 17 namespace { | 17 namespace { |
| 18 | 18 |
| 19 #if defined(WIN32) | 19 #if defined(WIN32) |
| 20 int64_t strtoull(const char* nptr, char** endptr, int base) { | 20 int64_t strtoull(const char* nptr, char** endptr, int base) { |
| 21 return _strtoui64(nptr, endptr, base); | 21 return _strtoui64(nptr, endptr, base); |
| 22 } | 22 } |
| 23 #endif | 23 #endif |
| 24 | 24 |
| 25 } // namespace | 25 } // namespace |
| 26 | 26 |
| 27 MountNode *MountHtml5Fs::Open(const Path& path, int mode) { | 27 Error MountHtml5Fs::Open(const Path& path, int mode, MountNode** out_node) { |
| 28 if (BlockUntilFilesystemOpen() != PP_OK) { | 28 *out_node = NULL; |
| 29 errno = ENODEV; | 29 |
| 30 return NULL; | 30 Error error = BlockUntilFilesystemOpen(); |
| 31 if (error) |
| 32 return error; |
| 33 |
| 34 PP_Resource fileref = ppapi()->GetFileRefInterface() |
| 35 ->Create(filesystem_resource_, path.Join().c_str()); |
| 36 if (!fileref) |
| 37 return ENOSYS; |
| 38 |
| 39 MountNodeHtml5Fs* node = new MountNodeHtml5Fs(this, fileref); |
| 40 error = node->Init(mode); |
| 41 if (error) { |
| 42 node->Release(); |
| 43 return error; |
| 31 } | 44 } |
| 32 | 45 |
| 33 PP_Resource fileref = ppapi()->GetFileRefInterface()->Create( | 46 *out_node = node; |
| 34 filesystem_resource_, path.Join().c_str()); | 47 return 0; |
| 35 if (!fileref) | |
| 36 return NULL; | |
| 37 | |
| 38 MountNodeHtml5Fs* node = new MountNodeHtml5Fs(this, fileref); | |
| 39 if (!node->Init(mode)) { | |
| 40 node->Release(); | |
| 41 return NULL; | |
| 42 } | |
| 43 | |
| 44 return node; | |
| 45 } | 48 } |
| 46 | 49 |
| 47 int MountHtml5Fs::Unlink(const Path& path) { | 50 Error MountHtml5Fs::Unlink(const Path& path) { return Remove(path); } |
| 48 return Remove(path); | |
| 49 } | |
| 50 | 51 |
| 51 int MountHtml5Fs::Mkdir(const Path& path, int permissions) { | 52 Error MountHtml5Fs::Mkdir(const Path& path, int permissions) { |
| 52 if (BlockUntilFilesystemOpen() != PP_OK) { | 53 Error error = BlockUntilFilesystemOpen(); |
| 53 errno = ENODEV; | 54 if (error) |
| 54 return -1; | 55 return error; |
| 55 } | |
| 56 | 56 |
| 57 ScopedResource fileref_resource( | 57 ScopedResource fileref_resource( |
| 58 ppapi(), ppapi()->GetFileRefInterface()->Create(filesystem_resource_, | 58 ppapi(), |
| 59 path.Join().c_str())); | 59 ppapi()->GetFileRefInterface()->Create(filesystem_resource_, |
| 60 if (!fileref_resource.pp_resource()) { | 60 path.Join().c_str())); |
| 61 errno = EINVAL; | 61 if (!fileref_resource.pp_resource()) |
| 62 return -1; | 62 return EIO; |
| 63 } | |
| 64 | 63 |
| 65 int32_t result = ppapi()->GetFileRefInterface()->MakeDirectory( | 64 int32_t result = ppapi()->GetFileRefInterface()->MakeDirectory( |
| 66 fileref_resource.pp_resource(), PP_FALSE, PP_BlockUntilComplete()); | 65 fileref_resource.pp_resource(), PP_FALSE, PP_BlockUntilComplete()); |
| 67 if (result != PP_OK) { | 66 if (result != PP_OK) |
| 68 errno = PPErrorToErrno(result); | 67 return PPErrorToErrno(result); |
| 69 return -1; | |
| 70 } | |
| 71 | 68 |
| 72 return 0; | 69 return 0; |
| 73 } | 70 } |
| 74 | 71 |
| 75 int MountHtml5Fs::Rmdir(const Path& path) { | 72 Error MountHtml5Fs::Rmdir(const Path& path) { return Remove(path); } |
| 76 return Remove(path); | |
| 77 } | |
| 78 | 73 |
| 79 int MountHtml5Fs::Remove(const Path& path) { | 74 Error MountHtml5Fs::Remove(const Path& path) { |
| 80 if (BlockUntilFilesystemOpen() != PP_OK) { | 75 Error error = BlockUntilFilesystemOpen(); |
| 81 errno = ENODEV; | 76 if (error) |
| 82 return -1; | 77 return error; |
| 83 } | |
| 84 | 78 |
| 85 ScopedResource fileref_resource( | 79 ScopedResource fileref_resource( |
| 86 ppapi(), ppapi()->GetFileRefInterface()->Create(filesystem_resource_, | 80 ppapi(), |
| 87 path.Join().c_str())); | 81 ppapi()->GetFileRefInterface()->Create(filesystem_resource_, |
| 88 if (!fileref_resource.pp_resource()) { | 82 path.Join().c_str())); |
| 89 errno = EINVAL; | 83 if (!fileref_resource.pp_resource()) |
| 90 return -1; | 84 return ENOSYS; |
| 91 } | |
| 92 | 85 |
| 93 int32_t result = ppapi()->GetFileRefInterface()->Delete( | 86 int32_t result = ppapi()->GetFileRefInterface() |
| 94 fileref_resource.pp_resource(), | 87 ->Delete(fileref_resource.pp_resource(), PP_BlockUntilComplete()); |
| 95 PP_BlockUntilComplete()); | 88 if (result != PP_OK) |
| 96 if (result != PP_OK) { | 89 return PPErrorToErrno(result); |
| 97 errno = PPErrorToErrno(result); | |
| 98 return -1; | |
| 99 } | |
| 100 | 90 |
| 101 return 0; | 91 return 0; |
| 102 } | 92 } |
| 103 | 93 |
| 104 | |
| 105 MountHtml5Fs::MountHtml5Fs() | 94 MountHtml5Fs::MountHtml5Fs() |
| 106 : filesystem_resource_(0), | 95 : filesystem_resource_(0), |
| 107 filesystem_open_has_result_(false), | 96 filesystem_open_has_result_(false), |
| 108 filesystem_open_result_(PP_OK) { | 97 filesystem_open_error_(0) {} |
| 109 } | |
| 110 | 98 |
| 111 bool MountHtml5Fs::Init(int dev, StringMap_t& args, PepperInterface* ppapi) { | 99 Error MountHtml5Fs::Init(int dev, StringMap_t& args, PepperInterface* ppapi) { |
| 112 if (!Mount::Init(dev, args, ppapi)) | 100 Error error = Mount::Init(dev, args, ppapi); |
| 113 return false; | 101 if (error) |
| 102 return error; |
| 114 | 103 |
| 115 if (!ppapi) | 104 if (!ppapi) |
| 116 return false; | 105 return ENOSYS; |
| 117 | 106 |
| 118 pthread_cond_init(&filesystem_open_cond_, NULL); | 107 pthread_cond_init(&filesystem_open_cond_, NULL); |
| 119 | 108 |
| 120 // Parse mount args. | 109 // Parse mount args. |
| 121 PP_FileSystemType filesystem_type = PP_FILESYSTEMTYPE_LOCALPERSISTENT; | 110 PP_FileSystemType filesystem_type = PP_FILESYSTEMTYPE_LOCALPERSISTENT; |
| 122 int64_t expected_size = 0; | 111 int64_t expected_size = 0; |
| 123 for (StringMap_t::iterator iter = args.begin(), end = args.end(); iter != end; | 112 for (StringMap_t::iterator iter = args.begin(), end = args.end(); iter != end; |
| 124 ++iter) { | 113 ++iter) { |
| 125 if (iter->first == "type") { | 114 if (iter->first == "type") { |
| 126 if (iter->second == "PERSISTENT") { | 115 if (iter->second == "PERSISTENT") { |
| 127 filesystem_type = PP_FILESYSTEMTYPE_LOCALPERSISTENT; | 116 filesystem_type = PP_FILESYSTEMTYPE_LOCALPERSISTENT; |
| 128 } else if (iter->second == "TEMPORARY") { | 117 } else if (iter->second == "TEMPORARY") { |
| 129 filesystem_type = PP_FILESYSTEMTYPE_LOCALTEMPORARY; | 118 filesystem_type = PP_FILESYSTEMTYPE_LOCALTEMPORARY; |
| 130 } | 119 } |
| 131 } else if (iter->first == "expected_size") { | 120 } else if (iter->first == "expected_size") { |
| 132 expected_size = strtoull(iter->second.c_str(), NULL, 10); | 121 expected_size = strtoull(iter->second.c_str(), NULL, 10); |
| 133 } | 122 } |
| 134 } | 123 } |
| 135 | 124 |
| 136 // Initialize filesystem. | 125 // Initialize filesystem. |
| 137 filesystem_resource_ = ppapi->GetFileSystemInterface()->Create( | 126 filesystem_resource_ = ppapi->GetFileSystemInterface() |
| 138 ppapi_->GetInstance(), filesystem_type); | 127 ->Create(ppapi_->GetInstance(), filesystem_type); |
| 139 | |
| 140 if (filesystem_resource_ == 0) | 128 if (filesystem_resource_ == 0) |
| 141 return false; | 129 return ENOSYS; |
| 142 | 130 |
| 143 // We can't block the main thread, so make an asynchronous call if on main | 131 // 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; | 132 // thread. If we are off-main-thread, then don't make an asynchronous call; |
| 145 // otherwise we require a message loop. | 133 // otherwise we require a message loop. |
| 146 bool main_thread = ppapi->IsMainThread(); | 134 bool main_thread = ppapi->IsMainThread(); |
| 147 PP_CompletionCallback cc = main_thread ? | 135 PP_CompletionCallback cc = |
| 148 PP_MakeCompletionCallback(&MountHtml5Fs::FilesystemOpenCallbackThunk, | 136 main_thread ? PP_MakeCompletionCallback( |
| 149 this) : | 137 &MountHtml5Fs::FilesystemOpenCallbackThunk, this) |
| 150 PP_BlockUntilComplete(); | 138 : PP_BlockUntilComplete(); |
| 151 | 139 |
| 152 int32_t result = ppapi->GetFileSystemInterface()->Open( | 140 int32_t result = ppapi->GetFileSystemInterface() |
| 153 filesystem_resource_, expected_size, cc); | 141 ->Open(filesystem_resource_, expected_size, cc); |
| 154 | 142 |
| 155 if (!main_thread) { | 143 if (!main_thread) { |
| 156 filesystem_open_has_result_ = true; | 144 filesystem_open_has_result_ = true; |
| 157 filesystem_open_result_ = result; | 145 filesystem_open_error_ = PPErrorToErrno(result); |
| 158 | 146 |
| 159 return filesystem_open_result_ == PP_OK; | 147 return filesystem_open_error_; |
| 160 } else { | 148 } else { |
| 161 // We have to assume the call to Open will succeed; there is no better | 149 // We have to assume the call to Open will succeed; there is no better |
| 162 // result to return here. | 150 // result to return here. |
| 163 return true; | 151 return 0; |
| 164 } | 152 } |
| 165 } | 153 } |
| 166 | 154 |
| 167 void MountHtml5Fs::Destroy() { | 155 void MountHtml5Fs::Destroy() { |
| 168 ppapi_->ReleaseResource(filesystem_resource_); | 156 ppapi_->ReleaseResource(filesystem_resource_); |
| 169 pthread_cond_destroy(&filesystem_open_cond_); | 157 pthread_cond_destroy(&filesystem_open_cond_); |
| 170 } | 158 } |
| 171 | 159 |
| 172 int32_t MountHtml5Fs::BlockUntilFilesystemOpen() { | 160 Error MountHtml5Fs::BlockUntilFilesystemOpen() { |
| 173 AutoLock lock(&lock_); | 161 AutoLock lock(&lock_); |
| 174 while (!filesystem_open_has_result_) { | 162 while (!filesystem_open_has_result_) { |
| 175 pthread_cond_wait(&filesystem_open_cond_, &lock_); | 163 pthread_cond_wait(&filesystem_open_cond_, &lock_); |
| 176 } | 164 } |
| 177 return filesystem_open_result_; | 165 return filesystem_open_error_; |
| 178 } | 166 } |
| 179 | 167 |
| 180 // static | 168 // static |
| 181 void MountHtml5Fs::FilesystemOpenCallbackThunk(void* user_data, | 169 void MountHtml5Fs::FilesystemOpenCallbackThunk(void* user_data, |
| 182 int32_t result) { | 170 int32_t result) { |
| 183 MountHtml5Fs* self = static_cast<MountHtml5Fs*>(user_data); | 171 MountHtml5Fs* self = static_cast<MountHtml5Fs*>(user_data); |
| 184 self->FilesystemOpenCallback(result); | 172 self->FilesystemOpenCallback(result); |
| 185 } | 173 } |
| 186 | 174 |
| 187 void MountHtml5Fs::FilesystemOpenCallback(int32_t result) { | 175 void MountHtml5Fs::FilesystemOpenCallback(int32_t result) { |
| 188 AutoLock lock(&lock_); | 176 AutoLock lock(&lock_); |
| 189 filesystem_open_has_result_ = true; | 177 filesystem_open_has_result_ = true; |
| 190 filesystem_open_result_ = result; | 178 filesystem_open_error_ = PPErrorToErrno(result); |
| 191 pthread_cond_signal(&filesystem_open_cond_); | 179 pthread_cond_signal(&filesystem_open_cond_); |
| 192 } | 180 } |
| OLD | NEW |