}
RecoveryFile::RecoveryFile(const bf::path& path, RequestType type, bool load)
- : type_(type), path_(path), backup_done_(false), cleanup_(false) {
+ : type_(type), path_(path), backup_done_(false), cleanup_(false),
+ security_operation_done_(false) {
backup_path_ = path_.string() + ".bck";
if (load) {
if (!ReadFileContent()) {
cleanup_ = cleanup;
}
+void RecoveryFile::set_security_operation_done(bool security_operation_done) {
+ security_operation_done_ = security_operation_done;
+}
+
const boost::filesystem::path& RecoveryFile::unpacked_dir() const {
return unpacked_dir_;
}
return cleanup_;
}
+bool RecoveryFile::security_operation_done() const {
+ return security_operation_done_;
+}
+
bool RecoveryFile::ReadFileContent() {
FILE* handle = fopen(path_.c_str(), "r");
if (!handle) {
cleanup_ = true;
else
cleanup_ = false;
+ if (!fgets(data.data(), data.size(), handle)) {
+ fclose(handle);
+ return true;
+ }
+ std::string security_operation_done_flag = TruncateNewLine(data.data());
+ if (security_operation_done_flag == "true")
+ security_operation_done_ = true;
+ else
+ security_operation_done_ = false;
fclose(handle);
return true;
}
ofs << pkgid_ << std::endl;
ofs << (backup_done_ ? "true" : "false") << std::endl;
ofs << (cleanup_ ? "cleanup" : "rollback") << std::endl;
+ ofs << (security_operation_done_ ? "true" : "false") << std::endl;
ofs.flush();
::fsync(ofs->handle());
ofs.close();
void set_cleanup(bool cleanup);
/**
+ * setter for security operation done
+ *
+ * \param security_operation_done boolean value of security_operation_done
+ */
+ void set_security_operation_done(bool security_operation_done);
+
+ /**
* getter for unpacked dir
*
* \return current unpacked_dir
bool cleanup() const;
/**
+ * getter for security operation done flag
+ *
+ * \return true if security operation done flag has set
+ */
+ bool security_operation_done() const;
+
+ /**
* Transaction of current RecoveryFile content into recovery file
*
* \return true if success
boost::filesystem::path backup_path_;
bool backup_done_;
bool cleanup_;
+ bool security_operation_done_;
};
} // namespace recovery
namespace bf = boost::filesystem;
namespace bs = boost::system;
+namespace {
+
+const char kExternalMemoryMountPoint[] = ".mmc";
+
+bool Move(const boost::filesystem::path& from,
+ const boost::filesystem::path& to,
+ common_installer::FSFlag flag = common_installer::FSFlag::FS_NONE) {
+ if (bf::is_directory(from)) {
+ if (!common_installer::MoveDir(from, to / from.filename(), flag)) {
+ LOG(ERROR) << "Failed to move directory: " << from;
+ return false;
+ }
+ } else {
+ if (!common_installer::MoveFile(from, to / from.filename())) {
+ LOG(ERROR) << "Fail to move file: " << from;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace
+
namespace common_installer {
namespace filesystem {
if (bf::exists(backup_path)) {
// Remove pkgdir only if backup original contents is completely done.
if (backup_done) {
- if (!RemoveAll(context_->GetPkgPath())) {
- LOG(ERROR) << "Cannot restore widget files to its correct location";
- return Status::RECOVERY_ERROR;
+ for (bf::directory_iterator iter(context_->GetPkgPath());
+ iter != bf::directory_iterator(); ++iter) {
+ if (iter->path().filename() == kExternalMemoryMountPoint)
+ continue;
+
+ if (!RemoveAll(iter->path())) {
+ LOG(ERROR) << "Cannot restore widget files to its correct location";
+ return Status::RECOVERY_ERROR;
+ }
}
// it may fail during recovery.
recovery_file->set_backup_done(false);
recovery_file->WriteAndCommitFileContent();
}
- (void) MoveDir(backup_path, context_->GetPkgPath(), FS_MERGE_OVERWRITE);
+
+ // create copy of old package content skipping the external memory mount point
+ for (bf::directory_iterator iter(backup_path);
+ iter != bf::directory_iterator(); ++iter) {
+ if (!Move(iter->path(), context_->GetPkgPath()))
+ return Status::RECOVERY_ERROR;
+ }
+
+ RemoveAll(backup_path);
}
LOG(INFO) << "Package files recovery done";
return Status::OK;
Step::Status StepRecoverSecurity::RecoveryNew() {
if (!Check(false))
return Status::OK;
+ recovery::RecoveryFile* recovery_file =
+ context_->recovery_info.get().recovery_file.get();
+ if (!recovery_file->security_operation_done()) {
+ LOG(DEBUG) << "security_operation_done false skip recover security";
+ return Status::OK;
+ }
std::string error_message;
if (!context_->manifest_data.get()) {
if (!UnregisterSecurityContextForPkgId(context_->pkgid.get(),
LOG(ERROR) << "Invalid parameters";
return Status::INVALID_VALUE;
}
+ recovery::RecoveryFile* recovery_file =
+ context_->recovery_info.get().recovery_file.get();
+ if (!recovery_file->security_operation_done()) {
+ LOG(DEBUG) << "security_operation_done false skip recover security";
+ return Status::OK;
+ }
std::string error_message;
if (!RegisterSecurityContextForManifest(context_, &error_message)) {
LOG(ERROR) << "Unsuccessful update";
LOG(ERROR) << "Invalid parameters";
return Status::INVALID_VALUE;
}
+ recovery::RecoveryFile* recovery_file =
+ context_->recovery_info.get().recovery_file.get();
+ if (!recovery_file->security_operation_done()) {
+ LOG(DEBUG) << "security_operation_done false skip recover security";
+ return Status::OK;
+ }
std::string error_message;
if (!RegisterSecurityContextForManifest(context_, &error_message)) {
LOG(ERROR) << "Unsuccessful update";
}
Step::Status StepRegisterSecurity::process() {
+ AddRecoveryInfo();
+
std::string error_message;
if (context_->request_type.get() != RequestType::Move &&
!RegisterSecurityContextForManifest(context_, &error_message)) {
return Status::OK;
}
+void StepRegisterSecurity::AddRecoveryInfo() {
+ recovery::RecoveryFile* recovery_file =
+ context_->recovery_info.get().recovery_file.get();
+ recovery_file->set_security_operation_done(true);
+ recovery_file->WriteAndCommitFileContent();
+}
+
} // namespace security
} // namespace common_installer
Status clean() override { return Status::OK; }
Status precheck() override;
+ private:
+ void AddRecoveryInfo();
+
STEP_NAME(RegisterSecurity)
};
namespace security {
Step::Status StepUpdateSecurity::process() {
+ AddRecoveryInfo();
+
std::string error_message;
if (!RegisterSecurityContextForManifest(context_, &error_message)) {
if (!error_message.empty()) {
return Status::OK;
}
+void StepUpdateSecurity::AddRecoveryInfo() {
+ recovery::RecoveryFile* recovery_file =
+ context_->recovery_info.get().recovery_file.get();
+ recovery_file->set_security_operation_done(true);
+ recovery_file->WriteAndCommitFileContent();
+}
+
} // namespace security
} // namespace common_installer
Status clean() override { return Status::OK; }
Status precheck() override { return Status::OK; }
+ private:
+ void AddRecoveryInfo();
+
STEP_NAME(UpdateSecurity)
};