Commit 8619027f authored by Guillaume Roguez's avatar Guillaume Roguez

account: delete filesystem traces of an account

This patch adds a new virtual API to Account, flush(),
that does nothing by default. Concrete classes may overload it
when it's needed to remove filesystem entries created by them.

Then this patch adds also overloads of this method in SIPAccountBase and
RingAccount to delete all files added by these account classes.

Finaly, the removeAccount() external API calls flush by default, but
internal calls do not, to keep a conservative behaviour
and not destroying account files due to yml parsing errors.

Change-Id: I52c4e225f4d41f0e3d74f63838e56a769011b58e
Tuleap: #988
parent 4f448e13
......@@ -301,6 +301,13 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
*/
virtual void connectivityChanged() {};
public: // virtual methods that has to be implemented by concrete classes
/**
* This method is called to request removal of possible account traces on the system,
* like internal account setup files.
*/
virtual void flush() { /* nothing to do here - overload */ };
private:
NON_COPYABLE(Account);
......
......@@ -343,7 +343,7 @@ addAccount(const std::map<std::string, std::string>& details)
void
removeAccount(const std::string& accountID)
{
return ring::Manager::instance().removeAccount(accountID);
return ring::Manager::instance().removeAccount(accountID, true); // with 'flush' enabled
}
std::vector<std::string>
......
......@@ -24,8 +24,8 @@
#include "config.h"
#endif
#include "fileutils.h"
#include "logger.h"
#include "fileutils.h"
#include "compiler_intrinsics.h"
#ifdef __APPLE__
......@@ -222,6 +222,20 @@ bool isDirectoryWritable(const std::string &directory)
return access(directory.c_str(), W_OK) == 0;
}
bool isSymLink(const std::string& path)
{
#ifndef _WIN32
struct stat s;
if (lstat(path.c_str(), &s) == 0)
return S_ISLNK(s.st_mode);
#else
DWORD attr = GetFileAttributes(ring::to_wstring(path).c_str());
if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
return true;
#endif
return false;
}
std::chrono::system_clock::time_point
writeTime(const std::string& path)
{
......@@ -511,4 +525,19 @@ recursive_mkdir(const std::string& path, mode_t mode)
return true;
}
int
removeAll(const std::string& path)
{
if (path.empty())
return -1;
if (isDirectory(path) and !isSymLink(path)) {
auto dir = path;
if (dir.back() != DIR_SEPARATOR_CH)
dir += DIR_SEPARATOR_CH;
for (auto& entry : fileutils::readDirectory(dir))
removeAll(dir + entry);
}
return remove(path);
}
}} // namespace ring::fileutils
......@@ -24,6 +24,7 @@
#include <string>
#include <vector>
#include <chrono>
#include <cstdio>
#define PROTECTED_GETENV(str) ({char *envvar_ = getenv((str)); \
envvar_ ? envvar_ : "";})
......@@ -67,6 +68,8 @@ namespace ring { namespace fileutils {
bool isDirectory(const std::string& path);
bool isSymLink(const std::string& path);
std::chrono::system_clock::time_point writeTime(const std::string& path);
/**
......@@ -87,6 +90,17 @@ namespace ring { namespace fileutils {
};
FileHandle create_pidfile();
/**
* Direct binding on std::remove, with std::string as argument
*/
static inline int remove(const std::string& path) { return std::remove(path.c_str()); }
/**
* Prune given directory's content and remove it, symlinks are not followed.
* Return 0 if succeed, -1 if directory is not removed (content can be removed partially).
*/
int removeAll(const std::string& path);
}} // namespace ring::fileutils
#endif // FILEUTILS_H_
......@@ -2510,11 +2510,13 @@ void Manager::removeAccounts()
removeAccount(acc);
}
void Manager::removeAccount(const std::string& accountID)
void Manager::removeAccount(const std::string& accountID, bool flush)
{
// Get it down and dying
if (const auto& remAccount = getAccount(accountID)) {
remAccount->doUnregister();
if (flush)
remAccount->flush();
accountFactory_.removeAccount(*remAccount);
}
......
......@@ -514,9 +514,10 @@ class Manager {
/**
* Delete an existing account, unregister VoIPLink associated, and
* purge from configuration.
* If 'flush' argument is true, filesystem entries are also removed.
* @param accountID The account unique ID
*/
void removeAccount(const std::string& accountID);
void removeAccount(const std::string& accountID, bool flush=false);
/**
* Set input audio plugin
......
......@@ -152,6 +152,17 @@ RingAccount::~RingAccount()
dht_.join();
}
void
RingAccount::flush()
{
// Class base method
SIPAccountBase::flush();
fileutils::removeAll(dataPath_);
fileutils::removeAll(cachePath_);
fileutils::removeAll(idPath_);
}
std::shared_ptr<SIPCall>
RingAccount::newIncomingCall(const std::string& from)
{
......@@ -1255,7 +1266,7 @@ RingAccount::loadValues() const
} catch (const std::exception& e) {
RING_ERR("Error reading value: %s", e.what());
}
remove(file.c_str());
fileutils::remove(file);
}
RING_DBG("Loaded %zu values", values.size());
return values;
......
......@@ -256,6 +256,9 @@ class RingAccount : public SIPAccountBase {
void connectivityChanged() override;
public: // overloaded methods
void flush() override;
private:
NON_COPYABLE(RingAccount);
......
......@@ -53,6 +53,15 @@ SIPAccountBase::SIPAccountBase(const std::string& accountID)
SIPAccountBase::~SIPAccountBase() {}
void
SIPAccountBase::flush()
{
// Class base method
Account::flush();
fileutils::remove(fileutils::get_cache_dir() + DIR_SEPARATOR_STR + getAccountID() + DIR_SEPARATOR_STR "messages");
}
template <typename T>
static void
validate(std::string &member, const std::string &param, const T& valid)
......
......@@ -252,6 +252,9 @@ public:
void connectivityChanged() override {};
public: // overloaded methods
virtual void flush() override;
protected:
virtual void serialize(YAML::Emitter &out) override;
virtual void serializeTls(YAML::Emitter &out);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment