pxmlw6n2f/Gazebo_Distributed_MPI/gazebo/common/CommonIface.cc

343 lines
8.6 KiB
C++

/*
* Copyright (C) 2012 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifdef _WIN32
#include <Windows.h>
#endif
#include <cstdlib>
#include <fstream>
#include <fcntl.h>
#include <sys/stat.h>
#ifdef __linux__
#include <sys/sendfile.h>
#endif
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <gazebo/gazebo_config.h>
#include <gazebo/common/ffmpeg_inc.h>
#include "gazebo/common/Console.hh"
#include "gazebo/common/CommonIface.hh"
#include "gazebo/common/Exception.hh"
#include "gazebo/common/SystemPaths.hh"
using namespace gazebo;
#ifdef _WIN32
# define GZ_PATH_MAX _MAX_PATH
#elif defined(PATH_MAX)
# define GZ_PATH_MAX PATH_MAX
#elif defined(_XOPEN_PATH_MAX)
# define GZ_PATH_MAX _XOPEN_PATH_MAX
#else
# define GZ_PATH_MAX _POSIX_PATH_MAX
#endif
/////////////////////////////////////////////////
void common::load()
{
#ifdef HAVE_FFMPEG
static bool first = true;
if (first)
{
first = false;
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
avcodec_register_all();
av_register_all();
#endif
}
#endif
}
/////////////////////////////////////////////////
void common::add_search_path_suffix(const std::string &_suffix)
{
common::SystemPaths::Instance()->AddSearchPathSuffix(_suffix);
}
/////////////////////////////////////////////////
std::string common::find_file(const std::string &_file)
{
return common::SystemPaths::Instance()->FindFile(_file, true);
}
/////////////////////////////////////////////////
std::string common::find_file(const std::string &_file, bool _searchLocalPath)
{
return common::SystemPaths::Instance()->FindFile(_file, _searchLocalPath);
}
/////////////////////////////////////////////////
std::string common::find_file_path(const std::string &_file)
{
std::string filepath = common::find_file(_file);
boost::filesystem::path path(filepath);
if (boost::filesystem::is_directory(path))
{
return filepath;
}
else
{
int index = filepath.find_last_of("/");
return filepath.substr(0, index);
}
}
/////////////////////////////////////////////////
const char *common::getEnv(const char *_name)
{
#ifdef _WIN32
const DWORD buffSize = 65535;
static char buffer[buffSize];
if (GetEnvironmentVariable(_name, buffer, buffSize))
return buffer;
else
return NULL;
#else
return getenv(_name);
#endif
}
/////////////////////////////////////////////////
std::string common::cwd()
{
char buf[GZ_PATH_MAX + 1] = {'\0'};
#ifdef _WIN32
return _getcwd(buf, sizeof(buf)) == nullptr ? "" : buf;
#else
return getcwd(buf, sizeof(buf)) == nullptr ? "" : buf;
#endif
}
/////////////////////////////////////////////////
bool common::exists(const std::string &_path)
{
return common::isFile(_path) || common::isDirectory(_path);
}
/////////////////////////////////////////////////
bool common::isFile(const std::string &_path)
{
std::ifstream f(_path);
return f.good();
}
/////////////////////////////////////////////////
bool common::isDirectory(const std::string &_path)
{
struct stat info;
if (stat(_path.c_str(), &info) != 0)
return false;
else if (info.st_mode & S_IFDIR)
return true;
else
return false;
}
/////////////////////////////////////////////////
bool common::moveFile(const std::string &_existingFilename,
const std::string &_newFilename)
{
return copyFile(_existingFilename, _newFilename) &&
std::remove(_existingFilename.c_str()) == 0;
}
/////////////////////////////////////////////////
void common::replaceAll(std::string &_result,
const std::string &_orig,
const std::string &_key,
const std::string &_replacement)
{
_result = _orig;
size_t pos = 0;
while ((pos = _result.find(_key, pos)) != std::string::npos)
{
_result = _result.replace(pos, _key.length(), _replacement);
pos += _key.length() > _replacement.length() ? 0 : _replacement.length();
}
}
/////////////////////////////////////////////////
std::string common::replaceAll(const std::string &_orig,
const std::string &_key,
const std::string &_replacement)
{
std::string result;
replaceAll(result, _orig, _key, _replacement);
return result;
}
/////////////////////////////////////////////////
std::string common::absPath(const std::string &_path)
{
std::string result;
char path[GZ_PATH_MAX] = "";
#ifdef _WIN32
if (GetFullPathName(_path.c_str(), GZ_PATH_MAX, &path[0], nullptr) != 0)
#else
if (realpath(_path.c_str(), &path[0]) != nullptr)
#endif
result = path;
else if (!_path.empty())
{
// If _path is an absolute path, then return _path.
// An absoluate path on Windows is a character followed by a colon and a
// forward-slash.
if (_path.compare(0, 1, "/") == 0 || _path.compare(1, 3, ":\\") == 0)
result = _path;
// Otherwise return the current working directory with _path appended.
else
result = common::cwd() + "/" + _path;
}
common::replaceAll(result, result, "//", "/");
return result;
}
/////////////////////////////////////////////////
bool common::copyFile(const std::string &_existingFilename,
const std::string &_newFilename)
{
std::string absExistingFilename = common::absPath(_existingFilename);
std::string absNewFilename = common::absPath(_newFilename);
if (absExistingFilename == absNewFilename)
return false;
#ifdef _WIN32
return CopyFile(absExistingFilename.c_str(), absNewFilename.c_str(), false);
#elif defined(__APPLE__)
bool result = false;
std::ifstream in(absExistingFilename.c_str(), std::ifstream::binary);
if (in.good())
{
std::ofstream out(absNewFilename.c_str(),
std::ifstream::trunc | std::ifstream::binary);
if (out.good())
{
out << in.rdbuf();
result = common::isFile(absNewFilename);
}
out.close();
}
in.close();
return result;
#else
int readFd = 0;
int writeFd = 0;
struct stat statBuf;
off_t offset = 0;
// Open the input file.
readFd = open(absExistingFilename.c_str(), O_RDONLY);
if (readFd < 0)
return false;
// Stat the input file to obtain its size.
fstat(readFd, &statBuf);
// Open the output file for writing, with the same permissions as the
// source file.
writeFd = open(absNewFilename.c_str(), O_WRONLY | O_CREAT, statBuf.st_mode);
while (offset >= 0 && offset < statBuf.st_size)
{
// Send the bytes from one file to the other.
ssize_t written = sendfile(writeFd, readFd, &offset, statBuf.st_size);
if (written < 0)
break;
}
close(readFd);
close(writeFd);
return offset == statBuf.st_size;
#endif
}
/////////////////////////////////////////////////
bool common::copyDir(const boost::filesystem::path &_source,
const boost::filesystem::path &_destination)
{
namespace fs = boost::filesystem;
try
{
// Check whether source directory exists
if (!fs::exists(_source) || !fs::is_directory(_source))
{
gzwarn << "Source directory " << _source.string()
<< " does not exist or is not a directory." << std::endl;
return false;
}
if (fs::exists(_destination))
{
fs::remove_all(_destination);
}
// Create the destination directory
if (!fs::create_directory(_destination))
{
gzwarn << "Unable to create the destination directory "
<< _destination.string() << ", please check the permission.\n";
return false;
}
}
catch(fs::filesystem_error const &e)
{
gzwarn << e.what() << std::endl;
return false;
}
// Start copy from source to destination directory
for (fs::directory_iterator file(_source);
file != fs::directory_iterator(); ++file)
{
try
{
fs::path current(file->path());
if (fs::is_directory(current))
{
if (!copyDir(current, _destination / current.filename()))
{
return false;
}
}
else
{
fs::copy_file(current, _destination / current.filename());
}
}
catch(fs::filesystem_error const &e)
{
gzwarn << e.what() << std::endl;
return false;
}
}
return true;
}