Osp-Installer merge changes from tizen_2.2
[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 #include "ConfigurationManager.h"
35
36 using namespace Tizen::App;
37 using namespace Tizen::Base;
38 using namespace Tizen::Base::Collection;
39 using namespace Tizen::Base::Utility;
40 using namespace Tizen::Io;
41
42 UnpackStep::UnpackStep(void)
43 :__state(STATE_BACKUP)
44 ,__pContext(null)
45 ,__pDirectoryList(null)
46 ,__uncompressedSize(0)
47 {
48 }
49
50 UnpackStep::~UnpackStep(void)
51 {
52         if (__pDirectoryList)
53         {
54                 GList* pList = null;
55                 app2ext_dir_details* pDirDetails = null;
56
57                 pList = g_list_first(__pDirectoryList);
58                 while (pList)
59                 {
60                         pDirDetails = (app2ext_dir_details*)pList->data;
61                         if (pDirDetails && pDirDetails->name)
62                         {
63                                 free(pDirDetails->name);
64                         }
65                         pList = g_list_next(pList);
66                 }
67                 g_list_free(__pDirectoryList);
68         }
69 }
70
71 InstallerError
72 UnpackStep::Run(InstallationContext* pContext)
73 {
74         InstallerError error = INSTALLER_ERROR_NONE;
75         AppLog(" UnpackStep - START");
76
77         __pContext = pContext;
78
79         while (true)
80         {
81                 switch (__state)
82                 {
83                 case STATE_BACKUP:
84                         AppLog("[STATE_BACKUP]");
85                         error = OnStateBackup();
86                         break;
87
88                 case STATE_UNZIP:
89                         AppLog("[STATE_UNZIP]");
90                         error = OnUnzip();
91                         break;
92
93                 case STATE_FILE_MOVE:
94                         AppLog("[STATE_FILE_MOVE]");
95                         error = OnStateFileMove();
96                         break;
97
98                 case STATE_CREATE_DIR:
99                         AppLog("[STATE_CREATE_DIR]");
100                         error = OnCreateDir();
101                         break;
102
103                 case STATE_DONE:
104                         AppLog("[STATE_DONE]");
105                         error = OnStateDone();
106                         break;
107
108                 default:
109                         break;
110                 }
111
112                 if (error != INSTALLER_ERROR_NONE)
113                 {
114                         break;
115                 }
116
117                 if (__state > STATE_DONE)
118                 {
119                         AppLog(" UnpackStep - END");
120                         break;
121                 }
122         }
123
124         return error;
125 }
126
127 void
128 UnpackStep::GoNextState(void)
129 {
130         __state++;
131 }
132
133 InstallerError
134 UnpackStep::OnStateBackup(void)
135 {
136         InstallerError error = INSTALLER_ERROR_NONE;
137
138 #if 0
139         if ((__pContext->__isUpdated == true) && (__pContext->__isPreloaded == false))
140         {
141                 ConfigurationManager configurationManager;
142                 bool res = configurationManager.CreateBackup(__pContext);
143                 TryReturn(res == true, INSTALLER_ERROR_BACKUP_FAILED, "configurationManager.CreateBackup(%ls) failed.", __pContext->__packageId.GetPointer());
144         }
145 #endif
146
147         GoNextState();
148         return error;
149 }
150
151 InstallerError
152 UnpackStep::OnUnzip(void)
153 {
154         InstallerError error = INSTALLER_ERROR_NONE;
155         String newInstallPath;
156         app2ext_handle* pHandle = null;
157
158         String installPath;
159         installPath = PATH_OPT_USR_APPS;
160         installPath += "/";
161         installPath += __pContext->__packageId;
162
163         result r = E_SUCCESS;
164         FileUnzipper unzipper;
165         r = unzipper.Construct(__pContext->__packagePath);
166         TryReturn(!IsFailed(r), INSTALLER_ERROR_INTERNAL_STATE, "unzipper.Construct() failed");
167
168         if (__pContext->__storage == INSTALLATION_STORAGE_EXTERNAL)
169         {
170                 int res = 0;
171                 PackageId packageId = __pContext->__packageId;
172
173                 std::unique_ptr<char[]> pPackageId(_StringConverter::CopyToCharArrayN(packageId));
174                 TryReturn(pPackageId, INSTALLER_ERROR_INTERNAL_STATE, "pPackageId is null");
175
176                 GetUncompressedInfo(unzipper);
177                 TryReturn((__pDirectoryList && (__uncompressedSize > 0)), INSTALLER_ERROR_INTERNAL_STATE, "GetUncompressedInfo() failed");
178
179                 pHandle = app2ext_init(APP2EXT_SD_CARD);
180                 TryReturn(pHandle, INSTALLER_ERROR_INTERNAL_STATE, "app2ext_init() failed");
181
182                 __pContext->__pApp2ExtHandle = (void*)pHandle;
183
184                 res = pHandle->interface.pre_install(pPackageId.get(), __pDirectoryList, __uncompressedSize);
185                 TryReturn(res == 0, INSTALLER_ERROR_INTERNAL_STATE, "pHandle->interface.pre_install() failed [%d]", res);
186
187                 AppLog("[app2sd] pre_install(%s)", pPackageId.get());
188         }
189
190         if (File::IsFileExist(installPath) == false)
191         {
192                 r = Directory::Create(installPath, false);
193                 TryReturn(!IsFailed(r), INSTALLER_ERROR_INTERNAL_STATE, "Directory::Create() failed, installPath=%ls", installPath.GetPointer());
194         }
195
196         InstallerUtil::CreateSymlinkForAppDirectory(installPath, newInstallPath);
197         __pContext->__installDir = newInstallPath;
198         __pContext->__rootPath = newInstallPath;
199
200         if (__pContext->__isUpdated == true)
201         {
202                 RemoveRoDirectory(installPath);
203         }
204
205         AppLog("UnzipTo - START");
206         r = unzipper.UnzipTo(newInstallPath);
207         TryReturn(!IsFailed(r), INSTALLER_ERROR_PACKAGE_INVALID, "UnzipTo(%ls) failed.", newInstallPath.GetPointer());
208         AppLog("UnzipTo - END");
209
210         // GoNextState();
211         __state = STATE_DONE;
212         return error;
213 }
214
215 InstallerError
216 UnpackStep::OnStateFileMove(void)
217 {
218         InstallerError error = INSTALLER_ERROR_NONE;
219
220         GoNextState();
221         return error;
222 }
223
224 InstallerError
225 UnpackStep::OnCreateDir(void)
226 {
227         InstallerError error = INSTALLER_ERROR_NONE;
228
229         GoNextState();
230         return error;
231 }
232
233 InstallerError
234 UnpackStep::OnStateDone(void)
235 {
236         InstallerError error = INSTALLER_ERROR_NONE;
237
238         GoNextState();
239         return error;
240 }
241
242 bool
243 UnpackStep::CreateDefaultDir(void)
244 {
245         // Directory::Create(DIR_OSP_APPLICATION_PHONE, true);
246         // Directory::Create(DIR_OSP_APPLICATION_MMC, true);
247
248         return true;
249 }
250
251 bool
252 UnpackStep::GetUncompressedInfo(const FileUnzipper& unzipper)
253 {
254         result r = E_SUCCESS;
255         unsigned long totalSize = 0;
256         String directory;
257         String entryName;
258         ArrayList directoryList;
259         int entryCount = unzipper.GetEntryCount();
260
261         directoryList.Construct();
262
263         for(int i = 0; i < entryCount; i++)
264         {
265                 int indexOf = 0;
266                 int startIndex = 0;
267                 unsigned long uncompressedSize = 0;
268                 ZipEntry zipEntry;
269
270                 unzipper.GetEntry(i, zipEntry);
271                 entryName = zipEntry.GetName();
272
273                 while((r = entryName.IndexOf(L'/', startIndex, indexOf)) == E_SUCCESS)
274                 {
275                         String* pCurDirectory = new (std::nothrow) String;
276                         TryReturn(pCurDirectory, false, "pCurDirectory is null.");
277
278                         entryName.SubString(0, indexOf, *pCurDirectory);
279
280                         if (directoryList.Contains(*pCurDirectory) == false)
281                         {
282                                 if (startIndex == 0)
283                                 {
284                                         AddDirectory(*pCurDirectory);
285                                 }
286
287                                 AppLog("Folder[%ls], Size[%d]", pCurDirectory->GetPointer(), INSTALLER_BLOCK_SIZE);
288                                 totalSize += INSTALLER_BLOCK_SIZE;
289
290                                 directoryList.Add(*pCurDirectory);
291                         }
292
293                         startIndex = indexOf + 1;
294                 }
295
296                 if (zipEntry.IsDirectory() == false)
297                 {
298                         uncompressedSize = zipEntry.GetUncompressedSize();
299
300                         int blockCount = uncompressedSize / INSTALLER_BLOCK_SIZE;
301
302                         if ((blockCount == 0) && (uncompressedSize != 0))
303                         {
304                                 uncompressedSize = INSTALLER_BLOCK_SIZE;
305                         }
306                         else
307                         {
308                                 int mod = uncompressedSize % INSTALLER_BLOCK_SIZE;
309                                 if (mod != 0)
310                                 {
311                                         blockCount++;
312                                 }
313                                 uncompressedSize = (INSTALLER_BLOCK_SIZE * blockCount);
314                         }
315
316                         totalSize += uncompressedSize;
317                         AppLog(" -File[%ls], UncompressedSize[%d]", entryName.GetPointer(), (int)uncompressedSize);
318                 }
319         }
320
321         directoryList.RemoveAll(true);
322         __uncompressedSize = (int)(totalSize / (1024 * 1024)) + 1;
323
324         AppLog("------------------------------------------");
325         AppLog("TotalSize = [%d]B", (int)totalSize);
326         AppLog("TotalSize = [%d]MB", __uncompressedSize);
327         AppLog("------------------------------------------");
328
329
330         return true;
331 }
332
333 bool
334 UnpackStep::AddDirectory(const String& rootDirectory)
335 {
336         int length = 0;
337         app2ext_dir_details* pDirDetails = null;
338
339         pDirDetails = (app2ext_dir_details*) calloc(1, sizeof(app2ext_dir_details));
340         TryReturn(pDirDetails, false, "pDirDetails is null");
341
342         length = rootDirectory.GetLength();
343         pDirDetails->name = (char*) calloc(1, (sizeof(char) * length) + 1);
344         snprintf(pDirDetails->name, length + 1, "%ls", rootDirectory.GetPointer());
345
346         if ((rootDirectory == L"data") || (rootDirectory == L"shared") || (rootDirectory == L"setting"))
347         {
348                 pDirDetails->type = APP2EXT_DIR_RW;
349         }
350         else
351         {
352                 pDirDetails->type = APP2EXT_DIR_RO;
353         }
354
355         AppLog("------------------------------------------");
356         AppLog("# Root Directory = [%s], Type = [%d]", pDirDetails->name, pDirDetails->type);
357
358         __pDirectoryList = g_list_append(__pDirectoryList, pDirDetails);
359
360         return true;
361 }
362
363 bool
364 UnpackStep::RemoveRoDirectory(const String& rootPath)
365 {
366         std::unique_ptr<Directory> pDir(new (std::nothrow) Directory);
367         TryReturn(pDir, false, "pDir is null.");
368
369         result r = pDir->Construct(rootPath);
370         TryReturn(!IsFailed(r), false, "pDir->Construct() failed. rootPath = [%ls]", rootPath.GetPointer());
371
372         std::unique_ptr<DirEnumerator> pDirEnum(pDir->ReadN());
373         TryReturn(pDirEnum, false, "pDirEnum is null.");
374
375         while (pDirEnum->MoveNext() == E_SUCCESS)
376         {
377                 DirEntry entry = pDirEnum->GetCurrentDirEntry();
378
379                 String entryName = entry.GetName();
380                 String srcEntryDir = rootPath;
381                 srcEntryDir += L"/";
382                 srcEntryDir += entryName;
383
384                 if (entryName == L"." || entryName == L"..")
385                 {
386                         continue;
387                 }
388                 else if (entryName == L"data")
389                 {
390                         AppLog("skip, directory=[%ls]", srcEntryDir.GetPointer());
391                         continue;
392                 }
393                 else if (entryName == L"shared")
394                 {
395                         RemoveSharedDirectory(srcEntryDir);
396                         continue;
397                 }
398
399                 InstallerUtil::Remove(srcEntryDir);
400         }
401
402         return true;
403 }
404
405 bool
406 UnpackStep::RemoveSharedDirectory(const String& sharedPath)
407 {
408         std::unique_ptr<Directory> pDir(new (std::nothrow) Directory);
409         TryReturn(pDir, false, "pDir is null.");
410
411         result r = pDir->Construct(sharedPath);
412         TryReturn(!IsFailed(r), false, "pDir->Construct() failed. sharedPath = [%ls]", sharedPath.GetPointer());
413
414         std::unique_ptr<DirEnumerator> pDirEnum(pDir->ReadN());
415         TryReturn(pDirEnum, false, "pDirEnum is null.");
416
417         while (pDirEnum->MoveNext() == E_SUCCESS)
418         {
419                 DirEntry entry = pDirEnum->GetCurrentDirEntry();
420
421                 String entryName = entry.GetName();
422                 String srcEntryDir = sharedPath;
423                 srcEntryDir += L"/";
424                 srcEntryDir += entryName;
425
426                 if (entryName == L"." || entryName == L"..")
427                 {
428                         continue;
429                 }
430                 else if (entryName == L"data" || entryName == L"trusted")
431                 {
432                         AppLog("skip, directory=[%ls]", srcEntryDir.GetPointer());
433                         continue;
434                 }
435
436                 InstallerUtil::Remove(srcEntryDir);
437         }
438
439         return true;
440 }