Home | History | Annotate | Download | only in source
      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