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<INT>::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( |
| 130 buf, static_cast<int>(bytes_to_write.size())); |
125 if (num_bytes_written < 0) { | 131 if (num_bytes_written < 0) { |
126 callback.Run(ERROR_FAILED, 0); | 132 callback.Run(FILE_ERROR_FAILED, 0); |
127 return; | 133 return; |
128 } | 134 } |
129 | 135 |
130 DCHECK_LE(static_cast<size_t>(num_bytes_written), | 136 DCHECK_LE(static_cast<size_t>(num_bytes_written), |
131 std::numeric_limits<uint32_t>::max()); | 137 std::numeric_limits<uint32_t>::max()); |
132 callback.Run(ERROR_OK, static_cast<uint32_t>(num_bytes_written)); | 138 callback.Run(FILE_ERROR_OK, static_cast<uint32_t>(num_bytes_written)); |
133 } | 139 } |
134 | 140 |
135 void FileImpl::Tell(const TellCallback& callback) { | 141 void FileImpl::Tell(const TellCallback& callback) { |
136 Seek(0, WHENCE_FROM_CURRENT, callback); | 142 Seek(0, WHENCE_FROM_CURRENT, callback); |
137 } | 143 } |
138 | 144 |
139 void FileImpl::Seek(int64_t offset, | 145 void FileImpl::Seek(int64_t offset, |
140 Whence whence, | 146 Whence whence, |
141 const SeekCallback& callback) { | 147 const SeekCallback& callback) { |
142 if (!file_.IsValid()) { | 148 if (!file_.IsValid()) { |
143 callback.Run(GetError(file_), 0); | 149 callback.Run(GetError(file_), 0); |
144 return; | 150 return; |
145 } | 151 } |
146 if (Error error = IsOffsetValid(offset)) { | 152 if (FileError error = IsOffsetValid(offset)) { |
147 callback.Run(error, 0); | 153 callback.Run(error, 0); |
148 return; | 154 return; |
149 } | 155 } |
150 if (Error error = IsWhenceValid(whence)) { | 156 if (FileError error = IsWhenceValid(whence)) { |
151 callback.Run(error, 0); | 157 callback.Run(error, 0); |
152 return; | 158 return; |
153 } | 159 } |
154 | 160 |
155 int64 position = file_.Seek(static_cast<base::File::Whence>(whence), offset); | 161 int64 position = file_.Seek(static_cast<base::File::Whence>(whence), offset); |
156 if (position < 0) { | 162 if (position < 0) { |
157 callback.Run(ERROR_FAILED, 0); | 163 callback.Run(FILE_ERROR_FAILED, 0); |
158 return; | 164 return; |
159 } | 165 } |
160 | 166 |
161 callback.Run(ERROR_OK, static_cast<int64>(position)); | 167 callback.Run(FILE_ERROR_OK, static_cast<int64>(position)); |
162 } | 168 } |
163 | 169 |
164 void FileImpl::Stat(const StatCallback& callback) { | 170 void FileImpl::Stat(const StatCallback& callback) { |
165 if (!file_.IsValid()) { | 171 if (!file_.IsValid()) { |
166 callback.Run(GetError(file_), nullptr); | 172 callback.Run(GetError(file_), nullptr); |
167 return; | 173 return; |
168 } | 174 } |
169 | 175 |
170 base::File::Info info; | 176 base::File::Info info; |
171 if (!file_.GetInfo(&info)) { | 177 if (!file_.GetInfo(&info)) { |
172 callback.Run(ERROR_FAILED, nullptr); | 178 callback.Run(FILE_ERROR_FAILED, nullptr); |
173 return; | 179 return; |
174 } | 180 } |
175 | 181 |
176 callback.Run(ERROR_OK, MakeFileInformation(info).Pass()); | 182 callback.Run(FILE_ERROR_OK, MakeFileInformation(info).Pass()); |
177 } | 183 } |
178 | 184 |
179 void FileImpl::Truncate(int64_t size, const TruncateCallback& callback) { | 185 void FileImpl::Truncate(int64_t size, const TruncateCallback& callback) { |
180 if (!file_.IsValid()) { | 186 if (!file_.IsValid()) { |
181 callback.Run(GetError(file_)); | 187 callback.Run(GetError(file_)); |
182 return; | 188 return; |
183 } | 189 } |
184 if (size < 0) { | 190 if (size < 0) { |
185 callback.Run(ERROR_INVALID_OPERATION); | 191 callback.Run(FILE_ERROR_INVALID_OPERATION); |
186 return; | 192 return; |
187 } | 193 } |
188 if (Error error = IsOffsetValid(size)) { | 194 if (FileError error = IsOffsetValid(size)) { |
189 callback.Run(error); | 195 callback.Run(error); |
190 return; | 196 return; |
191 } | 197 } |
192 | 198 |
193 if (!file_.SetLength(size)) { | 199 if (!file_.SetLength(size)) { |
194 callback.Run(ERROR_NOT_FOUND); | 200 callback.Run(FILE_ERROR_NOT_FOUND); |
195 return; | 201 return; |
196 } | 202 } |
197 | 203 |
198 callback.Run(ERROR_OK); | 204 callback.Run(FILE_ERROR_OK); |
199 } | 205 } |
200 | 206 |
201 void FileImpl::Touch(TimespecOrNowPtr atime, | 207 void FileImpl::Touch(TimespecOrNowPtr atime, |
202 TimespecOrNowPtr mtime, | 208 TimespecOrNowPtr mtime, |
203 const TouchCallback& callback) { | 209 const TouchCallback& callback) { |
204 if (!file_.IsValid()) { | 210 if (!file_.IsValid()) { |
205 callback.Run(GetError(file_)); | 211 callback.Run(GetError(file_)); |
206 return; | 212 return; |
207 } | 213 } |
208 | 214 |
209 base::Time base_atime = Time::Now(); | 215 base::Time base_atime = Time::Now(); |
210 if (!atime) { | 216 if (!atime) { |
211 base::File::Info info; | 217 base::File::Info info; |
212 if (!file_.GetInfo(&info)) { | 218 if (!file_.GetInfo(&info)) { |
213 callback.Run(ERROR_FAILED); | 219 callback.Run(FILE_ERROR_FAILED); |
214 return; | 220 return; |
215 } | 221 } |
216 | 222 |
217 base_atime = info.last_accessed; | 223 base_atime = info.last_accessed; |
218 } else if (!atime->now) { | 224 } else if (!atime->now) { |
219 base_atime = Time::FromDoubleT(atime->seconds); | 225 base_atime = Time::FromDoubleT(atime->seconds); |
220 } | 226 } |
221 | 227 |
222 base::Time base_mtime = Time::Now(); | 228 base::Time base_mtime = Time::Now(); |
223 if (!mtime) { | 229 if (!mtime) { |
224 base::File::Info info; | 230 base::File::Info info; |
225 if (!file_.GetInfo(&info)) { | 231 if (!file_.GetInfo(&info)) { |
226 callback.Run(ERROR_FAILED); | 232 callback.Run(FILE_ERROR_FAILED); |
227 return; | 233 return; |
228 } | 234 } |
229 | 235 |
230 base_mtime = info.last_modified; | 236 base_mtime = info.last_modified; |
231 } else if (!mtime->now) { | 237 } else if (!mtime->now) { |
232 base_mtime = Time::FromDoubleT(mtime->seconds); | 238 base_mtime = Time::FromDoubleT(mtime->seconds); |
233 } | 239 } |
234 | 240 |
235 file_.SetTimes(base_atime, base_mtime); | 241 file_.SetTimes(base_atime, base_mtime); |
236 callback.Run(ERROR_OK); | 242 callback.Run(FILE_ERROR_OK); |
237 } | 243 } |
238 | 244 |
239 void FileImpl::Dup(mojo::InterfaceRequest<File> file, | 245 void FileImpl::Dup(mojo::InterfaceRequest<File> file, |
240 const DupCallback& callback) { | 246 const DupCallback& callback) { |
241 if (!file_.IsValid()) { | 247 if (!file_.IsValid()) { |
242 callback.Run(GetError(file_)); | 248 callback.Run(GetError(file_)); |
243 return; | 249 return; |
244 } | 250 } |
245 | 251 |
246 base::File new_file = file_.Duplicate(); | 252 base::File new_file = file_.Duplicate(); |
247 if (!new_file.IsValid()) { | 253 if (!new_file.IsValid()) { |
248 callback.Run(GetError(new_file)); | 254 callback.Run(GetError(new_file)); |
249 return; | 255 return; |
250 } | 256 } |
251 | 257 |
252 if (file.is_pending()) | 258 if (file.is_pending()) |
253 new FileImpl(file.Pass(), new_file.Pass()); | 259 new FileImpl(file.Pass(), new_file.Pass()); |
254 callback.Run(ERROR_OK); | 260 callback.Run(FILE_ERROR_OK); |
255 } | 261 } |
256 | 262 |
257 void FileImpl::AsHandle(const AsHandleCallback& callback) { | 263 void FileImpl::AsHandle(const AsHandleCallback& callback) { |
258 if (!file_.IsValid()) { | 264 if (!file_.IsValid()) { |
259 callback.Run(GetError(file_), ScopedHandle()); | 265 callback.Run(GetError(file_), ScopedHandle()); |
260 return; | 266 return; |
261 } | 267 } |
262 | 268 |
263 base::File new_file = file_.Duplicate(); | 269 base::File new_file = file_.Duplicate(); |
264 if (!new_file.IsValid()) { | 270 if (!new_file.IsValid()) { |
265 callback.Run(GetError(new_file), ScopedHandle()); | 271 callback.Run(GetError(new_file), ScopedHandle()); |
266 return; | 272 return; |
267 } | 273 } |
268 | 274 |
269 base::File::Info info; | 275 base::File::Info info; |
270 if (!new_file.GetInfo(&info)) { | 276 if (!new_file.GetInfo(&info)) { |
271 callback.Run(ERROR_FAILED, ScopedHandle()); | 277 callback.Run(FILE_ERROR_FAILED, ScopedHandle()); |
272 return; | 278 return; |
273 } | 279 } |
274 | 280 |
275 // Perform one additional check right before we send the file's file | 281 // Perform one additional check right before we send the file's file |
276 // descriptor over mojo. This is theoretically redundant, but given that | 282 // descriptor over mojo. This is theoretically redundant, but given that |
277 // passing a file descriptor to a directory is a sandbox escape on Windows, | 283 // passing a file descriptor to a directory is a sandbox escape on Windows, |
278 // we should be absolutely paranoid. | 284 // we should be absolutely paranoid. |
279 if (info.is_directory) { | 285 if (info.is_directory) { |
280 callback.Run(ERROR_NOT_A_FILE, ScopedHandle()); | 286 callback.Run(FILE_ERROR_NOT_A_FILE, ScopedHandle()); |
281 return; | 287 return; |
282 } | 288 } |
283 | 289 |
284 MojoHandle mojo_handle; | 290 MojoHandle mojo_handle; |
285 MojoResult create_result = MojoCreatePlatformHandleWrapper( | 291 MojoResult create_result = MojoCreatePlatformHandleWrapper( |
286 new_file.TakePlatformFile(), &mojo_handle); | 292 new_file.TakePlatformFile(), &mojo_handle); |
287 if (create_result != MOJO_RESULT_OK) { | 293 if (create_result != MOJO_RESULT_OK) { |
288 callback.Run(ERROR_FAILED, ScopedHandle()); | 294 callback.Run(FILE_ERROR_FAILED, ScopedHandle()); |
289 return; | 295 return; |
290 } | 296 } |
291 | 297 |
292 callback.Run(ERROR_OK, ScopedHandle(mojo::Handle(mojo_handle)).Pass()); | 298 callback.Run(FILE_ERROR_OK, ScopedHandle(mojo::Handle(mojo_handle)).Pass()); |
293 } | 299 } |
294 | 300 |
295 } // namespace filesystem | 301 } // namespace filesystem |
OLD | NEW |