• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "webrtc/system_wrappers/source/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 #include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
23 
24 namespace webrtc {
25 
Create()26 FileWrapper* FileWrapper::Create() {
27   return new FileWrapperImpl();
28 }
29 
FileWrapperImpl()30 FileWrapperImpl::FileWrapperImpl()
31     : rw_lock_(RWLockWrapper::CreateRWLock()),
32       id_(NULL),
33       managed_file_handle_(true),
34       open_(false),
35       looping_(false),
36       read_only_(false),
37       max_size_in_bytes_(0),
38       size_in_bytes_(0) {
39   memset(file_name_utf8_, 0, kMaxFileNameSize);
40 }
41 
~FileWrapperImpl()42 FileWrapperImpl::~FileWrapperImpl() {
43   if (id_ != NULL && managed_file_handle_) {
44     fclose(id_);
45   }
46 }
47 
CloseFile()48 int FileWrapperImpl::CloseFile() {
49   WriteLockScoped write(*rw_lock_);
50   return CloseFileImpl();
51 }
52 
Rewind()53 int FileWrapperImpl::Rewind() {
54   WriteLockScoped write(*rw_lock_);
55   if (looping_ || !read_only_) {
56     if (id_ != NULL) {
57       size_in_bytes_ = 0;
58       return fseek(id_, 0, SEEK_SET);
59     }
60   }
61   return -1;
62 }
63 
SetMaxFileSize(size_t bytes)64 int FileWrapperImpl::SetMaxFileSize(size_t bytes) {
65   WriteLockScoped write(*rw_lock_);
66   max_size_in_bytes_ = bytes;
67   return 0;
68 }
69 
Flush()70 int FileWrapperImpl::Flush() {
71   WriteLockScoped write(*rw_lock_);
72   return FlushImpl();
73 }
74 
FileName(char * file_name_utf8,size_t size) const75 int FileWrapperImpl::FileName(char* file_name_utf8, size_t size) const {
76   ReadLockScoped read(*rw_lock_);
77   size_t length = strlen(file_name_utf8_);
78   if (length > kMaxFileNameSize) {
79     assert(false);
80     return -1;
81   }
82   if (length < 1) {
83     return -1;
84   }
85 
86   // Make sure to NULL terminate
87   if (size < length) {
88     length = size - 1;
89   }
90   memcpy(file_name_utf8, file_name_utf8_, length);
91   file_name_utf8[length] = 0;
92   return 0;
93 }
94 
Open() const95 bool FileWrapperImpl::Open() const {
96   ReadLockScoped read(*rw_lock_);
97   return open_;
98 }
99 
OpenFile(const char * file_name_utf8,bool read_only,bool loop,bool text)100 int FileWrapperImpl::OpenFile(const char* file_name_utf8, bool read_only,
101                               bool loop, bool text) {
102   WriteLockScoped write(*rw_lock_);
103   if (id_ != NULL && !managed_file_handle_)
104     return -1;
105   size_t length = strlen(file_name_utf8);
106   if (length > kMaxFileNameSize - 1) {
107     return -1;
108   }
109 
110   read_only_ = read_only;
111 
112   FILE* tmp_id = NULL;
113 #if defined _WIN32
114   wchar_t wide_file_name[kMaxFileNameSize];
115   wide_file_name[0] = 0;
116 
117   MultiByteToWideChar(CP_UTF8,
118                       0,  // UTF8 flag
119                       file_name_utf8,
120                       -1,  // Null terminated string
121                       wide_file_name,
122                       kMaxFileNameSize);
123   if (text) {
124     if (read_only) {
125       tmp_id = _wfopen(wide_file_name, L"rt");
126     } else {
127       tmp_id = _wfopen(wide_file_name, L"wt");
128     }
129   } else {
130     if (read_only) {
131       tmp_id = _wfopen(wide_file_name, L"rb");
132     } else {
133       tmp_id = _wfopen(wide_file_name, L"wb");
134     }
135   }
136 #else
137   if (text) {
138     if (read_only) {
139       tmp_id = fopen(file_name_utf8, "rt");
140     } else {
141       tmp_id = fopen(file_name_utf8, "wt");
142     }
143   } else {
144     if (read_only) {
145       tmp_id = fopen(file_name_utf8, "rb");
146     } else {
147       tmp_id = fopen(file_name_utf8, "wb");
148     }
149   }
150 #endif
151 
152   if (tmp_id != NULL) {
153     // +1 comes from copying the NULL termination character.
154     memcpy(file_name_utf8_, file_name_utf8, length + 1);
155     if (id_ != NULL) {
156       fclose(id_);
157     }
158     id_ = tmp_id;
159     managed_file_handle_ = true;
160     looping_ = loop;
161     open_ = true;
162     return 0;
163   }
164   return -1;
165 }
166 
OpenFromFileHandle(FILE * handle,bool manage_file,bool read_only,bool loop)167 int FileWrapperImpl::OpenFromFileHandle(FILE* handle,
168                                         bool manage_file,
169                                         bool read_only,
170                                         bool loop) {
171   WriteLockScoped write(*rw_lock_);
172   if (!handle)
173     return -1;
174 
175   if (id_ != NULL) {
176     if (managed_file_handle_)
177       fclose(id_);
178     else
179       return -1;
180   }
181 
182   id_ = handle;
183   managed_file_handle_ = manage_file;
184   read_only_ = read_only;
185   looping_ = loop;
186   open_ = true;
187   return 0;
188 }
189 
Read(void * buf,int length)190 int FileWrapperImpl::Read(void* buf, int length) {
191   WriteLockScoped write(*rw_lock_);
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     CloseFileImpl();
201   }
202   return bytes_read;
203 }
204 
WriteText(const char * format,...)205 int FileWrapperImpl::WriteText(const char* format, ...) {
206   WriteLockScoped write(*rw_lock_);
207   if (format == NULL)
208     return -1;
209 
210   if (read_only_)
211     return -1;
212 
213   if (id_ == NULL)
214     return -1;
215 
216   va_list args;
217   va_start(args, format);
218   int num_chars = vfprintf(id_, format, args);
219   va_end(args);
220 
221   if (num_chars >= 0) {
222     return num_chars;
223   } else {
224     CloseFileImpl();
225     return -1;
226   }
227 }
228 
Write(const void * buf,int length)229 bool FileWrapperImpl::Write(const void* buf, int length) {
230   WriteLockScoped write(*rw_lock_);
231   if (buf == NULL)
232     return false;
233 
234   if (length < 0)
235     return false;
236 
237   if (read_only_)
238     return false;
239 
240   if (id_ == NULL)
241     return false;
242 
243   // Check if it's time to stop writing.
244   if (max_size_in_bytes_ > 0 &&
245       (size_in_bytes_ + length) > max_size_in_bytes_) {
246     FlushImpl();
247     return false;
248   }
249 
250   size_t num_bytes = fwrite(buf, 1, length, id_);
251   if (num_bytes > 0) {
252     size_in_bytes_ += num_bytes;
253     return true;
254   }
255 
256   CloseFileImpl();
257   return false;
258 }
259 
CloseFileImpl()260 int FileWrapperImpl::CloseFileImpl() {
261   if (id_ != NULL) {
262     if (managed_file_handle_)
263       fclose(id_);
264     id_ = NULL;
265   }
266   memset(file_name_utf8_, 0, kMaxFileNameSize);
267   open_ = false;
268   return 0;
269 }
270 
FlushImpl()271 int FileWrapperImpl::FlushImpl() {
272   if (id_ != NULL) {
273     return fflush(id_);
274   }
275   return -1;
276 }
277 
278 }  // namespace webrtc
279