Fix static analysis issues
[platform/core/appfw/app-installers.git] / src / common / step / filesystem / step_recover_files.cc
1 // Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by an apache-2.0 license that can be
3 // found in the LICENSE file.
4
5 #include "common/step/filesystem/step_recover_files.h"
6
7 #include <boost/filesystem/operations.hpp>
8 #include <boost/filesystem/path.hpp>
9 #include <boost/system/error_code.hpp>
10
11 #include "common/utils/paths.h"
12 #include "common/recovery_file.h"
13 #include "common/utils/file_util.h"
14 #include "common/utils/request.h"
15
16 namespace bf = boost::filesystem;
17 namespace bs = boost::system;
18
19 namespace {
20
21 const char kExternalMemoryMountPoint[] = ".mmc";
22
23 bool Move(const boost::filesystem::path& from,
24     const boost::filesystem::path& to,
25     common_installer::FSFlag flag = common_installer::FSFlag::FS_NONE) {
26   if (bf::is_directory(from)) {
27     if (!common_installer::MoveDir(from, to / from.filename(), flag)) {
28       LOG(ERROR) << "Failed to move directory: " << from;
29       return false;
30     }
31   } else {
32     if (!common_installer::MoveFile(from, to / from.filename())) {
33       LOG(ERROR) << "Fail to move file: " << from;
34       return false;
35     }
36   }
37
38   return true;
39 }
40
41 }  // namespace
42
43 namespace common_installer {
44 namespace filesystem {
45
46 Step::Status StepRecoverFiles::RecoveryNew() {
47   if (!ClearPath(context_->GetPkgPath()))
48     return Status::RECOVERY_ERROR;
49
50   LOG(INFO) << "Package files recovery done";
51   return Status::OK;
52 }
53
54 Step::Status StepRecoverFiles::RecoveryUpdate() {
55   recovery::RecoveryFile* recovery_file =
56       context_->recovery_info.get().recovery_file.get();
57   bool backup_done = recovery_file->backup_done();
58   bf::path backup_path = GetBackupPathForPackagePath(context_->GetPkgPath());
59   if (bf::exists(backup_path)) {
60     // Remove pkgdir only if backup original contents is completely done.
61     if (backup_done) {
62       for (bf::directory_iterator iter(context_->GetPkgPath());
63            iter != bf::directory_iterator(); ++iter) {
64         if (iter->path().filename() == kExternalMemoryMountPoint)
65           continue;
66
67         if (!ClearPath(iter->path())) {
68           LOG(ERROR) << "Cannot restore widget files to its correct location";
69           return Status::RECOVERY_ERROR;
70         }
71       }
72       // it may fail during recovery.
73       recovery_file->set_backup_done(false);
74       recovery_file->WriteAndCommitFileContent();
75     }
76
77     // create copy of old package content skipping the external memory mount point
78     for (bf::directory_iterator iter(backup_path);
79          iter != bf::directory_iterator(); ++iter) {
80       if (!Move(iter->path(), context_->GetPkgPath()))
81         return Status::RECOVERY_ERROR;
82     }
83
84     ClearPath(backup_path);
85   }
86   LOG(INFO) << "Package files recovery done";
87   return Status::OK;
88 }
89
90 Step::Status StepRecoverFiles::RecoveryMountNew() {
91   bf::path zip_location = GetZipPackageLocation(
92         context_->GetPkgPath(), context_->pkgid.get());
93   Remove(zip_location);
94   ClearPath(context_->GetPkgPath());
95   LOG(INFO) << "Package files recovery done";
96   return Status::OK;
97 }
98
99 Step::Status StepRecoverFiles::RecoveryMountUpdate() {
100   bf::path zip_location = GetZipPackageLocation(
101         context_->GetPkgPath(), context_->pkgid.get());
102   bf::path backup_zip_location = GetBackupPathForZipFile(zip_location);
103   if (bf::exists(backup_zip_location)) {
104     Remove(zip_location);
105     if (!MoveFile(backup_zip_location, zip_location))
106       LOG(ERROR) << "Failed to move " << backup_zip_location << " to "
107           << zip_location;
108   }
109
110   // During mount update some files are still backed up separately from zip
111   // package file. This is because of the fact that we need to access bin/, lib/
112   // directories without mounting zip package file. In other words in mount
113   // install or mount update mode we don't mount everything - some files are
114   // still unpacked due to necessity.
115   bf::path backup_path = GetBackupPathForPackagePath(context_->GetPkgPath());
116   if (bf::exists(backup_path)) {
117     for (bf::directory_iterator iter(backup_path);
118          iter != bf::directory_iterator(); ++iter) {
119       ClearPath(context_->GetPkgPath() / iter->path().filename());
120       if (!Move(iter->path(), context_->GetPkgPath())) {
121         LOG(ERROR) << "Failed to recovery backup file(" << iter->path()
122             << ") in recovery of mount update";
123         return Status::RECOVERY_ERROR;
124       }
125     }
126     ClearPath(backup_path);
127   }
128
129   LOG(INFO) << "Package files recovery done";
130   return Status::OK;
131 }
132
133 Step::Status StepRecoverFiles::RecoveryReadonlyUpdateInstall() {
134   // Remove package directory at RW area
135   bf::path pkg_path =
136       bf::path(GetRootAppPath(false, context_->uid.get())) /
137       context_->pkgid.get();
138   if (!ClearPath(pkg_path))
139     return Status::RECOVERY_ERROR;
140
141   LOG(INFO) << "Package files recovery done";
142   return Status::OK;
143 }
144
145 Step::Status StepRecoverFiles::Cleanup() {
146   recovery::RecoveryFile* recovery_file =
147       context_->recovery_info.get().recovery_file.get();
148   bf::path root_path(GetRootAppPath(
149       context_->is_readonly_package.get(), context_->uid.get()));
150   bf::path backup_path = GetBackupPathForPackagePath(
151       root_path / recovery_file->pkgid());
152   if (!bf::exists(backup_path))
153     return Status::OK;
154
155   if (!ClearPath(backup_path)) {
156     LOG(ERROR) << "Failed to remove backup path";
157     return Status::RECOVERY_ERROR;
158   }
159
160   return Status::OK;
161 }
162
163 bool StepRecoverFiles::ClearPath(const bf::path& path) {
164   return RemoveAll(path);
165 }
166
167 }  // namespace filesystem
168 }  // namespace common_installer