Terminate apps when MoveToSD() API
[platform/framework/native/installer.git] / src / Util / InstallerUtil.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        InstallerUtil.cpp
19  * @brief       This is the implementation file for %InstallerUtil class.
20  */
21
22 #include <sys/stat.h>
23 #include <dirent.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <unique_ptr.h>
27
28 #include <FBaseErrorDefine.h>
29 #include <FIoFile.h>
30 #include <FIoDirectory.h>
31 #include <FAppPkgPackageAppInfo.h>
32 #include <FAppPkgPackageInfo.h>
33 #include <FBase_StringConverter.h>
34 #include <FSecCryptoSha2Hash.h>
35 #include <FApp_Aul.h>
36 #include <FAppPkg_PackageManagerImpl.h>
37 #include <FAppPkg_PackageInfoImpl.h>
38 #include <FAppPkg_PackageAppInfoImpl.h>
39
40 #include "InstallerDefs.h"
41 #include "InstallerUtil.h"
42 #include "InstallerManager.h"
43 #include "SmackManager.h"
44
45 using namespace Tizen::Base;
46 using namespace Tizen::Base::Collection;
47 using namespace Tizen::Base::Utility;
48 using namespace Tizen::App;
49 using namespace Tizen::App::Package;
50 using namespace Tizen::Io;
51 using namespace Tizen::Security::Crypto;
52
53 InstallerUtil::InstallerUtil(void)
54 {
55 }
56
57 InstallerUtil::~InstallerUtil(void)
58 {
59 }
60
61 bool
62 InstallerUtil::Remove(const Tizen::Base::String& filePath)
63 {
64         int err = -1;
65         result r = E_SUCCESS;
66         struct stat fileinfo;
67
68         std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
69         TryReturn(pFilePath, false, "pFilePath is null");
70
71         err = lstat(pFilePath.get(), &fileinfo);
72         if (err < 0)
73         {
74                 AppLog("Remove(): [%s] - %s[errno(%d)]: skip", pFilePath.get(), strerror(errno), errno);
75                 return true;
76         }
77
78         if (S_ISLNK(fileinfo.st_mode))
79         {
80                 AppLog("Remove(): symlink=[%s]", pFilePath.get());
81                 err = unlink(pFilePath.get());
82                 TryReturn(err >= 0, false, "unlink() failed(%s), file=[%s]", strerror(errno), pFilePath.get());
83         }
84         else if (S_ISDIR(fileinfo.st_mode))
85         {
86                 AppLog("Remove(): directory=[%ls]", filePath.GetPointer());
87                 r = Directory::Remove(filePath, true);
88                 TryReturn(!IsFailed(r), false, "Directory::Remove() failed, filePath=%ls", filePath.GetPointer());
89         }
90         else
91         {
92                 AppLog("Remove(): file=[%ls]", filePath.GetPointer());
93                 r = File::Remove(filePath);
94                 TryReturn(!IsFailed(r), false, "File::Remove() failed, filePath=%ls", filePath.GetPointer());
95         }
96
97         return true;
98 }
99
100 bool
101 InstallerUtil::Copy(const String& srcFilePath, const String& destFilePath)
102 {
103         int bufSize = 4096;
104         int readBytes = 0;
105         result r = E_SUCCESS;
106
107         // AppLog("+ Copy(): src=[%ls], dest=[%ls]", srcFilePath.GetPointer(), destFilePath.GetPointer());
108
109         File srcFile;
110         File destFile;
111
112         std::unique_ptr<char[]> pBuf(new (std::nothrow) char[bufSize]);
113         TryReturn(pBuf, false, "pBuf is null");
114
115         r = srcFile.Construct(srcFilePath, L"r");
116         TryReturn(!IsFailed(r), false, "srcFile.Construct is failed");
117
118         r = destFile.Construct(destFilePath, L"w");
119         TryReturn(!IsFailed(r), false, "destFile.Construct is failed");
120
121         do
122         {
123                 readBytes = srcFile.Read(pBuf.get(), bufSize);
124                 if (readBytes > 0)
125                 {
126                         r = destFile.Write(pBuf.get(), readBytes);
127                         TryReturn(!IsFailed(r), false, "destFile.Write is failed");
128                 }
129         }
130         while (readBytes > 0);
131
132         return true;
133 }
134
135 bool
136 InstallerUtil::CopyDirectory(const String& srcFilePath, const String& destFilePath)
137 {
138         result r = E_SUCCESS;
139         bool res = false;
140
141         res = File::IsFileExist(srcFilePath);
142         if (res == false)
143         {
144                 AppLog("CopyDirectory(): src=[%ls]: skip", srcFilePath.GetPointer());
145                 return true;
146         }
147
148         std::unique_ptr<Directory> pDir(new (std::nothrow) Directory);
149         TryReturn(pDir, false, "pDir is null.");
150
151         r = pDir->Construct(srcFilePath);
152         TryReturn(!IsFailed(r), false, "pDir->Construct() failed, srcFilePath=[%ls].", srcFilePath.GetPointer());
153
154         std::unique_ptr<DirEnumerator> pDirEnum(pDir->ReadN());
155         TryReturn(pDirEnum, false, "pDirEnum is null.");
156
157         while (pDirEnum->MoveNext() == E_SUCCESS)
158         {
159                 DirEntry entry = pDirEnum->GetCurrentDirEntry();
160
161                 String entryName = entry.GetName();
162                 String srcEntryDir = srcFilePath;
163                 srcEntryDir += L"/";
164                 srcEntryDir += entryName;
165
166                 if (entryName == L"." || entryName == L"..")
167                 {
168                         continue;
169                 }
170
171                 // if file or directory is symbolic link, skip this.
172                 if (InstallerUtil::IsSymlink(srcEntryDir) == true)
173                 {
174                         continue;
175                 }
176
177                 String destEntryDir = destFilePath;
178                 destEntryDir += L"/";
179                 destEntryDir += entryName;
180
181                 if (entry.IsDirectory() == false)
182                 {
183                         // file
184                         Directory::Create(destFilePath, true);
185                         InstallerUtil::Copy(srcEntryDir, destEntryDir);
186                 }
187                 else
188                 {
189                         Directory::Create(destEntryDir, true);
190                         CopyDirectory(srcEntryDir, destEntryDir);
191                 }
192         }
193
194         AppLog("CopyDirectory(): src=[%ls], dest=[%ls]", srcFilePath.GetPointer(), destFilePath.GetPointer());
195         return true;
196 }
197
198 bool
199 InstallerUtil::IsSymlink(const Tizen::Base::String& filePath)
200 {
201         int err = -1;
202         struct stat fileinfo;
203
204         std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
205         TryReturn(pFilePath, false, "pFilePath is null");
206
207         err = lstat(pFilePath.get(), &fileinfo);
208         TryReturn(err >= 0, false, "lstat() failed(%s), file=[%s]", strerror(errno), pFilePath.get());
209
210         if (S_ISLNK(fileinfo.st_mode))
211         {
212                 return true;
213         }
214
215         return false;
216 }
217
218 bool
219 InstallerUtil::GetRealPath(const String& filePath, String& realPath)
220 {
221         char* pRealPath = null;
222
223         std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
224         TryReturn(pFilePath, false, "pFilePath is null");
225
226         char tmpPath[PATH_MAX] = {0};
227         pRealPath = realpath(pFilePath.get(), tmpPath);
228         TryReturn(pRealPath, false, "pRealPath is null");
229
230         realPath = tmpPath;
231
232         AppLog("GetRealPath(): path=[%ls], realPath=[%ls]", filePath.GetPointer(), realPath.GetPointer());
233
234         return true;
235 }
236
237 bool
238 InstallerUtil::CreateSymlink(const String& oldPath, const String& newPath)
239 {
240         int err = -1;
241         bool res = false;
242
243         res = File::IsFileExist(oldPath);
244         if (res == false)
245         {
246                 AppLog("CreateSymlink(): oldPath=[%ls] not found", oldPath.GetPointer());
247                 return true;
248         }
249
250         std::unique_ptr<char[]> pOldPath(_StringConverter::CopyToCharArrayN(oldPath));
251         TryReturn(pOldPath, false, "pOldPath is null");
252
253         std::unique_ptr<char[]> pNewPath(_StringConverter::CopyToCharArrayN(newPath));
254         TryReturn(pNewPath, false, "pNewPath is null");
255
256         err = symlink(pOldPath.get(), pNewPath.get());
257         TryReturn(err == 0, false, "symlink() is failed(%s), oldpath=[%s], newpath=[%s]", strerror(errno), pOldPath.get(), pNewPath.get());
258
259         SmackManager smackManager;
260         String label("_");
261         smackManager.AddLabelDir(label, newPath);
262
263         AppLog("CreateSymlink(): [%ls] -> [%ls]", newPath.GetPointer(), oldPath.GetPointer());
264
265         return true;
266 }
267
268 bool
269 InstallerUtil::ChangeMode(const String& filePath, int mode)
270 {
271         int err = -1;
272
273         std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
274         TryReturn(pFilePath, false, "pFilePath is null");
275
276         err = chmod(pFilePath.get(), mode);
277         TryReturn(err == 0, false, "chmod() is failed(%s), file=[%s], mode=[%o]", strerror(errno), pFilePath.get(), mode);
278
279         return true;
280 }
281
282 bool
283 InstallerUtil::ChangeOwner(const String& filePath)
284 {
285         int err = -1;
286
287         std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
288         TryReturn(pFilePath, false, "pFilePath is null");
289
290         err = chown(pFilePath.get(), APP_OWNER_ID, APP_GROUP_ID);
291         TryReturn(err == 0, false, "chown() is failed(%s), file=[%s]", strerror(errno), pFilePath.get());
292
293         return true;
294 }
295
296 bool
297 InstallerUtil::ChangeDirectoryPermission(const String& filePath, int mode, bool appOwner)
298 {
299         result r = E_SUCCESS;
300         bool res = false;
301
302         res = File::IsFileExist(filePath);
303         if (res == false)
304         {
305                 AppLog("path=[%ls]: skip", filePath.GetPointer());
306                 return true;
307         }
308
309         std::unique_ptr<Directory> pDir(new (std::nothrow) Directory);
310         TryReturn(pDir, false, "pDir is null.");
311
312         r = pDir->Construct(filePath);
313         TryReturn(!IsFailed(r), false, "pDir->Construct() failed, filePath=[%ls]", filePath.GetPointer());
314
315         std::unique_ptr<DirEnumerator> pDirEnum(pDir->ReadN());
316         TryReturn(pDirEnum, false, "pDirEnum is null.");
317
318         while (pDirEnum->MoveNext() == E_SUCCESS)
319         {
320                 DirEntry entry = pDirEnum->GetCurrentDirEntry();
321                 String entryName = entry.GetName();
322                 if (entryName.IsEmpty() == true)
323                 {
324                         AppLog("entryName is empty.", entryName.GetPointer());
325                         continue;
326                 }
327
328                 String entryDir = filePath;
329                 entryDir += L"/";
330                 entryDir += entryName;
331
332                 if (entryName == L".")
333                 {
334                         if (appOwner == true)
335                         {
336                                 InstallerUtil::ChangeOwner(entryDir);
337                         }
338                         InstallerUtil::ChangeMode(entryDir, mode | PERM_EXECUTE);
339                         continue;
340                 }
341                 else if (entryName == L"..")
342                 {
343                         continue;
344                 }
345
346                 if (entry.IsDirectory() == false)
347                 {
348                         if (appOwner == true)
349                         {
350                                 InstallerUtil::ChangeOwner(entryDir);
351                         }
352                         InstallerUtil::ChangeMode(entryDir, mode);
353                 }
354                 else
355                 {
356                         ChangeDirectoryPermission(entryDir, mode, appOwner);
357                         if (appOwner == true)
358                         {
359                                 InstallerUtil::ChangeOwner(entryDir);
360                         }
361                         InstallerUtil::ChangeMode(entryDir, mode | PERM_EXECUTE);
362                 }
363         }
364
365         AppLog("path=[%ls], mode=[%04o], appOwner=[%s]",
366                         filePath.GetPointer(), mode, appOwner?"true":"false");
367
368         return true;
369 }
370
371 bool
372 InstallerUtil::IsDrmFile(const String& path)
373 {
374         return false;
375 }
376
377 bool
378 InstallerUtil::DecryptPackage(const String& packagePath)
379 {
380         return true;
381 }
382
383 String
384 InstallerUtil::GetCategory(int categoryType)
385 {
386         String category;
387
388         if (categoryType == CATEGORY_TYPE_IME)
389         {
390                 category = L"Ime";
391         }
392         else if (categoryType == CATEGORY_TYPE_HOME_SCREEN)
393         {
394                 category = L"home-screen";
395         }
396         else if (categoryType == CATEGORY_TYPE_LOCK_SCREEN)
397         {
398                 category = L"lock-screen";
399         }
400
401         return category;
402 }
403
404 int
405 InstallerUtil::GetCategoryType(char* pCategory)
406 {
407         CategoryType category = CATEGORY_TYPE_NONE;
408
409         if (strcasecmp(pCategory, "Ime") == 0)
410         {
411                 category = CATEGORY_TYPE_IME;
412         }
413         else if (strcasecmp(pCategory, "home-screen") == 0)
414         {
415                 category = CATEGORY_TYPE_HOME_SCREEN;
416         }
417         else if (strcasecmp(pCategory, "lock-screen") == 0)
418         {
419                 category = CATEGORY_TYPE_LOCK_SCREEN;
420         }
421
422         return category;
423 }
424
425 bool
426 InstallerUtil::CreateSymlinkForAppDirectory(const String& inPath, String& outPath)
427 {
428         String appId;
429
430         int length = inPath.GetLength();
431         inPath.SubString(length - PACKAGE_ID_LENGTH, PACKAGE_ID_LENGTH, appId);
432
433         String newPath;
434         newPath = PATH_OPT_APPS;
435         newPath += L"/";
436         newPath += appId;
437
438         if (inPath != newPath)
439         {
440                 InstallerUtil::CreateSymlink(inPath, newPath);
441         }
442
443         outPath = newPath;
444         AppLog("CreateSymlinkForAppDirectory(): output path=[%ls]", outPath.GetPointer());
445
446         return true;
447 }
448
449 bool
450 InstallerUtil::CreateInfoFile(const String& filePath, const String* pContext)
451 {
452         result r = E_SUCCESS;
453         File file;
454
455         r = file.Construct(filePath, "w");
456         TryReturn(!IsFailed(r), false, "file.Construct() failed, filePath=[%ls]", filePath.GetPointer());
457
458         AppLog("------------------------------------------");
459         AppLog("CreateInfoFile(), filePath = [%ls]", filePath.GetPointer());
460
461         if (pContext)
462         {
463                 r = file.Write(*pContext);
464                 TryReturn(!IsFailed(r), false, "file.Write() failed, filePath=[%ls]", filePath.GetPointer());
465                 AppLog("string = [%ls]", pContext->GetPointer());
466         }
467         AppLog("------------------------------------------");
468
469         return true;
470 }
471
472 bool
473 InstallerUtil::DumpLog(const char* pBuf)
474 {
475         TryReturn(pBuf, false, "pBuf is null");
476
477         char temp[4096] = {0};
478         int bufLen = strlen(pBuf);
479         strncpy(temp, pBuf, sizeof(temp)-1);
480
481         char* pStart = &temp[0];
482
483         for (int i = 0; i < bufLen; i++)
484         {
485                 if (temp[i] == '\n')
486                 {
487                         temp[i] = 0;
488                         AppLog("%s", pStart);
489                         pStart = temp + i + 1;
490                 }
491         }
492
493         return true;
494 }
495
496 #define LOG_PRINT_LINE_MAX 20
497 #define LOG_BUFFER_COUNT_MAX 4096
498 bool
499 InstallerUtil::DumpLogData(char *pData, int dataLen)
500 {
501         const char      *szData = (const char*)pData;
502         char            ch = 0;
503         int                     i = 0, j = 0, idx = 0, idx2 = 0, high = 0, low = 0, temp = 0;
504
505         char            buf[LOG_PRINT_LINE_MAX + 2]                     = {0};
506         char            buf2[(LOG_PRINT_LINE_MAX + 2) * 3]      = {0};
507         char            buf_out[sizeof(buf) + sizeof(buf2) + 1] = {0};
508
509
510         if (dataLen > LOG_BUFFER_COUNT_MAX)
511         {
512                 dataLen = LOG_BUFFER_COUNT_MAX;
513         }
514
515         // 16 characters by 20 line are proper. // too many logs decrease performance.
516 //      if (dataLen > 16*20)
517 //              dataLen = 16*20;
518
519         AppLog("------------------------------------------");
520
521         while (i < (int)dataLen)
522         {
523                 ch      = szData[i];
524
525                 /* make ascii table */
526                 if (ch >= 32 && ch <= 128)
527                 {
528                         buf[idx++]      = ch;
529                 }
530                 else
531                         buf[idx++]      = '.';
532
533                 // make binary table
534                 high = (ch & 0xf0)>>4;
535                 low = ch & 0x0f;
536
537                 buf2[idx2++]    = LogChangeHexToStr(high);
538                 buf2[idx2++]    = LogChangeHexToStr(low);
539                 buf2[idx2++]    = ' ';
540
541                 if (idx >= LOG_PRINT_LINE_MAX)
542                 {
543                         memcpy(buf_out, buf2, idx2);
544
545                         buf_out[idx2++] = ' ';
546                         buf_out[idx2++] = ' ';
547
548                         memcpy(buf_out + idx2, buf, idx);
549                         buf_out[idx2+idx]       = '\0';
550
551                         idx             = 0;
552                         idx2    = 0;
553
554                         AppLog("%s\n", buf_out);
555                 }
556
557                 i++;
558         }
559
560         // last line
561         if (idx > 0)
562         {
563                 memcpy(buf_out, buf2, idx2);
564                 temp    = idx2;
565
566                 for (j = 0; j < (LOG_PRINT_LINE_MAX * 3) - temp; j++)
567                 {
568                         buf_out[idx2++] = ' ';
569                 }
570
571                 buf_out[idx2++] = ' ';
572                 buf_out[idx2++] = ' ';
573
574                 memcpy(buf_out+idx2, buf, idx);
575                 buf_out[idx2+idx]       = '\0';
576
577                 AppLog("%s\n", buf_out);
578         }
579
580         AppLog("------------------------------------------");
581
582         return true;
583 }
584
585 char
586 InstallerUtil::LogChangeHexToStr(int hex)
587 {
588         char ch = '0';
589
590         const static char       hexValues[]     = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 0};
591
592
593         if (hex >= 0 && hex <= 0x0F)
594         {
595                 ch      = hexValues[hex];
596         }
597         else
598         {
599                 AppLog("LogChangeHexToStr: Error! [Hex Val: %d]\n", hex);
600         }
601
602         return ch;
603 }
604
605 bool
606 InstallerUtil::CreateLog(const String& logFile)
607 {
608         File file;
609
610         result r = file.Construct(logFile, "w");
611         if (IsFailed(r))
612         {
613                 return false;
614         }
615
616         return true;
617 }
618
619 bool
620 InstallerUtil::AppendLog(const char* pFunction, int lineNumber, bool fatal, const char* pFormat, ...)
621 {
622         File file;
623
624         InstallerManager *pManager = InstallerManager::GetInstance();
625         if (pManager == null)
626         {
627                 return false;
628         }
629
630         if (pManager->IsFileLogOn() == false)
631         {
632                 return true;
633         }
634
635         String logFile = pManager->GetLogFilePath();
636         result r = file.Construct(logFile, "a");
637         if (IsFailed(r))
638         {
639                 return false;
640         }
641
642         va_list args;
643         va_start(args, pFormat);
644         const int bufSize = 1024;
645         char logs[bufSize+1] = {0};
646         char logs2[bufSize+1] = {0};
647         if (fatal == false)
648         {
649                 snprintf(logs, bufSize, "     | %s (%d). > %s", (char*)pFunction, lineNumber, pFormat);
650         }
651         else
652         {
653                 snprintf(logs, bufSize, "[TRY]| %s (%d). > %s", (char*)pFunction, lineNumber, pFormat);
654         }
655
656         vsnprintf(logs2, bufSize, logs, args);
657         int length = strlen(logs2);
658         logs2[length] = '\n';
659
660         r = file.Write(logs2, length+1);
661         if (IsFailed(r))
662         {
663                 va_end(args);
664                 return false;
665         }
666
667         if (pManager->IsHistoryFileLogOn() == true)
668         {
669                 File historyLogFile;
670                 String historyLogFilePath = pManager->GetHistoryLogFilePath();
671                 r = historyLogFile.Construct(historyLogFilePath, "a");
672                 if (!IsFailed(r))
673                 {
674                         r = historyLogFile.Write(logs2, length+1);
675                         if (!IsFailed(r))
676                         {
677                                 // success
678                         }
679                 }
680         }
681
682         va_end(args);
683
684         return true;
685 }
686
687 bool
688 InstallerUtil::PrintLog(const String& logFile)
689 {
690         InstallerManager *pManager = InstallerManager::GetInstance();
691         if (pManager == null)
692         {
693                 return false;
694         }
695
696         if (pManager->IsFileLogOn() == false)
697         {
698                 return true;
699         }
700
701         File file;
702         FileAttributes attribute;
703
704         result r = File::GetAttributes(logFile, attribute);
705         if (IsFailed(r))
706         {
707                 return false;
708         }
709
710         int bufSize = 4096;
711         std::unique_ptr<char[]> pBuf(new (std::nothrow) char[bufSize]);
712         if (pBuf == null)
713         {
714                 return false;
715         }
716
717         r = file.Construct(logFile, "r");
718         if (IsFailed(r))
719         {
720                 return false;
721         }
722
723         int readBytes = 0;
724         do
725         {
726                 memset(pBuf.get(), 0, bufSize);
727                 readBytes = file.Read(pBuf.get(), bufSize);
728                 if (readBytes > 0)
729                 {
730                         fprintf(stderr, "%s", pBuf.get());
731                 }
732         }
733         while (readBytes > 0);
734
735         return true;
736 }
737
738 bool
739 InstallerUtil::GetRdsList(const PackageId& packageId, IList* pDeletedList, IList* pAddedList, IList* pModifiedList)
740 {
741         bool res = true;
742         FILE* fp = null;
743         char rdsFilePath[1024] = {0};
744         char buffer[1024] = {0};
745         InstallerRdsState state = INSTALLER_RDS_STATE_NONE;
746
747         snprintf(rdsFilePath, sizeof(rdsFilePath), "%s/%ls/%s", DIR_APPLICATIONS_TMP, packageId.GetPointer(), INSTALLER_RDS_FILE_NAME);
748
749         fp = fopen(rdsFilePath, "r");
750         TryReturn(fp, false, "fp is null.");
751         AppLog(".rds_delta file");
752         int line = 1;
753
754         while (fgets(buffer, sizeof(buffer), fp) != null)
755         {
756                 bool isMetadata = false;
757
758                 if (buffer[0] == '#')
759                 {
760                         if (strcasestr(buffer, INSTALLER_RDS_DELETE_STR))
761                         {
762                                 state = INSTALLER_RDS_STATE_DELETE;
763                         }
764                         else if (strcasestr(buffer, INSTALLER_RDS_ADD_STR))
765                         {
766                                 state = INSTALLER_RDS_STATE_ADD;
767                         }
768                         else if (strcasestr(buffer, INSTALLER_RDS_MODIFY_STR))
769                         {
770                                 state = INSTALLER_RDS_STATE_MODIFY;
771                         }
772
773                         isMetadata = true;
774                 }
775
776                 if (state == INSTALLER_RDS_STATE_NONE)
777                 {
778                         AppLog("Unknown RDS State, INSTALLER_RDS_STATE_NONE");
779                         continue;
780                 }
781
782                 std::unique_ptr<String> pStr(new (std::nothrow) String(buffer));
783                 TryCatch(pStr, res = false, "pStr is null.");
784                 TryCatch(pStr->IsEmpty() == false, res = false, "pStr is empty.");
785
786                 pStr->Trim();
787                 AppLog(".rds_delta: line(%03d)=[%ls]", line, pStr->GetPointer());
788                 line++;
789
790                 if (isMetadata == true)
791                         continue;
792
793                 if (state == INSTALLER_RDS_STATE_DELETE)
794                 {
795                         pDeletedList->Add(pStr.release());
796                 }
797                 else if (state == INSTALLER_RDS_STATE_ADD)
798                 {
799                         pAddedList->Add(pStr.release());
800                 }
801                 else if (state == INSTALLER_RDS_STATE_MODIFY)
802                 {
803                         pModifiedList->Add(pStr.release());
804                 }
805
806                 memset(buffer, 0, sizeof(buffer));
807         }
808
809 CATCH:
810         fclose(fp);
811         return res;
812 }
813
814 const char*
815 InstallerUtil::GetInstallerOperationString(int operation)
816 {
817         if (operation == INSTALLER_OPERATION_INSTALL)
818         {
819                 return "Install";
820         }
821         else if (operation == INSTALLER_OPERATION_UNINSTALL)
822         {
823                 return "Uninstall";
824         }
825         else if (operation == INSTALLER_OPERATION_REINSTALL)
826         {
827                 return "Reinstall";
828         }
829
830         return "Unknown";
831 }
832
833 bool
834 InstallerUtil::GetFileDigest(const String& filePath, String& digestValue)
835 {
836         const int bufSize = 64*1024;
837         int readBytes = 0;
838         result r = E_SUCCESS;
839
840         File file;
841         std::unique_ptr<Sha2Hash> pHash(new (std::nothrow) Sha2Hash());
842
843         r = pHash->SetAlgorithm("SHA2/256");
844         TryReturn(!IsFailed(r), false, "pHash->SetAlgorithm() is failed.");
845
846         r = pHash->Initialize();
847         TryReturn(!IsFailed(r), false, "pHash->Initialize() is failed.");
848
849         std::unique_ptr<char[]> pBuf(new (std::nothrow) char[bufSize]);
850         TryReturn(pBuf, false, "pBuf is null");
851
852         r = file.Construct(filePath, L"r");
853         TryReturn(!IsFailed(r), false, "file.Construct() is failed.");
854
855         do
856         {
857                 readBytes = file.Read(pBuf.get(), bufSize);
858                 AppLog("readBytes for Hash=[%d]", readBytes);
859
860                 if (readBytes > 0)
861                 {
862                         ByteBuffer buffer;
863                         r = buffer.Construct((const byte*)pBuf.get(), 0, readBytes, bufSize);
864                         TryReturn(!IsFailed(r), false, "buffer.Construct() is failed.");
865
866                         r = pHash->Update(buffer);
867                         TryReturn(!IsFailed(r), false, "pHash->Update() is failed.");
868                 }
869         }
870         while (readBytes > 0);
871
872         std::unique_ptr<ByteBuffer> pResultBuf(pHash->FinalizeN());
873         TryReturn(pResultBuf, false, "pResultBuf is null.");
874
875         r = StringUtil::EncodeToBase64String(*pResultBuf, digestValue);
876         TryReturn(!IsFailed(r), false, "EncodeToBase64String() is failed.");
877
878         return true;
879 }
880
881 IMap*
882 InstallerUtil::ParseN(const String& str, const String& tokenDelimiter)
883 {
884         TryReturn(str.IsEmpty() == false, null, "str is empty.");
885         TryReturn(tokenDelimiter.IsEmpty() == false, null, "tokenDelimiter is empty.");
886
887         std::unique_ptr< HashMap > pMap(new (std::nothrow) HashMap);
888         TryReturn(pMap, null, "pMap is null.");
889
890         result r = pMap->Construct();
891         TryReturn(!IsFailed(r), null, "pMap->Construct() is failed.");
892
893         StringTokenizer strTok(str, tokenDelimiter);
894         while(strTok.HasMoreTokens() == true)
895         {
896                 String token;
897                 r = strTok.GetNextToken(token);
898                 TryReturn(!IsFailed(r), null, "strTok.GetNextToken() is failed.");
899
900                 AppLog("token = [%ls]", token.GetPointer());
901
902                 StringTokenizer infoTok(token, L"=");
903
904                 if (infoTok.GetTokenCount() != 2)
905                 {
906                         AppLog("'=' is not existed.");
907                         continue;
908                 }
909
910                 std::unique_ptr< String > pKey(new (std::nothrow) String);
911                 r = infoTok.GetNextToken(*pKey);
912                 TryReturn(!IsFailed(r), null, "infoTok.GetNextToken(*pKey) is failed.");
913                 AppLog(" - key = [%ls]", pKey->GetPointer());
914
915                 std::unique_ptr< String > pValue(new (std::nothrow) String);
916                 r = infoTok.GetNextToken(*pValue);
917                 TryReturn(!IsFailed(r), null, "infoTok.GetNextToken(*pValue) is failed.");
918                 AppLog(" - value = [%ls]", pValue->GetPointer());
919
920                 r = pMap->Add(pKey.release(), pValue.release());
921                 TryReturn(!IsFailed(r), null, "pMap->Add() is failed.");
922         }
923
924         if (pMap->GetCount() <= 0)
925         {
926                 AppLog("pMap->GetCount() is invalid.");
927                 return null;
928         }
929
930         return pMap.release();
931 }
932
933 bool
934 InstallerUtil::TerminateApp(const AppId& appId)
935 {
936         bool res = true;
937
938         if (_Aul::IsRunning(appId) == true)
939         {
940                 AppLog("App(%ls) is running.", appId.GetPointer());
941
942                 result r = _Aul::TerminateApplication(appId);
943                 TryReturn(r == E_SUCCESS, false, "TerminateApplication() failed. [%ls]", appId.GetPointer());
944
945                 for (int j = 0; j < TERMINATE_RETRY_COUNT; j++)
946                 {
947                         res = _Aul::IsRunning(appId);
948                         if (res == false)
949                         {
950                                 AppLog("App(%ls) is terminated.", appId.GetPointer());
951                                 break;
952                         }
953                         else
954                         {
955                                 AppLog("App(%ls) is not terminated yet. wait count = [%d]", appId.GetPointer(), j);
956                                 usleep(100000);
957                         }
958                 }
959
960                 if (res == true)
961                 {
962                         AppLog("App(%ls) can't be terminated.", appId.GetPointer());
963                         return false;
964                 }
965         }
966         else
967         {
968                 AppLog("App(%ls) is not running.", appId.GetPointer());
969         }
970
971         return true;
972 }
973
974 bool
975 InstallerUtil::TerminateApps(const PackageId& packageId)
976 {
977         std::unique_ptr< PackageInfo > pPackageInfo(_PackageManagerImpl::GetInstance()->GetPackageInfoN(packageId));
978
979         _PackageInfoImpl* pPackageInfoImpl = _PackageInfoImpl::GetInstance(pPackageInfo.get());
980         TryReturn(pPackageInfoImpl, false, "GetInstance() failed.");
981
982         std::unique_ptr< IList > pPackageAppList(pPackageInfoImpl->GetPackageAppInfoListN());
983         TryReturn(pPackageAppList, false, "GetPackageAppInfoListN() failed.");
984
985         for (int i = 0; i < pPackageAppList->GetCount(); i++)
986         {
987                 PackageAppInfo* pPackageAppInfo = dynamic_cast < PackageAppInfo* >(pPackageAppList->GetAt(i));
988                 TryReturn(pPackageAppInfo, false, "pPackageAppList->GetAt(%d) failed.", i);
989
990                 AppId appId = pPackageAppInfo->GetAppId();
991                 TerminateApp(appId);
992         }
993
994         return true;
995 }