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