syncevolution/src/core/SyncEvolutionUtil.cpp

176 lines
4.1 KiB
C++

/*
* Copyright (C) 2008 Patrick Ohly
*/
#include <config.h>
#include "SyncEvolutionUtil.h"
#include "EvolutionSyncClient.h"
#include <base/test.h>
#include <boost/scoped_array.hpp>
#include <boost/foreach.hpp>
#include <fstream>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#ifdef ENABLE_UNIT_TESTS
CPPUNIT_REGISTRY_ADD_TO_DEFAULT("SyncEvolution");
#endif
string normalizePath(const string &path)
{
string res;
res.reserve(path.size());
size_t index = 0;
while (index < path.size()) {
char curr = path[index];
res += curr;
index++;
if (curr == '/') {
while (index < path.size() &&
(path[index] == '/' ||
(path[index] == '.' &&
index + 1 < path.size() &&
(path[index + 1] == '.' ||
path[index + 1] == '/')))) {
index++;
}
}
}
if (!res.empty() && res[res.size() - 1] == '/') {
res.resize(res.size() - 1);
}
return res;
}
void mkdir_p(const string &path)
{
boost::scoped_array<char> dirs(new char[path.size() + 1]);
char *curr = dirs.get();
strcpy(curr, path.c_str());
do {
char *nextdir = strchr(curr, '/');
if (nextdir) {
*nextdir = 0;
nextdir++;
}
if (*curr) {
if (access(dirs.get(),
nextdir ? (R_OK|X_OK) : (R_OK|X_OK|W_OK)) &&
(errno != ENOENT ||
mkdir(dirs.get(), 0777))) {
EvolutionSyncClient::throwError(string(dirs.get()), errno);
}
}
if (nextdir) {
nextdir[-1] = '/';
}
curr = nextdir;
} while (curr);
}
void rm_r(const string &path)
{
struct stat buffer;
if (lstat(path.c_str(), &buffer)) {
if (errno == ENOENT) {
return;
} else {
EvolutionSyncClient::throwError(path, errno);
}
}
if (!S_ISDIR(buffer.st_mode)) {
if (!unlink(path.c_str())) {
return;
} else {
EvolutionSyncClient::throwError(path, errno);
}
}
ReadDir dir(path);
BOOST_FOREACH(const string &entry, dir) {
rm_r(path + "/" + entry);
}
if (rmdir(path.c_str())) {
EvolutionSyncClient::throwError(path, errno);
}
}
bool isDir(const string &path)
{
DIR *dir = opendir(path.c_str());
if (dir) {
closedir(dir);
return true;
} else if (errno != ENOTDIR && errno != ENOENT) {
EvolutionSyncClient::throwError(path, errno);
}
return false;
}
UUID::UUID()
{
static class InitSRand {
public:
InitSRand() {
ifstream seedsource("/dev/urandom");
unsigned int seed;
if (!seedsource.get((char *)&seed, sizeof(seed))) {
seed = time(NULL);
}
srand(seed);
}
} initSRand;
char buffer[16 * 4 + 5];
sprintf(buffer, "%08x-%04x-%04x-%02x%02x-%08x%04x",
rand() & 0xFFFFFFFF,
rand() & 0xFFFF,
rand() & 0x0FFF | 0x4000 /* RFC 4122 time_hi_and_version */,
rand() & 0xBF | 0x80 /* clock_seq_hi_and_reserved */,
rand() & 0xFF,
rand() & 0xFFFFFFFF,
rand() & 0xFFFF
);
this->assign(buffer);
}
ReadDir::ReadDir(const string &path) : m_path(path)
{
DIR *dir = NULL;
try {
dir = opendir(path.c_str());
if (!dir) {
EvolutionSyncClient::throwError(path, errno);
}
errno = 0;
struct dirent *entry = readdir(dir);
while (entry) {
if (strcmp(entry->d_name, ".") &&
strcmp(entry->d_name, "..")) {
m_entries.push_back(entry->d_name);
}
entry = readdir(dir);
}
if (errno) {
EvolutionSyncClient::throwError(path, errno);
}
} catch(...) {
if (dir) {
closedir(dir);
}
throw;
}
closedir(dir);
}