| OLD | NEW |
| (Empty) |
| 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. | |
| 4 */ | |
| 5 | |
| 6 #include "nacl_mounts/mount_node_html5fs.h" | |
| 7 | |
| 8 #include <errno.h> | |
| 9 #include <fcntl.h> | |
| 10 #include <ppapi/c/pp_completion_callback.h> | |
| 11 #include <ppapi/c/pp_errors.h> | |
| 12 #include <ppapi/c/pp_file_info.h> | |
| 13 #include <ppapi/c/ppb_file_io.h> | |
| 14 #include <string.h> | |
| 15 #include <vector> | |
| 16 #include "nacl_mounts/mount.h" | |
| 17 #include "nacl_mounts/osdirent.h" | |
| 18 #include "nacl_mounts/pepper_interface.h" | |
| 19 #include "utils/auto_lock.h" | |
| 20 | |
| 21 namespace { | |
| 22 | |
| 23 int32_t ModeToOpenFlags(int mode) { | |
| 24 int32_t open_flags = 0; | |
| 25 | |
| 26 switch (mode & 3) { | |
| 27 default: | |
| 28 case O_RDONLY: | |
| 29 open_flags = PP_FILEOPENFLAG_READ; | |
| 30 break; | |
| 31 case O_WRONLY: | |
| 32 open_flags = PP_FILEOPENFLAG_WRITE; | |
| 33 break; | |
| 34 case O_RDWR: | |
| 35 open_flags = PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_WRITE; | |
| 36 break; | |
| 37 } | |
| 38 | |
| 39 if (mode & O_CREAT) open_flags |= PP_FILEOPENFLAG_CREATE; | |
| 40 if (mode & O_TRUNC) open_flags |= PP_FILEOPENFLAG_TRUNCATE; | |
| 41 if (mode & O_EXCL) open_flags |= PP_FILEOPENFLAG_EXCLUSIVE; | |
| 42 | |
| 43 return open_flags; | |
| 44 } | |
| 45 | |
| 46 } // namespace | |
| 47 | |
| 48 int MountNodeHtml5Fs::FSync() { | |
| 49 int32_t result = mount_->ppapi()->GetFileIoInterface()->Flush( | |
| 50 fileio_resource_, PP_BlockUntilComplete()); | |
| 51 if (result != PP_OK) { | |
| 52 errno = PPErrorToErrno(result); | |
| 53 return -1; | |
| 54 } | |
| 55 | |
| 56 return 0; | |
| 57 } | |
| 58 | |
| 59 int MountNodeHtml5Fs::GetDents(size_t offs, struct dirent* pdir, size_t size) { | |
| 60 // The directory reader interface is a dev interface, if it doesn't exist, | |
| 61 // just fail. | |
| 62 if (!mount_->ppapi()->GetDirectoryReaderInterface()) { | |
| 63 errno = ENOSYS; | |
| 64 return -1; | |
| 65 } | |
| 66 | |
| 67 // If the buffer pointer is invalid, fail | |
| 68 if (NULL == pdir) { | |
| 69 errno = EINVAL; | |
| 70 return -1; | |
| 71 } | |
| 72 | |
| 73 // If the buffer is too small, fail | |
| 74 if (size < sizeof(struct dirent)) { | |
| 75 errno = EINVAL; | |
| 76 return -1; | |
| 77 } | |
| 78 | |
| 79 ScopedResource directory_reader( | |
| 80 mount_->ppapi(), | |
| 81 mount_->ppapi()->GetDirectoryReaderInterface()->Create( | |
| 82 fileref_resource_)); | |
| 83 if (!directory_reader.pp_resource()) { | |
| 84 errno = ENOSYS; | |
| 85 return -1; | |
| 86 } | |
| 87 | |
| 88 std::vector<struct dirent> dirents; | |
| 89 PP_DirectoryEntry_Dev directory_entry = {0}; | |
| 90 while (1) { | |
| 91 int32_t result = | |
| 92 mount_->ppapi()->GetDirectoryReaderInterface()->GetNextEntry( | |
| 93 directory_reader.pp_resource(), &directory_entry, | |
| 94 PP_BlockUntilComplete()); | |
| 95 if (result != PP_OK) { | |
| 96 errno = PPErrorToErrno(result); | |
| 97 return -1; | |
| 98 } | |
| 99 | |
| 100 // file_ref == 0 is a sentry marking the end of the directory list. | |
| 101 if (!directory_entry.file_ref) | |
| 102 break; | |
| 103 | |
| 104 PP_Var file_name_var = mount_->ppapi()->GetFileRefInterface()->GetName( | |
| 105 directory_entry.file_ref); | |
| 106 if (file_name_var.type != PP_VARTYPE_STRING) | |
| 107 continue; | |
| 108 | |
| 109 uint32_t file_name_length; | |
| 110 const char* file_name = mount_->ppapi()->GetVarInterface()->VarToUtf8( | |
| 111 file_name_var, &file_name_length); | |
| 112 if (!file_name) | |
| 113 continue; | |
| 114 | |
| 115 file_name_length = std::min( | |
| 116 static_cast<size_t>(file_name_length), | |
| 117 sizeof(static_cast<struct dirent*>(0)->d_name) - 1); // -1 for NULL. | |
| 118 | |
| 119 dirents.push_back(dirent()); | |
| 120 struct dirent& direntry = dirents.back(); | |
| 121 direntry.d_ino = 0; // TODO(binji): Is this needed? | |
| 122 direntry.d_off = sizeof(struct dirent); | |
| 123 direntry.d_reclen = sizeof(struct dirent); | |
| 124 strncpy(direntry.d_name, file_name, file_name_length); | |
| 125 direntry.d_name[file_name_length] = 0; | |
| 126 } | |
| 127 | |
| 128 // Force size to a multiple of dirent | |
| 129 size -= size % sizeof(struct dirent); | |
| 130 size_t max = dirents.size() * sizeof(struct dirent); | |
| 131 | |
| 132 if (offs >= max) return 0; | |
| 133 if (offs + size >= max) size = max - offs; | |
| 134 | |
| 135 memcpy(pdir, reinterpret_cast<char*>(dirents.data()) + offs, size); | |
| 136 return 0; | |
| 137 } | |
| 138 | |
| 139 int MountNodeHtml5Fs::GetStat(struct stat* stat) { | |
| 140 AutoLock lock(&lock_); | |
| 141 | |
| 142 PP_FileInfo info; | |
| 143 int32_t result = mount_->ppapi()->GetFileIoInterface()->Query( | |
| 144 fileio_resource_, &info, PP_BlockUntilComplete()); | |
| 145 if (result != PP_OK) { | |
| 146 errno = PPErrorToErrno(result); | |
| 147 return -1; | |
| 148 } | |
| 149 | |
| 150 // Fill in known info here. | |
| 151 memcpy(stat, &stat_, sizeof(stat_)); | |
| 152 | |
| 153 // Fill in the additional info from ppapi. | |
| 154 switch (info.type) { | |
| 155 case PP_FILETYPE_REGULAR: stat->st_mode |= S_IFREG; break; | |
| 156 case PP_FILETYPE_DIRECTORY: stat->st_mode |= S_IFDIR; break; | |
| 157 case PP_FILETYPE_OTHER: | |
| 158 default: break; | |
| 159 } | |
| 160 stat->st_size = static_cast<off_t>(info.size); | |
| 161 stat->st_atime = info.last_access_time; | |
| 162 stat->st_mtime = info.last_modified_time; | |
| 163 stat->st_ctime = info.creation_time; | |
| 164 | |
| 165 return 0; | |
| 166 } | |
| 167 | |
| 168 int MountNodeHtml5Fs::Read(size_t offs, void* buf, size_t count) { | |
| 169 int32_t result = mount_->ppapi()->GetFileIoInterface()->Read( | |
| 170 fileio_resource_, offs, static_cast<char*>(buf), | |
| 171 static_cast<int32_t>(count), | |
| 172 PP_BlockUntilComplete()); | |
| 173 if (result < 0) { | |
| 174 errno = PPErrorToErrno(result); | |
| 175 return -1; | |
| 176 } | |
| 177 | |
| 178 return result; | |
| 179 } | |
| 180 | |
| 181 int MountNodeHtml5Fs::Truncate(size_t size) { | |
| 182 int32_t result = mount_->ppapi()->GetFileIoInterface()->SetLength( | |
| 183 fileio_resource_, size, PP_BlockUntilComplete()); | |
| 184 if (result != PP_OK) { | |
| 185 errno = PPErrorToErrno(result); | |
| 186 return -1; | |
| 187 } | |
| 188 | |
| 189 return 0; | |
| 190 } | |
| 191 | |
| 192 int MountNodeHtml5Fs::Write(size_t offs, const void* buf, size_t count) { | |
| 193 int32_t result = mount_->ppapi()->GetFileIoInterface()->Write( | |
| 194 fileio_resource_, offs, static_cast<const char*>(buf), | |
| 195 static_cast<int32_t>(count), PP_BlockUntilComplete()); | |
| 196 if (result < 0) { | |
| 197 errno = PPErrorToErrno(result); | |
| 198 return -1; | |
| 199 } | |
| 200 | |
| 201 return result; | |
| 202 } | |
| 203 | |
| 204 size_t MountNodeHtml5Fs::GetSize() { | |
| 205 AutoLock lock(&lock_); | |
| 206 | |
| 207 PP_FileInfo info; | |
| 208 int32_t result = mount_->ppapi()->GetFileIoInterface()->Query( | |
| 209 fileio_resource_, &info, PP_BlockUntilComplete()); | |
| 210 if (result != PP_OK) { | |
| 211 errno = PPErrorToErrno(result); | |
| 212 return -1; | |
| 213 } | |
| 214 | |
| 215 return static_cast<size_t>(info.size); | |
| 216 } | |
| 217 | |
| 218 MountNodeHtml5Fs::MountNodeHtml5Fs(Mount* mount, PP_Resource fileref_resource) | |
| 219 : MountNode(mount), | |
| 220 fileref_resource_(fileref_resource), | |
| 221 fileio_resource_(0) { | |
| 222 } | |
| 223 | |
| 224 bool MountNodeHtml5Fs::Init(int perm) { | |
| 225 if (!MountNode::Init(Mount::OpenModeToPermission(perm))) | |
| 226 return false; | |
| 227 | |
| 228 fileio_resource_= mount_->ppapi()->GetFileIoInterface()->Create( | |
| 229 mount_->ppapi()->GetInstance()); | |
| 230 if (!fileio_resource_) | |
| 231 return false; | |
| 232 | |
| 233 int32_t open_result = mount_->ppapi()->GetFileIoInterface()->Open( | |
| 234 fileio_resource_, fileref_resource_, ModeToOpenFlags(perm), | |
| 235 PP_BlockUntilComplete()); | |
| 236 if (open_result != PP_OK) | |
| 237 return false; | |
| 238 | |
| 239 return true; | |
| 240 } | |
| 241 | |
| 242 void MountNodeHtml5Fs::Destroy() { | |
| 243 FSync(); | |
| 244 | |
| 245 if (fileio_resource_) { | |
| 246 mount_->ppapi()->GetFileIoInterface()->Close(fileio_resource_); | |
| 247 mount_->ppapi()->ReleaseResource(fileio_resource_); | |
| 248 } | |
| 249 | |
| 250 mount_->ppapi()->ReleaseResource(fileref_resource_); | |
| 251 fileio_resource_ = 0; | |
| 252 fileref_resource_ = 0; | |
| 253 MountNode::Destroy(); | |
| 254 } | |
| OLD | NEW |