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 <fcntl.h>
10 #include <sys/stat.h>
11 #include <unistd.h>
12 
13 #include <memory>
14 
15 #include "core/fxcrt/fx_stream.h"
16 #include "third_party/base/ptr_util.h"
17 
18 #ifndef O_BINARY
19 #define O_BINARY 0
20 #endif  // O_BINARY
21 
22 #ifndef O_LARGEFILE
23 #define O_LARGEFILE 0
24 #endif  // O_LARGEFILE
25 
26 namespace {
27 
GetFileMode(uint32_t dwModes,int32_t & nFlags,int32_t & nMasks)28 void GetFileMode(uint32_t dwModes, int32_t& nFlags, int32_t& nMasks) {
29   nFlags = O_BINARY | O_LARGEFILE;
30   if (dwModes & FX_FILEMODE_ReadOnly) {
31     nFlags |= O_RDONLY;
32     nMasks = 0;
33   } else {
34     nFlags |= O_RDWR | O_CREAT;
35     if (dwModes & FX_FILEMODE_Truncate) {
36       nFlags |= O_TRUNC;
37     }
38     nMasks = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
39   }
40 }
41 
42 }  // namespace
43 
44 // static
Create()45 std::unique_ptr<FileAccessIface> FileAccessIface::Create() {
46   return pdfium::MakeUnique<CFX_FileAccess_Posix>();
47 }
48 
CFX_FileAccess_Posix()49 CFX_FileAccess_Posix::CFX_FileAccess_Posix() : m_nFD(-1) {}
50 
~CFX_FileAccess_Posix()51 CFX_FileAccess_Posix::~CFX_FileAccess_Posix() {
52   Close();
53 }
54 
Open(ByteStringView fileName,uint32_t dwMode)55 bool CFX_FileAccess_Posix::Open(ByteStringView fileName, 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 
Open(WideStringView fileName,uint32_t dwMode)68 bool CFX_FileAccess_Posix::Open(WideStringView fileName, uint32_t dwMode) {
69   return Open(FX_UTF8Encode(fileName).AsStringView(), dwMode);
70 }
71 
Close()72 void CFX_FileAccess_Posix::Close() {
73   if (m_nFD < 0) {
74     return;
75   }
76   close(m_nFD);
77   m_nFD = -1;
78 }
GetSize() const79 FX_FILESIZE CFX_FileAccess_Posix::GetSize() const {
80   if (m_nFD < 0) {
81     return 0;
82   }
83   struct stat s;
84   memset(&s, 0, sizeof(s));
85   fstat(m_nFD, &s);
86   return s.st_size;
87 }
GetPosition() const88 FX_FILESIZE CFX_FileAccess_Posix::GetPosition() const {
89   if (m_nFD < 0) {
90     return (FX_FILESIZE)-1;
91   }
92   return lseek(m_nFD, 0, SEEK_CUR);
93 }
SetPosition(FX_FILESIZE pos)94 FX_FILESIZE CFX_FileAccess_Posix::SetPosition(FX_FILESIZE pos) {
95   if (m_nFD < 0) {
96     return (FX_FILESIZE)-1;
97   }
98   return lseek(m_nFD, pos, SEEK_SET);
99 }
Read(void * pBuffer,size_t szBuffer)100 size_t CFX_FileAccess_Posix::Read(void* pBuffer, size_t szBuffer) {
101   if (m_nFD < 0) {
102     return 0;
103   }
104   return read(m_nFD, pBuffer, szBuffer);
105 }
Write(const void * pBuffer,size_t szBuffer)106 size_t CFX_FileAccess_Posix::Write(const void* pBuffer, size_t szBuffer) {
107   if (m_nFD < 0) {
108     return 0;
109   }
110   return write(m_nFD, pBuffer, szBuffer);
111 }
ReadPos(void * pBuffer,size_t szBuffer,FX_FILESIZE pos)112 size_t CFX_FileAccess_Posix::ReadPos(void* pBuffer,
113                                      size_t szBuffer,
114                                      FX_FILESIZE pos) {
115   if (m_nFD < 0) {
116     return 0;
117   }
118   if (pos >= GetSize()) {
119     return 0;
120   }
121   if (SetPosition(pos) == (FX_FILESIZE)-1) {
122     return 0;
123   }
124   return Read(pBuffer, szBuffer);
125 }
WritePos(const void * pBuffer,size_t szBuffer,FX_FILESIZE pos)126 size_t CFX_FileAccess_Posix::WritePos(const void* pBuffer,
127                                       size_t szBuffer,
128                                       FX_FILESIZE pos) {
129   if (m_nFD < 0) {
130     return 0;
131   }
132   if (SetPosition(pos) == (FX_FILESIZE)-1) {
133     return 0;
134   }
135   return Write(pBuffer, szBuffer);
136 }
137 
Flush()138 bool CFX_FileAccess_Posix::Flush() {
139   if (m_nFD < 0)
140     return false;
141 
142   return fsync(m_nFD) > -1;
143 }
144 
Truncate(FX_FILESIZE szFile)145 bool CFX_FileAccess_Posix::Truncate(FX_FILESIZE szFile) {
146   if (m_nFD < 0)
147     return false;
148 
149   return !ftruncate(m_nFD, szFile);
150 }
151