#include <boost/filesystem/path.hpp>
#include <glib.h>
-#include <common/request.h>
+#include <common/utils/file_util.h>
+#include <common/utils/request.h>
#include <common/utils/subprocess.h>
#include <common/utils/user_util.h>
#include <manifest_parser/utils/logging.h>
#include <sys/types.h>
#include <tzplatform_config.h>
+#include <array>
#include <regex>
#include <string>
#include <vector>
typedef std::pair<std::string, std::string> RecoverEntry;
const char kRecoveryFilePattern[] = "^(.*)-recovery-(.){6}$";
-const char kBackupFilePattern[] = "^(.*)-recovery-(.){6}\.bck$";
+const char kBackupFilePattern[] = "^(.*)-recovery-(.){6}\\.bck$";
const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+std::string TruncateNewLine(const char* data) {
+ int length = strlen(data);
+ if (data[length - 1] == '\n')
+ --length;
+ return std::string(data, length);
+}
+
+std::vector<std::string> ParseRecoveryFile(const char* file) {
+ FILE* handle = fopen(file, "r");
+ if (!handle) {
+ LOG(ERROR) << "Failed to open recovery file :" << file;
+ return {};
+ }
+
+ std::vector<std::string> arguments;
+ std::array<char, 200> data;
+ data[0] = '\0';
+ while (fgets(data.data(), data.size(), handle)) {
+ std::string line_data = TruncateNewLine(data.data());
+ if (line_data == "cleanup") {
+ arguments.emplace_back("--recovery-cleanup");
+ break;
+ }
+
+ if (!boost::filesystem::exists(line_data))
+ continue;
+
+ arguments.emplace_back(line_data);
+ }
+ fclose(handle);
+
+ return arguments;
+}
+
class PkgRecoveryService {
public:
PkgRecoveryService();
std::string backend_cmd = "/usr/bin/" + std::string(type) + "-backend";
ci::Subprocess backend(backend_cmd);
std::string str_uid = std::to_string(uid);
- backend.Run("-b", file, "-u", str_uid.c_str());
+ if (std::string(type) == "unified") {
+ auto arguments = ParseRecoveryFile(file);
+ if (!arguments.size())
+ return ci::Remove(bf::path(file));
+
+ arguments.emplace(arguments.begin(), "-b");
+ arguments.emplace_back("-u");
+ arguments.emplace_back(str_uid.c_str());
+
+ backend.RunWithArgs(arguments);
+ } else {
+ backend.Run("-b", file, "-u", str_uid.c_str());
+ }
int status = backend.Wait();
if (WIFSIGNALED(status) || WEXITSTATUS(status))
return false;
+
+ ci::Remove(bf::path(file));
+
return true;
}
// recover normal user packages
ci::UserList list = ci::GetUserList();
- for (auto userinfo : list) {
+ for (const auto& userinfo : list) {
uid_t uid = std::get<0>(userinfo);
LOG(INFO) << "Searching recovery files for user " << std::get<0>(userinfo);
SearchBackupFiles(uid);
void PkgRecoveryService::SearchBackupFiles(uid_t uid) {
const bf::path recovery_dir = ci::GetRootAppPath(false, uid);
- for (bf::directory_iterator iter(recovery_dir);
- iter != bf::directory_iterator();
- ++iter) {
- try {
+ try {
+ for (bf::directory_iterator iter(recovery_dir);
+ iter != bf::directory_iterator();
+ ++iter) {
std::string file = iter->path().filename().string();
std::regex backup_regex(kBackupFilePattern);
std::smatch match;
if (std::regex_search(file, match, backup_regex)) {
bf::path orig_file(iter->path().parent_path() / iter->path().stem());
if (bf::exists(orig_file))
- bf::remove(iter->path());
- else
- bf::rename(iter->path(), orig_file);
+ bf::remove(orig_file);
+ bf::rename(iter->path(), orig_file);
}
- } catch (...) {
- LOG(WARNING) << "Exception occurred: "
- << boost::current_exception_diagnostic_information();
- continue;
}
+ } catch (...) {
+ LOG(WARNING) << "Exception occurred: "
+ << boost::current_exception_diagnostic_information();
}
}
if (std::regex_search(file, match, recovery_regex)) {
LOG(INFO) << "Found recovery file: " << file;
std::string type(match[1]);
- list.emplace_back(type, iter->path().string());
+ if (type == "unified")
+ list.emplace(list.begin(), type, iter->path().string());
+ else
+ list.emplace_back(type, iter->path().string());
}
} catch (...) {
LOG(WARNING) << "Exception occurred: "
void PkgRecoveryService::ProcessRecovery(uid_t uid,
const std::vector<RecoverEntry>& entries) {
LOG(INFO) << "Process recovery for user " << uid;
- for (auto entry : entries) {
+ for (const auto& entry : entries) {
const char* type = entry.first.c_str();
const char* file = entry.second.c_str();
+ if (!bf::exists(file))
+ continue;
+
if (!RunBackend(uid, type, file))
LOG(ERROR) << "Recovery process for " << file << " failed";
}
} // namespace
int main() {
- PkgRecoveryService service;
- service.Run();
- return 0;
+ try {
+ PkgRecoveryService service;
+ service.Run();
+ return 0;
+ } catch(...) {
+ LOG(ERROR) << "Exception occured";
+ return -1;
+ }
}