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