00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #if !defined(_WIN32) || defined(__CYGWIN__)
00012 #include <unistd.h>
00013 #endif
00014 #if defined(_WIN32)
00015 #include <io.h>
00016 #endif
00017
00018 #include <cerrno>
00019 #include <cstdio>
00020
00021 #include <list>
00022 #include <map>
00023 #include <sstream>
00024 #include <fstream>
00025
00026 #include "colvarmodule.h"
00027 #include "colvarproxy_io.h"
00028
00029
00030 colvarproxy_io::colvarproxy_io()
00031 {
00032 input_buffer_ = NULL;
00033 restart_frequency_engine = 0;
00034 input_stream_error_ = new std::istringstream();
00035 input_stream_error_->setstate(std::ios::badbit);
00036 output_stream_error_ = new std::ostringstream();
00037 output_stream_error_->setstate(std::ios::badbit);
00038 }
00039
00040
00041 colvarproxy_io::~colvarproxy_io()
00042 {
00043 delete input_stream_error_;
00044 close_input_streams();
00045 delete output_stream_error_;
00046 close_output_streams();
00047 }
00048
00049
00050 bool colvarproxy_io::io_available()
00051 {
00052 return false;
00053 }
00054
00055
00056 int colvarproxy_io::get_frame(long int&)
00057 {
00058 return COLVARS_NOT_IMPLEMENTED;
00059 }
00060
00061
00062 int colvarproxy_io::set_frame(long int)
00063 {
00064 return COLVARS_NOT_IMPLEMENTED;
00065 }
00066
00067
00068 int colvarproxy_io::backup_file(char const *filename)
00069 {
00070
00071 int exit_code;
00072 do {
00073 #if defined(_WIN32) && !defined(__CYGWIN__)
00074
00075 exit_code = _access(filename, 00);
00076 #else
00077 exit_code = access(filename, F_OK);
00078 #endif
00079 } while ((exit_code != 0) && (errno == EINTR));
00080 if (exit_code != 0) {
00081 if (errno == ENOENT) {
00082
00083 return COLVARS_OK;
00084 } else {
00085 return cvm::error("Unknown error while checking if file \""+
00086 std::string(filename)+"\" exists.\n", COLVARS_ERROR);
00087 }
00088 }
00089
00090
00091 if (std::string(filename).rfind(std::string(".colvars.state")) !=
00092 std::string::npos) {
00093 return rename_file(filename, (std::string(filename)+".old").c_str());
00094 } else {
00095 return rename_file(filename, (std::string(filename)+".BAK").c_str());
00096 }
00097 }
00098
00099
00100 int colvarproxy_io::remove_file(char const *filename)
00101 {
00102 int error_code = COLVARS_OK;
00103 #if defined(_WIN32) && !defined(__CYGWIN__)
00104
00105 std::string const renamed_file(std::string(filename)+".old");
00106
00107 std::remove(renamed_file.c_str());
00108 int rename_exit_code = 0;
00109 while ((rename_exit_code = std::rename(filename,
00110 renamed_file.c_str())) != 0) {
00111 if (errno == EINTR) continue;
00112 error_code |= COLVARS_FILE_ERROR;
00113 break;
00114 }
00115
00116 std::remove(renamed_file.c_str());
00117 #else
00118 if (std::remove(filename)) {
00119 if (errno != ENOENT) {
00120 error_code |= COLVARS_FILE_ERROR;
00121 }
00122 }
00123 #endif
00124 if (error_code != COLVARS_OK) {
00125 return cvm::error("Error: in removing file \""+std::string(filename)+
00126 "\".\n.",
00127 error_code);
00128 }
00129 return COLVARS_OK;
00130 }
00131
00132
00133 int colvarproxy_io::rename_file(char const *filename, char const *newfilename)
00134 {
00135 int error_code = COLVARS_OK;
00136 #if defined(_WIN32) && !defined(__CYGWIN__)
00137
00138 error_code |= remove_file(newfilename);
00139 #endif
00140 int rename_exit_code = 0;
00141 while ((rename_exit_code = std::rename(filename, newfilename)) != 0) {
00142 if (errno == EINTR) continue;
00143
00144 cvm::log("Error: in renaming file \""+std::string(filename)+"\" to \""+
00145 std::string(newfilename)+"\".\n.");
00146 error_code |= COLVARS_FILE_ERROR;
00147 if (errno == EXDEV) continue;
00148 break;
00149 }
00150 return rename_exit_code ? error_code : COLVARS_OK;
00151 }
00152
00153
00154 std::istream &colvarproxy_io::input_stream(std::string const &input_name,
00155 std::string const description,
00156 bool error_on_fail)
00157 {
00158 if (!io_available()) {
00159 cvm::error("Error: trying to access an input file/channel "
00160 "from the wrong thread.\n", COLVARS_BUG_ERROR);
00161 return *input_stream_error_;
00162 }
00163
00164 if (colvarproxy_io::input_stream_exists(input_name)) {
00165 return *(input_streams_[input_name]);
00166 }
00167
00168
00169
00170 input_streams_[input_name] = new std::ifstream(input_name.c_str(),
00171 std::ios::binary);
00172
00173 if (input_streams_[input_name]->fail() && error_on_fail) {
00174 cvm::error("Error: cannot open "+description+" \""+input_name+"\".\n",
00175 COLVARS_FILE_ERROR);
00176 }
00177
00178 return *(input_streams_[input_name]);
00179 }
00180
00181
00182 bool colvarproxy_io::input_stream_exists(std::string const &input_name)
00183 {
00184 return (input_streams_.count(input_name) > 0);
00185 }
00186
00187
00188 int colvarproxy_io::close_input_stream(std::string const &input_name)
00189 {
00190 if (colvarproxy_io::input_stream_exists(input_name)) {
00191 delete input_streams_[input_name];
00192 input_streams_.erase(input_name);
00193 return COLVARS_OK;
00194 }
00195 return cvm::error("Error: input file/channel \""+input_name+
00196 "\" does not exist.\n", COLVARS_FILE_ERROR);
00197 }
00198
00199
00200 int colvarproxy_io::close_input_streams()
00201 {
00202 for (std::map<std::string, std::istream *>::iterator ii = input_streams_.begin();
00203 ii != input_streams_.end();
00204 ii++) {
00205 delete ii->second;
00206 }
00207 input_streams_.clear();
00208 return COLVARS_OK;
00209 }
00210
00211
00212 std::ostream & colvarproxy_io::output_stream(std::string const &output_name,
00213 std::string const description)
00214 {
00215 if (cvm::debug()) {
00216 cvm::log("Using colvarproxy_io::output_stream()\n");
00217 }
00218
00219 if (!io_available()) {
00220 cvm::error("Error: trying to access an output file/channel "
00221 "from the wrong thread.\n", COLVARS_BUG_ERROR);
00222 return *output_stream_error_;
00223 }
00224
00225 if (colvarproxy_io::output_stream_exists(output_name)) {
00226 return *(output_streams_[output_name]);
00227 }
00228
00229 backup_file(output_name.c_str());
00230
00231 output_streams_[output_name] = new std::ofstream(output_name.c_str());
00232 if (!*(output_streams_[output_name])) {
00233 cvm::error("Error: cannot write to "+description+" \""+output_name+"\".\n",
00234 COLVARS_FILE_ERROR);
00235 }
00236
00237 return *(output_streams_[output_name]);
00238 }
00239
00240
00241 bool colvarproxy_io::output_stream_exists(std::string const &output_name)
00242 {
00243 return (output_streams_.count(output_name) > 0);
00244 }
00245
00246
00247 int colvarproxy_io::flush_output_stream(std::string const &output_name)
00248 {
00249 if (!io_available()) {
00250
00251 return COLVARS_OK;
00252 }
00253
00254 if (colvarproxy_io::output_stream_exists(output_name)) {
00255 (dynamic_cast<std::ofstream *>(output_streams_[output_name]))->flush();
00256 return COLVARS_OK;
00257 }
00258
00259 return COLVARS_OK;
00260 }
00261
00262
00263 int colvarproxy_io::flush_output_streams()
00264 {
00265 if (!io_available()) {
00266 return COLVARS_OK;
00267 }
00268
00269 for (std::map<std::string, std::ostream *>::iterator osi = output_streams_.begin();
00270 osi != output_streams_.end();
00271 osi++) {
00272 (dynamic_cast<std::ofstream *>(osi->second))->flush();
00273 }
00274
00275 return COLVARS_OK;
00276 }
00277
00278
00279 int colvarproxy_io::close_output_stream(std::string const &output_name)
00280 {
00281 if (!io_available()) {
00282 return cvm::error("Error: trying to access an output file/channel "
00283 "from the wrong thread.\n", COLVARS_BUG_ERROR);
00284 }
00285
00286 if (colvarproxy_io::output_stream_exists(output_name)) {
00287 (dynamic_cast<std::ofstream *>(output_streams_[output_name]))->close();
00288 delete output_streams_[output_name];
00289 output_streams_.erase(output_name);
00290 }
00291
00292 return COLVARS_OK;
00293 }
00294
00295
00296 int colvarproxy_io::close_output_streams()
00297 {
00298 if (! io_available()) {
00299 return COLVARS_OK;
00300 }
00301
00302 for (std::map<std::string, std::ostream *>::iterator osi = output_streams_.begin();
00303 osi != output_streams_.end();
00304 osi++) {
00305 (dynamic_cast<std::ofstream *>(osi->second))->close();
00306 }
00307 output_streams_.clear();
00308
00309 return COLVARS_OK;
00310 }