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 26 FileWrapper* FileWrapper::Create() { 27 return new FileWrapperImpl(); 28 } 29 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 42 FileWrapperImpl::~FileWrapperImpl() { 43 if (id_ != NULL && managed_file_handle_) { 44 fclose(id_); 45 } 46 } 47 48 int FileWrapperImpl::CloseFile() { 49 WriteLockScoped write(*rw_lock_); 50 return CloseFileImpl(); 51 } 52 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 64 int FileWrapperImpl::SetMaxFileSize(size_t bytes) { 65 WriteLockScoped write(*rw_lock_); 66 max_size_in_bytes_ = bytes; 67 return 0; 68 } 69 70 int FileWrapperImpl::Flush() { 71 WriteLockScoped write(*rw_lock_); 72 return FlushImpl(); 73 } 74 75 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 95 bool FileWrapperImpl::Open() const { 96 ReadLockScoped read(*rw_lock_); 97 return open_; 98 } 99 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 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 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 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 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 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 271 int FileWrapperImpl::FlushImpl() { 272 if (id_ != NULL) { 273 return fflush(id_); 274 } 275 return -1; 276 } 277 278 } // namespace webrtc 279