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