xref: /aosp_15_r20/external/webrtc/rtc_base/system/file_wrapper.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/system/file_wrapper.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <cerrno>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
16*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_conversions.h"
17*d9f75844SAndroid Build Coastguard Worker 
18*d9f75844SAndroid Build Coastguard Worker #ifdef _WIN32
19*d9f75844SAndroid Build Coastguard Worker #include <Windows.h>
20*d9f75844SAndroid Build Coastguard Worker #else
21*d9f75844SAndroid Build Coastguard Worker #include <string.h>
22*d9f75844SAndroid Build Coastguard Worker #endif
23*d9f75844SAndroid Build Coastguard Worker 
24*d9f75844SAndroid Build Coastguard Worker #include <utility>
25*d9f75844SAndroid Build Coastguard Worker 
26*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
27*d9f75844SAndroid Build Coastguard Worker namespace {
FileOpen(absl::string_view file_name_utf8,bool read_only,int * error)28*d9f75844SAndroid Build Coastguard Worker FILE* FileOpen(absl::string_view file_name_utf8, bool read_only, int* error) {
29*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK_EQ(file_name_utf8.find_first_of('\0'), absl::string_view::npos)
30*d9f75844SAndroid Build Coastguard Worker       << "Invalid filename, containing NUL character";
31*d9f75844SAndroid Build Coastguard Worker   std::string file_name(file_name_utf8);
32*d9f75844SAndroid Build Coastguard Worker #if defined(_WIN32)
33*d9f75844SAndroid Build Coastguard Worker   int len = MultiByteToWideChar(CP_UTF8, 0, file_name.c_str(), -1, nullptr, 0);
34*d9f75844SAndroid Build Coastguard Worker   std::wstring wstr(len, 0);
35*d9f75844SAndroid Build Coastguard Worker   MultiByteToWideChar(CP_UTF8, 0, file_name.c_str(), -1, &wstr[0], len);
36*d9f75844SAndroid Build Coastguard Worker   FILE* file = _wfopen(wstr.c_str(), read_only ? L"rb" : L"wb");
37*d9f75844SAndroid Build Coastguard Worker #else
38*d9f75844SAndroid Build Coastguard Worker   FILE* file = fopen(file_name.c_str(), read_only ? "rb" : "wb");
39*d9f75844SAndroid Build Coastguard Worker #endif
40*d9f75844SAndroid Build Coastguard Worker   if (!file && error) {
41*d9f75844SAndroid Build Coastguard Worker     *error = errno;
42*d9f75844SAndroid Build Coastguard Worker   }
43*d9f75844SAndroid Build Coastguard Worker   return file;
44*d9f75844SAndroid Build Coastguard Worker }
45*d9f75844SAndroid Build Coastguard Worker 
46*d9f75844SAndroid Build Coastguard Worker }  // namespace
47*d9f75844SAndroid Build Coastguard Worker 
48*d9f75844SAndroid Build Coastguard Worker // static
OpenReadOnly(absl::string_view file_name_utf8)49*d9f75844SAndroid Build Coastguard Worker FileWrapper FileWrapper::OpenReadOnly(absl::string_view file_name_utf8) {
50*d9f75844SAndroid Build Coastguard Worker   return FileWrapper(FileOpen(file_name_utf8, true, nullptr));
51*d9f75844SAndroid Build Coastguard Worker }
52*d9f75844SAndroid Build Coastguard Worker 
53*d9f75844SAndroid Build Coastguard Worker // static
OpenWriteOnly(absl::string_view file_name_utf8,int * error)54*d9f75844SAndroid Build Coastguard Worker FileWrapper FileWrapper::OpenWriteOnly(absl::string_view file_name_utf8,
55*d9f75844SAndroid Build Coastguard Worker                                        int* error /*=nullptr*/) {
56*d9f75844SAndroid Build Coastguard Worker   return FileWrapper(FileOpen(file_name_utf8, false, error));
57*d9f75844SAndroid Build Coastguard Worker }
58*d9f75844SAndroid Build Coastguard Worker 
FileWrapper(FileWrapper && other)59*d9f75844SAndroid Build Coastguard Worker FileWrapper::FileWrapper(FileWrapper&& other) {
60*d9f75844SAndroid Build Coastguard Worker   operator=(std::move(other));
61*d9f75844SAndroid Build Coastguard Worker }
62*d9f75844SAndroid Build Coastguard Worker 
operator =(FileWrapper && other)63*d9f75844SAndroid Build Coastguard Worker FileWrapper& FileWrapper::operator=(FileWrapper&& other) {
64*d9f75844SAndroid Build Coastguard Worker   Close();
65*d9f75844SAndroid Build Coastguard Worker   file_ = other.file_;
66*d9f75844SAndroid Build Coastguard Worker   other.file_ = nullptr;
67*d9f75844SAndroid Build Coastguard Worker   return *this;
68*d9f75844SAndroid Build Coastguard Worker }
69*d9f75844SAndroid Build Coastguard Worker 
SeekRelative(int64_t offset)70*d9f75844SAndroid Build Coastguard Worker bool FileWrapper::SeekRelative(int64_t offset) {
71*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(file_);
72*d9f75844SAndroid Build Coastguard Worker   return fseek(file_, rtc::checked_cast<long>(offset), SEEK_CUR) == 0;
73*d9f75844SAndroid Build Coastguard Worker }
74*d9f75844SAndroid Build Coastguard Worker 
SeekTo(int64_t position)75*d9f75844SAndroid Build Coastguard Worker bool FileWrapper::SeekTo(int64_t position) {
76*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(file_);
77*d9f75844SAndroid Build Coastguard Worker   return fseek(file_, rtc::checked_cast<long>(position), SEEK_SET) == 0;
78*d9f75844SAndroid Build Coastguard Worker }
79*d9f75844SAndroid Build Coastguard Worker 
FileSize()80*d9f75844SAndroid Build Coastguard Worker long FileWrapper::FileSize() {
81*d9f75844SAndroid Build Coastguard Worker   if (file_ == nullptr)
82*d9f75844SAndroid Build Coastguard Worker     return -1;
83*d9f75844SAndroid Build Coastguard Worker   long original_position = ftell(file_);
84*d9f75844SAndroid Build Coastguard Worker   if (original_position < 0)
85*d9f75844SAndroid Build Coastguard Worker     return -1;
86*d9f75844SAndroid Build Coastguard Worker   int seek_error = fseek(file_, 0, SEEK_END);
87*d9f75844SAndroid Build Coastguard Worker   if (seek_error)
88*d9f75844SAndroid Build Coastguard Worker     return -1;
89*d9f75844SAndroid Build Coastguard Worker   long file_size = ftell(file_);
90*d9f75844SAndroid Build Coastguard Worker   seek_error = fseek(file_, original_position, SEEK_SET);
91*d9f75844SAndroid Build Coastguard Worker   if (seek_error)
92*d9f75844SAndroid Build Coastguard Worker     return -1;
93*d9f75844SAndroid Build Coastguard Worker   return file_size;
94*d9f75844SAndroid Build Coastguard Worker }
95*d9f75844SAndroid Build Coastguard Worker 
Flush()96*d9f75844SAndroid Build Coastguard Worker bool FileWrapper::Flush() {
97*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(file_);
98*d9f75844SAndroid Build Coastguard Worker   return fflush(file_) == 0;
99*d9f75844SAndroid Build Coastguard Worker }
100*d9f75844SAndroid Build Coastguard Worker 
Read(void * buf,size_t length)101*d9f75844SAndroid Build Coastguard Worker size_t FileWrapper::Read(void* buf, size_t length) {
102*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(file_);
103*d9f75844SAndroid Build Coastguard Worker   return fread(buf, 1, length, file_);
104*d9f75844SAndroid Build Coastguard Worker }
105*d9f75844SAndroid Build Coastguard Worker 
ReadEof() const106*d9f75844SAndroid Build Coastguard Worker bool FileWrapper::ReadEof() const {
107*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(file_);
108*d9f75844SAndroid Build Coastguard Worker   return feof(file_);
109*d9f75844SAndroid Build Coastguard Worker }
110*d9f75844SAndroid Build Coastguard Worker 
Write(const void * buf,size_t length)111*d9f75844SAndroid Build Coastguard Worker bool FileWrapper::Write(const void* buf, size_t length) {
112*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(file_);
113*d9f75844SAndroid Build Coastguard Worker   return fwrite(buf, 1, length, file_) == length;
114*d9f75844SAndroid Build Coastguard Worker }
115*d9f75844SAndroid Build Coastguard Worker 
Close()116*d9f75844SAndroid Build Coastguard Worker bool FileWrapper::Close() {
117*d9f75844SAndroid Build Coastguard Worker   if (file_ == nullptr)
118*d9f75844SAndroid Build Coastguard Worker     return true;
119*d9f75844SAndroid Build Coastguard Worker 
120*d9f75844SAndroid Build Coastguard Worker   bool success = fclose(file_) == 0;
121*d9f75844SAndroid Build Coastguard Worker   file_ = nullptr;
122*d9f75844SAndroid Build Coastguard Worker   return success;
123*d9f75844SAndroid Build Coastguard Worker }
124*d9f75844SAndroid Build Coastguard Worker 
Release()125*d9f75844SAndroid Build Coastguard Worker FILE* FileWrapper::Release() {
126*d9f75844SAndroid Build Coastguard Worker   FILE* file = file_;
127*d9f75844SAndroid Build Coastguard Worker   file_ = nullptr;
128*d9f75844SAndroid Build Coastguard Worker   return file;
129*d9f75844SAndroid Build Coastguard Worker }
130*d9f75844SAndroid Build Coastguard Worker 
131*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
132