Directory install feature fix
[framework/web/wrt-installer.git] / src / jobs / widget_install / task_file_manipulation.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /**
17  * @file    task_db_update.cpp
18  * @author  Lukasz Wrzosek(l.wrzosek@samsung.com)
19  * @version 1.0
20  * @brief   Implementation file for installer task database updating
21  */
22 #include <sys/stat.h>
23 #include <widget_install/task_file_manipulation.h>
24 #include <widget_install/job_widget_install.h>
25 #include <widget_install/widget_install_errors.h>
26 #include <widget_install/widget_install_context.h>
27 #include <dpl/utils/wrt_utility.h>
28 #include <dpl/foreach.h>
29 #include <dpl/log/log.h>
30 #include <dpl/assert.h>
31 #include <string>
32
33 #define WEBAPP_DEFAULT_UID  5000
34 #define WEBAPP_DEFAULT_GID  5000
35
36 namespace {
37 const mode_t PRIVATE_STORAGE_MODE = 0700;
38 const mode_t SHARE_MODE = 0705;
39 }
40
41 using namespace WrtDB;
42
43 namespace Jobs {
44 namespace WidgetInstall {
45 TaskFileManipulation::TaskFileManipulation(InstallerContext& context) :
46     DPL::TaskDecl<TaskFileManipulation>(this),
47     m_context(context)
48 {
49     AddStep(&TaskFileManipulation::StepCreateDirs);
50     AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir);
51     AddStep(&TaskFileManipulation::StepCreateShareDir);
52     if (m_context.widgetConfig.packagingType !=
53         WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
54     {
55         AddStep(&TaskFileManipulation::StepRenamePath);
56         AddAbortStep(&TaskFileManipulation::StepAbortRenamePath);
57     }
58 }
59
60 void TaskFileManipulation::StepCreateDirs()
61 {
62     std::string widgetPath;
63     DPL::OptionalString pkgname = m_context.widgetConfig.pkgname;
64     if (pkgname.IsNull()) {
65         ThrowMsg(Exceptions::InternalError, "No Package name exists.");
66     }
67
68     widgetPath = m_context.locations->getPackageInstallationDir();
69
70     std::string widgetBinPath = m_context.locations->getBinaryDir();
71     std::string widgetSrcPath = m_context.locations->getSourceDir();
72
73     WrtUtilMakeDir(widgetPath);
74
75     // If package type is widget with osp service, we don't need to make bin
76     // and src directory
77     if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
78         LogDebug("Doesn't need to create resource directory");
79     } else {
80         LogDebug("Create resource directory");
81         WrtUtilMakeDir(widgetBinPath);
82         WrtUtilMakeDir(widgetSrcPath);
83     }
84
85     m_context.job->UpdateProgress(
86         InstallerContext::INSTALL_DIR_CREATE,
87         "Widget Directory Created");
88 }
89
90 void TaskFileManipulation::StepCreatePrivateStorageDir()
91 {
92     std::string storagePath = m_context.locations->getPrivateStorageDir();
93
94     if (euidaccess(storagePath.c_str(), F_OK) != 0) {
95         if(!WrtUtilMakeDir(storagePath, PRIVATE_STORAGE_MODE)){
96             LogError("Failed to create directory for private storage");
97             ThrowMsg(Exceptions::InternalError,
98                     "Failed to create directory for private storage");
99         }
100         // '5000' is default uid, gid for applications.
101         // So installed applications should be launched as process of uid '5000'.
102         // the process can access private directory 'data' of itself.
103         if(chown(storagePath.c_str(),
104                  WEBAPP_DEFAULT_UID,
105                  WEBAPP_DEFAULT_GID) != 0)
106         {
107             ThrowMsg(Exceptions::InternalError,
108                  "Chown to invaild user");
109         }
110     } else if (euidaccess(storagePath.c_str(), W_OK | R_OK | X_OK) == 0) {
111         LogInfo("Private storage already exists.");
112         // Even if private directory already is created, private dircetory
113         // should change owner.
114         if(chown(storagePath.c_str(),
115                  WEBAPP_DEFAULT_UID,
116                  WEBAPP_DEFAULT_GID) != 0)
117         {
118             ThrowMsg(Exceptions::InternalError,
119                  "Chown to invaild user");
120         }
121         if(chmod(storagePath.c_str(), PRIVATE_STORAGE_MODE) != 0) {
122             ThrowMsg(Exceptions::InternalError,
123                  "chmod to 0700");
124         }
125
126     } else {
127         ThrowMsg(Exceptions::InternalError,
128                  "No access to private storage.");
129     }
130 }
131
132 void TaskFileManipulation::StepCreateShareDir()
133 {
134     std::string sharePath = m_context.locations->getShareDir();
135
136     if (euidaccess(sharePath.c_str(), F_OK) != 0) {
137         if(!WrtUtilMakeDir(sharePath, SHARE_MODE)){
138             LogError("Failed to create directory for share");
139             ThrowMsg(Exceptions::InternalError,
140                     "Failed to create directory for share");
141         }
142         // '5000' is default uid, gid for applications.
143         // So installed applications should be launched as process of uid '5000'.
144         // the process can access private directory 'data' of itself.
145         if(chown(sharePath.c_str(),
146                  WEBAPP_DEFAULT_UID,
147                  WEBAPP_DEFAULT_GID) != 0)
148         {
149             ThrowMsg(Exceptions::InternalError,
150                  "Chown to invaild user");
151         }
152     } else if (euidaccess(sharePath.c_str(), W_OK | R_OK | X_OK) == 0) {
153         LogInfo("Share directory already exists.");
154         // Even if share directory already is created, share dircetory
155         // should change owner.
156         if(chown(sharePath.c_str(),
157                  WEBAPP_DEFAULT_UID,
158                  WEBAPP_DEFAULT_GID) != 0)
159         {
160             ThrowMsg(Exceptions::InternalError,
161                  "Chown to invaild user");
162         }
163         if(chmod(sharePath.c_str(), SHARE_MODE) != 0) {
164             ThrowMsg(Exceptions::InternalError,
165                  "chmod to 0700");
166         }
167
168     } else {
169         ThrowMsg(Exceptions::InternalError,
170                  "No access to private storage.");
171     }
172
173 }
174
175 void TaskFileManipulation::StepRenamePath()
176 {
177     std::string instDir;
178     DPL::OptionalString pkgname = m_context.widgetConfig.pkgname;
179     if (pkgname.IsNull()) {
180         ThrowMsg(Exceptions::InternalError, "No Package name exists.");
181     }
182
183     if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
184         instDir = m_context.locations->getPackageInstallationDir();
185     } else {
186         instDir = m_context.locations->getSourceDir();
187     }
188
189     LogDebug("Copy file from temp directory to " << instDir);
190     if (!WrtUtilRemove(instDir)) {
191         ThrowMsg(Exceptions::RemovingFolderFailure,
192                 "Error occurs during removing existing folder");
193     }
194
195     if (!(rename(m_context.locations->getTemporaryPackageDir().c_str(), instDir.c_str()) == 0)) {
196         ThrowMsg(Exceptions::UnknownError,
197                 "Error occurs during renaming widget folder");
198     }
199     m_context.job->UpdateProgress(
200         InstallerContext::INSTALL_RENAME_PATH,
201         "Widget Rename path Finished");
202 }
203
204 void TaskFileManipulation::StepAbortRenamePath()
205 {
206     LogDebug("[Rename Widget Path] Aborting.... (Rename path)");
207     std::string widgetPath;
208     if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
209         widgetPath = m_context.locations->getPackageInstallationDir();
210     } else {
211         widgetPath = m_context.locations->getSourceDir();
212     }
213     struct stat fileInfo;
214     if (stat(widgetPath.c_str(), &fileInfo) != 0) {
215         LogError("Failed to get widget file path : " << widgetPath);
216         return;
217     }
218
219     if (!(rename(widgetPath.c_str(), m_context.locations->getTemporaryPackageDir().c_str()) == 0)) {
220         LogError("Failed to rename");
221     }
222     LogDebug("Rename widget path sucessful!");
223 }
224 } //namespace WidgetInstall
225 } //namespace Jobs