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