Signature configuration on
[platform/framework/native/installer.git] / src / Step / UnpackStep.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 /**
18  * @file        UnpackStep.cpp
19  * @brief       This is the implementation file for %UnpackStep class.
20  */
21
22 #include <unique_ptr.h>
23
24 #include <app2ext_interface.h>
25
26 #include <FIoFile.h>
27 #include <FIoDirectory.h>
28 #include <FBaseUtilFileUnzipper.h>
29 #include <FBase_StringConverter.h>
30
31 #include "InstallationContext.h"
32 #include "UnpackStep.h"
33 #include "InstallerUtil.h"
34
35 using namespace Tizen::App;
36 using namespace Tizen::Base;
37 using namespace Tizen::Base::Collection;
38 using namespace Tizen::Base::Utility;
39 using namespace Tizen::Io;
40
41 UnpackStep::UnpackStep(void)
42 :__state(STATE_UNZIP)
43 ,__pContext(null)
44 ,__pDirectoryList(null)
45 ,__uncompressedSize(0)
46 {
47 }
48
49 UnpackStep::~UnpackStep(void)
50 {
51         if (__pDirectoryList)
52         {
53                 GList* pList = null;
54                 app2ext_dir_details* pDirDetails = null;
55
56                 pList = g_list_first(__pDirectoryList);
57                 while (pList)
58                 {
59                         pDirDetails = (app2ext_dir_details*)pList->data;
60                         if (pDirDetails && pDirDetails->name)
61                         {
62                                 free(pDirDetails->name);
63                         }
64                         pList = g_list_next(pList);
65                 }
66                 g_list_free(__pDirectoryList);
67         }
68 }
69
70 InstallerError
71 UnpackStep::Run(InstallationContext* pContext)
72 {
73         InstallerError error = INSTALLER_ERROR_NONE;
74         AppLog(" UnpackStep - START");
75
76         __pContext = pContext;
77
78         while (true)
79         {
80                 switch (__state)
81                 {
82                 case STATE_UNZIP:
83                         AppLog("[STATE_UNZIP]");
84                         error = OnUnzip();
85                         break;
86
87                 case STATE_FILE_MOVE:
88                         AppLog("[STATE_FILE_MOVE]");
89                         error = OnStateFileMove();
90                         break;
91
92                 case STATE_CREATE_DIR:
93                         AppLog("[STATE_CREATE_DIR]");
94                         error = OnCreateDir();
95                         break;
96
97                 case STATE_DONE:
98                         AppLog("[STATE_DONE]");
99                         error = OnStateDone();
100                         break;
101
102                 default:
103                         break;
104                 }
105
106                 if (error != INSTALLER_ERROR_NONE)
107                 {
108                         break;
109                 }
110
111                 if (__state > STATE_DONE)
112                 {
113                         AppLog(" UnpackStep - END");
114                         break;
115                 }
116         }
117
118         return error;
119 }
120
121 void
122 UnpackStep::GoNextState(void)
123 {
124         __state++;
125 }
126
127 InstallerError
128 UnpackStep::OnUnzip(void)
129 {
130         InstallerError error = INSTALLER_ERROR_NONE;
131         String newInstallPath;
132         app2ext_handle* pHandle = null;
133
134         String installPath;
135         installPath = PATH_OPT_USR_APPS;
136         installPath += "/";
137         installPath += __pContext->__packageId;
138
139         result r = E_SUCCESS;
140         FileUnzipper unzipper;
141         r = unzipper.Construct(__pContext->__packagePath);
142         TryReturn(!IsFailed(r), INSTALLER_ERROR_INTERNAL_STATE, "unzipper.Construct() failed");
143
144         if (__pContext->__storage == INSTALLATION_STORAGE_EXTERNAL)
145         {
146                 int res = 0;
147                 PackageId packageId = __pContext->__packageId;
148
149                 std::unique_ptr<char[]> pPackageId(_StringConverter::CopyToCharArrayN(packageId));
150                 TryReturn(pPackageId, INSTALLER_ERROR_INTERNAL_STATE, "pPackageId is null");
151
152                 GetUncompressedInfo(unzipper);
153                 TryReturn((__pDirectoryList && (__uncompressedSize > 0)), INSTALLER_ERROR_INTERNAL_STATE, "GetUncompressedInfo() failed");
154
155                 pHandle = app2ext_init(APP2EXT_SD_CARD);
156                 TryReturn(pHandle, INSTALLER_ERROR_INTERNAL_STATE, "app2ext_init() failed");
157
158                 __pContext->__pApp2ExtHandle = (void*)pHandle;
159
160                 res = pHandle->interface.pre_install(pPackageId.get(), __pDirectoryList, __uncompressedSize);
161                 TryReturn(res == 0, INSTALLER_ERROR_INTERNAL_STATE, "pHandle->interface.pre_install() failed [%d]", res);
162
163                 AppLog("[app2sd] pre_install(%s)", pPackageId.get());
164         }
165
166         if (File::IsFileExist(installPath) == false)
167         {
168                 r = Directory::Create(installPath, false);
169                 TryReturn(!IsFailed(r), INSTALLER_ERROR_INTERNAL_STATE, "Directory::Create() failed, installPath=%ls", installPath.GetPointer());
170         }
171
172         InstallerUtil::CreateSymlinkForAppDirectory(installPath, newInstallPath);
173         __pContext->__installDir = newInstallPath;
174         __pContext->__rootPath = newInstallPath;
175
176         if (__pContext->__isUpdated == true)
177         {
178                 RemoveRoDirectory(installPath);
179         }
180
181         AppLog("UnzipTo - START");
182         r = unzipper.UnzipTo(newInstallPath);
183         TryReturn(!IsFailed(r), INSTALLER_ERROR_PACKAGE_INVALID, "UnzipTo(%ls) failed.", newInstallPath.GetPointer());
184         AppLog("UnzipTo - END");
185
186         // GoNextState();
187         __state = STATE_DONE;
188         return error;
189 }
190
191 InstallerError
192 UnpackStep::OnStateFileMove(void)
193 {
194         InstallerError error = INSTALLER_ERROR_NONE;
195
196         GoNextState();
197         return error;
198 }
199
200 InstallerError
201 UnpackStep::OnCreateDir(void)
202 {
203         InstallerError error = INSTALLER_ERROR_NONE;
204
205         GoNextState();
206         return error;
207 }
208
209 InstallerError
210 UnpackStep::OnStateDone(void)
211 {
212         InstallerError error = INSTALLER_ERROR_NONE;
213
214         GoNextState();
215         return error;
216 }
217
218 bool
219 UnpackStep::CreateDefaultDir(void)
220 {
221         // Directory::Create(DIR_OSP_APPLICATION_PHONE, true);
222         // Directory::Create(DIR_OSP_APPLICATION_MMC, true);
223
224         return true;
225 }
226
227 bool
228 UnpackStep::GetUncompressedInfo(const FileUnzipper& unzipper)
229 {
230         result r = E_SUCCESS;
231         unsigned long totalSize = 0;
232         String directory;
233         String entryName;
234         ArrayList directoryList;
235         int entryCount = unzipper.GetEntryCount();
236
237         directoryList.Construct();
238
239         for(int i = 0; i < entryCount; i++)
240         {
241                 int indexOf = 0;
242                 int startIndex = 0;
243                 unsigned long uncompressedSize = 0;
244                 ZipEntry zipEntry;
245
246                 unzipper.GetEntry(i, zipEntry);
247                 entryName = zipEntry.GetName();
248
249                 while((r = entryName.IndexOf(L'/', startIndex, indexOf)) == E_SUCCESS)
250                 {
251                         String* pCurDirectory = new (std::nothrow) String;
252                         TryReturn(pCurDirectory, false, "pCurDirectory is null.");
253
254                         entryName.SubString(0, indexOf, *pCurDirectory);
255
256                         if (directoryList.Contains(*pCurDirectory) == false)
257                         {
258                                 if (startIndex == 0)
259                                 {
260                                         AddDirectory(*pCurDirectory);
261                                 }
262
263                                 AppLog("Folder[%ls], Size[%d]", pCurDirectory->GetPointer(), INSTALLER_BLOCK_SIZE);
264                                 totalSize += INSTALLER_BLOCK_SIZE;
265
266                                 directoryList.Add(*pCurDirectory);
267                         }
268
269                         startIndex = indexOf + 1;
270                 }
271
272                 if (zipEntry.IsDirectory() == false)
273                 {
274                         uncompressedSize = zipEntry.GetUncompressedSize();
275
276                         int blockCount = uncompressedSize / INSTALLER_BLOCK_SIZE;
277
278                         if ((blockCount == 0) && (uncompressedSize != 0))
279                         {
280                                 uncompressedSize = INSTALLER_BLOCK_SIZE;
281                         }
282                         else
283                         {
284                                 int mod = uncompressedSize % INSTALLER_BLOCK_SIZE;
285                                 if (mod != 0)
286                                 {
287                                         blockCount++;
288                                 }
289                                 uncompressedSize = (INSTALLER_BLOCK_SIZE * blockCount);
290                         }
291
292                         totalSize += uncompressedSize;
293                         AppLog(" -File[%ls], UncompressedSize[%d]", entryName.GetPointer(), (int)uncompressedSize);
294                 }
295         }
296
297         directoryList.RemoveAll(true);
298         __uncompressedSize = (int)(totalSize / (1024 * 1024)) + 1;
299
300         AppLog("------------------------------------------");
301         AppLog("TotalSize = [%d]B", (int)totalSize);
302         AppLog("TotalSize = [%d]MB", __uncompressedSize);
303         AppLog("------------------------------------------");
304
305
306         return true;
307 }
308
309 bool
310 UnpackStep::AddDirectory(const String& rootDirectory)
311 {
312         int length = 0;
313         app2ext_dir_details* pDirDetails = null;
314
315         pDirDetails = (app2ext_dir_details*) calloc(1, sizeof(app2ext_dir_details));
316         TryReturn(pDirDetails, false, "pDirDetails is null");
317
318         length = rootDirectory.GetLength();
319         pDirDetails->name = (char*) calloc(1, (sizeof(char) * length) + 1);
320         snprintf(pDirDetails->name, length + 1, "%ls", rootDirectory.GetPointer());
321
322         if ((rootDirectory == L"data") || (rootDirectory == L"shared") || (rootDirectory == L"setting"))
323         {
324                 pDirDetails->type = APP2EXT_DIR_RW;
325         }
326         else
327         {
328                 pDirDetails->type = APP2EXT_DIR_RO;
329         }
330
331         AppLog("------------------------------------------");
332         AppLog("# Root Directory = [%s], Type = [%d]", pDirDetails->name, pDirDetails->type);
333
334         __pDirectoryList = g_list_append(__pDirectoryList, pDirDetails);
335
336         return true;
337 }
338
339 bool
340 UnpackStep::RemoveRoDirectory(const String& rootPath)
341 {
342         std::unique_ptr<Directory> pDir(new (std::nothrow) Directory);
343         TryReturn(pDir, false, "pDir is null.");
344
345         result r = pDir->Construct(rootPath);
346         TryReturn(!IsFailed(r), false, "pDir->Construct() failed. rootPath = [%ls]", rootPath.GetPointer());
347
348         std::unique_ptr<DirEnumerator> pDirEnum(pDir->ReadN());
349         TryReturn(pDirEnum, false, "pDirEnum is null.");
350
351         while (pDirEnum->MoveNext() == E_SUCCESS)
352         {
353                 DirEntry entry = pDirEnum->GetCurrentDirEntry();
354
355                 String entryName = entry.GetName();
356                 String srcEntryDir = rootPath;
357                 srcEntryDir += L"/";
358                 srcEntryDir += entryName;
359
360                 if (entryName == L"." || entryName == L"..")
361                 {
362                         continue;
363                 }
364                 else if (entryName == L"data")
365                 {
366                         AppLog("skip, directory=[%ls]", srcEntryDir.GetPointer());
367                         continue;
368                 }
369                 else if (entryName == L"shared")
370                 {
371                         RemoveSharedDirectory(srcEntryDir);
372                         continue;
373                 }
374
375                 InstallerUtil::Remove(srcEntryDir);
376         }
377
378         return true;
379 }
380
381 bool
382 UnpackStep::RemoveSharedDirectory(const String& sharedPath)
383 {
384         std::unique_ptr<Directory> pDir(new (std::nothrow) Directory);
385         TryReturn(pDir, false, "pDir is null.");
386
387         result r = pDir->Construct(sharedPath);
388         TryReturn(!IsFailed(r), false, "pDir->Construct() failed. sharedPath = [%ls]", sharedPath.GetPointer());
389
390         std::unique_ptr<DirEnumerator> pDirEnum(pDir->ReadN());
391         TryReturn(pDirEnum, false, "pDirEnum is null.");
392
393         while (pDirEnum->MoveNext() == E_SUCCESS)
394         {
395                 DirEntry entry = pDirEnum->GetCurrentDirEntry();
396
397                 String entryName = entry.GetName();
398                 String srcEntryDir = sharedPath;
399                 srcEntryDir += L"/";
400                 srcEntryDir += entryName;
401
402                 if (entryName == L"." || entryName == L"..")
403                 {
404                         continue;
405                 }
406                 else if (entryName == L"data" || entryName == L"trusted")
407                 {
408                         AppLog("skip, directory=[%ls]", srcEntryDir.GetPointer());
409                         continue;
410                 }
411
412                 InstallerUtil::Remove(srcEntryDir);
413         }
414
415         return true;
416 }