1// files.cpp - written and placed in the public domain by Wei Dai 2 3#include "pch.h" 4 5#ifndef CRYPTOPP_IMPORTS 6 7#include "files.h" 8 9#include <limits> 10 11NAMESPACE_BEGIN(CryptoPP) 12 13using namespace std; 14 15void Files_TestInstantiations() 16{ 17 FileStore f0; 18 FileSource f1; 19 FileSink f2; 20} 21 22void FileStore::StoreInitialize(const NameValuePairs ¶meters) 23{ 24 m_file.reset(new std::ifstream); 25 const char *fileName; 26 if (parameters.GetValue(Name::InputFileName(), fileName)) 27 { 28 ios::openmode binary = parameters.GetValueWithDefault(Name::InputBinaryMode(), true) ? ios::binary : ios::openmode(0); 29 m_file->open(fileName, ios::in | binary); 30 if (!*m_file) 31 throw OpenErr(fileName); 32 m_stream = m_file.get(); 33 } 34 else 35 { 36 m_stream = NULL; 37 parameters.GetValue(Name::InputStreamPointer(), m_stream); 38 } 39 m_waiting = false; 40} 41 42lword FileStore::MaxRetrievable() const 43{ 44 if (!m_stream) 45 return 0; 46 47 streampos current = m_stream->tellg(); 48 streampos end = m_stream->seekg(0, ios::end).tellg(); 49 m_stream->seekg(current); 50 return end-current; 51} 52 53size_t FileStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) 54{ 55 if (!m_stream) 56 { 57 transferBytes = 0; 58 return 0; 59 } 60 61 lword size=transferBytes; 62 transferBytes = 0; 63 64 if (m_waiting) 65 goto output; 66 67 while (size && m_stream->good()) 68 { 69 { 70 size_t spaceSize = 1024; 71 m_space = HelpCreatePutSpace(target, channel, 1, UnsignedMin(size_t(0)-1, size), spaceSize); 72 73 m_stream->read((char *)m_space, (unsigned int)STDMIN(size, (lword)spaceSize)); 74 } 75 m_len = m_stream->gcount(); 76 size_t blockedBytes; 77output: 78 blockedBytes = target.ChannelPutModifiable2(channel, m_space, m_len, 0, blocking); 79 m_waiting = blockedBytes > 0; 80 if (m_waiting) 81 return blockedBytes; 82 size -= m_len; 83 transferBytes += m_len; 84 } 85 86 if (!m_stream->good() && !m_stream->eof()) 87 throw ReadErr(); 88 89 return 0; 90} 91 92size_t FileStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const 93{ 94 if (!m_stream) 95 return 0; 96 97 if (begin == 0 && end == 1) 98 { 99 int result = m_stream->peek(); 100 if (result == char_traits<char>::eof()) 101 return 0; 102 else 103 { 104 size_t blockedBytes = target.ChannelPut(channel, byte(result), blocking); 105 begin += 1-blockedBytes; 106 return blockedBytes; 107 } 108 } 109 110 // TODO: figure out what happens on cin 111 streampos current = m_stream->tellg(); 112 streampos endPosition = m_stream->seekg(0, ios::end).tellg(); 113 streampos newPosition = current + (streamoff)begin; 114 115 if (newPosition >= endPosition) 116 { 117 m_stream->seekg(current); 118 return 0; // don't try to seek beyond the end of file 119 } 120 m_stream->seekg(newPosition); 121 try 122 { 123 assert(!m_waiting); 124 lword copyMax = end-begin; 125 size_t blockedBytes = const_cast<FileStore *>(this)->TransferTo2(target, copyMax, channel, blocking); 126 begin += copyMax; 127 if (blockedBytes) 128 { 129 const_cast<FileStore *>(this)->m_waiting = false; 130 return blockedBytes; 131 } 132 } 133 catch(...) 134 { 135 m_stream->clear(); 136 m_stream->seekg(current); 137 throw; 138 } 139 m_stream->clear(); 140 m_stream->seekg(current); 141 142 return 0; 143} 144 145lword FileStore::Skip(lword skipMax) 146{ 147 lword oldPos = m_stream->tellg(); 148 std::istream::off_type offset; 149 if (!SafeConvert(skipMax, offset)) 150 throw InvalidArgument("FileStore: maximum seek offset exceeded"); 151 m_stream->seekg(offset, ios::cur); 152 return (lword)m_stream->tellg() - oldPos; 153} 154 155void FileSink::IsolatedInitialize(const NameValuePairs ¶meters) 156{ 157 m_file.reset(new std::ofstream); 158 const char *fileName; 159 if (parameters.GetValue(Name::OutputFileName(), fileName)) 160 { 161 ios::openmode binary = parameters.GetValueWithDefault(Name::OutputBinaryMode(), true) ? ios::binary : ios::openmode(0); 162 m_file->open(fileName, ios::out | ios::trunc | binary); 163 if (!*m_file) 164 throw OpenErr(fileName); 165 m_stream = m_file.get(); 166 } 167 else 168 { 169 m_stream = NULL; 170 parameters.GetValue(Name::OutputStreamPointer(), m_stream); 171 } 172} 173 174bool FileSink::IsolatedFlush(bool hardFlush, bool blocking) 175{ 176 if (!m_stream) 177 throw Err("FileSink: output stream not opened"); 178 179 m_stream->flush(); 180 if (!m_stream->good()) 181 throw WriteErr(); 182 183 return false; 184} 185 186size_t FileSink::Put2(const byte *inString, size_t length, int messageEnd, bool blocking) 187{ 188 if (!m_stream) 189 throw Err("FileSink: output stream not opened"); 190 191 while (length > 0) 192 { 193 std::streamsize size; 194 if (!SafeConvert(length, size)) 195 size = numeric_limits<std::streamsize>::max(); 196 m_stream->write((const char *)inString, size); 197 inString += size; 198 length -= size; 199 } 200 201 if (messageEnd) 202 m_stream->flush(); 203 204 if (!m_stream->good()) 205 throw WriteErr(); 206 207 return 0; 208} 209 210NAMESPACE_END 211 212#endif 213