arrangement of directory creation.
[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 }
39
40 using namespace WrtDB;
41
42 namespace Jobs {
43 namespace WidgetInstall {
44 TaskFileManipulation::TaskFileManipulation(InstallerContext& context) :
45     DPL::TaskDecl<TaskFileManipulation>(this),
46     m_context(context)
47 {
48     AddStep(&TaskFileManipulation::StepCreateDirs);
49     AddStep(&TaskFileManipulation::StepCreatePrivateStorageDir);
50     AddStep(&TaskFileManipulation::StepRenamePath);
51
52     AddAbortStep(&TaskFileManipulation::StepAbortRenamePath);
53 }
54
55 void TaskFileManipulation::StepCreateDirs()
56 {
57     std::string widgetPath;
58     DPL::OptionalString pkgname = m_context.widgetConfig.pkgname;
59     if (pkgname.IsNull()) {
60         ThrowMsg(Exceptions::InternalError, "No Package name exists.");
61     }
62
63     widgetPath = m_context.locations->getPackageInstallationDir();
64
65     std::string widgetBinPath = m_context.locations->getBinaryDir();
66     std::string widgetSrcPath = m_context.locations->getSourceDir();
67
68     WrtUtilMakeDir(widgetPath);
69
70     // If package type is widget with osp service, we don't need to make bin
71     // and src directory
72     if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
73         LogDebug("Doesn't need to create resource directory");
74     } else {
75         LogDebug("Create resource directory");
76         WrtUtilMakeDir(widgetBinPath);
77         WrtUtilMakeDir(widgetSrcPath);
78     }
79
80     m_context.job->UpdateProgress(
81         InstallerContext::INSTALL_DIR_CREATE,
82         "Widget Directory Created");
83 }
84
85 void TaskFileManipulation::StepCreatePrivateStorageDir()
86 {
87     std::string storagePath = m_context.locations->getPrivateStorageDir();
88
89     if (euidaccess(storagePath.c_str(), F_OK) != 0) {
90         if(!WrtUtilMakeDir(storagePath, PRIVATE_STORAGE_MODE)){
91             LogError("Failed to create directory for private storage");
92             ThrowMsg(Exceptions::InternalError,
93                     "Failed to create directory for private storage");
94         }
95         // '5000' is default uid, gid for applications.
96         // So installed applications should be launched as process of uid '5000'.
97         // the process can access private directory 'data' of itself.
98         if(chown(storagePath.c_str(),
99                  WEBAPP_DEFAULT_UID,
100                  WEBAPP_DEFAULT_GID) != 0)
101         {
102             ThrowMsg(Exceptions::InternalError,
103                  "Chown to invaild user");
104         }
105     } else if (euidaccess(storagePath.c_str(), W_OK | R_OK | X_OK) == 0) {
106         LogInfo("Private storage already exists.");
107         // Even if private directory already is created, private dircetory
108         // should change owner.
109         if(chown(storagePath.c_str(),
110                  WEBAPP_DEFAULT_UID,
111                  WEBAPP_DEFAULT_GID) != 0)
112         {
113             ThrowMsg(Exceptions::InternalError,
114                  "Chown to invaild user");
115         }
116         if(chmod(storagePath.c_str(), PRIVATE_STORAGE_MODE) != 0) {
117             ThrowMsg(Exceptions::InternalError,
118                  "chmod to 0700");
119         }
120
121     } else {
122         ThrowMsg(Exceptions::InternalError,
123                  "No access to private storage.");
124     }
125 }
126
127 void TaskFileManipulation::StepRenamePath()
128 {
129     std::string instDir;
130     DPL::OptionalString pkgname = m_context.widgetConfig.pkgname;
131     if (pkgname.IsNull()) {
132         ThrowMsg(Exceptions::InternalError, "No Package name exists.");
133     }
134
135     if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
136         instDir = m_context.locations->getPackageInstallationDir();
137     } else {
138         instDir = m_context.locations->getSourceDir();
139     }
140
141     LogDebug("Copy file from temp directory to " << instDir);
142     if (!WrtUtilRemove(instDir)) {
143         ThrowMsg(Exceptions::RemovingFolderFailure,
144                 "Error occurs during removing existing folder");
145     }
146
147     if (!(rename(m_context.locations->getTemporaryPackageDir().c_str(), instDir.c_str()) == 0)) {
148         ThrowMsg(Exceptions::UnknownError,
149                 "Error occurs during renaming widget folder");
150     }
151     m_context.job->UpdateProgress(
152         InstallerContext::INSTALL_RENAME_PATH,
153         "Widget Rename path Finished");
154 }
155
156 void TaskFileManipulation::StepAbortRenamePath()
157 {
158     LogDebug("[Rename Widget Path] Aborting.... (Rename path)");
159     std::string widgetPath;
160     if (m_context.widgetConfig.packagingType == PKG_TYPE_HYBRID_WEB_APP) {
161         widgetPath = m_context.locations->getPackageInstallationDir();
162     } else {
163         widgetPath = m_context.locations->getSourceDir();
164     }
165     struct stat fileInfo;
166     if (stat(widgetPath.c_str(), &fileInfo) != 0) {
167         LogError("Failed to get widget file path : " << widgetPath);
168         return;
169     }
170
171     if (!(rename(widgetPath.c_str(), m_context.locations->getTemporaryPackageDir().c_str()) == 0)) {
172         LogError("Failed to rename");
173     }
174     LogDebug("Rename widget path sucessful!");
175 }
176 } //namespace WidgetInstall
177 } //namespace Jobs