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