Add OOM exception handler
[platform/core/appfw/wgt-backend.git] / src / wgt / step / filesystem / step_wgt_undo_patch_storage_directories.cc
1 // Copyright (c) 2016 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 "wgt/step/filesystem/step_wgt_undo_patch_storage_directories.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/file_util.h>
12
13 namespace bf = boost::filesystem;
14 namespace bs = boost::system;
15 namespace ci = common_installer;
16
17 namespace {
18
19 const char kSharedLocation[] = "shared";
20 const char kSharedResLocation[] = "shared/res";
21 const char kResWgtSubPath[] = "res/wgt";
22
23 }  // namespace
24
25 namespace wgt {
26 namespace filesystem {
27
28 ci::Step::Status StepWgtUndoPatchStorageDirectories::process() {
29   int version = std::stoi(context_->manifest_data.get()->api_version);
30   if (version >= 3) {
31     LOG(DEBUG) <<
32         "Unlinking and moving widget's shared/res directory content back in "
33         << context_->pkg_path.get();
34     if (!UndoShareDirFor3x())
35       return Status::APP_DIR_ERROR;
36   }
37
38   return Status::OK;
39 }
40
41 ci::Step::Status StepWgtUndoPatchStorageDirectories::clean() {
42   if (!backup_dir_.empty())
43     ci::RemoveAll(backup_dir_);
44   return Status::OK;
45 }
46
47 ci::Step::Status StepWgtUndoPatchStorageDirectories::undo() {
48   if (!backup_dir_.empty()) {
49     LOG(DEBUG) << "Restore res/wgt/shared/res from backup dir";
50     // restore link
51     bf::path wgt_shared_res_dir =
52         context_->pkg_path.get() / kResWgtSubPath / kSharedResLocation;
53     bf::path backup_wgt_shared_res = backup_dir_ / "wgt_shared_res";
54     if (!backup_wgt_shared_res.empty()) {
55       if (!ci::RemoveAll(wgt_shared_res_dir)) {
56         LOG(ERROR) << "Failed to remove res/wgt/shared/res";
57         return Status::APP_DIR_ERROR;
58       }
59       if (!ci::CopyDir(backup_dir_, wgt_shared_res_dir,
60                        ci::FS_MERGE_OVERWRITE, false)) {
61         LOG(ERROR) << "Failed to copy from backup";
62         return Status::APP_DIR_ERROR;
63       }
64     }
65     // restore original contents
66     bf::path shared_res_dir = context_->pkg_path.get() / kSharedResLocation;
67     bf::path backup_shared_res = backup_dir_ / "shared_res";
68     if (!backup_shared_res.empty()) {
69       if (!ci::CopyDir(backup_dir_, shared_res_dir,
70                        ci::FS_MERGE_OVERWRITE, false)) {
71         LOG(ERROR) << "Failed to copy from backup";
72         return Status::APP_DIR_ERROR;
73       }
74     }
75   }
76   return Status::OK;
77 }
78
79 bool StepWgtUndoPatchStorageDirectories::UndoShareDirFor3x() {
80   // check if ${pkg_path}/shared/res exists
81   bf::path shared_res_dir = context_->pkg_path.get() / kSharedResLocation;
82   if (!bf::exists(shared_res_dir))
83     return true;
84   bf::path wgt_shared_res_dir =
85       context_->pkg_path.get() / kResWgtSubPath / kSharedResLocation;
86   if (!bf::exists(wgt_shared_res_dir))
87     return true;
88
89   if (bf::is_symlink(wgt_shared_res_dir)) {
90     LOG(ERROR) << "Can't support this step, pkg should be fully updated";
91     return false;
92   }
93
94   // backup for undo
95   backup_dir_ = context_->unpacked_dir_path.get();
96   backup_dir_ += ".SharedRes";
97   bf::path backup_shared_res = backup_dir_ / "shared_res";
98   if (!ci::CreateDir(backup_shared_res))
99     return false;
100   bf::path backup_wgt_shared_res = backup_dir_ / "wgt_shared_res";
101   if (!ci::CopyDir(wgt_shared_res_dir, backup_wgt_shared_res,
102                    ci::FS_MERGE_OVERWRITE, false)) {
103     backup_dir_.clear();
104     return false;
105   }
106
107   // unlink and move all linked contents from ${pkg_path}/shared/res
108   // to ${pkg_path}/res/wgt/shared/res
109   bf::directory_iterator end_itr;
110   for (bf::directory_iterator itr(wgt_shared_res_dir); itr != end_itr; ++itr) {
111     bf::path link_file = itr->path();
112     if (!bf::is_symlink(link_file)) {
113       continue;
114     }
115     bf::path link_target = bf::read_symlink(link_file);
116     if (link_target.native().substr(0, shared_res_dir.native().length()) !=
117         shared_res_dir.native()) {
118       continue;
119     }
120     if (!ci::Remove(link_file))
121       return false;
122     bf::path tmp_backup = backup_shared_res / link_target.filename();
123     if (bf::is_directory(link_target)) {
124       if (!ci::CopyDir(link_target, tmp_backup, ci::FS_MERGE_OVERWRITE, false))
125         return false;
126       if (!ci::MoveDir(link_target, link_file, ci::FS_MERGE_OVERWRITE))
127         return false;
128     } else {
129       if (!ci::CopyFile(link_target, tmp_backup))
130         return false;
131       if (!ci::MoveFile(link_target, link_file, true))
132         return false;
133     }
134   }
135
136   return true;
137 }
138
139 }  // namespace filesystem
140 }  // namespace wgt