* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include <RemoveEngine.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <Directory.h>
#include <Entry.h>
#include <Path.h>
namespace BPrivate {
BRemoveEngine::BRemoveEngine()
:
fController(NULL)
{
}
BRemoveEngine::~BRemoveEngine()
{
}
BRemoveEngine::BController*
BRemoveEngine::Controller() const
{
return fController;
}
void
BRemoveEngine::SetController(BController* controller)
{
fController = controller;
}
status_t
BRemoveEngine::RemoveEntry(const Entry& entry)
{
BPath pathBuffer;
const char* path;
status_t error = entry.GetPath(pathBuffer, path);
if (error != B_OK)
return error;
return _RemoveEntry(path);
}
status_t
BRemoveEngine::_RemoveEntry(const char* path)
{
if (fController != NULL && !fController->EntryStarted(path))
return B_OK;
struct stat st;
if (lstat(path, &st) < 0) {
return _HandleEntryError(path, errno, "Couldn't access \"%s\": %s\n",
path, strerror(errno));
}
if (S_ISDIR(st.st_mode)) {
BDirectory directory;
status_t error = directory.SetTo(path);
if (error != B_OK) {
return _HandleEntryError(path, error,
"Failed to open directory \"%s\": %s\n", path, strerror(error));
}
char buffer[offsetof(struct dirent, d_name) + B_FILE_NAME_LENGTH];
dirent *entry = (dirent*)buffer;
while (directory.GetNextDirents(entry, sizeof(buffer), 1) == 1) {
if (strcmp(entry->d_name, ".") == 0
|| strcmp(entry->d_name, "..") == 0) {
continue;
}
BPath childPath;
error = childPath.SetTo(path, entry->d_name);
if (error != B_OK) {
return _HandleEntryError(path, error,
"Failed to construct entry path from dir \"%s\" and name "
"\"%s\": %s\n", path, entry->d_name, strerror(error));
}
error = _RemoveEntry(childPath.Path());
if (error != B_OK) {
if (fController != NULL
&& fController->EntryFinished(path, error)) {
return B_OK;
}
return error;
}
}
}
if (S_ISDIR(st.st_mode)) {
if (rmdir(path) < 0) {
return _HandleEntryError(path, errno,
"Failed to remove \"%s\": %s\n", path, strerror(errno));
}
} else {
if (unlink(path) < 0) {
return _HandleEntryError(path, errno,
"Failed to unlink \"%s\": %s\n", path, strerror(errno));
}
}
if (fController != NULL)
fController->EntryFinished(path, B_OK);
return B_OK;
}
void
BRemoveEngine::_NotifyErrorVarArgs(status_t error, const char* format,
va_list args)
{
if (fController != NULL) {
BString message;
message.SetToFormatVarArgs(format, args);
fController->ErrorOccurred(message, error);
}
}
status_t
BRemoveEngine::_HandleEntryError(const char* path, status_t error,
const char* format, ...)
{
if (fController == NULL)
return error;
va_list args;
va_start(args, format);
_NotifyErrorVarArgs(error, format, args);
va_end(args);
if (fController->EntryFinished(path, error))
return B_OK;
return error;
}
BRemoveEngine::BController::BController()
{
}
BRemoveEngine::BController::~BController()
{
}
bool
BRemoveEngine::BController::EntryStarted(const char* path)
{
return true;
}
bool
BRemoveEngine::BController::EntryFinished(const char* path, status_t error)
{
return error == B_OK;
}
void
BRemoveEngine::BController::ErrorOccurred(const char* message, status_t error)
{
}
}