xref: /aosp_15_r20/external/cronet/base/files/file.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "base/files/file.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <utility>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/files/file_tracing.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/timer/elapsed_timer.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/base_tracing.h"
17*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
20*6777b538SAndroid Build Coastguard Worker #include <errno.h>
21*6777b538SAndroid Build Coastguard Worker #endif
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker namespace base {
24*6777b538SAndroid Build Coastguard Worker 
25*6777b538SAndroid Build Coastguard Worker File::Info::Info() = default;
26*6777b538SAndroid Build Coastguard Worker 
27*6777b538SAndroid Build Coastguard Worker File::Info::~Info() = default;
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker File::File() = default;
30*6777b538SAndroid Build Coastguard Worker 
31*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_NACL)
File(const FilePath & path,uint32_t flags)32*6777b538SAndroid Build Coastguard Worker File::File(const FilePath& path, uint32_t flags) : error_details_(FILE_OK) {
33*6777b538SAndroid Build Coastguard Worker   Initialize(path, flags);
34*6777b538SAndroid Build Coastguard Worker }
35*6777b538SAndroid Build Coastguard Worker #endif
36*6777b538SAndroid Build Coastguard Worker 
File(ScopedPlatformFile platform_file)37*6777b538SAndroid Build Coastguard Worker File::File(ScopedPlatformFile platform_file)
38*6777b538SAndroid Build Coastguard Worker     : File(std::move(platform_file), false) {}
39*6777b538SAndroid Build Coastguard Worker 
File(PlatformFile platform_file)40*6777b538SAndroid Build Coastguard Worker File::File(PlatformFile platform_file) : File(platform_file, false) {}
41*6777b538SAndroid Build Coastguard Worker 
File(ScopedPlatformFile platform_file,bool async)42*6777b538SAndroid Build Coastguard Worker File::File(ScopedPlatformFile platform_file, bool async)
43*6777b538SAndroid Build Coastguard Worker     : file_(std::move(platform_file)), error_details_(FILE_OK), async_(async) {
44*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
45*6777b538SAndroid Build Coastguard Worker   DCHECK_GE(file_.get(), -1);
46*6777b538SAndroid Build Coastguard Worker #endif
47*6777b538SAndroid Build Coastguard Worker }
48*6777b538SAndroid Build Coastguard Worker 
File(PlatformFile platform_file,bool async)49*6777b538SAndroid Build Coastguard Worker File::File(PlatformFile platform_file, bool async)
50*6777b538SAndroid Build Coastguard Worker     : file_(platform_file),
51*6777b538SAndroid Build Coastguard Worker       error_details_(FILE_OK),
52*6777b538SAndroid Build Coastguard Worker       async_(async) {
53*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
54*6777b538SAndroid Build Coastguard Worker   DCHECK_GE(platform_file, -1);
55*6777b538SAndroid Build Coastguard Worker #endif
56*6777b538SAndroid Build Coastguard Worker }
57*6777b538SAndroid Build Coastguard Worker 
File(Error error_details)58*6777b538SAndroid Build Coastguard Worker File::File(Error error_details) : error_details_(error_details) {}
59*6777b538SAndroid Build Coastguard Worker 
File(File && other)60*6777b538SAndroid Build Coastguard Worker File::File(File&& other)
61*6777b538SAndroid Build Coastguard Worker     : file_(other.TakePlatformFile()),
62*6777b538SAndroid Build Coastguard Worker       tracing_path_(other.tracing_path_),
63*6777b538SAndroid Build Coastguard Worker       error_details_(other.error_details()),
64*6777b538SAndroid Build Coastguard Worker       created_(other.created()),
65*6777b538SAndroid Build Coastguard Worker       async_(other.async_) {}
66*6777b538SAndroid Build Coastguard Worker 
~File()67*6777b538SAndroid Build Coastguard Worker File::~File() {
68*6777b538SAndroid Build Coastguard Worker   // Go through the AssertIOAllowed logic.
69*6777b538SAndroid Build Coastguard Worker   Close();
70*6777b538SAndroid Build Coastguard Worker }
71*6777b538SAndroid Build Coastguard Worker 
operator =(File && other)72*6777b538SAndroid Build Coastguard Worker File& File::operator=(File&& other) {
73*6777b538SAndroid Build Coastguard Worker   Close();
74*6777b538SAndroid Build Coastguard Worker   SetPlatformFile(other.TakePlatformFile());
75*6777b538SAndroid Build Coastguard Worker   tracing_path_ = other.tracing_path_;
76*6777b538SAndroid Build Coastguard Worker   error_details_ = other.error_details();
77*6777b538SAndroid Build Coastguard Worker   created_ = other.created();
78*6777b538SAndroid Build Coastguard Worker   async_ = other.async_;
79*6777b538SAndroid Build Coastguard Worker   return *this;
80*6777b538SAndroid Build Coastguard Worker }
81*6777b538SAndroid Build Coastguard Worker 
82*6777b538SAndroid Build Coastguard Worker #if !BUILDFLAG(IS_NACL)
Initialize(const FilePath & path,uint32_t flags)83*6777b538SAndroid Build Coastguard Worker void File::Initialize(const FilePath& path, uint32_t flags) {
84*6777b538SAndroid Build Coastguard Worker   if (path.ReferencesParent()) {
85*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
86*6777b538SAndroid Build Coastguard Worker     ::SetLastError(ERROR_ACCESS_DENIED);
87*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
88*6777b538SAndroid Build Coastguard Worker     errno = EACCES;
89*6777b538SAndroid Build Coastguard Worker #else
90*6777b538SAndroid Build Coastguard Worker #error Unsupported platform
91*6777b538SAndroid Build Coastguard Worker #endif
92*6777b538SAndroid Build Coastguard Worker     error_details_ = FILE_ERROR_ACCESS_DENIED;
93*6777b538SAndroid Build Coastguard Worker     return;
94*6777b538SAndroid Build Coastguard Worker   }
95*6777b538SAndroid Build Coastguard Worker   if (FileTracing::IsCategoryEnabled())
96*6777b538SAndroid Build Coastguard Worker     tracing_path_ = path;
97*6777b538SAndroid Build Coastguard Worker   SCOPED_FILE_TRACE("Initialize");
98*6777b538SAndroid Build Coastguard Worker   DoInitialize(path, flags);
99*6777b538SAndroid Build Coastguard Worker }
100*6777b538SAndroid Build Coastguard Worker #endif
101*6777b538SAndroid Build Coastguard Worker 
Read(int64_t offset,span<uint8_t> data)102*6777b538SAndroid Build Coastguard Worker std::optional<size_t> File::Read(int64_t offset, span<uint8_t> data) {
103*6777b538SAndroid Build Coastguard Worker   span<char> chars = base::as_writable_chars(data);
104*6777b538SAndroid Build Coastguard Worker   int size = checked_cast<int>(chars.size());
105*6777b538SAndroid Build Coastguard Worker   int result = Read(offset, chars.data(), size);
106*6777b538SAndroid Build Coastguard Worker   if (result < 0) {
107*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
108*6777b538SAndroid Build Coastguard Worker   }
109*6777b538SAndroid Build Coastguard Worker   return checked_cast<size_t>(result);
110*6777b538SAndroid Build Coastguard Worker }
111*6777b538SAndroid Build Coastguard Worker 
ReadAndCheck(int64_t offset,span<uint8_t> data)112*6777b538SAndroid Build Coastguard Worker bool File::ReadAndCheck(int64_t offset, span<uint8_t> data) {
113*6777b538SAndroid Build Coastguard Worker   // Size checked in span form of Read() above.
114*6777b538SAndroid Build Coastguard Worker   return Read(offset, data) == static_cast<int>(data.size());
115*6777b538SAndroid Build Coastguard Worker }
116*6777b538SAndroid Build Coastguard Worker 
ReadAtCurrentPos(span<uint8_t> data)117*6777b538SAndroid Build Coastguard Worker std::optional<size_t> File::ReadAtCurrentPos(span<uint8_t> data) {
118*6777b538SAndroid Build Coastguard Worker   span<char> chars = base::as_writable_chars(data);
119*6777b538SAndroid Build Coastguard Worker   int size = checked_cast<int>(chars.size());
120*6777b538SAndroid Build Coastguard Worker   int result = ReadAtCurrentPos(chars.data(), size);
121*6777b538SAndroid Build Coastguard Worker   if (result < 0) {
122*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
123*6777b538SAndroid Build Coastguard Worker   }
124*6777b538SAndroid Build Coastguard Worker   return checked_cast<size_t>(result);
125*6777b538SAndroid Build Coastguard Worker }
126*6777b538SAndroid Build Coastguard Worker 
ReadAtCurrentPosAndCheck(span<uint8_t> data)127*6777b538SAndroid Build Coastguard Worker bool File::ReadAtCurrentPosAndCheck(span<uint8_t> data) {
128*6777b538SAndroid Build Coastguard Worker   // Size checked in span form of ReadAtCurrentPos() above.
129*6777b538SAndroid Build Coastguard Worker   return ReadAtCurrentPos(data) == static_cast<int>(data.size());
130*6777b538SAndroid Build Coastguard Worker }
131*6777b538SAndroid Build Coastguard Worker 
Write(int64_t offset,span<const uint8_t> data)132*6777b538SAndroid Build Coastguard Worker std::optional<size_t> File::Write(int64_t offset, span<const uint8_t> data) {
133*6777b538SAndroid Build Coastguard Worker   span<const char> chars = base::as_chars(data);
134*6777b538SAndroid Build Coastguard Worker   int size = checked_cast<int>(chars.size());
135*6777b538SAndroid Build Coastguard Worker   int result = Write(offset, chars.data(), size);
136*6777b538SAndroid Build Coastguard Worker   if (result < 0) {
137*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
138*6777b538SAndroid Build Coastguard Worker   }
139*6777b538SAndroid Build Coastguard Worker   return checked_cast<size_t>(result);
140*6777b538SAndroid Build Coastguard Worker }
141*6777b538SAndroid Build Coastguard Worker 
WriteAndCheck(int64_t offset,span<const uint8_t> data)142*6777b538SAndroid Build Coastguard Worker bool File::WriteAndCheck(int64_t offset, span<const uint8_t> data) {
143*6777b538SAndroid Build Coastguard Worker   // Size checked in span form of Write() above.
144*6777b538SAndroid Build Coastguard Worker   return Write(offset, data) == static_cast<int>(data.size());
145*6777b538SAndroid Build Coastguard Worker }
146*6777b538SAndroid Build Coastguard Worker 
WriteAtCurrentPos(span<const uint8_t> data)147*6777b538SAndroid Build Coastguard Worker std::optional<size_t> File::WriteAtCurrentPos(span<const uint8_t> data) {
148*6777b538SAndroid Build Coastguard Worker   span<const char> chars = base::as_chars(data);
149*6777b538SAndroid Build Coastguard Worker   int size = checked_cast<int>(chars.size());
150*6777b538SAndroid Build Coastguard Worker   int result = WriteAtCurrentPos(chars.data(), size);
151*6777b538SAndroid Build Coastguard Worker   if (result < 0) {
152*6777b538SAndroid Build Coastguard Worker     return std::nullopt;
153*6777b538SAndroid Build Coastguard Worker   }
154*6777b538SAndroid Build Coastguard Worker   return checked_cast<size_t>(result);
155*6777b538SAndroid Build Coastguard Worker }
156*6777b538SAndroid Build Coastguard Worker 
WriteAtCurrentPosAndCheck(span<const uint8_t> data)157*6777b538SAndroid Build Coastguard Worker bool File::WriteAtCurrentPosAndCheck(span<const uint8_t> data) {
158*6777b538SAndroid Build Coastguard Worker   // Size checked in span form of WriteAtCurrentPos() above.
159*6777b538SAndroid Build Coastguard Worker   return WriteAtCurrentPos(data) == static_cast<int>(data.size());
160*6777b538SAndroid Build Coastguard Worker }
161*6777b538SAndroid Build Coastguard Worker 
162*6777b538SAndroid Build Coastguard Worker // static
ErrorToString(Error error)163*6777b538SAndroid Build Coastguard Worker std::string File::ErrorToString(Error error) {
164*6777b538SAndroid Build Coastguard Worker   switch (error) {
165*6777b538SAndroid Build Coastguard Worker     case FILE_OK:
166*6777b538SAndroid Build Coastguard Worker       return "FILE_OK";
167*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_FAILED:
168*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_FAILED";
169*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_IN_USE:
170*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_IN_USE";
171*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_EXISTS:
172*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_EXISTS";
173*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_NOT_FOUND:
174*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_NOT_FOUND";
175*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_ACCESS_DENIED:
176*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_ACCESS_DENIED";
177*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_TOO_MANY_OPENED:
178*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_TOO_MANY_OPENED";
179*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_NO_MEMORY:
180*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_NO_MEMORY";
181*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_NO_SPACE:
182*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_NO_SPACE";
183*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_NOT_A_DIRECTORY:
184*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_NOT_A_DIRECTORY";
185*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_INVALID_OPERATION:
186*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_INVALID_OPERATION";
187*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_SECURITY:
188*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_SECURITY";
189*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_ABORT:
190*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_ABORT";
191*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_NOT_A_FILE:
192*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_NOT_A_FILE";
193*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_NOT_EMPTY:
194*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_NOT_EMPTY";
195*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_INVALID_URL:
196*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_INVALID_URL";
197*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_IO:
198*6777b538SAndroid Build Coastguard Worker       return "FILE_ERROR_IO";
199*6777b538SAndroid Build Coastguard Worker     case FILE_ERROR_MAX:
200*6777b538SAndroid Build Coastguard Worker       break;
201*6777b538SAndroid Build Coastguard Worker   }
202*6777b538SAndroid Build Coastguard Worker 
203*6777b538SAndroid Build Coastguard Worker   NOTREACHED();
204*6777b538SAndroid Build Coastguard Worker   return "";
205*6777b538SAndroid Build Coastguard Worker }
206*6777b538SAndroid Build Coastguard Worker 
WriteIntoTrace(perfetto::TracedValue context) const207*6777b538SAndroid Build Coastguard Worker void File::WriteIntoTrace(perfetto::TracedValue context) const {
208*6777b538SAndroid Build Coastguard Worker   auto dict = std::move(context).WriteDictionary();
209*6777b538SAndroid Build Coastguard Worker   dict.Add("is_valid", IsValid());
210*6777b538SAndroid Build Coastguard Worker   dict.Add("created", created_);
211*6777b538SAndroid Build Coastguard Worker   dict.Add("async", async_);
212*6777b538SAndroid Build Coastguard Worker   dict.Add("error_details", ErrorToString(error_details_));
213*6777b538SAndroid Build Coastguard Worker }
214*6777b538SAndroid Build Coastguard Worker 
215*6777b538SAndroid Build Coastguard Worker }  // namespace base
216