Error loadLibrary(const std::string& libPath, int options, void** ppLib) { *ppLib = NULL; *ppLib = ::dlopen(libPath.c_str(), options); if (*ppLib == NULL) { Error error = systemError( boost::system::errc::no_such_file_or_directory, ERROR_LOCATION); error.addProperty("lib-path", libPath); addLastDLErrorMessage(&error); return error; } else { return Success(); } }
Error Settings::initialize(const FilePath& filePath) { settingsFile_ = filePath ; settingsMap_.clear() ; Error error = core::readStringMapFromFile(settingsFile_, &settingsMap_) ; if (error) { // we don't consider file-not-found and error because it is a // common initialization case if (error.code() != boost::system::errc::no_such_file_or_directory) { error.addProperty("settings-file", settingsFile_); return error ; } } return Success() ; }
bool isReadOnly(const FilePath& filePath) { if (::access(filePath.absolutePath().c_str(), W_OK) == -1) { if (errno == EACCES) { return true; } else { Error error = systemError(errno, ERROR_LOCATION); error.addProperty("path", filePath); LOG_ERROR(error); return false; } } else { return false; } }
Error parseDcfFile(const FilePath& dcfFilePath, bool preserveKeyCase, DcfFieldRecorder recordField, std::string* pUserErrMsg) { // read the file std::string dcfFileContents; Error error = readStringFromFile(dcfFilePath, &dcfFileContents); if (error) { error.addProperty("dcf-file", dcfFilePath.absolutePath()); *pUserErrMsg = error.summary(); return error; } return parseDcfFile(dcfFileContents, preserveKeyCase, recordField, pUserErrMsg); }
Error evaluateString(const std::string& str, SEXP* pSEXP, sexp::Protect* pProtect) { // refresh source if necessary (no-op in production) r::sourceManager().reloadIfNecessary(); // surrond the string with try in silent mode so we can capture error text std::string rCode = "try(" + str + ", TRUE)"; // parse expression SEXP ps; Error parseError = parseString(rCode, &ps, pProtect); if (parseError) return parseError; // evaluate the expression Error evalError = evaluateExpressions(ps, pSEXP, pProtect); if (evalError) { evalError.addProperty("code", str); return evalError; } // check for try-error if (Rf_inherits(*pSEXP, "try-error")) { // get error message (merely log on failure so we can continue // and return the real error) std::string errorMsg ; Error extractError = sexp::extract(*pSEXP, &errorMsg); if (extractError) LOG_ERROR(extractError); // add it to the error return rCodeExecutionError(errorMsg, ERROR_LOCATION); } return Success(); }
void reportError(const std::string& action, const std::string& context, const Error& error, const ErrorLocation& location, const boost::function<void(const char*)>& reportFunction = boost::function<void(const char*)>()) { // build the message std::string message = "Error " + action + " session"; if (!context.empty()) message += std::string(" (" + context + ")"); // add context to error and log it Error serializationError = error ; serializationError.addProperty("context", message); core::log::logError(serializationError, location); // notify end-user std::string report = message + ": " + error.code().message() + "\n"; if (reportFunction) reportFunction(report.c_str()); else REprintf(report.c_str()); }
Error executeInterruptableChildProcess( std::string path, Options args, int checkContinueIntervalMs, const boost::function<bool()>& checkContinueFunction) { pid_t pid = ::fork(); // error if (pid < 0) { Error error = systemError(errno, ERROR_LOCATION) ; error.addProperty("commmand", path) ; return error ; } // child else if (pid == 0) { // obtain a new process group (using our own process id) so our // lifetime isn't tied to our parent's lifetime if (::setpgid(0,0) == -1) { Error error = systemError(errno, ERROR_LOCATION); LOG_ERROR(error); ::exit(EXIT_FAILURE); } // clear the signal mask so the child process can handle whatever // signals it wishes to Error error = clearSignalMask(); if (error) { LOG_ERROR(error); ::exit(EXIT_FAILURE); } // close all open file descriptors other than std streams error = closeNonStdFileDescriptors(); if (error) { LOG_ERROR(error); ::exit(EXIT_FAILURE); } // build process args std::vector<std::string> argVector; argVector.push_back(path); for (Options::const_iterator it = args.begin(); it != args.end(); ++it) { argVector.push_back(it->first); argVector.push_back(it->second); } // allocate ProcessArgs on heap so memory stays around after we exec // (some systems including OSX seem to require this) core::system::ProcessArgs* pProcessArgs = new core::system::ProcessArgs( argVector); // execute child ::execv(path.c_str(), pProcessArgs->args()) ; // in the normal case control should never return from execv (it starts // anew at main of the process pointed to by path). therefore, if we get // here then there was an error LOG_ERROR(systemError(errno, ERROR_LOCATION)) ; ::exit(EXIT_FAILURE) ; } else // parent { while (true) { // sleep waiting for the next check using boost::posix_time::milliseconds; boost::this_thread::sleep(milliseconds(checkContinueIntervalMs)); // check whether we should continue waiting if (!checkContinueFunction()) { // kill the child process group int result = ::kill(-pid, SIGTERM); if (result == -1 && errno != ECHILD && errno != ESRCH) return systemError(errno, ERROR_LOCATION); else return Success(); } // call waitpid int stat; int result = ::waitpid (pid, &stat, WNOHANG); if (result == pid) { // process "status changed" (i.e. exited, core dumped, terminated // by a signal, or stopped). in all cases we stop waiting return Success(); } else if (result == 0) { // no status change, keep waiting... continue; } else if (result < 0) { if (errno == EINTR) { // system call interrupted, keep waiting... continue; } else if (errno == ECHILD) { // the child was already reaped (probably by a global handler) return Success(); } else { // some other unexpected error return systemError(errno, ERROR_LOCATION); } } else // a totally unexpected return from waitpid { Error error = systemError( boost::system::errc::state_not_recoverable, ERROR_LOCATION); error.addProperty("result", boost::lexical_cast<std::string>(result)); return error; } } } return Success() ; }
Error parseDcfFile(const FilePath& dcfFilePath, bool preserveKeyCase, std::map<std::string,std::string>* pFields, std::string* pUserErrMsg) { // read the file std::string dcfFileContents; Error error = readStringFromFile(dcfFilePath, &dcfFileContents); if (error) { error.addProperty("dcf-file", dcfFilePath.absolutePath()); *pUserErrMsg = error.summary(); return error; } // split into lines std::vector<std::string> dcfLines; boost::algorithm::split(dcfLines, dcfFileContents, boost::algorithm::is_any_of("\r\n")); // iterate over lines int lineNumber = 0; std::string currentKey; std::string currentValue; for(std::vector<std::string>::const_iterator it = dcfLines.begin(); it != dcfLines.end(); ++it) { lineNumber++; // skip blank lines if (it->empty() || boost::algorithm::trim_copy(*it).empty()) continue; // skip comment lines if (it->at(0) == '#') continue; // define regexes boost::regex keyValueRegx("([^\\s]+?)\\s*\\:\\s*(.*)$"); boost::regex continuationRegex("[\t\\s](.*)"); // look for a key-value pair line boost::smatch keyValueMatch, continuationMatch; if (regex_match(*it, keyValueMatch, keyValueRegx)) { // if we have a pending key & value then resolve it if (!currentKey.empty()) { pFields->insert(std::make_pair(currentKey,currentValue)); currentKey.clear(); currentValue.clear(); } // update the current key and value currentKey = preserveKeyCase ? keyValueMatch[1] : string_utils::toLower(keyValueMatch[1]); currentValue = keyValueMatch[2]; } // look for a continuation else if (!currentKey.empty() && regex_match(*it, continuationMatch, continuationRegex)) { currentValue.append("\n"); currentValue.append(continuationMatch[1]); } // invalid line else { Error error = systemError(boost::system::errc::protocol_error, ERROR_LOCATION); boost::format fmt("file line number %1% is invalid"); *pUserErrMsg = boost::str(fmt % lineNumber); error.addProperty("parse-error", *pUserErrMsg); error.addProperty("line-contents", *it); return error; } } // resolve any pending key and value if (!currentKey.empty()) pFields->insert(std::make_pair(currentKey,currentValue)); return Success(); }
core::Error iconvstr(const std::string& value, const std::string& from, const std::string& to, bool allowSubstitution, std::string* pResult) { std::string effectiveFrom = from; if (effectiveFrom.empty()) effectiveFrom = "UTF-8"; std::string effectiveTo = to; if (effectiveTo.empty()) effectiveTo = "UTF-8"; if (effectiveFrom == effectiveTo) { *pResult = value; return Success(); } std::vector<char> output; output.reserve(value.length()); void* handle = ::Riconv_open(to.c_str(), from.c_str()); if (handle == (void*)(-1)) return systemError(errno, ERROR_LOCATION); const char* pIn = value.data(); size_t inBytes = value.size(); char buffer[256]; while (inBytes > 0) { const char* pInOrig = pIn; char* pOut = buffer; size_t outBytes = sizeof(buffer); size_t result = ::Riconv(handle, &pIn, &inBytes, &pOut, &outBytes); if (buffer != pOut) output.insert(output.end(), buffer, pOut); if (result == (size_t)(-1)) { if ((errno == EILSEQ || errno == EINVAL) && allowSubstitution) { output.push_back('?'); pIn++; inBytes--; } else if (errno == E2BIG && pInOrig != pIn) { continue; } else { ::Riconv_close(handle); Error error = systemError(errno, ERROR_LOCATION); error.addProperty("str", value); error.addProperty("len", value.length()); return error; } } } ::Riconv_close(handle); *pResult = std::string(output.begin(), output.end()); return Success(); }
Error readCollectionFromFile( const core::FilePath& filePath, CollectionType* pCollection, boost::function<ReadCollectionAction(const std::string& line, typename CollectionType::value_type* pValue)> parseFunction, bool trimAndIgnoreBlankLines=true) { using namespace boost::system::errc ; // open the file stream boost::shared_ptr<std::istream> pIfs; Error error = filePath.open_r(&pIfs); if (error) return error; // create insert iterator std::insert_iterator<CollectionType> insertIterator(*pCollection, pCollection->begin()); try { // read each line std::string nextLine ; while (true) { // read the next line std::getline(*pIfs, nextLine) ; if (pIfs->eof()) break; else if (pIfs->fail()) return systemError(io_error, ERROR_LOCATION); // trim whitespace then ignore it if it is a blank line if (trimAndIgnoreBlankLines) { boost::algorithm::trim(nextLine) ; if (nextLine.empty()) continue ; } // parse it and add it to the collection typename CollectionType::value_type value ; ReadCollectionAction action = parseFunction(nextLine, &value); if (action == ReadCollectionAddLine) { *insertIterator++ = value ; } else if (action == ReadCollectionIgnoreLine) { // do nothing } else if (action == ReadCollectionTerminate) { break; // exit read loop } } } catch(const std::exception& e) { Error error = systemError(boost::system::errc::io_error, ERROR_LOCATION); error.addProperty("what", e.what()); error.addProperty("path", filePath.absolutePath()); return error; } return Success() ; }
Error parseJsonRpcRequest(const std::string& input, JsonRpcRequest* pRequest) { // json_spirit is not documented to throw an exceptions but surround // the code with an exception handling block just to be defensive... try { // parse data and verify it contains an object json::Value var; if ( !json::parse(input, &var) || (var.type() != json::ObjectType) ) { return Error(errc::InvalidRequest, ERROR_LOCATION) ; } // extract the fields json::Object& requestObject = var.get_obj(); for (json::Object::const_iterator it = requestObject.begin(); it != requestObject.end(); ++it) { std::string fieldName = it->first ; json::Value fieldValue = it->second ; if ( fieldName == "method" ) { if (fieldValue.type() != json::StringType) return Error(errc::InvalidRequest, ERROR_LOCATION) ; pRequest->method = fieldValue.get_str() ; } else if ( fieldName == "params" ) { if (fieldValue.type() != json::ArrayType) return Error(errc::ParamTypeMismatch, ERROR_LOCATION) ; pRequest->params = fieldValue.get_array(); } else if ( fieldName == "kwparams" ) { if (fieldValue.type() != json::ObjectType) return Error(errc::ParamTypeMismatch, ERROR_LOCATION) ; pRequest->kwparams = fieldValue.get_obj(); } else if (fieldName == "sourceWnd") { if (fieldValue.type() != json::StringType) return Error(errc::InvalidRequest, ERROR_LOCATION); pRequest->sourceWindow = fieldValue.get_str(); } else if (fieldName == "clientId" ) { if (fieldValue.type() != json::StringType) return Error(errc::InvalidRequest, ERROR_LOCATION); pRequest->clientId = fieldValue.get_str(); } else if (fieldName == "version" ) { if (!json::isType<double>(fieldValue)) return Error(errc::InvalidRequest, ERROR_LOCATION); pRequest->version = fieldValue.get_value<double>(); } } // method is required if (pRequest->method.empty() ) return Error(errc::InvalidRequest, ERROR_LOCATION) ; return Success() ; } catch(const std::exception& e) { Error error = Error(errc::ParseError, ERROR_LOCATION); error.addProperty("exception", e.what()) ; return error ; } }
Error pathNotFoundError(const std::string& path, const ErrorLocation& location) { Error error = pathNotFoundError(location); error.addProperty("path", path); return error; }