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