#include <boost/filesystem/path.hpp>
#include <boost/system/error_code.hpp>
-#include "common/paths.h"
+#include "common/utils/paths.h"
+#include "common/recovery_file.h"
#include "common/utils/file_util.h"
+#include "common/utils/request.h"
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 {
Step::Status StepRecoverFiles::RecoveryNew() {
- if (!SetPackagePath()) {
- LOG(DEBUG) << "Package files recovery not needed";
- return Status::OK;
- }
- if (bf::exists(context_->pkg_path.get())) {
- bs::error_code error;
- bf::remove_all(context_->pkg_path.get(), error);
- }
+ if (!RemoveAll(context_->GetPkgPath()))
+ return Status::RECOVERY_ERROR;
+
LOG(INFO) << "Package files recovery done";
return Status::OK;
}
Step::Status StepRecoverFiles::RecoveryUpdate() {
- if (!SetPackagePath()) {
- LOG(DEBUG) << "Package files recovery not needed";
- return Status::OK;
- }
- bf::path backup_path = GetBackupPathForPackagePath(context_->pkg_path.get());
+ recovery::RecoveryFile* recovery_file =
+ context_->recovery_info.get().recovery_file.get();
+ bool backup_done = recovery_file->backup_done();
+ bf::path backup_path = GetBackupPathForPackagePath(context_->GetPkgPath());
if (bf::exists(backup_path)) {
- if (bf::exists(context_->pkg_path.get())) {
- bs::error_code error;
- bf::remove_all(context_->pkg_path.get(), error);
- if (error) {
- LOG(ERROR) << "Cannot restore widget files to its correct location";
- return Status::RECOVERY_ERROR;
+ // Remove pkgdir only if backup original contents is completely done.
+ if (backup_done) {
+ 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_->pkg_path.get());
+
+ // 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;
}
-bool StepRecoverFiles::SetPackagePath() {
- if (context_->pkgid.get().empty())
- return false;
- context_->pkg_path.set(
- context_->root_application_path.get() / context_->pkgid.get());
- return true;
+Step::Status StepRecoverFiles::RecoveryMountNew() {
+ bf::path zip_location = GetZipPackageLocation(
+ context_->GetPkgPath(), context_->pkgid.get());
+ Remove(zip_location);
+ RemoveAll(context_->GetPkgPath());
+ LOG(INFO) << "Package files recovery done";
+ return Status::OK;
+}
+
+Step::Status StepRecoverFiles::RecoveryMountUpdate() {
+ bf::path zip_location = GetZipPackageLocation(
+ context_->GetPkgPath(), context_->pkgid.get());
+ bf::path backup_zip_location = GetBackupPathForZipFile(zip_location);
+ if (bf::exists(backup_zip_location)) {
+ Remove(zip_location);
+ MoveFile(backup_zip_location, zip_location);
+ }
+
+ // During mount update some files are still backed up separately from zip
+ // package file. This is because of the fact that we need to access bin/, lib/
+ // directories without mounting zip package file. In other words in mount
+ // install or mount update mode we don't mount everything - some files are
+ // still unpacked due to necessity.
+ bf::path backup_path = GetBackupPathForPackagePath(context_->GetPkgPath());
+ if (bf::exists(backup_path)) {
+ if (!MoveDir(backup_path, context_->GetPkgPath(),
+ FS_MERGE_OVERWRITE | FS_COMMIT_COPY_FILE)) {
+ LOG(ERROR) << "Failed to recovery backup file "
+ << "in recovery of mount update";
+ return Status::APP_DIR_ERROR;
+ }
+ }
+
+ LOG(INFO) << "Package files recovery done";
+ return Status::OK;
+}
+
+Step::Status StepRecoverFiles::RecoveryReadonlyUpdateInstall() {
+ // Remove package directory at RW area
+ bf::path pkg_path =
+ bf::path(GetRootAppPath(false, context_->uid.get())) /
+ context_->pkgid.get();
+ if (!RemoveAll(pkg_path))
+ return Status::RECOVERY_ERROR;
+
+ LOG(INFO) << "Package files recovery done";
+ return Status::OK;
+}
+
+Step::Status StepRecoverFiles::Cleanup() {
+ recovery::RecoveryFile* recovery_file =
+ context_->recovery_info.get().recovery_file.get();
+ bf::path root_path(GetRootAppPath(
+ context_->is_readonly_package.get(), context_->uid.get()));
+ bf::path backup_path = GetBackupPathForPackagePath(
+ root_path / recovery_file->pkgid());
+ if (!bf::exists(backup_path))
+ return Status::OK;
+
+ if (!RemoveAll(backup_path)) {
+ LOG(ERROR) << "Failed to remove backup path";
+ return Status::RECOVERY_ERROR;
+ }
+
+ return Status::OK;
}
} // namespace filesystem