Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Side by Side Diff: components/filesystem/file_impl.cc

Issue 1147083002: mandoline: Fork the files service from the mojo repository. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: I think the problem was in the mandoline build.gn Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/filesystem/file_impl.h ('k') | components/filesystem/file_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/filesystem/file_impl.h"
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <sys/stat.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12
13 #include <limits>
14
15 #include "base/files/scoped_file.h"
16 #include "base/logging.h"
17 #include "base/posix/eintr_wrapper.h"
18 #include "components/filesystem/shared_impl.h"
19 #include "components/filesystem/util.h"
20
21 static_assert(sizeof(off_t) <= sizeof(int64_t), "off_t too big");
22 static_assert(sizeof(size_t) >= sizeof(uint32_t), "size_t too small");
23
24 namespace mojo {
25 namespace files {
26
27 const size_t kMaxReadSize = 1 * 1024 * 1024; // 1 MB.
28
29 FileImpl::FileImpl(InterfaceRequest<File> request, base::ScopedFD file_fd)
30 : binding_(this, request.Pass()), file_fd_(file_fd.Pass()) {
31 DCHECK(file_fd_.is_valid());
32 }
33
34 FileImpl::~FileImpl() {
35 }
36
37 void FileImpl::Close(const CloseCallback& callback) {
38 if (!file_fd_.is_valid()) {
39 callback.Run(ERROR_CLOSED);
40 return;
41 }
42 int fd_to_try_to_close = file_fd_.release();
43 // POSIX.1 (2013) leaves the validity of the FD undefined on EINTR and EIO. On
44 // Linux, the FD is always invalidated, so we'll pretend that the close
45 // succeeded. (On other Unixes, the situation may be different and possibly
46 // totally broken; see crbug.com/269623.)
47 if (IGNORE_EINTR(close(fd_to_try_to_close)) != 0) {
48 // Save errno, since we do a few things and we don't want it trampled.
49 int error = errno;
50 CHECK_NE(error, EBADF); // This should never happen.
51 DCHECK_NE(error, EINTR); // We already ignored EINTR.
52 // I don't know what Linux does on EIO (or any other errors) -- POSIX leaves
53 // it undefined -- so report the error and hope that the FD was invalidated.
54 callback.Run(ErrnoToError(error));
55 return;
56 }
57
58 callback.Run(ERROR_OK);
59 }
60
61 // TODO(vtl): Move the implementation to a thread pool.
62 void FileImpl::Read(uint32_t num_bytes_to_read,
63 int64_t offset,
64 Whence whence,
65 const ReadCallback& callback) {
66 if (!file_fd_.is_valid()) {
67 callback.Run(ERROR_CLOSED, Array<uint8_t>());
68 return;
69 }
70 if (num_bytes_to_read > kMaxReadSize) {
71 callback.Run(ERROR_OUT_OF_RANGE, Array<uint8_t>());
72 return;
73 }
74 if (Error error = IsOffsetValid(offset)) {
75 callback.Run(error, Array<uint8_t>());
76 return;
77 }
78 if (Error error = IsWhenceValid(whence)) {
79 callback.Run(error, Array<uint8_t>());
80 return;
81 }
82
83 if (offset != 0 || whence != WHENCE_FROM_CURRENT) {
84 // TODO(vtl): Use |pread()| below in the |WHENCE_FROM_START| case. This
85 // implementation is obviously not atomic. (If someone seeks simultaneously,
86 // we'll end up writing somewhere else. Or, well, we would if we were
87 // multithreaded.) Maybe we should do an |ftell()| and always use |pread()|.
88 // TODO(vtl): Possibly, at least sometimes we should not change the file
89 // position. See TODO in file.mojom.
90 if (lseek(file_fd_.get(), static_cast<off_t>(offset),
91 WhenceToStandardWhence(whence)) < 0) {
92 callback.Run(ErrnoToError(errno), Array<uint8_t>());
93 return;
94 }
95 }
96
97 Array<uint8_t> bytes_read(num_bytes_to_read);
98 ssize_t num_bytes_read = HANDLE_EINTR(
99 read(file_fd_.get(), &bytes_read.front(), num_bytes_to_read));
100 if (num_bytes_read < 0) {
101 callback.Run(ErrnoToError(errno), Array<uint8_t>());
102 return;
103 }
104
105 DCHECK_LE(static_cast<size_t>(num_bytes_read), num_bytes_to_read);
106 bytes_read.resize(static_cast<size_t>(num_bytes_read));
107 callback.Run(ERROR_OK, bytes_read.Pass());
108 }
109
110 // TODO(vtl): Move the implementation to a thread pool.
111 void FileImpl::Write(Array<uint8_t> bytes_to_write,
112 int64_t offset,
113 Whence whence,
114 const WriteCallback& callback) {
115 DCHECK(!bytes_to_write.is_null());
116
117 if (!file_fd_.is_valid()) {
118 callback.Run(ERROR_CLOSED, 0);
119 return;
120 }
121 // Who knows what |write()| would return if the size is that big (and it
122 // actually wrote that much).
123 if (bytes_to_write.size() >
124 static_cast<size_t>(std::numeric_limits<ssize_t>::max())) {
125 callback.Run(ERROR_OUT_OF_RANGE, 0);
126 return;
127 }
128 if (Error error = IsOffsetValid(offset)) {
129 callback.Run(error, 0);
130 return;
131 }
132 if (Error error = IsWhenceValid(whence)) {
133 callback.Run(error, 0);
134 return;
135 }
136
137 if (offset != 0 || whence != WHENCE_FROM_CURRENT) {
138 // TODO(vtl): Use |pwrite()| below in the |WHENCE_FROM_START| case. This
139 // implementation is obviously not atomic. (If someone seeks simultaneously,
140 // we'll end up writing somewhere else. Or, well, we would if we were
141 // multithreaded.) Maybe we should do an |ftell()| and always use
142 // |pwrite()|.
143 // TODO(vtl): Possibly, at least sometimes we should not change the file
144 // position. See TODO in file.mojom.
145 if (lseek(file_fd_.get(), static_cast<off_t>(offset),
146 WhenceToStandardWhence(whence)) < 0) {
147 callback.Run(ErrnoToError(errno), 0);
148 return;
149 }
150 }
151
152 const void* buf =
153 (bytes_to_write.size() > 0) ? &bytes_to_write.front() : nullptr;
154 ssize_t num_bytes_written =
155 HANDLE_EINTR(write(file_fd_.get(), buf, bytes_to_write.size()));
156 if (num_bytes_written < 0) {
157 callback.Run(ErrnoToError(errno), 0);
158 return;
159 }
160
161 DCHECK_LE(static_cast<size_t>(num_bytes_written),
162 std::numeric_limits<uint32_t>::max());
163 callback.Run(ERROR_OK, static_cast<uint32_t>(num_bytes_written));
164 }
165
166 void FileImpl::ReadToStream(ScopedDataPipeProducerHandle source,
167 int64_t offset,
168 Whence whence,
169 int64_t num_bytes_to_read,
170 const ReadToStreamCallback& callback) {
171 if (!file_fd_.is_valid()) {
172 callback.Run(ERROR_CLOSED);
173 return;
174 }
175 if (Error error = IsOffsetValid(offset)) {
176 callback.Run(error);
177 return;
178 }
179 if (Error error = IsWhenceValid(whence)) {
180 callback.Run(error);
181 return;
182 }
183
184 // TODO(vtl): FIXME soon
185 NOTIMPLEMENTED();
186 callback.Run(ERROR_UNIMPLEMENTED);
187 }
188
189 void FileImpl::WriteFromStream(ScopedDataPipeConsumerHandle sink,
190 int64_t offset,
191 Whence whence,
192 const WriteFromStreamCallback& callback) {
193 if (!file_fd_.is_valid()) {
194 callback.Run(ERROR_CLOSED);
195 return;
196 }
197 if (Error error = IsOffsetValid(offset)) {
198 callback.Run(error);
199 return;
200 }
201 if (Error error = IsWhenceValid(whence)) {
202 callback.Run(error);
203 return;
204 }
205
206 // TODO(vtl): FIXME soon
207 NOTIMPLEMENTED();
208 callback.Run(ERROR_UNIMPLEMENTED);
209 }
210
211 void FileImpl::Tell(const TellCallback& callback) {
212 Seek(0, WHENCE_FROM_CURRENT, callback);
213 }
214
215 void FileImpl::Seek(int64_t offset,
216 Whence whence,
217 const SeekCallback& callback) {
218 if (!file_fd_.is_valid()) {
219 callback.Run(ERROR_CLOSED, 0);
220 return;
221 }
222 if (Error error = IsOffsetValid(offset)) {
223 callback.Run(error, 0);
224 return;
225 }
226 if (Error error = IsWhenceValid(whence)) {
227 callback.Run(error, 0);
228 return;
229 }
230
231 off_t position = lseek(file_fd_.get(), static_cast<off_t>(offset),
232 WhenceToStandardWhence(whence));
233 if (position < 0) {
234 callback.Run(ErrnoToError(errno), 0);
235 return;
236 }
237
238 callback.Run(ERROR_OK, static_cast<int64>(position));
239 }
240
241 void FileImpl::Stat(const StatCallback& callback) {
242 if (!file_fd_.is_valid()) {
243 callback.Run(ERROR_CLOSED, nullptr);
244 return;
245 }
246 StatFD(file_fd_.get(), FILE_TYPE_REGULAR_FILE, callback);
247 }
248
249 void FileImpl::Truncate(int64_t size, const TruncateCallback& callback) {
250 if (!file_fd_.is_valid()) {
251 callback.Run(ERROR_CLOSED);
252 return;
253 }
254 if (size < 0) {
255 callback.Run(ERROR_INVALID_ARGUMENT);
256 return;
257 }
258 if (Error error = IsOffsetValid(size)) {
259 callback.Run(error);
260 return;
261 }
262
263 if (ftruncate(file_fd_.get(), static_cast<off_t>(size)) != 0) {
264 callback.Run(ErrnoToError(errno));
265 return;
266 }
267
268 callback.Run(ERROR_OK);
269 }
270
271 void FileImpl::Touch(TimespecOrNowPtr atime,
272 TimespecOrNowPtr mtime,
273 const TouchCallback& callback) {
274 if (!file_fd_.is_valid()) {
275 callback.Run(ERROR_CLOSED);
276 return;
277 }
278 TouchFD(file_fd_.get(), atime.Pass(), mtime.Pass(), callback);
279 }
280
281 void FileImpl::Dup(InterfaceRequest<File> file, const DupCallback& callback) {
282 if (!file_fd_.is_valid()) {
283 callback.Run(ERROR_CLOSED);
284 return;
285 }
286
287 base::ScopedFD file_fd(dup(file_fd_.get()));
288 if (!file_fd.is_valid()) {
289 callback.Run(ErrnoToError(errno));
290 return;
291 }
292
293 new FileImpl(file.Pass(), file_fd.Pass());
294 callback.Run(ERROR_OK);
295 }
296
297 void FileImpl::Reopen(InterfaceRequest<File> file,
298 uint32_t open_flags,
299 const ReopenCallback& callback) {
300 if (!file_fd_.is_valid()) {
301 callback.Run(ERROR_CLOSED);
302 return;
303 }
304
305 // TODO(vtl): FIXME soon
306 NOTIMPLEMENTED();
307 callback.Run(ERROR_UNIMPLEMENTED);
308 }
309
310 void FileImpl::AsBuffer(const AsBufferCallback& callback) {
311 if (!file_fd_.is_valid()) {
312 callback.Run(ERROR_CLOSED, ScopedSharedBufferHandle());
313 return;
314 }
315
316 // TODO(vtl): FIXME soon
317 NOTIMPLEMENTED();
318 callback.Run(ERROR_UNIMPLEMENTED, ScopedSharedBufferHandle());
319 }
320
321 void FileImpl::Ioctl(uint32_t request,
322 Array<uint32_t> in_values,
323 const IoctlCallback& callback) {
324 if (!file_fd_.is_valid()) {
325 callback.Run(ERROR_CLOSED, Array<uint32_t>());
326 return;
327 }
328
329 // TODO(vtl): The "correct" error code should be one that can be translated to
330 // ENOTTY!
331 callback.Run(ERROR_UNAVAILABLE, Array<uint32_t>());
332 }
333
334 } // namespace files
335 } // namespace mojo
OLDNEW
« no previous file with comments | « components/filesystem/file_impl.h ('k') | components/filesystem/file_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698