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 "system_wrappers/include/file_wrapper.h"
12
13 #ifdef _WIN32
14 #include <Windows.h>
15 #else
16 #include <stdarg.h>
17 #include <string.h>
18 #endif
19
20 #include "rtc_base/checks.h"
21
22 namespace webrtc {
23 namespace {
FileOpen(const char * file_name_utf8,bool read_only)24 FILE* FileOpen(const char* file_name_utf8, bool read_only) {
25 #if defined(_WIN32)
26 int len = MultiByteToWideChar(CP_UTF8, 0, file_name_utf8, -1, nullptr, 0);
27 std::wstring wstr(len, 0);
28 MultiByteToWideChar(CP_UTF8, 0, file_name_utf8, -1, &wstr[0], len);
29 FILE* file = _wfopen(wstr.c_str(), read_only ? L"rb" : L"wb");
30 #else
31 FILE* file = fopen(file_name_utf8, read_only ? "rb" : "wb");
32 #endif
33 return file;
34 }
35 } // namespace
36
37 // static
Create()38 FileWrapper* FileWrapper::Create() {
39 return new FileWrapper();
40 }
41
42 // static
Open(const char * file_name_utf8,bool read_only)43 FileWrapper FileWrapper::Open(const char* file_name_utf8, bool read_only) {
44 return FileWrapper(FileOpen(file_name_utf8, read_only), 0);
45 }
46
FileWrapper()47 FileWrapper::FileWrapper() {}
48
FileWrapper(FILE * file,size_t max_size)49 FileWrapper::FileWrapper(FILE* file, size_t max_size)
50 : file_(file), max_size_in_bytes_(max_size) {}
51
~FileWrapper()52 FileWrapper::~FileWrapper() {
53 CloseFileImpl();
54 }
55
FileWrapper(FileWrapper && other)56 FileWrapper::FileWrapper(FileWrapper&& other) {
57 operator=(std::move(other));
58 }
59
operator =(FileWrapper && other)60 FileWrapper& FileWrapper::operator=(FileWrapper&& other) {
61 file_ = other.file_;
62 max_size_in_bytes_ = other.max_size_in_bytes_;
63 position_ = other.position_;
64 other.file_ = nullptr;
65 return *this;
66 }
67
CloseFile()68 void FileWrapper::CloseFile() {
69 rtc::CritScope lock(&lock_);
70 CloseFileImpl();
71 }
72
Rewind()73 int FileWrapper::Rewind() {
74 rtc::CritScope lock(&lock_);
75 if (file_ != nullptr) {
76 position_ = 0;
77 return fseek(file_, 0, SEEK_SET);
78 }
79 return -1;
80 }
81
SetMaxFileSize(size_t bytes)82 void FileWrapper::SetMaxFileSize(size_t bytes) {
83 rtc::CritScope lock(&lock_);
84 max_size_in_bytes_ = bytes;
85 }
86
Flush()87 int FileWrapper::Flush() {
88 rtc::CritScope lock(&lock_);
89 return FlushImpl();
90 }
91
OpenFile(const char * file_name_utf8,bool read_only)92 bool FileWrapper::OpenFile(const char* file_name_utf8, bool read_only) {
93 size_t length = strlen(file_name_utf8);
94 if (length > kMaxFileNameSize - 1)
95 return false;
96
97 rtc::CritScope lock(&lock_);
98 if (file_ != nullptr)
99 return false;
100
101 file_ = FileOpen(file_name_utf8, read_only);
102 return file_ != nullptr;
103 }
104
OpenFromFileHandle(FILE * handle)105 bool FileWrapper::OpenFromFileHandle(FILE* handle) {
106 if (!handle)
107 return false;
108 rtc::CritScope lock(&lock_);
109 CloseFileImpl();
110 file_ = handle;
111 return true;
112 }
113
Read(void * buf,size_t length)114 int FileWrapper::Read(void* buf, size_t length) {
115 rtc::CritScope lock(&lock_);
116 if (file_ == nullptr)
117 return -1;
118
119 size_t bytes_read = fread(buf, 1, length, file_);
120 return static_cast<int>(bytes_read);
121 }
122
Write(const void * buf,size_t length)123 bool FileWrapper::Write(const void* buf, size_t length) {
124 if (buf == nullptr)
125 return false;
126
127 rtc::CritScope lock(&lock_);
128
129 if (file_ == nullptr)
130 return false;
131
132 // Check if it's time to stop writing.
133 if (max_size_in_bytes_ > 0 && (position_ + length) > max_size_in_bytes_)
134 return false;
135
136 size_t num_bytes = fwrite(buf, 1, length, file_);
137 position_ += num_bytes;
138
139 return num_bytes == length;
140 }
141
CloseFileImpl()142 void FileWrapper::CloseFileImpl() {
143 if (file_ != nullptr)
144 fclose(file_);
145 file_ = nullptr;
146 }
147
FlushImpl()148 int FileWrapper::FlushImpl() {
149 return (file_ != nullptr) ? fflush(file_) : -1;
150 }
151
152 } // namespace webrtc
153