mirror of https://gitee.com/bigwinds/arangodb
437 lines
9.8 KiB
C++
437 lines
9.8 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief file utilities
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2004-2012 triagens GmbH, Cologne, Germany
|
|
///
|
|
/// 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.
|
|
///
|
|
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// @author Dr. Frank Celler
|
|
/// @author Copyright 2008-2012, triAGENS GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "FileUtils.h"
|
|
|
|
#include <errno.h>
|
|
#include <fstream>
|
|
#include <stdio.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
#ifdef TRI_HAVE_DIRENT_H
|
|
#include <dirent.h>
|
|
#endif
|
|
|
|
#ifdef TRI_HAVE_DIRECT_H
|
|
#include <direct.h>
|
|
#endif
|
|
|
|
#include "Basics/Exceptions.h"
|
|
#include "Logger/Logger.h"
|
|
#include "Basics/StringBuffer.h"
|
|
#include "BasicsC/files.h"
|
|
|
|
namespace triagens {
|
|
namespace basics {
|
|
namespace FileUtils {
|
|
ifstream * createInput (string const& filename) {
|
|
ifstream * s = new ifstream(filename.c_str());
|
|
|
|
if (!*s) {
|
|
delete s;
|
|
return 0;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
|
|
|
|
ofstream * createOutput (string const& filename) {
|
|
ofstream * s = new ofstream(filename.c_str());
|
|
|
|
if (!*s) {
|
|
delete s;
|
|
return 0;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
|
|
|
|
string slurp (string const& filename) {
|
|
int fd = TRI_OPEN(filename.c_str(), O_RDONLY);
|
|
|
|
if (fd == -1) {
|
|
THROW_FILE_OPEN_ERROR("open", filename, "O_RDONLY", errno);
|
|
}
|
|
|
|
char buffer[10240];
|
|
StringBuffer result(TRI_CORE_MEM_ZONE);
|
|
|
|
while (true) {
|
|
ssize_t n = TRI_READ(fd, buffer, sizeof(buffer));
|
|
|
|
if (n == 0) {
|
|
break;
|
|
}
|
|
|
|
if (n < 0) {
|
|
TRI_CLOSE(fd);
|
|
LOGGER_TRACE << "read failed for '" << filename << "' with " << strerror(errno) << " and result " << n
|
|
<< " on fd " << fd;
|
|
THROW_FILE_FUNC_ERROR("read", "", errno);
|
|
}
|
|
|
|
result.appendText(buffer, n);
|
|
}
|
|
|
|
TRI_CLOSE(fd);
|
|
|
|
string r(result.c_str());
|
|
|
|
return r;
|
|
}
|
|
|
|
|
|
|
|
void slurp (string const& filename, StringBuffer& result) {
|
|
int fd = TRI_OPEN(filename.c_str(), O_RDONLY);
|
|
|
|
if (fd == -1) {
|
|
THROW_FILE_OPEN_ERROR("open", filename, "O_RDONLY", errno);
|
|
}
|
|
|
|
char buffer[10240];
|
|
|
|
while (true) {
|
|
ssize_t n = TRI_READ(fd, buffer, sizeof(buffer));
|
|
|
|
if (n == 0) {
|
|
break;
|
|
}
|
|
|
|
if (n < 0) {
|
|
TRI_CLOSE(fd);
|
|
LOGGER_TRACE << "read failed for '" << filename << "' with " << strerror(errno) << " and result " << n
|
|
<< " on fd " << fd;
|
|
THROW_FILE_FUNC_ERROR("read", "", errno);
|
|
}
|
|
|
|
result.appendText(buffer, n);
|
|
}
|
|
|
|
TRI_CLOSE(fd);
|
|
}
|
|
|
|
|
|
|
|
void spit (string const& filename, string const& content) {
|
|
int fd = TRI_CREATE(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
|
|
|
if (fd == -1) {
|
|
LOGGER_TRACE << "open failed for '" << filename << "' with " << strerror(errno);
|
|
THROW_FILE_OPEN_ERROR("open", filename, "O_RDONLY | O_CREAT | O_TRUNC", errno);
|
|
}
|
|
|
|
char const* ptr = content.c_str();
|
|
size_t len = content.size();
|
|
|
|
while (0 < len) {
|
|
ssize_t n = TRI_WRITE(fd, ptr, len);
|
|
|
|
if (n < 1) {
|
|
TRI_CLOSE(fd);
|
|
LOGGER_TRACE << "write failed for '" << filename << "' with " << strerror(errno) << " and result " << n
|
|
<< " on fd " << fd;
|
|
THROW_FILE_FUNC_ERROR("write", "", errno);
|
|
}
|
|
|
|
ptr += n;
|
|
len -= n;
|
|
}
|
|
|
|
TRI_CLOSE(fd);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void spit (string const& filename, StringBuffer const& content) {
|
|
int fd = TRI_CREATE(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
|
|
|
|
if (fd == -1) {
|
|
LOGGER_TRACE << "open failed for '" << filename << "' with " << strerror(errno);
|
|
THROW_FILE_OPEN_ERROR("open", filename, "O_WRONLY | O_CREAT | O_TRUNC", errno);
|
|
}
|
|
|
|
char const* ptr = content.c_str();
|
|
size_t len = content.length();
|
|
|
|
while (0 < len) {
|
|
ssize_t n = TRI_WRITE(fd, ptr, len);
|
|
|
|
if (n < 1) {
|
|
TRI_CLOSE(fd);
|
|
LOGGER_TRACE << "write failed for '" << filename << "' with " << strerror(errno) << " and result " << n
|
|
<< " on fd " << fd;
|
|
THROW_FILE_FUNC_ERROR("write", "", errno);
|
|
}
|
|
|
|
ptr += n;
|
|
len -= n;
|
|
}
|
|
|
|
TRI_CLOSE(fd);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
bool remove (string const& fileName, int* errorNumber) {
|
|
if (errorNumber != 0) {
|
|
*errorNumber = 0;
|
|
}
|
|
|
|
int result = std::remove(fileName.c_str());
|
|
|
|
if (errorNumber != 0) {
|
|
*errorNumber = errno;
|
|
}
|
|
|
|
return (result != 0) ? false : true;
|
|
}
|
|
|
|
|
|
|
|
bool rename (string const& oldName, string const& newName, int* errorNumber) {
|
|
if (errorNumber != 0) {
|
|
*errorNumber = 0;
|
|
}
|
|
|
|
int result = std::rename(oldName.c_str(), newName.c_str());
|
|
|
|
if (errorNumber) {
|
|
*errorNumber = errno;
|
|
}
|
|
|
|
return (result != 0) ? false : true;
|
|
}
|
|
|
|
|
|
|
|
bool createDirectory (string const& name, int* errorNumber) {
|
|
if (errorNumber != 0) {
|
|
*errorNumber = 0;
|
|
}
|
|
|
|
return createDirectory(name, 0777, errorNumber);
|
|
}
|
|
|
|
|
|
|
|
bool createDirectory (string const& name, int mask, int* errorNumber) {
|
|
if (errorNumber != 0) {
|
|
*errorNumber = 0;
|
|
}
|
|
|
|
int result = TRI_MKDIR(name.c_str(), mask);
|
|
|
|
if (result != 0 && errno == EEXIST && isDirectory(name)) {
|
|
result = 0;
|
|
}
|
|
|
|
if (errorNumber) {
|
|
*errorNumber = errno;
|
|
}
|
|
|
|
return (result != 0) ? false : true;
|
|
}
|
|
|
|
|
|
|
|
vector<string> listFiles (string const& directory) {
|
|
vector < string > result;
|
|
|
|
#ifdef TRI_HAVE_WIN32_LIST_FILES
|
|
|
|
struct _finddata_t fd;
|
|
intptr_t handle;
|
|
|
|
string filter = directory + "\\*";
|
|
handle = _findfirst(filter.c_str(), &fd);
|
|
|
|
if (handle == -1) {
|
|
return result;
|
|
}
|
|
|
|
do {
|
|
if (strcmp(fd.name, ".") != 0 && strcmp(fd.name, "..") != 0) {
|
|
result.push_back(fd.name);
|
|
}
|
|
} while(_findnext(handle, &fd) != -1);
|
|
|
|
_findclose(handle);
|
|
|
|
#else
|
|
|
|
DIR * d = opendir(directory.c_str());
|
|
|
|
if (d == 0) {
|
|
return result;
|
|
}
|
|
|
|
dirent * de = readdir(d);
|
|
|
|
while (de != 0) {
|
|
if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) {
|
|
result.push_back(de->d_name);
|
|
}
|
|
|
|
de = readdir(d);
|
|
}
|
|
|
|
closedir(d);
|
|
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
bool isDirectory (string const& path) {
|
|
struct stat stbuf;
|
|
int res = stat(path.c_str(), &stbuf);
|
|
|
|
return (res == 0) && ((stbuf.st_mode & S_IFMT) == S_IFDIR);
|
|
}
|
|
|
|
|
|
|
|
bool isSymbolicLink (string const& path) {
|
|
|
|
#ifdef TRI_HAVE_WIN32_SYMBOLIC_LINK
|
|
|
|
// .........................................................................
|
|
// TODO: On the NTFS file system, there are the following file links:
|
|
// hard links -
|
|
// junctions -
|
|
// symbolic links -
|
|
// .........................................................................
|
|
return false;
|
|
|
|
#else
|
|
|
|
struct stat stbuf;
|
|
int res = stat(path.c_str(), &stbuf);
|
|
|
|
return (res == 0) && ((stbuf.st_mode & S_IFMT) == S_IFLNK);
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
bool isRegularFile (string const& path) {
|
|
struct stat stbuf;
|
|
int res = stat(path.c_str(), &stbuf);
|
|
|
|
return (res == 0) && ((stbuf.st_mode & S_IFMT) == S_IFREG);
|
|
}
|
|
|
|
|
|
|
|
bool exists (string const& path) {
|
|
struct stat stbuf;
|
|
int res = stat(path.c_str(), &stbuf);
|
|
|
|
return res == 0;
|
|
}
|
|
|
|
|
|
off_t size (string const& path) {
|
|
int64_t result = TRI_SizeFile(path.c_str());
|
|
|
|
if (result < 0) {
|
|
return (off_t) 0;
|
|
}
|
|
|
|
return (off_t) result;
|
|
}
|
|
|
|
|
|
string stripExtension (string const& path, string const& extension) {
|
|
size_t pos = path.rfind(extension);
|
|
if (pos == string::npos) {
|
|
return path;
|
|
}
|
|
|
|
string last = path.substr(pos);
|
|
if (last == extension) {
|
|
return path.substr(0, pos);
|
|
}
|
|
|
|
return path;
|
|
}
|
|
|
|
|
|
|
|
bool changeDirectory (string const& path) {
|
|
return TRI_CHDIR(path.c_str()) == 0;
|
|
}
|
|
|
|
|
|
|
|
string currentDirectory (int* errorNumber) {
|
|
if (errorNumber != 0) {
|
|
*errorNumber = 0;
|
|
}
|
|
|
|
size_t len = 1000;
|
|
char* current = new char[len];
|
|
|
|
while (TRI_GETCWD(current, len) == NULL) {
|
|
if (errno == ERANGE) {
|
|
len += 1000;
|
|
delete[] current;
|
|
current = new char[len];
|
|
}
|
|
else {
|
|
delete[] current;
|
|
|
|
if (errorNumber != 0) {
|
|
*errorNumber = errno;
|
|
}
|
|
|
|
return "";
|
|
}
|
|
}
|
|
|
|
string result = current;
|
|
|
|
delete[] current;
|
|
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|