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_node_html5fs.h" | 6 #include "nacl_io/mount_node_html5fs.h" |
7 | 7 |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <fcntl.h> | 9 #include <fcntl.h> |
10 #include <ppapi/c/pp_completion_callback.h> | 10 #include <ppapi/c/pp_completion_callback.h> |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 open_flags = PP_FILEOPENFLAG_READ; | 48 open_flags = PP_FILEOPENFLAG_READ; |
49 break; | 49 break; |
50 case O_WRONLY: | 50 case O_WRONLY: |
51 open_flags = PP_FILEOPENFLAG_WRITE; | 51 open_flags = PP_FILEOPENFLAG_WRITE; |
52 break; | 52 break; |
53 case O_RDWR: | 53 case O_RDWR: |
54 open_flags = PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_WRITE; | 54 open_flags = PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_WRITE; |
55 break; | 55 break; |
56 } | 56 } |
57 | 57 |
58 if (mode & O_CREAT) open_flags |= PP_FILEOPENFLAG_CREATE; | 58 if (mode & O_CREAT) |
59 if (mode & O_TRUNC) open_flags |= PP_FILEOPENFLAG_TRUNCATE; | 59 open_flags |= PP_FILEOPENFLAG_CREATE; |
60 if (mode & O_EXCL) open_flags |= PP_FILEOPENFLAG_EXCLUSIVE; | 60 if (mode & O_TRUNC) |
| 61 open_flags |= PP_FILEOPENFLAG_TRUNCATE; |
| 62 if (mode & O_EXCL) |
| 63 open_flags |= PP_FILEOPENFLAG_EXCLUSIVE; |
61 | 64 |
62 return open_flags; | 65 return open_flags; |
63 } | 66 } |
64 | 67 |
65 } // namespace | 68 } // namespace |
66 | 69 |
67 int MountNodeHtml5Fs::FSync() { | 70 Error MountNodeHtml5Fs::FSync() { |
68 // Cannot call Flush on a directory; simply do nothing. | 71 // Cannot call Flush on a directory; simply do nothing. |
69 if (IsDirectory()) | 72 if (IsDirectory()) |
70 return 0; | 73 return 0; |
71 | 74 |
72 int32_t result = mount_->ppapi()->GetFileIoInterface()->Flush( | 75 int32_t result = mount_->ppapi()->GetFileIoInterface() |
73 fileio_resource_, PP_BlockUntilComplete()); | 76 ->Flush(fileio_resource_, PP_BlockUntilComplete()); |
74 if (result != PP_OK) { | 77 if (result != PP_OK) |
75 errno = PPErrorToErrno(result); | 78 return PPErrorToErrno(result); |
76 return -1; | |
77 } | |
78 | |
79 return 0; | 79 return 0; |
80 } | 80 } |
81 | 81 |
82 int MountNodeHtml5Fs::GetDents(size_t offs, struct dirent* pdir, size_t size) { | 82 Error MountNodeHtml5Fs::GetDents(size_t offs, |
| 83 struct dirent* pdir, |
| 84 size_t size, |
| 85 int* out_bytes) { |
| 86 *out_bytes = 0; |
| 87 |
83 // If the buffer pointer is invalid, fail | 88 // If the buffer pointer is invalid, fail |
84 if (NULL == pdir) { | 89 if (NULL == pdir) |
85 errno = EINVAL; | 90 return EINVAL; |
86 return -1; | |
87 } | |
88 | 91 |
89 // If the buffer is too small, fail | 92 // If the buffer is too small, fail |
90 if (size < sizeof(struct dirent)) { | 93 if (size < sizeof(struct dirent)) |
91 errno = EINVAL; | 94 return EINVAL; |
92 return -1; | |
93 } | |
94 | 95 |
95 // If this is not a directory, fail | 96 // If this is not a directory, fail |
96 if (!IsDirectory()) { | 97 if (!IsDirectory()) |
97 errno = ENOTDIR; | 98 return ENOTDIR; |
98 return -1; | |
99 } | |
100 | 99 |
101 OutputBuffer output_buf = { NULL, 0 }; | 100 OutputBuffer output_buf = {NULL, 0}; |
102 PP_ArrayOutput output = { &GetOutputBuffer, &output_buf }; | 101 PP_ArrayOutput output = {&GetOutputBuffer, &output_buf}; |
103 int32_t result = | 102 int32_t result = mount_->ppapi()->GetFileRefInterface()->ReadDirectoryEntries( |
104 mount_->ppapi()->GetFileRefInterface()->ReadDirectoryEntries( | 103 fileref_resource_, output, PP_BlockUntilComplete()); |
105 fileref_resource_, output, PP_BlockUntilComplete()); | 104 if (result != PP_OK) |
106 if (result != PP_OK) { | 105 return PPErrorToErrno(result); |
107 errno = PPErrorToErrno(result); | |
108 return -1; | |
109 } | |
110 | 106 |
111 std::vector<struct dirent> dirents; | 107 std::vector<struct dirent> dirents; |
112 PP_DirectoryEntry* entries = | 108 PP_DirectoryEntry* entries = static_cast<PP_DirectoryEntry*>(output_buf.data); |
113 static_cast<PP_DirectoryEntry*>(output_buf.data); | |
114 | 109 |
115 for (int i = 0; i < output_buf.element_count; ++i) { | 110 for (int i = 0; i < output_buf.element_count; ++i) { |
116 PP_Var file_name_var = mount_->ppapi()->GetFileRefInterface()->GetName( | 111 PP_Var file_name_var = |
117 entries[i].file_ref); | 112 mount_->ppapi()->GetFileRefInterface()->GetName(entries[i].file_ref); |
118 | 113 |
119 // Release the file reference. | 114 // Release the file reference. |
120 mount_->ppapi()->ReleaseResource(entries[i].file_ref); | 115 mount_->ppapi()->ReleaseResource(entries[i].file_ref); |
121 | 116 |
122 if (file_name_var.type != PP_VARTYPE_STRING) | 117 if (file_name_var.type != PP_VARTYPE_STRING) |
123 continue; | 118 continue; |
124 | 119 |
125 uint32_t file_name_length; | 120 uint32_t file_name_length; |
126 const char* file_name = mount_->ppapi()->GetVarInterface()->VarToUtf8( | 121 const char* file_name = mount_->ppapi()->GetVarInterface() |
127 file_name_var, &file_name_length); | 122 ->VarToUtf8(file_name_var, &file_name_length); |
128 if (!file_name) | 123 if (!file_name) |
129 continue; | 124 continue; |
130 | 125 |
131 file_name_length = std::min( | 126 file_name_length = std::min( |
132 static_cast<size_t>(file_name_length), | 127 static_cast<size_t>(file_name_length), |
133 sizeof(static_cast<struct dirent*>(0)->d_name) - 1); // -1 for NULL. | 128 sizeof(static_cast<struct dirent*>(0)->d_name) - 1); // -1 for NULL. |
134 | 129 |
135 dirents.push_back(dirent()); | 130 dirents.push_back(dirent()); |
136 struct dirent& direntry = dirents.back(); | 131 struct dirent& direntry = dirents.back(); |
137 direntry.d_ino = 1; // Must be > 0. | 132 direntry.d_ino = 1; // Must be > 0. |
138 direntry.d_off = sizeof(struct dirent); | 133 direntry.d_off = sizeof(struct dirent); |
139 direntry.d_reclen = sizeof(struct dirent); | 134 direntry.d_reclen = sizeof(struct dirent); |
140 strncpy(direntry.d_name, file_name, file_name_length); | 135 strncpy(direntry.d_name, file_name, file_name_length); |
141 direntry.d_name[file_name_length] = 0; | 136 direntry.d_name[file_name_length] = 0; |
142 } | 137 } |
143 | 138 |
144 // Release the output buffer. | 139 // Release the output buffer. |
145 free(output_buf.data); | 140 free(output_buf.data); |
146 | 141 |
147 // Force size to a multiple of dirent | 142 // Force size to a multiple of dirent |
148 size -= size % sizeof(struct dirent); | 143 size -= size % sizeof(struct dirent); |
149 size_t max = dirents.size() * sizeof(struct dirent); | 144 size_t max = dirents.size() * sizeof(struct dirent); |
150 | 145 |
151 if (offs >= max) return 0; | 146 if (offs >= max) |
152 if (offs + size >= max) size = max - offs; | 147 return 0; |
| 148 |
| 149 if (offs + size >= max) |
| 150 size = max - offs; |
153 | 151 |
154 memcpy(pdir, reinterpret_cast<char*>(dirents.data()) + offs, size); | 152 memcpy(pdir, reinterpret_cast<char*>(dirents.data()) + offs, size); |
155 return size; | 153 *out_bytes = size; |
| 154 return 0; |
156 } | 155 } |
157 | 156 |
158 int MountNodeHtml5Fs::GetStat(struct stat* stat) { | 157 Error MountNodeHtml5Fs::GetStat(struct stat* stat) { |
159 AutoLock lock(&lock_); | 158 AutoLock lock(&lock_); |
160 | 159 |
161 PP_FileInfo info; | 160 PP_FileInfo info; |
162 int32_t result = mount_->ppapi()->GetFileRefInterface()->Query( | 161 int32_t result = mount_->ppapi()->GetFileRefInterface()->Query( |
163 fileref_resource_, &info, PP_BlockUntilComplete()); | 162 fileref_resource_, &info, PP_BlockUntilComplete()); |
164 if (result != PP_OK) { | 163 if (result != PP_OK) |
165 errno = PPErrorToErrno(result); | 164 return PPErrorToErrno(result); |
166 return -1; | |
167 } | |
168 | 165 |
169 // Fill in known info here. | 166 // Fill in known info here. |
170 memcpy(stat, &stat_, sizeof(stat_)); | 167 memcpy(stat, &stat_, sizeof(stat_)); |
171 | 168 |
172 // Fill in the additional info from ppapi. | 169 // Fill in the additional info from ppapi. |
173 switch (info.type) { | 170 switch (info.type) { |
174 case PP_FILETYPE_REGULAR: stat->st_mode |= S_IFREG; break; | 171 case PP_FILETYPE_REGULAR: |
175 case PP_FILETYPE_DIRECTORY: stat->st_mode |= S_IFDIR; break; | 172 stat->st_mode |= S_IFREG; |
| 173 break; |
| 174 case PP_FILETYPE_DIRECTORY: |
| 175 stat->st_mode |= S_IFDIR; |
| 176 break; |
176 case PP_FILETYPE_OTHER: | 177 case PP_FILETYPE_OTHER: |
177 default: break; | 178 default: |
| 179 break; |
178 } | 180 } |
179 stat->st_size = static_cast<off_t>(info.size); | 181 stat->st_size = static_cast<off_t>(info.size); |
180 stat->st_atime = info.last_access_time; | 182 stat->st_atime = info.last_access_time; |
181 stat->st_mtime = info.last_modified_time; | 183 stat->st_mtime = info.last_modified_time; |
182 stat->st_ctime = info.creation_time; | 184 stat->st_ctime = info.creation_time; |
183 | 185 |
184 return 0; | 186 return 0; |
185 } | 187 } |
186 | 188 |
187 int MountNodeHtml5Fs::Read(size_t offs, void* buf, size_t count) { | 189 Error MountNodeHtml5Fs::Read(size_t offs, |
188 if (IsDirectory()) { | 190 void* buf, |
189 errno = EISDIR; | 191 size_t count, |
190 return -1; | 192 int* out_bytes) { |
191 } | 193 *out_bytes = 0; |
192 | 194 |
193 int32_t result = mount_->ppapi()->GetFileIoInterface()->Read( | 195 if (IsDirectory()) |
194 fileio_resource_, offs, static_cast<char*>(buf), | 196 return EISDIR; |
195 static_cast<int32_t>(count), | |
196 PP_BlockUntilComplete()); | |
197 if (result < 0) { | |
198 errno = PPErrorToErrno(result); | |
199 return -1; | |
200 } | |
201 | 197 |
202 return result; | 198 int32_t result = |
203 } | 199 mount_->ppapi()->GetFileIoInterface()->Read(fileio_resource_, |
| 200 offs, |
| 201 static_cast<char*>(buf), |
| 202 static_cast<int32_t>(count), |
| 203 PP_BlockUntilComplete()); |
| 204 if (result < 0) |
| 205 return PPErrorToErrno(result); |
204 | 206 |
205 int MountNodeHtml5Fs::FTruncate(off_t size) { | 207 *out_bytes = result; |
206 if (IsDirectory()) { | |
207 errno = EISDIR; | |
208 return -1; | |
209 } | |
210 | |
211 int32_t result = mount_->ppapi()->GetFileIoInterface()->SetLength( | |
212 fileio_resource_, size, PP_BlockUntilComplete()); | |
213 if (result != PP_OK) { | |
214 errno = PPErrorToErrno(result); | |
215 return -1; | |
216 } | |
217 | |
218 return 0; | 208 return 0; |
219 } | 209 } |
220 | 210 |
221 int MountNodeHtml5Fs::Write(size_t offs, const void* buf, size_t count) { | 211 Error MountNodeHtml5Fs::FTruncate(off_t size) { |
222 if (IsDirectory()) { | 212 if (IsDirectory()) |
223 errno = EISDIR; | 213 return EISDIR; |
224 return -1; | |
225 } | |
226 | 214 |
227 int32_t result = mount_->ppapi()->GetFileIoInterface()->Write( | 215 int32_t result = mount_->ppapi()->GetFileIoInterface() |
228 fileio_resource_, offs, static_cast<const char*>(buf), | 216 ->SetLength(fileio_resource_, size, PP_BlockUntilComplete()); |
229 static_cast<int32_t>(count), PP_BlockUntilComplete()); | 217 if (result != PP_OK) |
230 if (result < 0) { | 218 return PPErrorToErrno(result); |
231 errno = PPErrorToErrno(result); | 219 return 0; |
232 return -1; | |
233 } | |
234 | |
235 return result; | |
236 } | 220 } |
237 | 221 |
238 size_t MountNodeHtml5Fs::GetSize() { | 222 Error MountNodeHtml5Fs::Write(size_t offs, |
| 223 const void* buf, |
| 224 size_t count, |
| 225 int* out_bytes) { |
| 226 *out_bytes = 0; |
| 227 |
| 228 if (IsDirectory()) |
| 229 return EISDIR; |
| 230 |
| 231 int32_t result = mount_->ppapi()->GetFileIoInterface() |
| 232 ->Write(fileio_resource_, |
| 233 offs, |
| 234 static_cast<const char*>(buf), |
| 235 static_cast<int32_t>(count), |
| 236 PP_BlockUntilComplete()); |
| 237 if (result < 0) |
| 238 return PPErrorToErrno(result); |
| 239 |
| 240 *out_bytes = result; |
| 241 return 0; |
| 242 } |
| 243 |
| 244 Error MountNodeHtml5Fs::GetSize(size_t* out_size) { |
| 245 *out_size = 0; |
| 246 |
239 AutoLock lock(&lock_); | 247 AutoLock lock(&lock_); |
240 | 248 |
241 PP_FileInfo info; | 249 PP_FileInfo info; |
242 int32_t result = mount_->ppapi()->GetFileRefInterface()->Query( | 250 int32_t result = mount_->ppapi()->GetFileIoInterface() |
243 fileref_resource_, &info, PP_BlockUntilComplete()); | 251 ->Query(fileio_resource_, &info, PP_BlockUntilComplete()); |
244 if (result != PP_OK) { | 252 if (result != PP_OK) |
245 errno = PPErrorToErrno(result); | 253 return PPErrorToErrno(result); |
246 return -1; | |
247 } | |
248 | 254 |
249 return static_cast<size_t>(info.size); | 255 *out_size = static_cast<size_t>(info.size); |
| 256 return 0; |
250 } | 257 } |
251 | 258 |
252 MountNodeHtml5Fs::MountNodeHtml5Fs(Mount* mount, PP_Resource fileref_resource) | 259 MountNodeHtml5Fs::MountNodeHtml5Fs(Mount* mount, PP_Resource fileref_resource) |
253 : MountNode(mount), | 260 : MountNode(mount), |
254 fileref_resource_(fileref_resource), | 261 fileref_resource_(fileref_resource), |
255 fileio_resource_(0) { | 262 fileio_resource_(0) {} |
256 } | |
257 | 263 |
258 bool MountNodeHtml5Fs::Init(int perm) { | 264 Error MountNodeHtml5Fs::Init(int perm) { |
259 if (!MountNode::Init(Mount::OpenModeToPermission(perm))) | 265 Error error = MountNode::Init(Mount::OpenModeToPermission(perm)); |
260 return false; | 266 if (error) |
| 267 return error; |
261 | 268 |
262 // First query the FileRef to see if it is a file or directory. | 269 // First query the FileRef to see if it is a file or directory. |
263 PP_FileInfo file_info; | 270 PP_FileInfo file_info; |
264 mount_->ppapi()->GetFileRefInterface()->Query(fileref_resource_, &file_info, | 271 mount_->ppapi()->GetFileRefInterface()->Query(fileref_resource_, &file_info, |
265 PP_BlockUntilComplete()); | 272 PP_BlockUntilComplete()); |
266 // If this is a directory, do not get a FileIO. | 273 // If this is a directory, do not get a FileIO. |
267 if (file_info.type == PP_FILETYPE_DIRECTORY) | 274 if (file_info.type == PP_FILETYPE_DIRECTORY) |
268 return true; | 275 return 0; |
269 | 276 |
270 fileio_resource_= mount_->ppapi()->GetFileIoInterface()->Create( | 277 fileio_resource_ = mount_->ppapi()->GetFileIoInterface() |
271 mount_->ppapi()->GetInstance()); | 278 ->Create(mount_->ppapi()->GetInstance()); |
272 if (!fileio_resource_) | 279 if (!fileio_resource_) |
273 return false; | 280 return ENOSYS; |
274 | 281 |
275 int32_t open_result = mount_->ppapi()->GetFileIoInterface()->Open( | 282 int32_t open_result = |
276 fileio_resource_, fileref_resource_, ModeToOpenFlags(perm), | 283 mount_->ppapi()->GetFileIoInterface()->Open(fileio_resource_, |
277 PP_BlockUntilComplete()); | 284 fileref_resource_, |
| 285 ModeToOpenFlags(perm), |
| 286 PP_BlockUntilComplete()); |
278 if (open_result != PP_OK) | 287 if (open_result != PP_OK) |
279 return false; | 288 return PPErrorToErrno(open_result); |
280 | 289 return 0; |
281 return true; | |
282 } | 290 } |
283 | 291 |
284 void MountNodeHtml5Fs::Destroy() { | 292 void MountNodeHtml5Fs::Destroy() { |
285 FSync(); | 293 FSync(); |
286 | 294 |
287 if (fileio_resource_) { | 295 if (fileio_resource_) { |
288 mount_->ppapi()->GetFileIoInterface()->Close(fileio_resource_); | 296 mount_->ppapi()->GetFileIoInterface()->Close(fileio_resource_); |
289 mount_->ppapi()->ReleaseResource(fileio_resource_); | 297 mount_->ppapi()->ReleaseResource(fileio_resource_); |
290 } | 298 } |
291 | 299 |
292 mount_->ppapi()->ReleaseResource(fileref_resource_); | 300 mount_->ppapi()->ReleaseResource(fileref_resource_); |
293 fileio_resource_ = 0; | 301 fileio_resource_ = 0; |
294 fileref_resource_ = 0; | 302 fileref_resource_ = 0; |
295 MountNode::Destroy(); | 303 MountNode::Destroy(); |
296 } | 304 } |
OLD | NEW |