Home | History | Annotate | Download | only in fxcrt
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "core/fxcrt/cfx_fileaccess_posix.h"
      8 
      9 #include <memory>
     10 
     11 #include "third_party/base/ptr_util.h"
     12 
     13 #ifndef O_BINARY
     14 #define O_BINARY 0
     15 #endif  // O_BINARY
     16 
     17 #ifndef O_LARGEFILE
     18 #define O_LARGEFILE 0
     19 #endif  // O_LARGEFILE
     20 
     21 #if _FX_PLATFORM_ == _FX_PLATFORM_LINUX_ || \
     22     _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ || \
     23     _FX_PLATFORM_ == _FX_PLATFORM_ANDROID_
     24 
     25 namespace {
     26 
     27 void GetFileMode(uint32_t dwModes, int32_t& nFlags, int32_t& nMasks) {
     28   nFlags = O_BINARY | O_LARGEFILE;
     29   if (dwModes & FX_FILEMODE_ReadOnly) {
     30     nFlags |= O_RDONLY;
     31     nMasks = 0;
     32   } else {
     33     nFlags |= O_RDWR | O_CREAT;
     34     if (dwModes & FX_FILEMODE_Truncate) {
     35       nFlags |= O_TRUNC;
     36     }
     37     nMasks = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
     38   }
     39 }
     40 
     41 }  // namespace
     42 
     43 // static
     44 std::unique_ptr<IFX_FileAccess> IFX_FileAccess::Create() {
     45   return pdfium::MakeUnique<CFX_FileAccess_Posix>();
     46 }
     47 
     48 CFX_FileAccess_Posix::CFX_FileAccess_Posix() : m_nFD(-1) {}
     49 
     50 CFX_FileAccess_Posix::~CFX_FileAccess_Posix() {
     51   Close();
     52 }
     53 
     54 bool CFX_FileAccess_Posix::Open(const ByteStringView& fileName,
     55                                 uint32_t dwMode) {
     56   if (m_nFD > -1)
     57     return false;
     58 
     59   int32_t nFlags;
     60   int32_t nMasks;
     61   GetFileMode(dwMode, nFlags, nMasks);
     62 
     63   // TODO(tsepez): check usage of c_str() below.
     64   m_nFD = open(fileName.unterminated_c_str(), nFlags, nMasks);
     65   return m_nFD > -1;
     66 }
     67 
     68 bool CFX_FileAccess_Posix::Open(const WideStringView& fileName,
     69                                 uint32_t dwMode) {
     70   return Open(FX_UTF8Encode(fileName).AsStringView(), dwMode);
     71 }
     72 
     73 void CFX_FileAccess_Posix::Close() {
     74   if (m_nFD < 0) {
     75     return;
     76   }
     77   close(m_nFD);
     78   m_nFD = -1;
     79 }
     80 FX_FILESIZE CFX_FileAccess_Posix::GetSize() const {
     81   if (m_nFD < 0) {
     82     return 0;
     83   }
     84   struct stat s;
     85   memset(&s, 0, sizeof(s));
     86   fstat(m_nFD, &s);
     87   return s.st_size;
     88 }
     89 FX_FILESIZE CFX_FileAccess_Posix::GetPosition() const {
     90   if (m_nFD < 0) {
     91     return (FX_FILESIZE)-1;
     92   }
     93   return lseek(m_nFD, 0, SEEK_CUR);
     94 }
     95 FX_FILESIZE CFX_FileAccess_Posix::SetPosition(FX_FILESIZE pos) {
     96   if (m_nFD < 0) {
     97     return (FX_FILESIZE)-1;
     98   }
     99   return lseek(m_nFD, pos, SEEK_SET);
    100 }
    101 size_t CFX_FileAccess_Posix::Read(void* pBuffer, size_t szBuffer) {
    102   if (m_nFD < 0) {
    103     return 0;
    104   }
    105   return read(m_nFD, pBuffer, szBuffer);
    106 }
    107 size_t CFX_FileAccess_Posix::Write(const void* pBuffer, size_t szBuffer) {
    108   if (m_nFD < 0) {
    109     return 0;
    110   }
    111   return write(m_nFD, pBuffer, szBuffer);
    112 }
    113 size_t CFX_FileAccess_Posix::ReadPos(void* pBuffer,
    114                                      size_t szBuffer,
    115                                      FX_FILESIZE pos) {
    116   if (m_nFD < 0) {
    117     return 0;
    118   }
    119   if (pos >= GetSize()) {
    120     return 0;
    121   }
    122   if (SetPosition(pos) == (FX_FILESIZE)-1) {
    123     return 0;
    124   }
    125   return Read(pBuffer, szBuffer);
    126 }
    127 size_t CFX_FileAccess_Posix::WritePos(const void* pBuffer,
    128                                       size_t szBuffer,
    129                                       FX_FILESIZE pos) {
    130   if (m_nFD < 0) {
    131     return 0;
    132   }
    133   if (SetPosition(pos) == (FX_FILESIZE)-1) {
    134     return 0;
    135   }
    136   return Write(pBuffer, szBuffer);
    137 }
    138 
    139 bool CFX_FileAccess_Posix::Flush() {
    140   if (m_nFD < 0)
    141     return false;
    142 
    143   return fsync(m_nFD) > -1;
    144 }
    145 
    146 bool CFX_FileAccess_Posix::Truncate(FX_FILESIZE szFile) {
    147   if (m_nFD < 0)
    148     return false;
    149 
    150   return !ftruncate(m_nFD, szFile);
    151 }
    152 
    153 #endif
    154