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 "file_impl.h"
12 
13 #include <assert.h>
14 
15 #ifdef _WIN32
16 #include <Windows.h>
17 #else
18 #include <stdarg.h>
19 #include <string.h>
20 #endif
21 
22 namespace webrtc {
23 
Create()24 FileWrapper* FileWrapper::Create()
25 {
26     return new FileWrapperImpl();
27 }
28 
FileWrapperImpl()29 FileWrapperImpl::FileWrapperImpl()
30     : _id(NULL),
31       _open(false),
32       _looping(false),
33       _readOnly(false),
34       _maxSizeInBytes(0),
35       _sizeInBytes(0)
36 {
37     memset(_fileNameUTF8, 0, kMaxFileNameSize);
38 }
39 
~FileWrapperImpl()40 FileWrapperImpl::~FileWrapperImpl()
41 {
42     if (_id != NULL)
43     {
44         fclose(_id);
45     }
46 }
47 
CloseFile()48 int FileWrapperImpl::CloseFile()
49 {
50     if (_id != NULL)
51     {
52         fclose(_id);
53         _id = NULL;
54     }
55     memset(_fileNameUTF8, 0, kMaxFileNameSize);
56     _open = false;
57     return 0;
58 }
59 
Rewind()60 int FileWrapperImpl::Rewind()
61 {
62     if(_looping || !_readOnly)
63     {
64         if (_id != NULL)
65         {
66             _sizeInBytes = 0;
67             return fseek(_id, 0, SEEK_SET);
68         }
69     }
70     return -1;
71 }
72 
SetMaxFileSize(size_t bytes)73 int FileWrapperImpl::SetMaxFileSize(size_t bytes)
74 {
75     _maxSizeInBytes = bytes;
76     return 0;
77 }
78 
Flush()79 int FileWrapperImpl::Flush()
80 {
81     if (_id != NULL)
82     {
83         return fflush(_id);
84     }
85     return -1;
86 }
87 
FileName(char * fileNameUTF8,size_t size) const88 int FileWrapperImpl::FileName(char* fileNameUTF8,
89                               size_t size) const
90 {
91     size_t length = strlen(_fileNameUTF8);
92     if(length > kMaxFileNameSize)
93     {
94         assert(false);
95         return -1;
96     }
97     if(length < 1)
98     {
99         return -1;
100     }
101 
102     // Make sure to NULL terminate
103     if(size < length)
104     {
105         length = size - 1;
106     }
107     memcpy(fileNameUTF8, _fileNameUTF8, length);
108     fileNameUTF8[length] = 0;
109     return 0;
110 }
111 
Open() const112 bool FileWrapperImpl::Open() const
113 {
114     return _open;
115 }
116 
OpenFile(const char * fileNameUTF8,bool readOnly,bool loop,bool text)117 int FileWrapperImpl::OpenFile(const char *fileNameUTF8, bool readOnly,
118                               bool loop, bool text)
119 {
120     size_t length = strlen(fileNameUTF8);
121     if (length > kMaxFileNameSize - 1)
122     {
123         return -1;
124     }
125 
126     _readOnly = readOnly;
127 
128     FILE *tmpId = NULL;
129 #if defined _WIN32
130     wchar_t wideFileName[kMaxFileNameSize];
131     wideFileName[0] = 0;
132 
133     MultiByteToWideChar(CP_UTF8,
134                         0 /*UTF8 flag*/,
135                         fileNameUTF8,
136                         -1 /*Null terminated string*/,
137                         wideFileName,
138                         kMaxFileNameSize);
139     if(text)
140     {
141         if(readOnly)
142         {
143             tmpId = _wfopen(wideFileName, L"rt");
144         } else {
145             tmpId = _wfopen(wideFileName, L"wt");
146         }
147     } else {
148         if(readOnly)
149         {
150             tmpId = _wfopen(wideFileName, L"rb");
151         } else {
152             tmpId = _wfopen(wideFileName, L"wb");
153         }
154     }
155 #else
156     if(text)
157     {
158         if(readOnly)
159         {
160             tmpId = fopen(fileNameUTF8, "rt");
161         } else {
162             tmpId = fopen(fileNameUTF8, "wt");
163         }
164     } else {
165         if(readOnly)
166         {
167             tmpId = fopen(fileNameUTF8, "rb");
168         } else {
169             tmpId = fopen(fileNameUTF8, "wb");
170         }
171     }
172 #endif
173 
174     if (tmpId != NULL)
175     {
176         // +1 comes from copying the NULL termination character.
177         memcpy(_fileNameUTF8, fileNameUTF8, length + 1);
178         if (_id != NULL)
179         {
180             fclose(_id);
181         }
182         _id = tmpId;
183         _looping = loop;
184         _open = true;
185         return 0;
186     }
187     return -1;
188 }
189 
Read(void * buf,int length)190 int FileWrapperImpl::Read(void* buf, int length)
191 {
192     if (length < 0)
193         return -1;
194 
195     if (_id == NULL)
196         return -1;
197 
198     int bytes_read = static_cast<int>(fread(buf, 1, length, _id));
199     if (bytes_read != length && !_looping)
200     {
201         CloseFile();
202     }
203     return bytes_read;
204 }
205 
WriteText(const char * format,...)206 int FileWrapperImpl::WriteText(const char* format, ...)
207 {
208     if (format == NULL)
209         return -1;
210 
211     if (_readOnly)
212         return -1;
213 
214     if (_id == NULL)
215         return -1;
216 
217     va_list args;
218     va_start(args, format);
219     int num_chars = vfprintf(_id, format, args);
220     va_end(args);
221 
222     if (num_chars >= 0)
223     {
224         return num_chars;
225     }
226     else
227     {
228         CloseFile();
229         return -1;
230     }
231 }
232 
Write(const void * buf,int length)233 bool FileWrapperImpl::Write(const void* buf, int length)
234 {
235     if (buf == NULL)
236         return false;
237 
238     if (length < 0)
239         return false;
240 
241     if (_readOnly)
242         return false;
243 
244     if (_id == NULL)
245         return false;
246 
247     // Check if it's time to stop writing.
248     if (_maxSizeInBytes > 0 && (_sizeInBytes + length) > _maxSizeInBytes)
249     {
250         Flush();
251         return false;
252     }
253 
254     size_t num_bytes = fwrite(buf, 1, length, _id);
255     if (num_bytes > 0)
256     {
257         _sizeInBytes += num_bytes;
258         return true;
259     }
260 
261     CloseFile();
262     return false;
263 }
264 
265 } // namespace webrtc
266