Fix the crash while installing of ServiceApp
[platform/framework/native/installer.git] / src / Manager / InstallerManager.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        InstallerManager.cpp
19  * @brief       This is the implementation file for %InstallerManager class.
20  */
21
22 #include <unistd.h>
23 #include <unique_ptr.h>
24 #include <stdio.h>
25
26 #include <app2ext_interface.h>
27
28 #include <FIoFile.h>
29 #include <FIoDirectory.h>
30 #include <FBase_StringConverter.h>
31 #include <FAppPkgPackageInfo.h>
32 #include <FAppPkg_PackageManagerImpl.h>
33 #include <FAppPkg_PackageInfoImpl.h>
34 #include <FSysSystemTime.h>
35
36 #include "InstallerManager.h"
37 #include "GuestInstaller.h"
38 #include "IDEInstaller.h"
39 #include "PreloadedInstaller.h"
40 #include "RestorationInstaller.h"
41 #include "InstallerUtil.h"
42
43 using namespace Tizen::Base;
44 using namespace Tizen::Base::Utility;
45 using namespace Tizen::Base::Collection;
46 using namespace Tizen::Io;
47 using namespace Tizen::App;
48 using namespace Tizen::App::Package;
49
50 const int BUFSIZE = 512;
51 InstallerManager* InstallerManager::__pInstallerManager = null;
52
53 InstallerManager::InstallerManager(void)
54 :__pContext(null)
55 ,__pInstaller(null)
56 ,__errorType(0)
57 ,__operation(INSTALLER_OPERATION_INSTALL)
58 ,__startTick(0)
59 ,__endTick(0)
60 ,__isFileLogOn(false)
61 {
62 }
63
64 InstallerManager::~InstallerManager(void)
65 {
66         delete __pContext;
67         __pContext = null;
68
69         delete __pInstaller;
70         __pInstaller = null;
71 }
72
73 InstallerManager*
74 InstallerManager::GetInstance()
75 {
76         if (__pInstallerManager == null)
77         {
78                 __pInstallerManager = new InstallerManager();
79                 TryReturn(__pInstallerManager, null, "__pInstallerManager is null");
80         }
81
82         return __pInstallerManager;
83 }
84
85 InstallerError
86 InstallerManager::Construct(const String& path, InstallerOperation operation, InstallerOption option)
87 {
88         InstallerError error = INSTALLER_ERROR_NONE;
89         InstallerType installerType = INSTALLER_TYPE_INSTALLER;
90         result r = E_SUCCESS;
91         String newPath = path;
92
93         Tizen::System::SystemTime::GetTicks(__startTick);
94         SetInstallerOperation(operation);
95
96         if (option & INSTALLER_OPTION_FILELOG_ON)
97         {
98                 r = Directory::Create(DIR_OSP_APPLICATIONS_TEMP, false);
99                 if (!IsFailed(r))
100                 {
101                         __logFilePath = DIR_OSP_APPLICATIONS_TEMP;
102                         __logFilePath += L"/log.txt";
103                         InstallerUtil::CreateLog(__logFilePath);
104
105                         __isFileLogOn = true;
106                 }
107         }
108
109         AppLog("------------------------------------------");
110         AppLog("InstallerManager");
111         AppLog("------------------------------------------");
112         AppLog(" # operation = [%s]", (operation == INSTALLER_OPERATION_INSTALL)?"Install":"Uninstall");
113         AppLog(" # path      = [%ls]", path.GetPointer());
114         AppLog("------------------------------------------");
115
116         __pContext = new InstallationContext();
117         TryReturn(__pContext, INSTALLER_ERROR_OUT_OF_MEMORY, "__pContext is null.");
118
119         error = __pContext->Construct();
120         TryReturn(error == INSTALLER_ERROR_NONE, INSTALLER_ERROR_INTERNAL_STATE, "__pContext->Construct() failed.");
121
122         if (operation == INSTALLER_OPERATION_INSTALL)
123         {
124                 FileAttributes attr;
125                 r = File::GetAttributes(newPath, attr);
126                 TryReturn(!IsFailed(r), INSTALLER_ERROR_PACKAGE_NOT_FOUND, "File::GetAttributes() failed");
127
128                 if (attr.IsDirectory())
129                 {
130                         installerType = INSTALLER_TYPE_DIRECTORY;
131
132                         if (newPath.EndsWith("/") == true)
133                         {
134                                 int length = newPath.GetLength();
135                                 newPath.Remove(length - 1, 1);
136                                 AppLog("newPath=[%ls]", newPath.GetPointer());
137                         }
138
139                         if (newPath.StartsWith(PATH_USR_APPS, 0) == true)
140                         {
141                                 installerType = INSTALLER_TYPE_PRELOADED;
142                                 __pContext->__isPreloaded = true;
143                         }
144
145                         __pContext->__inputPath = newPath;
146                         __pContext->__installDir = newPath;
147                 }
148                 else
149                 {
150                         installerType = INSTALLER_TYPE_PACKAGE;
151                         __pContext->__packagePath = newPath;
152                 }
153         }
154         else if (operation == INSTALLER_OPERATION_UNINSTALL)
155         {
156                 installerType = INSTALLER_TYPE_INSTALLER;
157
158                 AppLog("operation is INSTALLER_OPERATION_UNINSTALL");
159                 __pContext->SetCurrentInstallationStep(INSTALLER_STEP_INIT_UNINSTALL);
160                 __pContext->__packageId = newPath;
161         }
162
163         __pContext->SetInstallerOperation(operation);
164
165         if (option & INSTALLER_OPTION_HYBRID)
166         {
167                 AppLog("Request to install HybridService app!");
168                 __pContext->__isHybridService = true;
169         }
170
171         __pInstaller = CreateInstaller(installerType);
172         TryReturn(__pInstaller, INSTALLER_ERROR_INTERNAL_STATE, "__pInstaller is null.");
173
174         error = __pInstaller->Construct(__pContext);
175         TryReturn(error == INSTALLER_ERROR_NONE, INSTALLER_ERROR_INTERNAL_STATE, "__pInstaller->Construct() failed");
176
177         return error;
178 }
179
180 void
181 InstallerManager::Release(void)
182 {
183         delete __pInstallerManager;
184         __pInstallerManager = null;
185 }
186
187 Installer*
188 InstallerManager::CreateInstaller(InstallerType installerType)
189 {
190         Installer* pInstaller = null;
191
192         switch (installerType)
193         {
194         case INSTALLER_TYPE_INSTALLER:
195                 AppLog("InstallerType = [Installer]");
196                 pInstaller = new (std::nothrow) Installer();
197                 break;
198
199         case INSTALLER_TYPE_PACKAGE:
200                 AppLog("InstallerType = [PackageInstaller]");
201                 pInstaller = new (std::nothrow) PackageInstaller();
202                 break;
203
204         case INSTALLER_TYPE_DIRECTORY:
205                 AppLog("InstallerType = [DirectoryInstaller]");
206                 pInstaller = new (std::nothrow) DirectoryInstaller();
207                 break;
208
209         case INSTALLER_TYPE_GUEST:
210                 AppLog("InstallerType = [GuestInstaller]");
211                 pInstaller = new (std::nothrow) GuestInstaller();
212                 break;
213
214         case INSTALLER_TYPE_PRELOADED:
215                 AppLog("InstallerType = [PreloadedInstaller]");
216                 pInstaller = new (std::nothrow) PreloadedInstaller();
217                 break;
218
219         case INSTALLER_TYPE_IDE:
220                 AppLog("InstallerType = [IDEInstaller]");
221                 pInstaller = new (std::nothrow) IDEInstaller();
222                 break;
223
224         case INSTALLER_TYPE_RESTORATION:
225                 AppLog("InstallerType = [RestorationInstaller]");
226                 pInstaller = new (std::nothrow) RestorationInstaller();
227                 break;
228
229         default:
230                 AppLogExceptionTag(OSP_INSTALLER, "Installer is not found.");
231                 break;
232         }
233
234         return pInstaller;
235 }
236
237 InstallationStep
238 InstallerManager::GetNext(void)
239 {
240         InstallationStep step = __pContext->GetCurrentInstallationStep();
241         return __pInstaller->GetNext(step);
242 }
243
244 InstallerError
245 InstallerManager::Init(void)
246 {
247         return __pInstaller->OnInit();
248 }
249
250 InstallerError
251 InstallerManager::Error(void)
252 {
253         return __pInstaller->OnError();
254 }
255
256 InstallerError
257 InstallerManager::Register(void)
258 {
259         return __pInstaller->OnRegister();
260 }
261
262 InstallerError
263 InstallerManager::End(void)
264 {
265         return __pInstaller->OnEnd();
266 }
267
268 InstallerError
269 InstallerManager::Rollback(void)
270 {
271         return __pInstaller->OnRollback();
272 }
273
274 InstallerError
275 InstallerManager::UserCancel(void)
276 {
277         return __pInstaller->OnUserCancel();
278 }
279
280 InstallerError
281 InstallerManager::Activate(void)
282 {
283         InstallerError error = INSTALLER_ERROR_NONE;
284         IInstallationStep* pStep = null;
285         InstallationStep currentStep;
286
287         while (__pContext->GetState() == INSTALLER_STATE_RUNNING)
288         {
289                 currentStep = GetNext();
290                 __pContext->ChangeStep(currentStep);
291
292                 pStep = __pContext->GetStep();
293                 if (pStep)
294                 {
295                         error = pStep->Run(__pContext);
296
297                         if (error != INSTALLER_ERROR_NONE)
298                         {
299                                 __pContext->SetError(error);
300                                 Error();
301                                 return error;
302                         }
303                 }
304
305                 if (currentStep == INSTALLER_STEP_INIT)
306                 {
307                         error = Init();
308                         TryReturn(error == INSTALLER_ERROR_NONE, error, "error is occurred.");
309                 }
310                 else if (currentStep == INSTALLER_STEP_END)
311                 {
312                         error = Register();
313                         TryReturn(error == INSTALLER_ERROR_NONE, error, "error is occurred.");
314
315                         error = End();
316                         TryReturn(error == INSTALLER_ERROR_NONE, error, "error is occurred.");
317                 }
318
319                 if (__pContext->IsContinue() == false)
320                 {
321                         break;
322                 }
323
324                 if (__pContext->GetCurrentInstallationStep() >= INSTALLER_STEP_MAX)
325                 {
326                         break;
327                 }
328         }
329
330         return error;
331 }
332
333 InstallerError
334 InstallerManager::Progress(void)
335 {
336         return INSTALLER_ERROR_NONE;
337 }
338
339 InstallationContext*
340 InstallerManager::GetContext(void)
341 {
342         return __pContext;
343 }
344
345 int
346 InstallerManager::ParseCommandArg(int argc, char **argv, int *mode, char *buf, bool *output)
347 {
348         const char* pOpts_str = "u:i:r:v";
349         int s = 0;
350
351         if (mode == NULL)
352         {
353                 AppLog("mode is null");
354                 exit(-1);
355         }
356
357         *mode = 0;
358
359         while (1)
360         {
361                 s = getopt(argc, argv, pOpts_str);
362
363                 if (s == -1)
364                 {
365                         break;
366                 }
367
368                 switch (s)
369                 {
370                 case 'i':
371                         if (*mode)
372                         {
373                                 break;
374                         }
375
376                         AppLog("__osp_installer_parse_options: i");
377                         *mode = INSTALLER_MODE_INSTALL;
378                         if (optarg[0] == 'v')
379                         {
380                                 AppLog("__osp_installer_parse_options: v");
381                                 *output = true;
382                                 strncpy(buf, argv[optind++], BUFSIZE);
383                                 AppLog("__osp_installer_parse_options: buf = [%s]", buf);
384                         }
385                         else
386                         {
387                                 strncpy(buf, optarg, BUFSIZE);
388                                 AppLog("__osp_installer_parse_options: optarg = [%s]", optarg);
389                         }
390                         break;
391
392                 case 'u':
393                         if (*mode)
394                         {
395                                 break;
396                         }
397
398                         AppLog("__osp_installer_parse_options: u");
399                         *mode = INSTALLER_MODE_UNINSTALL;
400                         if (optarg[0] == 'v')
401                         {
402                                 AppLog("__osp_installer_parse_options: v");
403                                 *output = true;
404                                 strncpy(buf, argv[optind++], BUFSIZE);
405                                 AppLog("__osp_installer_parse_options: buf = [%s]", buf);
406                         }
407                         else
408                         {
409                                 strncpy(buf, optarg, BUFSIZE);
410                                 AppLog("__osp_installer_parse_options: optarg = [%s]", optarg);
411                         }
412                         break;
413
414                 case 'r':
415                         if (*mode)
416                         {
417                                 break;
418                         }
419
420                         AppLog("__osp_installer_parse_options: r");
421                         *mode = INSTALLER_MODE_RECURSIVE_DIRECTORY_INSTALL;
422                         strncpy(buf, optarg, BUFSIZE);
423                         AppLog("__osp_installer_parse_options: optarg = [%s]", optarg);
424                         break;
425
426                 case 'v':
427                         AppLog("__osp_installer_parse_options: v");
428                         *output = true;
429                         AppLog("__osp_installer_parse_options: optarg = [%s]", optarg);
430                         break;
431
432                 default:
433                         AppLog("Invalid option");
434                         exit(-1);
435                         break;
436                 }
437         }
438
439         if (mode == 0)
440         {
441                 AppLog("Invalid mode");
442                 exit(-1);
443         }
444
445         return 0;
446 }
447
448 bool
449 InstallerManager::RemoveGarbage(const String& filePath)
450 {
451         AppLog("RemoveGarbage Directory = [%ls]", filePath.GetPointer());
452
453         String realPath;
454         if (InstallerUtil::IsSymlink(filePath) == true)
455         {
456                 if (InstallerUtil::GetRealPath(filePath, realPath) == true)
457                 {
458                         InstallerUtil::Remove(realPath);
459                 }
460         }
461
462         InstallerUtil::Remove(filePath);
463
464         return true;
465 }
466
467 int
468 InstallerManager::ReqeustByTest(void)
469 {
470         int errorType = 0;
471         String appId;
472         Tizen::Io::File file;
473         Tizen::Io::FileAttributes attr;
474         result r = E_SUCCESS;
475         char readBuf[512] = {0};
476         PackageId packageId;
477
478         r = File::GetAttributes(L"/opt/apps/cmtamb4mtv/data/configuration", attr);
479         TryCatch(!IsFailed(r), errorType = INSTALLER_ERROR_PACKAGE_NOT_FOUND, "file not found");
480
481         r = file.Construct(L"/opt/apps/cmtamb4mtv/data/configuration", L"r");
482         TryCatch(!IsFailed(r), errorType = INSTALLER_ERROR_PACKAGE_NOT_FOUND, "file.Construct failed");
483
484         if (file.Read(readBuf, sizeof(readBuf)-1) > 1)
485         {
486                 String path;
487                 path.Format(1024, L"%s", &readBuf[1]);
488
489                 if (readBuf[0] == '+')
490                 {
491                         errorType = InstallerManager::Request(path, INSTALLER_OPERATION_INSTALL, INSTALLER_OPTION_NORMAL, packageId);
492                 }
493                 else if (readBuf[0] == '-')
494                 {
495                         errorType = InstallerManager::Request(path, INSTALLER_OPERATION_UNINSTALL, INSTALLER_OPTION_NORMAL, packageId);
496                 }
497                 else if (readBuf[0] == '*')
498                 {
499                         errorType = InstallerManager::RequestRecursiveDirectory(path, errorType);
500                 }
501                 else if (readBuf[0] == '>')
502                 {
503                         errorType = InstallerManager::RequestMove(path, PM_MOVE_TO_SDCARD);
504                 }
505                 else if (readBuf[0] == '<')
506                 {
507                         errorType = InstallerManager::RequestMove(path, PM_MOVE_TO_INTERNAL);
508                 }
509         }
510
511 CATCH:
512         return errorType;
513 }
514
515 void
516 InstallerManager::PrintResult(void)
517 {
518         int errorType = GetErrorType();
519         InstallerOperation operation = GetInstallerOperation();
520
521         Tizen::System::SystemTime::GetTicks(__endTick);
522
523         const char* pOperation = null;
524         (operation == INSTALLER_OPERATION_INSTALL)? (pOperation = "Install"): (pOperation = "Uninstall");
525
526         const wchar_t* pPackageId = L"Unknown";
527         if (__pContext && !__pContext->__packageId.IsEmpty())
528         {
529                 pPackageId = __pContext->__packageId.GetPointer();
530         }
531
532         const wchar_t* pMainAppName = L"Unknown";
533         if (__pContext && !__pContext->__mainAppName.IsEmpty())
534         {
535                 pMainAppName = __pContext->__mainAppName.GetPointer();
536         }
537
538         const char* pError = null;
539         (errorType == 0)?(pError = "Success"):(pError = "Failure");
540
541         int duration = (int)(__endTick - __startTick);
542
543         AppLog("==========================================");
544         AppLog(" # operation = %s", pOperation);
545         AppLog(" # %s", OSP_INSTALLER_VERSION);
546         AppLog(" # PackageId = [%ls]", pPackageId);
547         AppLog(" # MainApp   = [%ls]", pMainAppName);
548         AppLog(" # Time      = [%d]ms", duration);
549         PrintError(errorType);
550         AppLog("==========================================");
551
552         fprintf(stderr, "  ## osp-installer: operation=[%s] result=[%s(%03d)] package id=[%ls] main appname=[%ls] time=[%d]ms\n",
553                         pOperation, pError, errorType, pPackageId, pMainAppName, duration);
554 }
555
556 void
557 InstallerManager::PrintError(int errorType)
558 {
559         const char* pError = null;
560
561         switch (errorType)
562         {
563         case INSTALLER_ERROR_NONE:
564                 pError = "Success";
565                 break;
566
567         case INSTALLER_ERROR_PACKAGE_NOT_FOUND:
568                 pError = "[PACKAGE_NOT_FOUND] Thrown when package file is not found.";
569                 break;
570
571         case INSTALLER_ERROR_PACKAGE_INVALID:
572                 pError = "[PACKAGE_INVALID] Thrown when package file is not valid due to file operation or directory hierarchy.";
573                 break;
574
575         case INSTALLER_ERROR_PACKAGE_LOWER_VERSION:
576                 pError = "[PACKAGE_LOWER_VERSION] Thrown when the lower version package is tried to install.";
577                 break;
578
579         case INSTALLER_ERROR_EXECUTABLE_NOT_FOUND:
580                 pError = "[EXECUTABLE_NOT_FOUND] Thrown when executable file is not found in the package.";
581                 break;
582
583         case INSTALLER_ERROR_MANIFEST_NOT_FOUND:
584                 pError = "[MANIFEST_NOT_FOUND] Thrown when manifest.xml is not found in the package.";
585                 break;
586
587         case INSTALLER_ERROR_MANIFEST_INVALID:
588                 pError = "[MANIFEST_INVALID] Thrown when manifest.xml is not valid due to schema or parsing failure.";
589                 break;
590
591         case INSTALLER_ERROR_SIGNATURE_NOT_FOUND:
592                 pError = "[SIGNATURE_NOT_FOUND] Thrown when the signature files are not found in the package.";
593                 break;
594
595         case INSTALLER_ERROR_SIGNATURE_INVALID:
596                 pError = "[SIGNATURE_INVALID] Thrown when the signature files are not valid due to schema or parsing failure.";
597                 break;
598
599         case INSTALLER_ERROR_SIGNATURE_VERIFICATION_FAILED:
600                 pError = "[SIGNATURE_VERIFICATION_FAILED] Thrown when the signature verification has failed due to be modified illegally.";
601                 break;
602
603         case INSTALLER_ERROR_ROOT_CERTIFICATE_NOT_FOUND:
604                 pError = "[ROOT_CERTIFICATE_NOT_FOUND] Thrown when the root certificate is not found.";
605                 break;
606
607         case INSTALLER_ERROR_CERTIFICATE_INVALID:
608                 pError = "[CERTIFICATE_INVALID] Thrown when the certificate verification has failed.";
609                 break;
610
611         case INSTALLER_ERROR_CERTIFICATE_CHAIN_VERIFICATION_FAILED:
612                 pError = "[CERTIFICATE_CHAIN_VERIFICATION_FAILED] Thrown when the certificate chain verification has failed.";
613                 break;
614
615         case INSTALLER_ERROR_CERTIFICATE_EXPIRED:
616                 pError = "[CERTIFICATE_EXPIRED] Thrown when the used certificates have expired.";
617                 break;
618
619         case INSTALLER_ERROR_PRIVILEGE_INVALID:
620                 pError = "[PRIVILEGE_INVALID] Thrown when unsupported privilege strings are detected.";
621                 break;
622
623         case INSTALLER_ERROR_MENU_ICON_NOT_FOUND:
624                 pError = "[MENU_ICON_NOT_FOUND] Thrown when an icon for menu is not found. This icon is mandatory.";
625                 break;
626
627         case INSTALLER_ERROR_FATAL_ERROR:
628                 pError = "[FATAL_ERROR] Thrown when an icon for menu is not found. This icon is mandatory.";
629                 break;
630
631         case INSTALLER_ERROR_OUT_OF_STORAGE:
632                 pError = "[OUT_OF_STORAGE] Thrown when the storage is full.";
633                 break;
634
635         case INSTALLER_ERROR_OUT_OF_MEMORY:
636                 pError = "[OUT_OF_MEMORY] Thrown when the memory is not sufficient to perform the requested installation or uninstallation.";
637                 break;
638
639         default:
640                 pError = "fatal error";
641                 break;
642         }
643
644         AppLog(" # Error     = %s(%d)", pError, errorType);
645 }
646
647 const PackageId&
648 InstallerManager::GetId(void) const
649 {
650         return __packageId;
651 }
652
653 void
654 InstallerManager::SetId(const PackageId& packageId)
655 {
656         __packageId = packageId;
657 }
658
659 int
660 InstallerManager::GetErrorType(void) const
661 {
662         return __errorType;
663 }
664
665 void
666 InstallerManager::SetErrorType(int errorType)
667 {
668         __errorType = errorType;
669 }
670
671 void
672 InstallerManager::SetInstallerOperation(InstallerOperation op)
673 {
674         __operation = op;
675 }
676
677 InstallerOperation
678 InstallerManager::GetInstallerOperation(void) const
679 {
680         return __operation;
681 }
682
683 String
684 InstallerManager::GetLogFilePath() const
685 {
686         return __logFilePath;
687 }
688
689 bool
690 InstallerManager::IsFileLogOn() const
691 {
692         return __isFileLogOn;
693 }
694
695 int
696 InstallerManager::Request(const String& path, InstallerOperation operation, InstallerOption option, PackageId& packageId)
697 {
698         InstallationContext* pContext = null;
699         InstallerError errorType = INSTALLER_ERROR_NONE;
700         InstallerManager* pInstallManager = null;
701
702         if (File::IsFileExist(DIR_OSP_APPLICATIONS_TEMP) == true)
703         {
704                 InstallerUtil::Remove(DIR_OSP_APPLICATIONS_TEMP);
705         }
706         pInstallManager = InstallerManager::GetInstance();
707         TryCatch(pInstallManager, errorType = INSTALLER_ERROR_INTERNAL_STATE, "pInstallManager is null.");
708
709         errorType = pInstallManager->Construct(path, operation, option);
710         TryCatch(errorType == INSTALLER_ERROR_NONE, , "pInstallManager->Construct() failed.");
711
712         errorType = pInstallManager->Activate();
713         TryCatch(errorType == INSTALLER_ERROR_NONE, , "pInstallManager->Activate() failed.");
714
715         pContext = pInstallManager->GetContext();
716         TryCatch(pContext, errorType = INSTALLER_ERROR_INTERNAL_STATE, "pInstallManager->GetContext failed.");
717         packageId = pContext->__packageId;
718
719 CATCH:
720         pInstallManager->SetErrorType(errorType);
721
722         if (pInstallManager)
723         {
724                 if (!(option & INSTALLER_OPTION_NO_INPUT))
725                 {
726                         pInstallManager->PrintResult();
727                 }
728
729                 if (errorType != INSTALLER_ERROR_NONE)
730                 {
731                         InstallerUtil::PrintLog(pInstallManager->GetLogFilePath());
732                 }
733
734                 pInstallManager->Release();
735         }
736
737         if (File::IsFileExist(DIR_OSP_APPLICATIONS_TEMP) == true)
738         {
739                 InstallerUtil::Remove(DIR_OSP_APPLICATIONS_TEMP);
740         }
741
742         return errorType;
743 }
744
745 int
746 InstallerManager::RequestRecursiveDirectory(const Tizen::Base::String& path, int& errorType)
747 {
748         Directory* pDir = null;
749         DirEnumerator* pDirEnum = null;
750         result r = E_SUCCESS;
751         int res = false;
752         String appid;
753         InstallerError error = INSTALLER_ERROR_NONE;
754         int totalCount = 0;
755         int successCount = 0;
756         int failureCount = 0;
757         PackageId packageId;
758
759         pDir = new (std::nothrow) Directory; // Allocate %Directory instance
760         TryCatch(pDir, res = false, "pDir is null");
761
762         r = pDir->Construct(path);
763         TryCatch(!IsFailed(r), res = false, "pDir->Construct() failed, path = [%ls]", path.GetPointer());
764
765         pDirEnum = pDir->ReadN();
766         TryCatch(pDirEnum, res = false, "pDirEnum is null");
767
768         while (pDirEnum->MoveNext() == E_SUCCESS)
769         {
770                 DirEntry entry = pDirEnum->GetCurrentDirEntry();
771
772                 String entryName = entry.GetName();
773                 String entryDir = path;
774                 entryDir += L"/";
775                 entryDir += entryName;
776
777                 if (entryName == L"." || entryName == L"..")
778                 {
779                         continue;
780                 }
781
782                 if (entry.IsDirectory() == false)
783                 {
784                         continue;
785                 }
786
787                 const int entryLength = entryName.GetLength();
788                 if (entryLength == PACKAGE_ID_LENGTH)
789                 {
790                         // PackageId
791                 }
792                 else if (entryLength == APP_DIR_LENGTH)
793                 {
794                         if (entryName.Contains(PACKAGE_NAME_PREFIX_ORG) == false)
795                         {
796                                 AppLog(" - Not osp = [%ls]: prefix mismatch", entryDir.GetPointer());
797                                 continue;
798                         }
799                 }
800                 else
801                 {
802                         AppLog(" - Not osp = [%ls]: length(%d) mismatch", entryDir.GetPointer(), entryLength);
803                         continue;
804                 }
805
806                 String xmlFile;
807                 xmlFile.Format(1024, L"%ls%ls", entryDir.GetPointer(), PACKAGE_XML_FILE);
808
809                 FileAttributes attr;
810                 r = File::GetAttributes(xmlFile, attr);
811                 if (IsFailed(r))
812                 {
813                         AppLog(" - Not osp = [%ls]: No manifest.xml", entryDir.GetPointer());
814                         continue;
815                 }
816
817                 totalCount++;
818
819                 AppLog("------------------------------------------");
820                 AppLog(" # Directory = [%ls]", entryDir.GetPointer());
821
822                 errorType = Request(entryDir, INSTALLER_OPERATION_INSTALL, INSTALLER_OPTION_NORMAL, packageId);
823                 if (errorType == 0)
824                 {
825                         successCount++;
826                 }
827                 else
828                 {
829                         failureCount++;
830                 }
831
832                 AppLog("------------------------------------------");
833         }
834
835         AppLog("------------------------------------------");
836         AppLog("recursive directory installation");
837         AppLog(" # totalCount   = [%d]", totalCount);
838         AppLog(" # successCount = [%d]", successCount);
839         AppLog(" # failureCount = [%d]", failureCount);
840
841 CATCH:
842         delete pDirEnum;
843         delete pDir;
844         return error;
845 }
846
847 int
848 InstallerManager::RequestByCommand(int argc, char **argv)
849 {
850         int mode = 0;
851         char buf[BUFSIZE] = {0};
852         PackageId packageId;
853         int errorType = 0;
854         bool output = false;
855         InstallerOption option = INSTALLER_OPTION_NORMAL;
856
857         AppLog(" # argc = [%d]", argc);
858
859         for (int i = 0; i < argc; i++)
860         {
861                 AppLog(" # argv[%d] = [%s]", i, argv[i]);
862         }
863
864         InstallerManager::ParseCommandArg(argc, argv, &mode, buf, &output);
865         if (output == true)
866         {
867                 AppLog("HybridService is detected in ParseCommandArg()");
868                 option = (InstallerOption)(option | INSTALLER_OPTION_HYBRID);
869         }
870
871         switch (mode)
872         {
873         case INSTALLER_MODE_INSTALL:
874                 {
875                         AppLog("------------------------------------------");
876                         AppLog(" # Directory = [%s]", buf);
877
878                         option = (InstallerOption)(option | INSTALLER_OPTION_FILELOG_ON);
879                         errorType = InstallerManager::Request(buf, INSTALLER_OPERATION_INSTALL, option, packageId);
880                         if (errorType != 0)
881                         {
882                                 // in case of command, garbage directory is not deleted.
883                                 // RemoveGarbage(buf);
884                         }
885                 }
886                 break;
887
888         case INSTALLER_MODE_UNINSTALL:
889                 {
890                         AppLog("------------------------------------------");
891                         AppLog(" # Directory = [%s]", buf);
892
893                         option = (InstallerOption)(option | INSTALLER_OPTION_FILELOG_ON);
894                         errorType = InstallerManager::Request(buf, INSTALLER_OPERATION_UNINSTALL, option, packageId);
895                 }
896                 break;
897
898         case INSTALLER_MODE_RECURSIVE_DIRECTORY_INSTALL:
899                 {
900                         AppLog("------------------------------------------");
901
902                         errorType = InstallerManager::RequestRecursiveDirectory(buf, errorType);
903                 }
904                 break;
905
906         default:
907                 {
908                         AppLog("__install_package_by_cmd, Invalid mode");
909                 }
910                 break;
911         }
912
913         AppLog("==========================================");
914
915         if (output == true)
916         {
917                 AppLog("stdout is updated by errorType");
918                 fprintf(stdout, "%d", errorType);
919         }
920
921         return errorType;
922 }
923
924 int
925 InstallerManager::RequestMove(const PackageId& packageId, int moveType)
926 {
927         result r = E_SUCCESS;
928         int res = 0;
929         InstallerError errorType = INSTALLER_ERROR_NONE;
930         app2ext_handle* pHandle = null;
931         app2ext_move_type location = APP2EXT_MOVE_TO_EXT;
932         GList* pDirectoryList = null;
933         Directory* pDir = null;
934         DirEnumerator* pDirEnum = null;
935         PackageInfo* pPackageInfo = null;
936         _PackageInfoImpl* pPackageInfoImpl = null;
937         String rootPath;
938
939         std::unique_ptr<char[]> pPackageId(_StringConverter::CopyToCharArrayN(packageId));
940         TryReturn(pPackageId, INSTALLER_ERROR_OUT_OF_MEMORY, "pPackageId is null");
941
942         if (moveType == PM_MOVE_TO_INTERNAL)
943         {
944                 location = APP2EXT_MOVE_TO_PHONE;
945         }
946
947         pPackageInfo = _PackageManagerImpl::GetInstance()->GetPackageInfoN(packageId);
948         TryCatch(pPackageInfo != null, errorType = INSTALLER_ERROR_INTERNAL_STATE, "GetPackageInfoN() failed");
949
950         pPackageInfoImpl = _PackageInfoImpl::GetInstance(pPackageInfo);
951         TryCatch(pPackageInfoImpl, errorType = INSTALLER_ERROR_INTERNAL_STATE, "GetInstance() failed");
952
953         rootPath = pPackageInfoImpl->GetAppRootPath();
954
955         pHandle = app2ext_init(APP2EXT_SD_CARD);
956         TryCatch(pHandle, errorType = INSTALLER_ERROR_INTERNAL_STATE, "app2ext_init() failed");
957
958         if (location == APP2EXT_MOVE_TO_PHONE)
959         {
960                 res = pHandle->interface.enable(pPackageId.get());
961         }
962
963         pDir = new (std::nothrow) Directory;
964         TryCatch(pDir, errorType = INSTALLER_ERROR_OUT_OF_MEMORY, "pDir is null");
965
966         r = pDir->Construct(rootPath);
967         TryCatch(!IsFailed(r), errorType = INSTALLER_ERROR_INTERNAL_STATE, "pDir->Construct() failed, path = [%ls]", rootPath.GetPointer());
968
969         pDirEnum = pDir->ReadN();
970         TryCatch(pDirEnum, errorType = INSTALLER_ERROR_INTERNAL_STATE, "pDirEnum is null");
971
972         while (pDirEnum->MoveNext() == E_SUCCESS)
973         {
974                 DirEntry entry = pDirEnum->GetCurrentDirEntry();
975
976                 String entryName = entry.GetName();
977                 //String rootDirectory = rootPath;
978                 //rootDirectory += L"/";
979                 //rootDirectory += entryName;
980
981                 if (entryName == L"." || entryName == L"..")
982                 {
983                         continue;
984                 }
985
986                 int length = 0;
987                 app2ext_dir_details* pDirDetails = null;
988
989                 pDirDetails = (app2ext_dir_details*) calloc(1, sizeof(app2ext_dir_details));
990                 TryCatch(pDirDetails, errorType = INSTALLER_ERROR_INTERNAL_STATE, "pDirDetails is null");
991
992                 length = entryName.GetLength();
993                 pDirDetails->name = (char*) calloc(1, (sizeof(char) * length) + 1);
994                 snprintf(pDirDetails->name, length + 1, "%ls", entryName.GetPointer());
995
996                 String bin(L"bin");
997                 String res(L"res");
998                 String icons(L"icons");
999
1000                 if (entryName.Contains(bin) || entryName.Contains(res) || entryName.Contains(icons))
1001                 {
1002                         pDirDetails->type = APP2EXT_DIR_RO;
1003                 }
1004                 else
1005                 {
1006                         pDirDetails->type = APP2EXT_DIR_RW;
1007                 }
1008
1009                 AppLog("------------------------------------------");
1010                 AppLog("# Root Directory = [%s], Type = [%d]", pDirDetails->name, pDirDetails->type);
1011
1012                 pDirectoryList = g_list_append(pDirectoryList, pDirDetails);
1013         }
1014
1015         res = pHandle->interface.move(pPackageId.get(), pDirectoryList, location);
1016         TryCatch(res == 0, errorType = INSTALLER_ERROR_INTERNAL_STATE, "pHandle->interface.move() failed [%d]", res);
1017
1018         app2ext_deinit(pHandle);
1019
1020 CATCH:
1021         if (pDirectoryList)
1022         {
1023                 GList* pList = null;
1024                 app2ext_dir_details* pDirDetails = null;
1025
1026                 pList = g_list_first(pDirectoryList);
1027                 while (pList)
1028                 {
1029                         pDirDetails = (app2ext_dir_details*)pList->data;
1030                         if (pDirDetails && pDirDetails->name)
1031                         {
1032                                 free(pDirDetails->name);
1033                         }
1034                         pList = g_list_next(pList);
1035                 }
1036                 g_list_free(pDirectoryList);
1037         }
1038
1039         delete pDirEnum;
1040         delete pDir;
1041         delete pPackageInfo;
1042
1043         return errorType;
1044 }
1045