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 #include "rtc_base/numerics/safe_conversions.h"
13
14 #include <cerrno>
15
16 #ifdef _WIN32
17 #include <Windows.h>
18 #else
19 #include <string.h>
20 #endif
21
22 #include <utility>
23
24 namespace webrtc {
25 namespace {
FileOpen(const char * file_name_utf8,bool read_only,int * error)26 FILE* FileOpen(const char* file_name_utf8, bool read_only, int* error) {
27 #if defined(_WIN32)
28 int len = MultiByteToWideChar(CP_UTF8, 0, file_name_utf8, -1, nullptr, 0);
29 std::wstring wstr(len, 0);
30 MultiByteToWideChar(CP_UTF8, 0, file_name_utf8, -1, &wstr[0], len);
31 FILE* file = _wfopen(wstr.c_str(), read_only ? L"rb" : L"wb");
32 #else
33 FILE* file = fopen(file_name_utf8, read_only ? "rb" : "wb");
34 #endif
35 if (!file && error) {
36 *error = errno;
37 }
38 return file;
39 }
40
GetCstrCheckNoEmbeddedNul(const std::string & s)41 const char* GetCstrCheckNoEmbeddedNul(const std::string& s) {
42 const char* p = s.c_str();
43 RTC_CHECK_EQ(strlen(p), s.size())
44 << "Invalid filename, containing NUL character";
45 return p;
46 }
47 } // namespace
48
49 // static
OpenReadOnly(const char * file_name_utf8)50 FileWrapper FileWrapper::OpenReadOnly(const char* file_name_utf8) {
51 return FileWrapper(FileOpen(file_name_utf8, true, nullptr));
52 }
53
54 // static
OpenReadOnly(const std::string & file_name_utf8)55 FileWrapper FileWrapper::OpenReadOnly(const std::string& file_name_utf8) {
56 return OpenReadOnly(GetCstrCheckNoEmbeddedNul(file_name_utf8));
57 }
58
59 // static
OpenWriteOnly(const char * file_name_utf8,int * error)60 FileWrapper FileWrapper::OpenWriteOnly(const char* file_name_utf8,
61 int* error /*=nullptr*/) {
62 return FileWrapper(FileOpen(file_name_utf8, false, error));
63 }
64
65 // static
OpenWriteOnly(const std::string & file_name_utf8,int * error)66 FileWrapper FileWrapper::OpenWriteOnly(const std::string& file_name_utf8,
67 int* error /*=nullptr*/) {
68 return OpenWriteOnly(GetCstrCheckNoEmbeddedNul(file_name_utf8), error);
69 }
70
FileWrapper(FileWrapper && other)71 FileWrapper::FileWrapper(FileWrapper&& other) {
72 operator=(std::move(other));
73 }
74
operator =(FileWrapper && other)75 FileWrapper& FileWrapper::operator=(FileWrapper&& other) {
76 Close();
77 file_ = other.file_;
78 other.file_ = nullptr;
79 return *this;
80 }
81
SeekRelative(int64_t offset)82 bool FileWrapper::SeekRelative(int64_t offset) {
83 RTC_DCHECK(file_);
84 return fseek(file_, rtc::checked_cast<long>(offset), SEEK_CUR) == 0;
85 }
86
SeekTo(int64_t position)87 bool FileWrapper::SeekTo(int64_t position) {
88 RTC_DCHECK(file_);
89 return fseek(file_, rtc::checked_cast<long>(position), SEEK_SET) == 0;
90 }
91
Flush()92 bool FileWrapper::Flush() {
93 RTC_DCHECK(file_);
94 return fflush(file_) == 0;
95 }
96
Read(void * buf,size_t length)97 size_t FileWrapper::Read(void* buf, size_t length) {
98 RTC_DCHECK(file_);
99 return fread(buf, 1, length, file_);
100 }
101
ReadEof() const102 bool FileWrapper::ReadEof() const {
103 RTC_DCHECK(file_);
104 return feof(file_);
105 }
106
Write(const void * buf,size_t length)107 bool FileWrapper::Write(const void* buf, size_t length) {
108 RTC_DCHECK(file_);
109 return fwrite(buf, 1, length, file_) == length;
110 }
111
Close()112 bool FileWrapper::Close() {
113 if (file_ == nullptr)
114 return true;
115
116 bool success = fclose(file_) == 0;
117 file_ = nullptr;
118 return success;
119 }
120
Release()121 FILE* FileWrapper::Release() {
122 FILE* file = file_;
123 file_ = nullptr;
124 return file;
125 }
126
127 } // namespace webrtc
128