• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
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 "net/base/file_stream_context.h"
6 
7 #include <errno.h>
8 
9 #include <optional>
10 #include <utility>
11 
12 #include "base/check.h"
13 #include "base/files/file_path.h"
14 #include "base/functional/bind.h"
15 #include "base/functional/callback.h"
16 #include "base/functional/callback_helpers.h"
17 #include "base/location.h"
18 #include "base/numerics/safe_conversions.h"
19 #include "base/posix/eintr_wrapper.h"
20 #include "base/task/task_runner.h"
21 #include "net/base/io_buffer.h"
22 #include "net/base/net_errors.h"
23 
24 #if BUILDFLAG(IS_MAC)
25 #include "net/base/apple/guarded_fd.h"
26 #endif  // BUILDFLAG(IS_MAC)
27 
28 namespace net {
29 
Context(scoped_refptr<base::TaskRunner> task_runner)30 FileStream::Context::Context(scoped_refptr<base::TaskRunner> task_runner)
31     : Context(base::File(), std::move(task_runner)) {}
32 
Context(base::File file,scoped_refptr<base::TaskRunner> task_runner)33 FileStream::Context::Context(base::File file,
34                              scoped_refptr<base::TaskRunner> task_runner)
35     : file_(std::move(file)), task_runner_(std::move(task_runner)) {
36 #if BUILDFLAG(IS_MAC)
37   // https://crbug.com/330771755: Guard against a file descriptor being closed
38   // out from underneath the file.
39   if (file_.IsValid()) {
40     guardid_t guardid = reinterpret_cast<guardid_t>(this);
41     PCHECK(change_fdguard_np(file_.GetPlatformFile(), /*guard=*/nullptr,
42                              /*guardflags=*/0, &guardid,
43                              GUARD_CLOSE | GUARD_DUP,
44                              /*fdflagsp=*/nullptr) == 0);
45   }
46 #endif
47 }
48 
49 FileStream::Context::~Context() = default;
50 
Read(IOBuffer * in_buf,int buf_len,CompletionOnceCallback callback)51 int FileStream::Context::Read(IOBuffer* in_buf,
52                               int buf_len,
53                               CompletionOnceCallback callback) {
54   DCHECK(!async_in_progress_);
55 
56   scoped_refptr<IOBuffer> buf = in_buf;
57   const bool posted = task_runner_->PostTaskAndReplyWithResult(
58       FROM_HERE,
59       base::BindOnce(&Context::ReadFileImpl, base::Unretained(this), buf,
60                      buf_len),
61       base::BindOnce(&Context::OnAsyncCompleted, base::Unretained(this),
62                      IntToInt64(std::move(callback))));
63   DCHECK(posted);
64 
65   async_in_progress_ = true;
66   return ERR_IO_PENDING;
67 }
68 
Write(IOBuffer * in_buf,int buf_len,CompletionOnceCallback callback)69 int FileStream::Context::Write(IOBuffer* in_buf,
70                                int buf_len,
71                                CompletionOnceCallback callback) {
72   DCHECK(!async_in_progress_);
73 
74   scoped_refptr<IOBuffer> buf = in_buf;
75   const bool posted = task_runner_->PostTaskAndReplyWithResult(
76       FROM_HERE,
77       base::BindOnce(&Context::WriteFileImpl, base::Unretained(this), buf,
78                      buf_len),
79       base::BindOnce(&Context::OnAsyncCompleted, base::Unretained(this),
80                      IntToInt64(std::move(callback))));
81   DCHECK(posted);
82 
83   async_in_progress_ = true;
84   return ERR_IO_PENDING;
85 }
86 
SeekFileImpl(int64_t offset)87 FileStream::Context::IOResult FileStream::Context::SeekFileImpl(
88     int64_t offset) {
89   int64_t res = file_.Seek(base::File::FROM_BEGIN, offset);
90   if (res == -1)
91     return IOResult::FromOSError(errno);
92 
93   return IOResult(res, 0);
94 }
95 
OnFileOpened()96 void FileStream::Context::OnFileOpened() {
97 }
98 
ReadFileImpl(scoped_refptr<IOBuffer> buf,int buf_len)99 FileStream::Context::IOResult FileStream::Context::ReadFileImpl(
100     scoped_refptr<IOBuffer> buf,
101     int buf_len) {
102   std::optional<size_t> res = file_.ReadAtCurrentPosNoBestEffort(
103       buf->span().first(base::checked_cast<size_t>(buf_len)));
104   if (!res.has_value()) {
105     return IOResult::FromOSError(errno);
106   }
107   return IOResult(res.value(), 0);
108 }
109 
WriteFileImpl(scoped_refptr<IOBuffer> buf,int buf_len)110 FileStream::Context::IOResult FileStream::Context::WriteFileImpl(
111     scoped_refptr<IOBuffer> buf,
112     int buf_len) {
113   std::optional<size_t> res = file_.WriteAtCurrentPosNoBestEffort(
114       buf->span().first(base::checked_cast<size_t>(buf_len)));
115   if (!res.has_value()) {
116     return IOResult::FromOSError(errno);
117   }
118   return IOResult(res.value(), 0);
119 }
120 
121 }  // namespace net
122