• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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/fx_stream.h"
8 
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 #include <vector>
13 
14 #include "build/build_config.h"
15 #include "core/fxcrt/fileaccess_iface.h"
16 #include "core/fxcrt/fx_safe_types.h"
17 #include "third_party/base/ptr_util.h"
18 
19 #if defined(OS_WIN)
20 #include <direct.h>
21 
22 struct FX_FolderHandle {
23   HANDLE m_Handle;
24   bool m_bEnd;
25   WIN32_FIND_DATAA m_FindData;
26 };
27 #else
28 #include <dirent.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 
33 struct FX_FolderHandle {
34   ByteString m_Path;
35   DIR* m_Dir;
36 };
37 #endif
38 
39 namespace {
40 
41 class CFX_CRTFileStream final : public IFX_SeekableStream {
42  public:
43   template <typename T, typename... Args>
44   friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
45 
46   // IFX_SeekableStream:
GetSize()47   FX_FILESIZE GetSize() override { return m_pFile->GetSize(); }
IsEOF()48   bool IsEOF() override { return GetPosition() >= GetSize(); }
GetPosition()49   FX_FILESIZE GetPosition() override { return m_pFile->GetPosition(); }
ReadBlockAtOffset(void * buffer,FX_FILESIZE offset,size_t size)50   bool ReadBlockAtOffset(void* buffer,
51                          FX_FILESIZE offset,
52                          size_t size) override {
53     return m_pFile->ReadPos(buffer, size, offset) > 0;
54   }
ReadBlock(void * buffer,size_t size)55   size_t ReadBlock(void* buffer, size_t size) override {
56     return m_pFile->Read(buffer, size);
57   }
WriteBlockAtOffset(const void * buffer,FX_FILESIZE offset,size_t size)58   bool WriteBlockAtOffset(const void* buffer,
59                           FX_FILESIZE offset,
60                           size_t size) override {
61     return !!m_pFile->WritePos(buffer, size, offset);
62   }
Flush()63   bool Flush() override { return m_pFile->Flush(); }
64 
65  private:
CFX_CRTFileStream(std::unique_ptr<FileAccessIface> pFA)66   explicit CFX_CRTFileStream(std::unique_ptr<FileAccessIface> pFA)
67       : m_pFile(std::move(pFA)) {}
~CFX_CRTFileStream()68   ~CFX_CRTFileStream() override {}
69 
70   std::unique_ptr<FileAccessIface> m_pFile;
71 };
72 
73 }  // namespace
74 
75 // static
CreateFromFilename(const char * filename,uint32_t dwModes)76 RetainPtr<IFX_SeekableStream> IFX_SeekableStream::CreateFromFilename(
77     const char* filename,
78     uint32_t dwModes) {
79   std::unique_ptr<FileAccessIface> pFA = FileAccessIface::Create();
80   if (!pFA->Open(filename, dwModes))
81     return nullptr;
82   return pdfium::MakeRetain<CFX_CRTFileStream>(std::move(pFA));
83 }
84 
85 // static
CreateFromFilename(const wchar_t * filename,uint32_t dwModes)86 RetainPtr<IFX_SeekableStream> IFX_SeekableStream::CreateFromFilename(
87     const wchar_t* filename,
88     uint32_t dwModes) {
89   std::unique_ptr<FileAccessIface> pFA = FileAccessIface::Create();
90   if (!pFA->Open(filename, dwModes))
91     return nullptr;
92   return pdfium::MakeRetain<CFX_CRTFileStream>(std::move(pFA));
93 }
94 
95 // static
CreateFromFilename(const char * filename)96 RetainPtr<IFX_SeekableReadStream> IFX_SeekableReadStream::CreateFromFilename(
97     const char* filename) {
98   return IFX_SeekableStream::CreateFromFilename(filename, FX_FILEMODE_ReadOnly);
99 }
100 
WriteBlock(const void * pData,size_t size)101 bool IFX_SeekableWriteStream::WriteBlock(const void* pData, size_t size) {
102   return WriteBlockAtOffset(pData, GetSize(), size);
103 }
104 
IsEOF()105 bool IFX_SeekableReadStream::IsEOF() {
106   return false;
107 }
108 
GetPosition()109 FX_FILESIZE IFX_SeekableReadStream::GetPosition() {
110   return 0;
111 }
112 
ReadBlock(void * buffer,size_t size)113 size_t IFX_SeekableReadStream::ReadBlock(void* buffer, size_t size) {
114   return 0;
115 }
116 
WriteBlock(const void * buffer,size_t size)117 bool IFX_SeekableStream::WriteBlock(const void* buffer, size_t size) {
118   return WriteBlockAtOffset(buffer, GetSize(), size);
119 }
120 
WriteString(ByteStringView str)121 bool IFX_SeekableStream::WriteString(ByteStringView str) {
122   return WriteBlock(str.unterminated_c_str(), str.GetLength());
123 }
124 
FX_OpenFolder(const char * path)125 FX_FolderHandle* FX_OpenFolder(const char* path) {
126   auto handle = pdfium::MakeUnique<FX_FolderHandle>();
127 #if defined(OS_WIN)
128   handle->m_Handle =
129       FindFirstFileExA((ByteString(path) + "/*.*").c_str(), FindExInfoStandard,
130                        &handle->m_FindData, FindExSearchNameMatch, nullptr, 0);
131   if (handle->m_Handle == INVALID_HANDLE_VALUE)
132     return nullptr;
133 
134   handle->m_bEnd = false;
135 #else
136   DIR* dir = opendir(path);
137   if (!dir)
138     return nullptr;
139 
140   handle->m_Path = path;
141   handle->m_Dir = dir;
142 #endif
143   return handle.release();
144 }
145 
FX_GetNextFile(FX_FolderHandle * handle,ByteString * filename,bool * bFolder)146 bool FX_GetNextFile(FX_FolderHandle* handle,
147                     ByteString* filename,
148                     bool* bFolder) {
149   if (!handle)
150     return false;
151 
152 #if defined(OS_WIN)
153   if (handle->m_bEnd)
154     return false;
155 
156   *filename = handle->m_FindData.cFileName;
157   *bFolder =
158       (handle->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
159   if (!FindNextFileA(handle->m_Handle, &handle->m_FindData))
160     handle->m_bEnd = true;
161   return true;
162 #else
163   struct dirent* de = readdir(handle->m_Dir);
164   if (!de)
165     return false;
166   ByteString fullpath = handle->m_Path + "/" + de->d_name;
167   struct stat deStat;
168   if (stat(fullpath.c_str(), &deStat) < 0)
169     return false;
170 
171   *filename = de->d_name;
172   *bFolder = S_ISDIR(deStat.st_mode);
173   return true;
174 #endif
175 }
176 
FX_CloseFolder(FX_FolderHandle * handle)177 void FX_CloseFolder(FX_FolderHandle* handle) {
178   if (!handle)
179     return;
180 
181 #if defined(OS_WIN)
182   FindClose(handle->m_Handle);
183 #else
184   closedir(handle->m_Dir);
185 #endif
186   delete handle;
187 }
188