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