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 24 FileWrapper* FileWrapper::Create() 25 { 26 return new FileWrapperImpl(); 27 } 28 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 40 FileWrapperImpl::~FileWrapperImpl() 41 { 42 if (_id != NULL) 43 { 44 fclose(_id); 45 } 46 } 47 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 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 73 int FileWrapperImpl::SetMaxFileSize(size_t bytes) 74 { 75 _maxSizeInBytes = bytes; 76 return 0; 77 } 78 79 int FileWrapperImpl::Flush() 80 { 81 if (_id != NULL) 82 { 83 return fflush(_id); 84 } 85 return -1; 86 } 87 88 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 112 bool FileWrapperImpl::Open() const 113 { 114 return _open; 115 } 116 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 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 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 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