/* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "webrtc/system_wrappers/source/file_impl.h" #include #ifdef _WIN32 #include #else #include #include #endif #include "webrtc/base/checks.h" #include "webrtc/system_wrappers/include/rw_lock_wrapper.h" namespace webrtc { FileWrapper* FileWrapper::Create() { return new FileWrapperImpl(); } FileWrapperImpl::FileWrapperImpl() : rw_lock_(RWLockWrapper::CreateRWLock()), id_(NULL), managed_file_handle_(true), open_(false), looping_(false), read_only_(false), max_size_in_bytes_(0), size_in_bytes_(0) { memset(file_name_utf8_, 0, kMaxFileNameSize); } FileWrapperImpl::~FileWrapperImpl() { if (id_ != NULL && managed_file_handle_) { fclose(id_); } } int FileWrapperImpl::CloseFile() { WriteLockScoped write(*rw_lock_); return CloseFileImpl(); } int FileWrapperImpl::Rewind() { WriteLockScoped write(*rw_lock_); if (looping_ || !read_only_) { if (id_ != NULL) { size_in_bytes_ = 0; return fseek(id_, 0, SEEK_SET); } } return -1; } int FileWrapperImpl::SetMaxFileSize(size_t bytes) { WriteLockScoped write(*rw_lock_); max_size_in_bytes_ = bytes; return 0; } int FileWrapperImpl::Flush() { WriteLockScoped write(*rw_lock_); return FlushImpl(); } int FileWrapperImpl::FileName(char* file_name_utf8, size_t size) const { ReadLockScoped read(*rw_lock_); size_t length = strlen(file_name_utf8_); if (length > kMaxFileNameSize) { assert(false); return -1; } if (length < 1) { return -1; } // Make sure to NULL terminate if (size < length) { length = size - 1; } memcpy(file_name_utf8, file_name_utf8_, length); file_name_utf8[length] = 0; return 0; } bool FileWrapperImpl::Open() const { ReadLockScoped read(*rw_lock_); return open_; } int FileWrapperImpl::OpenFile(const char* file_name_utf8, bool read_only, bool loop, bool text) { WriteLockScoped write(*rw_lock_); if (id_ != NULL && !managed_file_handle_) return -1; size_t length = strlen(file_name_utf8); if (length > kMaxFileNameSize - 1) { return -1; } read_only_ = read_only; FILE* tmp_id = NULL; #if defined _WIN32 wchar_t wide_file_name[kMaxFileNameSize]; wide_file_name[0] = 0; MultiByteToWideChar(CP_UTF8, 0, // UTF8 flag file_name_utf8, -1, // Null terminated string wide_file_name, kMaxFileNameSize); if (text) { if (read_only) { tmp_id = _wfopen(wide_file_name, L"rt"); } else { tmp_id = _wfopen(wide_file_name, L"wt"); } } else { if (read_only) { tmp_id = _wfopen(wide_file_name, L"rb"); } else { tmp_id = _wfopen(wide_file_name, L"wb"); } } #else if (text) { if (read_only) { tmp_id = fopen(file_name_utf8, "rt"); } else { tmp_id = fopen(file_name_utf8, "wt"); } } else { if (read_only) { tmp_id = fopen(file_name_utf8, "rb"); } else { tmp_id = fopen(file_name_utf8, "wb"); } } #endif if (tmp_id != NULL) { // +1 comes from copying the NULL termination character. memcpy(file_name_utf8_, file_name_utf8, length + 1); if (id_ != NULL) { fclose(id_); } id_ = tmp_id; managed_file_handle_ = true; looping_ = loop; open_ = true; return 0; } return -1; } int FileWrapperImpl::OpenFromFileHandle(FILE* handle, bool manage_file, bool read_only, bool loop) { WriteLockScoped write(*rw_lock_); if (!handle) return -1; if (id_ != NULL) { if (managed_file_handle_) fclose(id_); else return -1; } id_ = handle; managed_file_handle_ = manage_file; read_only_ = read_only; looping_ = loop; open_ = true; return 0; } int FileWrapperImpl::Read(void* buf, size_t length) { WriteLockScoped write(*rw_lock_); if (id_ == NULL) return -1; size_t bytes_read = fread(buf, 1, length, id_); if (bytes_read != length && !looping_) { CloseFileImpl(); } return static_cast(bytes_read); } int FileWrapperImpl::WriteText(const char* format, ...) { WriteLockScoped write(*rw_lock_); if (format == NULL) return -1; if (read_only_) return -1; if (id_ == NULL) return -1; va_list args; va_start(args, format); int num_chars = vfprintf(id_, format, args); va_end(args); if (num_chars >= 0) { return num_chars; } else { CloseFileImpl(); return -1; } } bool FileWrapperImpl::Write(const void* buf, size_t length) { WriteLockScoped write(*rw_lock_); if (buf == NULL) return false; if (read_only_) return false; if (id_ == NULL) return false; // Check if it's time to stop writing. if (max_size_in_bytes_ > 0 && (size_in_bytes_ + length) > max_size_in_bytes_) { FlushImpl(); return false; } size_t num_bytes = fwrite(buf, 1, length, id_); if (num_bytes > 0) { size_in_bytes_ += num_bytes; return true; } CloseFileImpl(); return false; } int FileWrapperImpl::CloseFileImpl() { if (id_ != NULL) { if (managed_file_handle_) fclose(id_); id_ = NULL; } memset(file_name_utf8_, 0, kMaxFileNameSize); open_ = false; return 0; } int FileWrapperImpl::FlushImpl() { if (id_ != NULL) { return fflush(id_); } return -1; } int FileWrapper::Rewind() { RTC_DCHECK(false); return -1; } } // namespace webrtc