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