2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file InstallerUtil.cpp
19 * @brief This is the implementation file for %InstallerUtil class.
26 #include <unique_ptr.h>
28 #include <FBaseErrorDefine.h>
30 #include <FIoDirectory.h>
31 #include <FBase_StringConverter.h>
32 #include <FSecCryptoSha2Hash.h>
35 #include "InstallerDefs.h"
36 #include "InstallerUtil.h"
37 #include "InstallerManager.h"
38 #include "SmackManager.h"
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;
47 InstallerUtil::InstallerUtil(void)
51 InstallerUtil::~InstallerUtil(void)
56 InstallerUtil::Remove(const Tizen::Base::String& filePath)
62 std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
63 TryReturn(pFilePath, false, "pFilePath is null");
65 err = lstat(pFilePath.get(), &fileinfo);
68 AppLog("Remove(): [%s] - %s[errno(%d)]: skip", pFilePath.get(), strerror(errno), errno);
72 if (S_ISLNK(fileinfo.st_mode))
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());
78 else if (S_ISDIR(fileinfo.st_mode))
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());
86 AppLog("Remove(): file=[%ls]", filePath.GetPointer());
87 r = File::Remove(filePath);
88 TryReturn(!IsFailed(r), false, "File::Remove() failed, filePath=%ls", filePath.GetPointer());
95 InstallerUtil::Copy(const String& srcFilePath, const String& destFilePath)
101 // AppLog("+ Copy(): src=[%ls], dest=[%ls]", srcFilePath.GetPointer(), destFilePath.GetPointer());
106 std::unique_ptr<char[]> pBuf(new (std::nothrow) char[bufSize]);
107 TryReturn(pBuf, false, "pBuf is null");
109 r = srcFile.Construct(srcFilePath, L"r");
110 TryReturn(!IsFailed(r), false, "srcFile.Construct is failed");
112 r = destFile.Construct(destFilePath, L"w");
113 TryReturn(!IsFailed(r), false, "destFile.Construct is failed");
117 readBytes = srcFile.Read(pBuf.get(), bufSize);
120 r = destFile.Write(pBuf.get(), readBytes);
121 TryReturn(!IsFailed(r), false, "destFile.Write is failed");
124 while (readBytes > 0);
130 InstallerUtil::CopyDirectory(const String& srcFilePath, const String& destFilePath)
132 result r = E_SUCCESS;
135 res = File::IsFileExist(srcFilePath);
138 AppLog("CopyDirectory(): src=[%ls]: skip", srcFilePath.GetPointer());
142 std::unique_ptr<Directory> pDir(new (std::nothrow) Directory);
143 TryReturn(pDir, false, "pDir is null.");
145 r = pDir->Construct(srcFilePath);
146 TryReturn(!IsFailed(r), false, "pDir->Construct() failed, srcFilePath=[%ls].", srcFilePath.GetPointer());
148 std::unique_ptr<DirEnumerator> pDirEnum(pDir->ReadN());
149 TryReturn(pDirEnum, false, "pDirEnum is null.");
151 while (pDirEnum->MoveNext() == E_SUCCESS)
153 DirEntry entry = pDirEnum->GetCurrentDirEntry();
155 String entryName = entry.GetName();
156 String srcEntryDir = srcFilePath;
158 srcEntryDir += entryName;
160 if (entryName == L"." || entryName == L"..")
165 // if file or directory is symbolic link, skip this.
166 if (InstallerUtil::IsSymlink(srcEntryDir) == true)
171 String destEntryDir = destFilePath;
172 destEntryDir += L"/";
173 destEntryDir += entryName;
175 if (entry.IsDirectory() == false)
178 Directory::Create(destFilePath, true);
179 InstallerUtil::Copy(srcEntryDir, destEntryDir);
183 Directory::Create(destEntryDir, true);
184 CopyDirectory(srcEntryDir, destEntryDir);
188 AppLog("CopyDirectory(): src=[%ls], dest=[%ls]", srcFilePath.GetPointer(), destFilePath.GetPointer());
193 InstallerUtil::IsSymlink(const Tizen::Base::String& filePath)
196 struct stat fileinfo;
198 std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
199 TryReturn(pFilePath, false, "pFilePath is null");
201 err = lstat(pFilePath.get(), &fileinfo);
202 TryReturn(err >= 0, false, "lstat() failed(%s), file=[%s]", strerror(errno), pFilePath.get());
204 if (S_ISLNK(fileinfo.st_mode))
213 InstallerUtil::GetRealPath(const String& filePath, String& realPath)
215 char* pRealPath = null;
217 std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
218 TryReturn(pFilePath, false, "pFilePath is null");
220 char tmpPath[PATH_MAX] = {0};
221 pRealPath = realpath(pFilePath.get(), tmpPath);
222 TryReturn(pRealPath, false, "pRealPath is null");
226 AppLog("GetRealPath(): path=[%ls], realPath=[%ls]", filePath.GetPointer(), realPath.GetPointer());
232 InstallerUtil::CreateSymlink(const String& oldPath, const String& newPath)
237 res = File::IsFileExist(oldPath);
240 AppLog("CreateSymlink(): oldPath=[%ls] not found", oldPath.GetPointer());
244 std::unique_ptr<char[]> pOldPath(_StringConverter::CopyToCharArrayN(oldPath));
245 TryReturn(pOldPath, false, "pOldPath is null");
247 std::unique_ptr<char[]> pNewPath(_StringConverter::CopyToCharArrayN(newPath));
248 TryReturn(pNewPath, false, "pNewPath is null");
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());
253 SmackManager smackManager;
255 smackManager.AddLabelDir(label, newPath);
257 AppLog("CreateSymlink(): [%ls] -> [%ls]", newPath.GetPointer(), oldPath.GetPointer());
263 InstallerUtil::ChangeMode(const String& filePath, int mode)
267 std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
268 TryReturn(pFilePath, false, "pFilePath is null");
270 err = chmod(pFilePath.get(), mode);
271 TryReturn(err == 0, false, "chmod() is failed(%s), file=[%s], mode=[%o]", strerror(errno), pFilePath.get(), mode);
277 InstallerUtil::ChangeOwner(const String& filePath)
281 std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
282 TryReturn(pFilePath, false, "pFilePath is null");
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());
291 InstallerUtil::ChangeDirectoryPermission(const String& filePath, int mode, bool appOwner)
293 result r = E_SUCCESS;
296 res = File::IsFileExist(filePath);
299 AppLog("path=[%ls]: skip", filePath.GetPointer());
303 std::unique_ptr<Directory> pDir(new (std::nothrow) Directory);
304 TryReturn(pDir, false, "pDir is null.");
306 r = pDir->Construct(filePath);
307 TryReturn(!IsFailed(r), false, "pDir->Construct() failed, filePath=[%ls]", filePath.GetPointer());
309 std::unique_ptr<DirEnumerator> pDirEnum(pDir->ReadN());
310 TryReturn(pDirEnum, false, "pDirEnum is null.");
312 while (pDirEnum->MoveNext() == E_SUCCESS)
314 DirEntry entry = pDirEnum->GetCurrentDirEntry();
315 String entryName = entry.GetName();
316 if (entryName.IsEmpty() == true)
318 AppLog("entryName is empty.", entryName.GetPointer());
322 String entryDir = filePath;
324 entryDir += entryName;
326 if (entryName == L".")
328 if (appOwner == true)
330 InstallerUtil::ChangeOwner(entryDir);
332 InstallerUtil::ChangeMode(entryDir, mode | PERM_EXECUTE);
335 else if (entryName == L"..")
340 if (entry.IsDirectory() == false)
342 if (appOwner == true)
344 InstallerUtil::ChangeOwner(entryDir);
346 InstallerUtil::ChangeMode(entryDir, mode);
350 ChangeDirectoryPermission(entryDir, mode, appOwner);
351 if (appOwner == true)
353 InstallerUtil::ChangeOwner(entryDir);
355 InstallerUtil::ChangeMode(entryDir, mode | PERM_EXECUTE);
359 AppLog("path=[%ls], mode=[%04o], appOwner=[%s]",
360 filePath.GetPointer(), mode, appOwner?"true":"false");
366 InstallerUtil::IsDrmFile(const String& path)
372 InstallerUtil::DecryptPackage(const String& packagePath)
378 InstallerUtil::GetCategory(int categoryType)
382 if (categoryType == CATEGORY_TYPE_IME)
386 else if (categoryType == CATEGORY_TYPE_HOME_SCREEN)
388 category = L"home-screen";
390 else if (categoryType == CATEGORY_TYPE_LOCK_SCREEN)
392 category = L"lock-screen";
399 InstallerUtil::GetCategoryType(char* pCategory)
401 CategoryType category = CATEGORY_TYPE_NONE;
403 if (strcasecmp(pCategory, "Ime") == 0)
405 category = CATEGORY_TYPE_IME;
407 else if (strcasecmp(pCategory, "home-screen") == 0)
409 category = CATEGORY_TYPE_HOME_SCREEN;
411 else if (strcasecmp(pCategory, "lock-screen") == 0)
413 category = CATEGORY_TYPE_LOCK_SCREEN;
420 InstallerUtil::CreateSymlinkForAppDirectory(const String& inPath, String& outPath)
424 int length = inPath.GetLength();
425 inPath.SubString(length - PACKAGE_ID_LENGTH, PACKAGE_ID_LENGTH, appId);
428 newPath = PATH_OPT_APPS;
432 if (inPath != newPath)
434 InstallerUtil::CreateSymlink(inPath, newPath);
438 AppLog("CreateSymlinkForAppDirectory(): output path=[%ls]", outPath.GetPointer());
444 InstallerUtil::CreateInfoFile(const String& filePath, const String* pContext)
446 result r = E_SUCCESS;
449 r = file.Construct(filePath, "w");
450 TryReturn(!IsFailed(r), false, "file.Construct() failed, filePath=[%ls]", filePath.GetPointer());
452 AppLog("------------------------------------------");
453 AppLog("CreateInfoFile(), filePath = [%ls]", filePath.GetPointer());
457 r = file.Write(*pContext);
458 TryReturn(!IsFailed(r), false, "file.Write() failed, filePath=[%ls]", filePath.GetPointer());
459 AppLog("string = [%ls]", pContext->GetPointer());
461 AppLog("------------------------------------------");
467 InstallerUtil::DumpLog(const char* pBuf)
469 TryReturn(pBuf, false, "pBuf is null");
471 char temp[4096] = {0};
472 int bufLen = strlen(pBuf);
473 strncpy(temp, pBuf, sizeof(temp)-1);
475 char* pStart = &temp[0];
477 for (int i = 0; i < bufLen; i++)
482 AppLog("%s", pStart);
483 pStart = temp + i + 1;
490 #define LOG_PRINT_LINE_MAX 20
491 #define LOG_BUFFER_COUNT_MAX 4096
493 InstallerUtil::DumpLogData(char *pData, int dataLen)
495 const char *szData = (const char*)pData;
497 int i = 0, j = 0, idx = 0, idx2 = 0, high = 0, low = 0, temp = 0;
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};
504 if (dataLen > LOG_BUFFER_COUNT_MAX)
506 dataLen = LOG_BUFFER_COUNT_MAX;
509 // 16 characters by 20 line are proper. // too many logs decrease performance.
510 // if (dataLen > 16*20)
513 AppLog("------------------------------------------");
515 while (i < (int)dataLen)
519 /* make ascii table */
520 if (ch >= 32 && ch <= 128)
528 high = (ch & 0xf0)>>4;
531 buf2[idx2++] = LogChangeHexToStr(high);
532 buf2[idx2++] = LogChangeHexToStr(low);
535 if (idx >= LOG_PRINT_LINE_MAX)
537 memcpy(buf_out, buf2, idx2);
539 buf_out[idx2++] = ' ';
540 buf_out[idx2++] = ' ';
542 memcpy(buf_out + idx2, buf, idx);
543 buf_out[idx2+idx] = '\0';
548 AppLog("%s\n", buf_out);
557 memcpy(buf_out, buf2, idx2);
560 for (j = 0; j < (LOG_PRINT_LINE_MAX * 3) - temp; j++)
562 buf_out[idx2++] = ' ';
565 buf_out[idx2++] = ' ';
566 buf_out[idx2++] = ' ';
568 memcpy(buf_out+idx2, buf, idx);
569 buf_out[idx2+idx] = '\0';
571 AppLog("%s\n", buf_out);
574 AppLog("------------------------------------------");
580 InstallerUtil::LogChangeHexToStr(int hex)
584 const static char hexValues[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 0};
587 if (hex >= 0 && hex <= 0x0F)
593 AppLog("LogChangeHexToStr: Error! [Hex Val: %d]\n", hex);
600 InstallerUtil::CreateLog(const String& logFile)
604 result r = file.Construct(logFile, "w");
614 InstallerUtil::AppendLog(const char* pFunction, int lineNumber, bool fatal, const char* pFormat, ...)
618 InstallerManager *pManager = InstallerManager::GetInstance();
619 if (pManager == null)
624 if (pManager->IsFileLogOn() == false)
629 String logFile = pManager->GetLogFilePath();
630 result r = file.Construct(logFile, "a");
637 va_start(args, pFormat);
638 const int bufSize = 1024;
639 char logs[bufSize+1] = {0};
640 char logs2[bufSize+1] = {0};
643 snprintf(logs, bufSize, " | %s (%d). > %s", (char*)pFunction, lineNumber, pFormat);
647 snprintf(logs, bufSize, "[TRY]| %s (%d). > %s", (char*)pFunction, lineNumber, pFormat);
650 vsnprintf(logs2, bufSize, logs, args);
651 int length = strlen(logs2);
652 logs2[length] = '\n';
654 r = file.Write(logs2, length+1);
661 if (pManager->IsHistoryFileLogOn() == true)
664 String historyLogFilePath = pManager->GetHistoryLogFilePath();
665 r = historyLogFile.Construct(historyLogFilePath, "a");
668 r = historyLogFile.Write(logs2, length+1);
682 InstallerUtil::PrintLog(const String& logFile)
684 InstallerManager *pManager = InstallerManager::GetInstance();
685 if (pManager == null)
690 if (pManager->IsFileLogOn() == false)
696 FileAttributes attribute;
698 result r = File::GetAttributes(logFile, attribute);
705 std::unique_ptr<char[]> pBuf(new (std::nothrow) char[bufSize]);
711 r = file.Construct(logFile, "r");
720 memset(pBuf.get(), 0, bufSize);
721 readBytes = file.Read(pBuf.get(), bufSize);
724 fprintf(stderr, "%s", pBuf.get());
727 while (readBytes > 0);
733 InstallerUtil::GetRdsList(const PackageId& packageId, IList* pDeletedList, IList* pAddedList, IList* pModifiedList)
737 char rdsFilePath[1024] = {0};
738 char buffer[1024] = {0};
739 InstallerRdsState state = INSTALLER_RDS_STATE_NONE;
741 snprintf(rdsFilePath, sizeof(rdsFilePath), "%s/%ls/%s", DIR_APPLICATIONS_TMP, packageId.GetPointer(), INSTALLER_RDS_FILE_NAME);
743 fp = fopen(rdsFilePath, "r");
744 TryReturn(fp, false, "fp is null.");
745 AppLog(".rds_delta file");
748 while (fgets(buffer, sizeof(buffer), fp) != null)
750 bool isMetadata = false;
752 if (buffer[0] == '#')
754 if (strcasestr(buffer, INSTALLER_RDS_DELETE_STR))
756 state = INSTALLER_RDS_STATE_DELETE;
758 else if (strcasestr(buffer, INSTALLER_RDS_ADD_STR))
760 state = INSTALLER_RDS_STATE_ADD;
762 else if (strcasestr(buffer, INSTALLER_RDS_MODIFY_STR))
764 state = INSTALLER_RDS_STATE_MODIFY;
770 if (state == INSTALLER_RDS_STATE_NONE)
772 AppLog("Unknown RDS State, INSTALLER_RDS_STATE_NONE");
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.");
781 AppLog(".rds_delta: line(%03d)=[%ls]", line, pStr->GetPointer());
784 if (isMetadata == true)
787 if (state == INSTALLER_RDS_STATE_DELETE)
789 pDeletedList->Add(pStr.release());
791 else if (state == INSTALLER_RDS_STATE_ADD)
793 pAddedList->Add(pStr.release());
795 else if (state == INSTALLER_RDS_STATE_MODIFY)
797 pModifiedList->Add(pStr.release());
800 memset(buffer, 0, sizeof(buffer));
809 InstallerUtil::GetInstallerOperationString(int operation)
811 if (operation == INSTALLER_OPERATION_INSTALL)
815 else if (operation == INSTALLER_OPERATION_UNINSTALL)
819 else if (operation == INSTALLER_OPERATION_REINSTALL)
828 InstallerUtil::GetFileDigest(const String& filePath, String& digestValue)
830 const int bufSize = 64*1024;
832 result r = E_SUCCESS;
835 std::unique_ptr<Sha2Hash> pHash(new (std::nothrow) Sha2Hash());
837 r = pHash->SetAlgorithm("SHA2/256");
838 TryReturn(!IsFailed(r), false, "pHash->SetAlgorithm() is failed.");
840 r = pHash->Initialize();
841 TryReturn(!IsFailed(r), false, "pHash->Initialize() is failed.");
843 std::unique_ptr<char[]> pBuf(new (std::nothrow) char[bufSize]);
844 TryReturn(pBuf, false, "pBuf is null");
846 r = file.Construct(filePath, L"r");
847 TryReturn(!IsFailed(r), false, "file.Construct() is failed.");
851 readBytes = file.Read(pBuf.get(), bufSize);
852 AppLog("readBytes for Hash=[%d]", readBytes);
857 r = buffer.Construct((const byte*)pBuf.get(), 0, readBytes, bufSize);
858 TryReturn(!IsFailed(r), false, "buffer.Construct() is failed.");
860 r = pHash->Update(buffer);
861 TryReturn(!IsFailed(r), false, "pHash->Update() is failed.");
864 while (readBytes > 0);
866 std::unique_ptr<ByteBuffer> pResultBuf(pHash->FinalizeN());
867 TryReturn(pResultBuf, false, "pResultBuf is null.");
869 r = StringUtil::EncodeToBase64String(*pResultBuf, digestValue);
870 TryReturn(!IsFailed(r), false, "EncodeToBase64String() is failed.");
876 InstallerUtil::ParseN(const String& str, const String& tokenDelimiter)
878 TryReturn(str.IsEmpty() == false, null, "str is empty.");
879 TryReturn(tokenDelimiter.IsEmpty() == false, null, "tokenDelimiter is empty.");
881 std::unique_ptr< HashMap > pMap(new (std::nothrow) HashMap);
882 TryReturn(pMap, null, "pMap is null.");
884 result r = pMap->Construct();
885 TryReturn(!IsFailed(r), null, "pMap->Construct() is failed.");
887 StringTokenizer strTok(str, tokenDelimiter);
888 while(strTok.HasMoreTokens() == true)
891 r = strTok.GetNextToken(token);
892 TryReturn(!IsFailed(r), null, "strTok.GetNextToken() is failed.");
894 AppLog("token = [%ls]", token.GetPointer());
896 StringTokenizer infoTok(token, L"=");
898 if (infoTok.GetTokenCount() != 2)
900 AppLog("'=' is not existed.");
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());
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());
914 r = pMap->Add(pKey.release(), pValue.release());
915 TryReturn(!IsFailed(r), null, "pMap->Add() is failed.");
918 if (pMap->GetCount() <= 0)
920 AppLog("pMap->GetCount() is invalid.");
924 return pMap.release();
928 InstallerUtil::TerminateApp(const AppId& appId)
932 if (_Aul::IsRunning(appId) == true)
934 AppLog("App(%ls) is running.", appId.GetPointer());
936 result r = _Aul::TerminateApplication(appId);
937 TryReturn(r == E_SUCCESS, false, "TerminateApplication() failed. [%ls]", appId.GetPointer());
939 for (int j = 0; j < TERMINATE_RETRY_COUNT; j++)
941 res = _Aul::IsRunning(appId);
944 AppLog("App(%ls) is terminated.", appId.GetPointer());
949 AppLog("App(%ls) is not terminated yet. wait count = [%d]", appId.GetPointer(), j);
956 AppLog("App(%ls) can't be terminated.", appId.GetPointer());
962 AppLog("App(%ls) is not running.", appId.GetPointer());