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 |