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