mirror of
https://github.com/uroni/urbackup_backend.git
synced 2025-10-26 11:36:50 +00:00
347 lines
9.3 KiB
C++
347 lines
9.3 KiB
C++
#include "action_header.h"
|
|
#include "../server_settings.h"
|
|
#include "../ClientMain.h"
|
|
|
|
namespace
|
|
{
|
|
void access_dir_details(std::string folder, std::string& ret)
|
|
{
|
|
bool has_error = false;
|
|
getFiles(folder, &has_error);
|
|
if (has_error)
|
|
{
|
|
ret += "Cannot access " + folder + ". " + os_last_error_str() + "\n";
|
|
}
|
|
else
|
|
{
|
|
ret += "Can access " + folder + "\n";
|
|
}
|
|
}
|
|
|
|
std::string access_err_details(std::string folder)
|
|
{
|
|
std::vector<std::string> toks;
|
|
Tokenize(folder, toks, os_file_sep());
|
|
|
|
std::string ret;
|
|
|
|
std::string cdir = os_file_sep();
|
|
access_dir_details(cdir, ret);
|
|
|
|
for (size_t i = 0; i < toks.size(); ++i)
|
|
{
|
|
if (toks[i].empty()) continue;
|
|
|
|
if (cdir != os_file_sep())
|
|
{
|
|
cdir += os_file_sep();
|
|
}
|
|
cdir += toks[i];
|
|
|
|
access_dir_details(cdir, ret);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
std::string access_dir_hint(std::string folder)
|
|
{
|
|
if (folder.size() > 1 && folder[1] == ':')
|
|
{
|
|
bool has_error = false;
|
|
getFiles(folder.substr(0, 2) + os_file_sep(), &has_error);
|
|
|
|
if (has_error)
|
|
{
|
|
return "volume_not_accessible";
|
|
}
|
|
}
|
|
|
|
if ((folder.size() > 2 && folder[0] == '\\'
|
|
&& folder[1] == '\\'
|
|
&& folder[2] != '?')
|
|
|| next(folder, 0, "\\\\?\\UNC"))
|
|
{
|
|
bool has_error = false;
|
|
getFiles(folder, &has_error);
|
|
|
|
if (has_error && os_last_error() == 5
|
|
|| os_last_error() == 1326)
|
|
{
|
|
return "folder_unc_access_denied";
|
|
}
|
|
}
|
|
|
|
return std::string();
|
|
}
|
|
|
|
bool is_stop_show(IDatabase* db, std::string stop_key)
|
|
{
|
|
db_results res = db->Read("SELECT tvalue FROM misc WHERE tkey='stop_show'");
|
|
if (!res.empty())
|
|
{
|
|
std::vector<std::string> toks;
|
|
Tokenize(res[0]["tvalue"], toks, ",");
|
|
return std::find(toks.begin(), toks.end(), stop_key) != toks.end();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void add_stop_show(IDatabase* db, JSON::Object& ret, std::string dir_error_stop_show_key)
|
|
{
|
|
ret.set("dir_error_stop_show_key", dir_error_stop_show_key);
|
|
if (is_stop_show(db, dir_error_stop_show_key))
|
|
{
|
|
ret.set("dir_error_show", false);
|
|
}
|
|
}
|
|
|
|
void access_dir_checks(IDatabase* db, ServerSettings& settings, std::string backupfolder, std::string backupfolder_uncompr,
|
|
JSON::Object& ret)
|
|
{
|
|
#ifdef _WIN32
|
|
if (backupfolder.size() == 2 && backupfolder[1] == ':')
|
|
{
|
|
backupfolder += os_file_sep();
|
|
}
|
|
if (backupfolder_uncompr.size() == 2 && backupfolder_uncompr[1] == ':')
|
|
{
|
|
backupfolder_uncompr += os_file_sep();
|
|
}
|
|
#endif
|
|
|
|
if (backupfolder.empty() || !os_directory_exists(os_file_prefix(backupfolder)) || !os_directory_exists(os_file_prefix(backupfolder_uncompr)))
|
|
{
|
|
if (!backupfolder.empty())
|
|
{
|
|
ret.set("system_err", os_last_error_str());
|
|
}
|
|
|
|
ret.set("dir_error", true);
|
|
|
|
if (settings.getSettings()->backupfolder.empty())
|
|
{
|
|
ret.set("dir_error_ext", "err_name_empty");
|
|
}
|
|
else if (!os_directory_exists(os_file_prefix(settings.getSettings()->backupfolder)))
|
|
{
|
|
ret.set("dir_error_ext", "err_folder_not_found");
|
|
add_stop_show(db, ret, "dir_error_not_found");
|
|
}
|
|
else
|
|
{
|
|
add_stop_show(db, ret, "dir_error_misc");
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
std::string hint = access_dir_hint(settings.getSettings()->backupfolder);
|
|
if (!hint.empty())
|
|
{
|
|
ret.set("dir_error_hint", hint);
|
|
}
|
|
#endif
|
|
|
|
#ifndef _WIN32
|
|
ret.set("detail_err_str", access_err_details(settings.getSettings()->backupfolder));
|
|
#endif
|
|
}
|
|
else if (!os_directory_exists(os_file_prefix(backupfolder + os_file_sep() + "clients")) && !os_create_dir(os_file_prefix(backupfolder + os_file_sep() + "clients")))
|
|
{
|
|
ret.set("system_err", os_last_error_str());
|
|
ret.set("dir_error", true);
|
|
ret.set("dir_error_ext", "err_cannot_create_subdir");
|
|
|
|
add_stop_show(db, ret, "dir_error_cannot_create_subdir");
|
|
|
|
#ifdef _WIN32
|
|
std::string hint = access_dir_hint(backupfolder);
|
|
if (!hint.empty())
|
|
{
|
|
ret.set("dir_error_hint", hint);
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
bool has_access_error = false;
|
|
std::string testfoldername = "testfolderHvfgh---dFFoeRRRf";
|
|
std::string testfolderpath = backupfolder + os_file_sep() + testfoldername;
|
|
if (os_directory_exists(os_file_prefix(testfolderpath)))
|
|
{
|
|
if (!os_remove_dir(os_file_prefix(testfolderpath)))
|
|
{
|
|
ret.set("system_err", os_last_error_str());
|
|
ret.set("dir_error", true);
|
|
ret.set("dir_error_ext", "err_cannot_create_subdir");
|
|
add_stop_show(db, ret, "dir_error_cannot_create_subdir2");
|
|
has_access_error = true;
|
|
#ifdef _WIN32
|
|
std::string hint = access_dir_hint(backupfolder);
|
|
if (!hint.empty())
|
|
{
|
|
ret.set("dir_error_hint", hint);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
SSettings* server_settings = settings.getSettings();
|
|
|
|
if (!has_access_error
|
|
&& !os_create_dir(os_file_prefix(testfolderpath)))
|
|
{
|
|
ret.set("system_err", os_last_error_str());
|
|
ret.set("dir_error", true);
|
|
ret.set("dir_error_ext", "err_cannot_create_subdir");
|
|
add_stop_show(db, ret, "dir_error_cannot_create_subdir3");
|
|
|
|
#ifdef _WIN32
|
|
std::string hint = access_dir_hint(backupfolder);
|
|
if (!hint.empty())
|
|
{
|
|
ret.set("dir_error_hint", hint);
|
|
}
|
|
#endif
|
|
has_access_error = true;
|
|
}
|
|
#ifdef _WIN32
|
|
else if (!server_settings->no_file_backups
|
|
&& os_directory_exists(os_file_prefix(backupfolder + os_file_sep() + "testfo~1")))
|
|
{
|
|
ret.set("dir_error", true);
|
|
ret.set("dir_error_ext", "dos_names_created");
|
|
add_stop_show(db, ret, "dos_names_created");
|
|
ret.set("dir_error_hint", "dos_names_created");
|
|
if (backupfolder.size() > 2
|
|
&& backupfolder[1] == ':')
|
|
{
|
|
ret.set("dir_error_volume", backupfolder.substr(0, 2));
|
|
}
|
|
else
|
|
{
|
|
ret.set("dir_error_volume", "<VOLUME>");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (!server_settings->no_file_backups)
|
|
{
|
|
std::string linkfolderpath = testfolderpath + "_link";
|
|
os_remove_symlink_dir(os_file_prefix(linkfolderpath));
|
|
Server->deleteFile(os_file_prefix(linkfolderpath));
|
|
|
|
if (!has_access_error
|
|
&& !os_link_symbolic(os_file_prefix(testfolderpath), os_file_prefix(linkfolderpath)))
|
|
{
|
|
ret.set("system_err", os_last_error_str());
|
|
ret.set("dir_error", true);
|
|
ret.set("dir_error_ext", "err_cannot_create_symbolic_links");
|
|
ret.set("dir_error_hint", "UrBackup cannot create symbolic links on the backup storage. "
|
|
"Your backup storage must support symbolic links in order for UrBackup to work correctly. "
|
|
"The UrBackup Server must run as administrative user on Windows (If not you get error code 1314). "
|
|
"Note: As of 2016-05-07 samba (which is used by many Linux based NAS operating systems for Windows file sharing) has not "
|
|
"implemented the necessary functionality to support symbolic link creation from Windows (With this you get error code 4390).");
|
|
add_stop_show(db, ret, "dir_error_cannot_create_symbolic_links");
|
|
}
|
|
|
|
os_remove_symlink_dir(os_file_prefix(linkfolderpath));
|
|
}
|
|
|
|
if (!server_settings->no_file_backups)
|
|
{
|
|
bool use_tmpfiles = server_settings->use_tmpfiles;
|
|
std::string tmpfile_path;
|
|
if (!use_tmpfiles)
|
|
{
|
|
tmpfile_path = server_settings->backupfolder + os_file_sep() + "urbackup_tmp_files";
|
|
}
|
|
|
|
std::auto_ptr<IFile> tmp_f(ClientMain::getTemporaryFileRetry(use_tmpfiles, tmpfile_path, logid_t()));
|
|
|
|
if (tmp_f.get() == NULL)
|
|
{
|
|
ret.set("tmpdir_error", true);
|
|
ret.set("tmpdir_error_stop_show_key", "tmpdir_error");
|
|
if (is_stop_show(db, "tmpdir_error"))
|
|
{
|
|
ret.set("tmpdir_error_show", false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::string teststring = base64_decode("WDVPIVAlQEFQWzRcUFpYNTQoUF4pN0NDKTd9JEVJQ0FSLVNUQU5EQVJELUFOVElWSVJVUy1URVNULUZJTEUhJEgrSCo=");
|
|
tmp_f->Write(teststring);
|
|
std::string tmp_fn = tmp_f->getFilename();
|
|
tmp_f.reset();
|
|
tmp_f.reset(Server->openFile(tmp_fn, MODE_RW));
|
|
|
|
std::string readstring;
|
|
if (tmp_f.get() != NULL)
|
|
{
|
|
readstring = tmp_f->Read(static_cast<_u32>(teststring.size()));
|
|
}
|
|
|
|
tmp_f.reset();
|
|
Server->deleteFile(tmp_fn);
|
|
|
|
if (teststring != readstring)
|
|
{
|
|
ret.set("virus_error", true);
|
|
ret.set("virus_error_path", ExtractFilePath(tmp_fn));
|
|
ret.set("virus_error_stop_show_key", "virus_error");
|
|
if (is_stop_show(db, "virus_error"))
|
|
{
|
|
ret.set("virus_error_show", false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!has_access_error
|
|
&& !os_remove_dir(os_file_prefix(testfolderpath)))
|
|
{
|
|
ret.set("system_err", os_last_error_str());
|
|
ret.set("dir_error", true);
|
|
ret.set("dir_error_ext", "err_cannot_create_subdir");
|
|
add_stop_show(db, ret, "dir_error_cannot_create_subdir4");
|
|
has_access_error = true;
|
|
}
|
|
}
|
|
|
|
IFile *tmp = Server->openTemporaryFile();
|
|
ScopedDeleteFile delete_tmp_file(tmp);
|
|
if (tmp == NULL)
|
|
{
|
|
ret.set("tmpdir_error", true);
|
|
ret.set("tmpdir_error_stop_show_key", "tmpdir_error");
|
|
if (is_stop_show(db, "tmpdir_error"))
|
|
{
|
|
ret.set("tmpdir_error_show", false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ACTION_IMPL(status_check)
|
|
{
|
|
Helper helper(tid, &POST, &PARAMS);
|
|
JSON::Object ret;
|
|
|
|
std::string rights = helper.getRights("status");
|
|
SUser *session = helper.getSession();
|
|
if (session != NULL && session->id == SESSION_ID_INVALID) return;
|
|
if (session != NULL && rights == "all")
|
|
{
|
|
IDatabase *db = helper.getDatabase();
|
|
helper.releaseAll();
|
|
ServerSettings settings(db);
|
|
access_dir_checks(db, settings, settings.getSettings()->backupfolder,
|
|
settings.getSettings()->backupfolder_uncompr, ret);
|
|
}
|
|
else
|
|
{
|
|
ret.set("error", 1);
|
|
}
|
|
helper.Write(ret.stringify(false));
|
|
} |