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 "core/fxcrt/fx_safe_types.h" 15 #include "core/fxcrt/ifx_fileaccess.h" 16 #include "third_party/base/ptr_util.h" 17 18 namespace { 19 20 class CFX_CRTFileStream final : public IFX_SeekableStream { 21 public: 22 template <typename T, typename... Args> 23 friend RetainPtr<T> pdfium::MakeRetain(Args&&... args); 24 25 // IFX_SeekableStream: 26 FX_FILESIZE GetSize() override { return m_pFile->GetSize(); } 27 bool IsEOF() override { return GetPosition() >= GetSize(); } 28 FX_FILESIZE GetPosition() override { return m_pFile->GetPosition(); } 29 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override { 30 return m_pFile->ReadPos(buffer, size, offset) > 0; 31 } 32 size_t ReadBlock(void* buffer, size_t size) override { 33 return m_pFile->Read(buffer, size); 34 } 35 bool WriteBlock(const void* buffer, 36 FX_FILESIZE offset, 37 size_t size) override { 38 return !!m_pFile->WritePos(buffer, size, offset); 39 } 40 bool Flush() override { return m_pFile->Flush(); } 41 42 private: 43 explicit CFX_CRTFileStream(std::unique_ptr<IFX_FileAccess> pFA) 44 : m_pFile(std::move(pFA)) {} 45 ~CFX_CRTFileStream() override {} 46 47 std::unique_ptr<IFX_FileAccess> m_pFile; 48 }; 49 50 } // namespace 51 52 // static 53 RetainPtr<IFX_SeekableStream> IFX_SeekableStream::CreateFromFilename( 54 const char* filename, 55 uint32_t dwModes) { 56 std::unique_ptr<IFX_FileAccess> pFA = IFX_FileAccess::Create(); 57 if (!pFA->Open(filename, dwModes)) 58 return nullptr; 59 return pdfium::MakeRetain<CFX_CRTFileStream>(std::move(pFA)); 60 } 61 62 // static 63 RetainPtr<IFX_SeekableStream> IFX_SeekableStream::CreateFromFilename( 64 const wchar_t* filename, 65 uint32_t dwModes) { 66 std::unique_ptr<IFX_FileAccess> pFA = IFX_FileAccess::Create(); 67 if (!pFA->Open(filename, dwModes)) 68 return nullptr; 69 return pdfium::MakeRetain<CFX_CRTFileStream>(std::move(pFA)); 70 } 71 72 // static 73 RetainPtr<IFX_SeekableReadStream> IFX_SeekableReadStream::CreateFromFilename( 74 const char* filename) { 75 return IFX_SeekableStream::CreateFromFilename(filename, FX_FILEMODE_ReadOnly); 76 } 77 78 bool IFX_SeekableWriteStream::WriteBlock(const void* pData, size_t size) { 79 return WriteBlock(pData, GetSize(), size); 80 } 81 82 bool IFX_SeekableReadStream::IsEOF() { 83 return false; 84 } 85 86 FX_FILESIZE IFX_SeekableReadStream::GetPosition() { 87 return 0; 88 } 89 90 size_t IFX_SeekableReadStream::ReadBlock(void* buffer, size_t size) { 91 return 0; 92 } 93 94 bool IFX_SeekableStream::WriteBlock(const void* buffer, size_t size) { 95 return WriteBlock(buffer, GetSize(), size); 96 } 97 98 bool IFX_SeekableStream::WriteString(const ByteStringView& str) { 99 return WriteBlock(str.unterminated_c_str(), str.GetLength()); 100 } 101 102 FX_FileHandle* FX_OpenFolder(const char* path) { 103 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ 104 auto pData = pdfium::MakeUnique<CFindFileDataA>(); 105 pData->m_Handle = 106 FindFirstFileExA((ByteString(path) + "/*.*").c_str(), FindExInfoStandard, 107 &pData->m_FindData, FindExSearchNameMatch, nullptr, 0); 108 if (pData->m_Handle == INVALID_HANDLE_VALUE) 109 return nullptr; 110 111 pData->m_bEnd = false; 112 return pData.release(); 113 #else 114 return opendir(path); 115 #endif 116 } 117 118 bool FX_GetNextFile(FX_FileHandle* handle, 119 ByteString* filename, 120 bool* bFolder) { 121 if (!handle) 122 return false; 123 124 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ 125 if (handle->m_bEnd) 126 return false; 127 128 *filename = handle->m_FindData.cFileName; 129 *bFolder = 130 (handle->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; 131 if (!FindNextFileA(handle->m_Handle, &handle->m_FindData)) 132 handle->m_bEnd = true; 133 return true; 134 #else 135 struct dirent* de = readdir(handle); 136 if (!de) 137 return false; 138 *filename = de->d_name; 139 *bFolder = de->d_type == DT_DIR; 140 return true; 141 #endif 142 } 143 144 void FX_CloseFolder(FX_FileHandle* handle) { 145 if (!handle) 146 return; 147 148 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ 149 FindClose(handle->m_Handle); 150 delete handle; 151 #else 152 closedir(handle); 153 #endif 154 } 155