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();
   }
}
Example #2
0
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() ;
}
Example #3
0
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;
   }
}
Example #4
0
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);
}
Example #5
0
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();
}
Example #6
0
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());
}
Example #7
0
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() ;
}   
Example #8
0
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();
}
Example #9
0
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();
}
Example #10
0
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() ;
}
Example #11
0
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 ;
   }
}
Example #12
0
Error pathNotFoundError(const std::string& path, const ErrorLocation& location)
{
   Error error = pathNotFoundError(location);
   error.addProperty("path", path);
   return error;
}