00001
00002
00003 #include "pch.h"
00004
00005 #ifndef CRYPTOPP_IMPORTS
00006
00007 #include "files.h"
00008
00009 #include <limits>
00010
00011 NAMESPACE_BEGIN(CryptoPP)
00012
00013 #if !defined(NDEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
00014 void Files_TestInstantiations()
00015 {
00016 FileStore f0;
00017 FileSource f1;
00018 FileSink f2;
00019 }
00020 #endif
00021
00022 void FileStore::StoreInitialize(const NameValuePairs ¶meters)
00023 {
00024 m_waiting = false;
00025 m_stream = NULL;
00026 m_file.release();
00027
00028 const char *fileName = NULL;
00029 #if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
00030 const wchar_t *fileNameWide = NULL;
00031 if (!parameters.GetValue(Name::InputFileNameWide(), fileNameWide))
00032 #endif
00033 if (!parameters.GetValue(Name::InputFileName(), fileName))
00034 {
00035 parameters.GetValue(Name::InputStreamPointer(), m_stream);
00036 return;
00037 }
00038
00039 std::ios::openmode binary = parameters.GetValueWithDefault(Name::InputBinaryMode(), true) ? std::ios::binary : std::ios::openmode(0);
00040 m_file.reset(new std::ifstream);
00041 #ifdef CRYPTOPP_UNIX_AVAILABLE
00042 std::string narrowed;
00043 if (fileNameWide)
00044 fileName = (narrowed = StringNarrow(fileNameWide)).c_str();
00045 #endif
00046 #if _MSC_VER >= 1400
00047 if (fileNameWide)
00048 {
00049 m_file->open(fileNameWide, std::ios::in | binary);
00050 if (!*m_file)
00051 throw OpenErr(StringNarrow(fileNameWide, false));
00052 }
00053 #endif
00054 if (fileName)
00055 {
00056 m_file->open(fileName, std::ios::in | binary);
00057 if (!*m_file)
00058 throw OpenErr(fileName);
00059 }
00060 m_stream = m_file.get();
00061 }
00062
00063 lword FileStore::MaxRetrievable() const
00064 {
00065 if (!m_stream)
00066 return 0;
00067
00068 std::streampos current = m_stream->tellg();
00069 std::streampos end = m_stream->seekg(0, std::ios::end).tellg();
00070 m_stream->seekg(current);
00071 return end-current;
00072 }
00073
00074 size_t FileStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
00075 {
00076 if (!m_stream)
00077 {
00078 transferBytes = 0;
00079 return 0;
00080 }
00081
00082 lword size=transferBytes;
00083 transferBytes = 0;
00084
00085 if (m_waiting)
00086 goto output;
00087
00088 while (size && m_stream->good())
00089 {
00090 {
00091 size_t spaceSize = 1024;
00092 m_space = HelpCreatePutSpace(target, channel, 1, UnsignedMin(size_t(SIZE_MAX), size), spaceSize);
00093
00094 m_stream->read((char *)m_space, (unsigned int)STDMIN(size, (lword)spaceSize));
00095 }
00096 m_len = (size_t)m_stream->gcount();
00097 size_t blockedBytes;
00098 output:
00099 blockedBytes = target.ChannelPutModifiable2(channel, m_space, m_len, 0, blocking);
00100 m_waiting = blockedBytes > 0;
00101 if (m_waiting)
00102 return blockedBytes;
00103 size -= m_len;
00104 transferBytes += m_len;
00105 }
00106
00107 if (!m_stream->good() && !m_stream->eof())
00108 throw ReadErr();
00109
00110 return 0;
00111 }
00112
00113 size_t FileStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
00114 {
00115 if (!m_stream)
00116 return 0;
00117
00118 if (begin == 0 && end == 1)
00119 {
00120 int result = m_stream->peek();
00121 if (result == std::char_traits<char>::eof())
00122 return 0;
00123 else
00124 {
00125 size_t blockedBytes = target.ChannelPut(channel, byte(result), blocking);
00126 begin += 1-blockedBytes;
00127 return blockedBytes;
00128 }
00129 }
00130
00131
00132 std::streampos current = m_stream->tellg();
00133 std::streampos endPosition = m_stream->seekg(0, std::ios::end).tellg();
00134 std::streampos newPosition = current + static_cast<std::streamoff>(begin);
00135
00136 if (newPosition >= endPosition)
00137 {
00138 m_stream->seekg(current);
00139 return 0;
00140 }
00141 m_stream->seekg(newPosition);
00142 try
00143 {
00144 assert(!m_waiting);
00145 lword copyMax = end-begin;
00146 size_t blockedBytes = const_cast<FileStore *>(this)->TransferTo2(target, copyMax, channel, blocking);
00147 begin += copyMax;
00148 if (blockedBytes)
00149 {
00150 const_cast<FileStore *>(this)->m_waiting = false;
00151 return blockedBytes;
00152 }
00153 }
00154 catch(...)
00155 {
00156 m_stream->clear();
00157 m_stream->seekg(current);
00158 throw;
00159 }
00160 m_stream->clear();
00161 m_stream->seekg(current);
00162
00163 return 0;
00164 }
00165
00166 lword FileStore::Skip(lword skipMax)
00167 {
00168 if (!m_stream)
00169 return 0;
00170
00171 lword oldPos = m_stream->tellg();
00172 std::istream::off_type offset;
00173 if (!SafeConvert(skipMax, offset))
00174 throw InvalidArgument("FileStore: maximum seek offset exceeded");
00175 m_stream->seekg(offset, std::ios::cur);
00176 return (lword)m_stream->tellg() - oldPos;
00177 }
00178
00179 void FileSink::IsolatedInitialize(const NameValuePairs ¶meters)
00180 {
00181 m_stream = NULL;
00182 m_file.release();
00183
00184 const char *fileName = NULL;
00185 #if defined(CRYPTOPP_UNIX_AVAILABLE) || _MSC_VER >= 1400
00186 const wchar_t *fileNameWide = NULL;
00187 if (!parameters.GetValue(Name::OutputFileNameWide(), fileNameWide))
00188 #endif
00189 if (!parameters.GetValue(Name::OutputFileName(), fileName))
00190 {
00191 parameters.GetValue(Name::OutputStreamPointer(), m_stream);
00192 return;
00193 }
00194
00195 std::ios::openmode binary = parameters.GetValueWithDefault(Name::OutputBinaryMode(), true) ? std::ios::binary : std::ios::openmode(0);
00196 m_file.reset(new std::ofstream);
00197 #ifdef CRYPTOPP_UNIX_AVAILABLE
00198 std::string narrowed;
00199 if (fileNameWide)
00200 fileName = (narrowed = StringNarrow(fileNameWide)).c_str();
00201 #elif (CRYPTOPP_MSC_VERSION >= 1400)
00202 if (fileNameWide)
00203 {
00204 m_file->open(fileNameWide, std::ios::out | std::ios::trunc | binary);
00205 if (!*m_file)
00206 throw OpenErr(StringNarrow(fileNameWide, false));
00207 }
00208 #endif
00209 if (fileName)
00210 {
00211 m_file->open(fileName, std::ios::out | std::ios::trunc | binary);
00212 if (!*m_file)
00213 throw OpenErr(fileName);
00214 }
00215 m_stream = m_file.get();
00216 }
00217
00218 bool FileSink::IsolatedFlush(bool hardFlush, bool blocking)
00219 {
00220 CRYPTOPP_UNUSED(hardFlush), CRYPTOPP_UNUSED(blocking);
00221 if (!m_stream)
00222 throw Err("FileSink: output stream not opened");
00223
00224 m_stream->flush();
00225 if (!m_stream->good())
00226 throw WriteErr();
00227
00228 return false;
00229 }
00230
00231 size_t FileSink::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
00232 {
00233 CRYPTOPP_UNUSED(blocking);
00234 if (!m_stream)
00235 throw Err("FileSink: output stream not opened");
00236
00237 while (length > 0)
00238 {
00239 std::streamsize size;
00240 if (!SafeConvert(length, size))
00241 size = ((std::numeric_limits<std::streamsize>::max)());
00242 m_stream->write((const char *)inString, size);
00243 inString += size;
00244 length -= (size_t)size;
00245 }
00246
00247 if (messageEnd)
00248 m_stream->flush();
00249
00250 if (!m_stream->good())
00251 throw WriteErr();
00252
00253 return 0;
00254 }
00255
00256 NAMESPACE_END
00257
00258 #endif