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 |