OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 #include "components/filesystem/file_impl.h" | 5 #include "components/filesystem/file_impl.h" |
6 | 6 |
| 7 #include <stdint.h> |
7 #include <limits> | 8 #include <limits> |
8 | 9 |
9 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
10 #include "base/files/scoped_file.h" | 11 #include "base/files/scoped_file.h" |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "components/filesystem/util.h" | 13 #include "components/filesystem/util.h" |
13 #include "mojo/platform_handle/platform_handle_functions.h" | 14 #include "mojo/platform_handle/platform_handle_functions.h" |
14 | 15 |
15 static_assert(sizeof(off_t) <= sizeof(int64_t), "off_t too big"); | 16 static_assert(sizeof(off_t) <= sizeof(int64_t), "off_t too big"); |
16 static_assert(sizeof(size_t) >= sizeof(uint32_t), "size_t too small"); | 17 static_assert(sizeof(size_t) >= sizeof(uint32_t), "size_t too small"); |
(...skipping 20 matching lines...) Expand all Loading... |
37 FileImpl::~FileImpl() { | 38 FileImpl::~FileImpl() { |
38 } | 39 } |
39 | 40 |
40 void FileImpl::Close(const CloseCallback& callback) { | 41 void FileImpl::Close(const CloseCallback& callback) { |
41 if (!file_.IsValid()) { | 42 if (!file_.IsValid()) { |
42 callback.Run(GetError(file_)); | 43 callback.Run(GetError(file_)); |
43 return; | 44 return; |
44 } | 45 } |
45 | 46 |
46 file_.Close(); | 47 file_.Close(); |
47 callback.Run(ERROR_OK); | 48 callback.Run(FILE_ERROR_OK); |
48 } | 49 } |
49 | 50 |
50 // TODO(vtl): Move the implementation to a thread pool. | 51 // TODO(vtl): Move the implementation to a thread pool. |
51 void FileImpl::Read(uint32_t num_bytes_to_read, | 52 void FileImpl::Read(uint32_t num_bytes_to_read, |
52 int64_t offset, | 53 int64_t offset, |
53 Whence whence, | 54 Whence whence, |
54 const ReadCallback& callback) { | 55 const ReadCallback& callback) { |
55 if (!file_.IsValid()) { | 56 if (!file_.IsValid()) { |
56 callback.Run(GetError(file_), mojo::Array<uint8_t>()); | 57 callback.Run(GetError(file_), mojo::Array<uint8_t>()); |
57 return; | 58 return; |
58 } | 59 } |
59 if (num_bytes_to_read > kMaxReadSize) { | 60 if (num_bytes_to_read > kMaxReadSize) { |
60 callback.Run(ERROR_INVALID_OPERATION, mojo::Array<uint8_t>()); | 61 callback.Run(FILE_ERROR_INVALID_OPERATION, mojo::Array<uint8_t>()); |
61 return; | 62 return; |
62 } | 63 } |
63 if (Error error = IsOffsetValid(offset)) { | 64 if (FileError error = IsOffsetValid(offset)) { |
64 callback.Run(error, mojo::Array<uint8_t>()); | 65 callback.Run(error, mojo::Array<uint8_t>()); |
65 return; | 66 return; |
66 } | 67 } |
67 if (Error error = IsWhenceValid(whence)) { | 68 if (FileError error = IsWhenceValid(whence)) { |
68 callback.Run(error, mojo::Array<uint8_t>()); | 69 callback.Run(error, mojo::Array<uint8_t>()); |
69 return; | 70 return; |
70 } | 71 } |
71 | 72 |
72 if (file_.Seek(static_cast<base::File::Whence>(whence), offset) == -1) { | 73 if (file_.Seek(static_cast<base::File::Whence>(whence), offset) == -1) { |
73 callback.Run(ERROR_FAILED, mojo::Array<uint8_t>()); | 74 callback.Run(FILE_ERROR_FAILED, mojo::Array<uint8_t>()); |
74 return; | 75 return; |
75 } | 76 } |
76 | 77 |
77 mojo::Array<uint8_t> bytes_read(num_bytes_to_read); | 78 mojo::Array<uint8_t> bytes_read(num_bytes_to_read); |
78 int num_bytes_read = file_.ReadAtCurrentPos( | 79 int num_bytes_read = file_.ReadAtCurrentPos( |
79 reinterpret_cast<char*>(&bytes_read.front()), num_bytes_to_read); | 80 reinterpret_cast<char*>(&bytes_read.front()), num_bytes_to_read); |
80 if (num_bytes_read < 0) { | 81 if (num_bytes_read < 0) { |
81 callback.Run(ERROR_FAILED, mojo::Array<uint8_t>()); | 82 callback.Run(FILE_ERROR_FAILED, mojo::Array<uint8_t>()); |
82 return; | 83 return; |
83 } | 84 } |
84 | 85 |
85 DCHECK_LE(static_cast<size_t>(num_bytes_read), num_bytes_to_read); | 86 DCHECK_LE(static_cast<size_t>(num_bytes_read), num_bytes_to_read); |
86 bytes_read.resize(static_cast<size_t>(num_bytes_read)); | 87 bytes_read.resize(static_cast<size_t>(num_bytes_read)); |
87 callback.Run(ERROR_OK, bytes_read.Pass()); | 88 callback.Run(FILE_ERROR_OK, bytes_read.Pass()); |
88 } | 89 } |
89 | 90 |
90 // TODO(vtl): Move the implementation to a thread pool. | 91 // TODO(vtl): Move the implementation to a thread pool. |
91 void FileImpl::Write(mojo::Array<uint8_t> bytes_to_write, | 92 void FileImpl::Write(mojo::Array<uint8_t> bytes_to_write, |
92 int64_t offset, | 93 int64_t offset, |
93 Whence whence, | 94 Whence whence, |
94 const WriteCallback& callback) { | 95 const WriteCallback& callback) { |
95 DCHECK(!bytes_to_write.is_null()); | 96 DCHECK(!bytes_to_write.is_null()); |
96 if (!file_.IsValid()) { | 97 if (!file_.IsValid()) { |
97 callback.Run(GetError(file_), 0); | 98 callback.Run(GetError(file_), 0); |
98 return; | 99 return; |
99 } | 100 } |
100 // Who knows what |write()| would return if the size is that big (and it | 101 // Who knows what |write()| would return if the size is that big (and it |
101 // actually wrote that much). | 102 // actually wrote that much). |
102 if (bytes_to_write.size() > | 103 if (bytes_to_write.size() > |
| 104 #if defined(OS_WIN) |
| 105 std::numeric_limits<DWORD>::max()) { |
| 106 #else |
103 static_cast<size_t>(std::numeric_limits<ssize_t>::max())) { | 107 static_cast<size_t>(std::numeric_limits<ssize_t>::max())) { |
104 callback.Run(ERROR_INVALID_OPERATION, 0); | 108 #endif |
| 109 callback.Run(FILE_ERROR_INVALID_OPERATION, 0); |
105 return; | 110 return; |
106 } | 111 } |
107 if (Error error = IsOffsetValid(offset)) { | 112 if (FileError error = IsOffsetValid(offset)) { |
108 callback.Run(error, 0); | 113 callback.Run(error, 0); |
109 return; | 114 return; |
110 } | 115 } |
111 if (Error error = IsWhenceValid(whence)) { | 116 if (FileError error = IsWhenceValid(whence)) { |
112 callback.Run(error, 0); | 117 callback.Run(error, 0); |
113 return; | 118 return; |
114 } | 119 } |
115 | 120 |
116 if (file_.Seek(static_cast<base::File::Whence>(whence), offset) == -1) { | 121 if (file_.Seek(static_cast<base::File::Whence>(whence), offset) == -1) { |
117 callback.Run(ERROR_FAILED, 0); | 122 callback.Run(FILE_ERROR_FAILED, 0); |
118 return; | 123 return; |
119 } | 124 } |
120 | 125 |
121 const char* buf = (bytes_to_write.size() > 0) | 126 const char* buf = (bytes_to_write.size() > 0) |
122 ? reinterpret_cast<char*>(&bytes_to_write.front()) | 127 ? reinterpret_cast<char*>(&bytes_to_write.front()) |
123 : nullptr; | 128 : nullptr; |
124 int num_bytes_written = file_.WriteAtCurrentPos(buf, bytes_to_write.size()); | 129 int num_bytes_written = file_.WriteAtCurrentPos(buf, bytes_to_write.size()); |
125 if (num_bytes_written < 0) { | 130 if (num_bytes_written < 0) { |
126 callback.Run(ERROR_FAILED, 0); | 131 callback.Run(FILE_ERROR_FAILED, 0); |
127 return; | 132 return; |
128 } | 133 } |
129 | 134 |
130 DCHECK_LE(static_cast<size_t>(num_bytes_written), | 135 DCHECK_LE(static_cast<size_t>(num_bytes_written), |
131 std::numeric_limits<uint32_t>::max()); | 136 std::numeric_limits<uint32_t>::max()); |
132 callback.Run(ERROR_OK, static_cast<uint32_t>(num_bytes_written)); | 137 callback.Run(FILE_ERROR_OK, static_cast<uint32_t>(num_bytes_written)); |
133 } | 138 } |
134 | 139 |
135 void FileImpl::Tell(const TellCallback& callback) { | 140 void FileImpl::Tell(const TellCallback& callback) { |
136 Seek(0, WHENCE_FROM_CURRENT, callback); | 141 Seek(0, WHENCE_FROM_CURRENT, callback); |
137 } | 142 } |
138 | 143 |
139 void FileImpl::Seek(int64_t offset, | 144 void FileImpl::Seek(int64_t offset, |
140 Whence whence, | 145 Whence whence, |
141 const SeekCallback& callback) { | 146 const SeekCallback& callback) { |
142 if (!file_.IsValid()) { | 147 if (!file_.IsValid()) { |
143 callback.Run(GetError(file_), 0); | 148 callback.Run(GetError(file_), 0); |
144 return; | 149 return; |
145 } | 150 } |
146 if (Error error = IsOffsetValid(offset)) { | 151 if (FileError error = IsOffsetValid(offset)) { |
147 callback.Run(error, 0); | 152 callback.Run(error, 0); |
148 return; | 153 return; |
149 } | 154 } |
150 if (Error error = IsWhenceValid(whence)) { | 155 if (FileError error = IsWhenceValid(whence)) { |
151 callback.Run(error, 0); | 156 callback.Run(error, 0); |
152 return; | 157 return; |
153 } | 158 } |
154 | 159 |
155 int64 position = file_.Seek(static_cast<base::File::Whence>(whence), offset); | 160 int64 position = file_.Seek(static_cast<base::File::Whence>(whence), offset); |
156 if (position < 0) { | 161 if (position < 0) { |
157 callback.Run(ERROR_FAILED, 0); | 162 callback.Run(FILE_ERROR_FAILED, 0); |
158 return; | 163 return; |
159 } | 164 } |
160 | 165 |
161 callback.Run(ERROR_OK, static_cast<int64>(position)); | 166 callback.Run(FILE_ERROR_OK, static_cast<int64>(position)); |
162 } | 167 } |
163 | 168 |
164 void FileImpl::Stat(const StatCallback& callback) { | 169 void FileImpl::Stat(const StatCallback& callback) { |
165 if (!file_.IsValid()) { | 170 if (!file_.IsValid()) { |
166 callback.Run(GetError(file_), nullptr); | 171 callback.Run(GetError(file_), nullptr); |
167 return; | 172 return; |
168 } | 173 } |
169 | 174 |
170 base::File::Info info; | 175 base::File::Info info; |
171 if (!file_.GetInfo(&info)) { | 176 if (!file_.GetInfo(&info)) { |
172 callback.Run(ERROR_FAILED, nullptr); | 177 callback.Run(FILE_ERROR_FAILED, nullptr); |
173 return; | 178 return; |
174 } | 179 } |
175 | 180 |
176 callback.Run(ERROR_OK, MakeFileInformation(info).Pass()); | 181 callback.Run(FILE_ERROR_OK, MakeFileInformation(info).Pass()); |
177 } | 182 } |
178 | 183 |
179 void FileImpl::Truncate(int64_t size, const TruncateCallback& callback) { | 184 void FileImpl::Truncate(int64_t size, const TruncateCallback& callback) { |
180 if (!file_.IsValid()) { | 185 if (!file_.IsValid()) { |
181 callback.Run(GetError(file_)); | 186 callback.Run(GetError(file_)); |
182 return; | 187 return; |
183 } | 188 } |
184 if (size < 0) { | 189 if (size < 0) { |
185 callback.Run(ERROR_INVALID_OPERATION); | 190 callback.Run(FILE_ERROR_INVALID_OPERATION); |
186 return; | 191 return; |
187 } | 192 } |
188 if (Error error = IsOffsetValid(size)) { | 193 if (FileError error = IsOffsetValid(size)) { |
189 callback.Run(error); | 194 callback.Run(error); |
190 return; | 195 return; |
191 } | 196 } |
192 | 197 |
193 if (!file_.SetLength(size)) { | 198 if (!file_.SetLength(size)) { |
194 callback.Run(ERROR_NOT_FOUND); | 199 callback.Run(FILE_ERROR_NOT_FOUND); |
195 return; | 200 return; |
196 } | 201 } |
197 | 202 |
198 callback.Run(ERROR_OK); | 203 callback.Run(FILE_ERROR_OK); |
199 } | 204 } |
200 | 205 |
201 void FileImpl::Touch(TimespecOrNowPtr atime, | 206 void FileImpl::Touch(TimespecOrNowPtr atime, |
202 TimespecOrNowPtr mtime, | 207 TimespecOrNowPtr mtime, |
203 const TouchCallback& callback) { | 208 const TouchCallback& callback) { |
204 if (!file_.IsValid()) { | 209 if (!file_.IsValid()) { |
205 callback.Run(GetError(file_)); | 210 callback.Run(GetError(file_)); |
206 return; | 211 return; |
207 } | 212 } |
208 | 213 |
209 base::Time base_atime = Time::Now(); | 214 base::Time base_atime = Time::Now(); |
210 if (!atime) { | 215 if (!atime) { |
211 base::File::Info info; | 216 base::File::Info info; |
212 if (!file_.GetInfo(&info)) { | 217 if (!file_.GetInfo(&info)) { |
213 callback.Run(ERROR_FAILED); | 218 callback.Run(FILE_ERROR_FAILED); |
214 return; | 219 return; |
215 } | 220 } |
216 | 221 |
217 base_atime = info.last_accessed; | 222 base_atime = info.last_accessed; |
218 } else if (!atime->now) { | 223 } else if (!atime->now) { |
219 base_atime = Time::FromDoubleT(atime->seconds); | 224 base_atime = Time::FromDoubleT(atime->seconds); |
220 } | 225 } |
221 | 226 |
222 base::Time base_mtime = Time::Now(); | 227 base::Time base_mtime = Time::Now(); |
223 if (!mtime) { | 228 if (!mtime) { |
224 base::File::Info info; | 229 base::File::Info info; |
225 if (!file_.GetInfo(&info)) { | 230 if (!file_.GetInfo(&info)) { |
226 callback.Run(ERROR_FAILED); | 231 callback.Run(FILE_ERROR_FAILED); |
227 return; | 232 return; |
228 } | 233 } |
229 | 234 |
230 base_mtime = info.last_modified; | 235 base_mtime = info.last_modified; |
231 } else if (!mtime->now) { | 236 } else if (!mtime->now) { |
232 base_mtime = Time::FromDoubleT(mtime->seconds); | 237 base_mtime = Time::FromDoubleT(mtime->seconds); |
233 } | 238 } |
234 | 239 |
235 file_.SetTimes(base_atime, base_mtime); | 240 file_.SetTimes(base_atime, base_mtime); |
236 callback.Run(ERROR_OK); | 241 callback.Run(FILE_ERROR_OK); |
237 } | 242 } |
238 | 243 |
239 void FileImpl::Dup(mojo::InterfaceRequest<File> file, | 244 void FileImpl::Dup(mojo::InterfaceRequest<File> file, |
240 const DupCallback& callback) { | 245 const DupCallback& callback) { |
241 if (!file_.IsValid()) { | 246 if (!file_.IsValid()) { |
242 callback.Run(GetError(file_)); | 247 callback.Run(GetError(file_)); |
243 return; | 248 return; |
244 } | 249 } |
245 | 250 |
246 base::File new_file = file_.Duplicate(); | 251 base::File new_file = file_.Duplicate(); |
247 if (!new_file.IsValid()) { | 252 if (!new_file.IsValid()) { |
248 callback.Run(GetError(new_file)); | 253 callback.Run(GetError(new_file)); |
249 return; | 254 return; |
250 } | 255 } |
251 | 256 |
252 if (file.is_pending()) | 257 if (file.is_pending()) |
253 new FileImpl(file.Pass(), new_file.Pass()); | 258 new FileImpl(file.Pass(), new_file.Pass()); |
254 callback.Run(ERROR_OK); | 259 callback.Run(FILE_ERROR_OK); |
255 } | 260 } |
256 | 261 |
257 void FileImpl::AsHandle(const AsHandleCallback& callback) { | 262 void FileImpl::AsHandle(const AsHandleCallback& callback) { |
258 if (!file_.IsValid()) { | 263 if (!file_.IsValid()) { |
259 callback.Run(GetError(file_), ScopedHandle()); | 264 callback.Run(GetError(file_), ScopedHandle()); |
260 return; | 265 return; |
261 } | 266 } |
262 | 267 |
263 base::File new_file = file_.Duplicate(); | 268 base::File new_file = file_.Duplicate(); |
264 if (!new_file.IsValid()) { | 269 if (!new_file.IsValid()) { |
265 callback.Run(GetError(new_file), ScopedHandle()); | 270 callback.Run(GetError(new_file), ScopedHandle()); |
266 return; | 271 return; |
267 } | 272 } |
268 | 273 |
269 base::File::Info info; | 274 base::File::Info info; |
270 if (!new_file.GetInfo(&info)) { | 275 if (!new_file.GetInfo(&info)) { |
271 callback.Run(ERROR_FAILED, ScopedHandle()); | 276 callback.Run(FILE_ERROR_FAILED, ScopedHandle()); |
272 return; | 277 return; |
273 } | 278 } |
274 | 279 |
275 // Perform one additional check right before we send the file's file | 280 // Perform one additional check right before we send the file's file |
276 // descriptor over mojo. This is theoretically redundant, but given that | 281 // descriptor over mojo. This is theoretically redundant, but given that |
277 // passing a file descriptor to a directory is a sandbox escape on Windows, | 282 // passing a file descriptor to a directory is a sandbox escape on Windows, |
278 // we should be absolutely paranoid. | 283 // we should be absolutely paranoid. |
279 if (info.is_directory) { | 284 if (info.is_directory) { |
280 callback.Run(ERROR_NOT_A_FILE, ScopedHandle()); | 285 callback.Run(FILE_ERROR_NOT_A_FILE, ScopedHandle()); |
281 return; | 286 return; |
282 } | 287 } |
283 | 288 |
284 MojoHandle mojo_handle; | 289 MojoHandle mojo_handle; |
285 MojoResult create_result = MojoCreatePlatformHandleWrapper( | 290 MojoResult create_result = MojoCreatePlatformHandleWrapper( |
286 new_file.TakePlatformFile(), &mojo_handle); | 291 new_file.TakePlatformFile(), &mojo_handle); |
287 if (create_result != MOJO_RESULT_OK) { | 292 if (create_result != MOJO_RESULT_OK) { |
288 callback.Run(ERROR_FAILED, ScopedHandle()); | 293 callback.Run(FILE_ERROR_FAILED, ScopedHandle()); |
289 return; | 294 return; |
290 } | 295 } |
291 | 296 |
292 callback.Run(ERROR_OK, ScopedHandle(mojo::Handle(mojo_handle)).Pass()); | 297 callback.Run(FILE_ERROR_OK, ScopedHandle(mojo::Handle(mojo_handle)).Pass()); |
293 } | 298 } |
294 | 299 |
295 } // namespace filesystem | 300 } // namespace filesystem |
OLD | NEW |