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