merge with master
[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 #include <drm-oem-intel.h>
28
29 #include <FBaseErrorDefine.h>
30 #include <FIoFile.h>
31 #include <FIoDirectory.h>
32 #include <FBase_StringConverter.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::App;
42 using namespace Tizen::Io;
43
44 InstallerUtil::InstallerUtil(void)
45 {
46 }
47
48 InstallerUtil::~InstallerUtil(void)
49 {
50 }
51
52 bool
53 InstallerUtil::Remove(const Tizen::Base::String& filePath)
54 {
55         int err = -1;
56         result r = E_SUCCESS;
57         struct stat fileinfo;
58
59         std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
60         TryReturn(pFilePath, false, "pFilePath is null");
61
62         err = lstat(pFilePath.get(), &fileinfo);
63         if (err < 0)
64         {
65                 AppLog("Remove(): [%s] - %s[errno(%d)]: skip", pFilePath.get(), strerror(errno), errno);
66                 return true;
67         }
68
69         if (S_ISLNK(fileinfo.st_mode))
70         {
71                 AppLog("Remove(): symlink, path=[%s]", pFilePath.get());
72                 err = unlink(pFilePath.get());
73                 TryReturn(err >= 0, false, "unlink() failed(%s), filepath=[%s]", strerror(errno), pFilePath.get());
74         }
75         else if (S_ISDIR(fileinfo.st_mode))
76         {
77                 AppLog("Remove(): directory, path=[%ls]", filePath.GetPointer());
78                 r = Directory::Remove(filePath, true);
79                 TryReturn(!IsFailed(r), false, "Directory::Remove() failed, filePath=%ls", filePath.GetPointer());
80         }
81         else
82         {
83                 AppLog("Remove(): file, path=[%ls]", filePath.GetPointer());
84                 r = File::Remove(filePath);
85                 TryReturn(!IsFailed(r), false, "File::Remove() failed, filePath=%ls", filePath.GetPointer());
86         }
87
88         return true;
89 }
90
91 bool
92 InstallerUtil::Copy(const String& srcFilePath, const String& destFilePath)
93 {
94         int bufSize = 4096;
95         int readBytes = 0;
96         result r = E_SUCCESS;
97
98         // AppLog("+ Copy(): src=[%ls], dest=[%ls]", srcFilePath.GetPointer(), destFilePath.GetPointer());
99
100         File srcFile;
101         File destFile;
102
103         std::unique_ptr<char[]> pBuf(new (std::nothrow) char[bufSize]);
104         TryReturn(pBuf, false, "pBuf is null");
105
106         r = srcFile.Construct(srcFilePath, L"r");
107         TryReturn(!IsFailed(r), false, "srcFile.Construct is failed");
108
109         r = destFile.Construct(destFilePath, L"w");
110         TryReturn(!IsFailed(r), false, "destFile.Construct is failed");
111
112         do
113         {
114                 readBytes = srcFile.Read(pBuf.get(), bufSize);
115                 if (readBytes > 0)
116                 {
117                         r = destFile.Write(pBuf.get(), readBytes);
118                         TryReturn(!IsFailed(r), false, "destFile.Write is failed");
119                 }
120         }
121         while (readBytes > 0);
122
123         return true;
124 }
125
126 bool
127 InstallerUtil::CopyDirectory(const String& srcFilePath, const String& destFilePath)
128 {
129         result r = E_SUCCESS;
130         bool res = false;
131
132         res = File::IsFileExist(srcFilePath);
133         if (res == false)
134         {
135                 AppLog("CopyDirectory(): src=[%ls]: skip", srcFilePath.GetPointer());
136                 return true;
137         }
138
139         std::unique_ptr<Directory> pDir(new (std::nothrow) Directory);
140         TryReturn(pDir, false, "pDir is null.");
141
142         r = pDir->Construct(srcFilePath);
143         TryReturn(!IsFailed(r), false, "pDir->Construct() failed, srcFilePath=[%ls].", srcFilePath.GetPointer());
144
145         std::unique_ptr<DirEnumerator> pDirEnum(pDir->ReadN());
146         TryReturn(pDirEnum, false, "pDirEnum is null.");
147
148         while (pDirEnum->MoveNext() == E_SUCCESS)
149         {
150                 DirEntry entry = pDirEnum->GetCurrentDirEntry();
151
152                 String entryName = entry.GetName();
153                 String srcEntryDir = srcFilePath;
154                 srcEntryDir += L"/";
155                 srcEntryDir += entryName;
156
157                 if (entryName == L"." || entryName == L"..")
158                 {
159                         continue;
160                 }
161
162                 // if file or directory is symbolic link, skip this.
163                 if (InstallerUtil::IsSymlink(srcEntryDir) == true)
164                 {
165                         continue;
166                 }
167
168                 String destEntryDir = destFilePath;
169                 destEntryDir += L"/";
170                 destEntryDir += entryName;
171
172                 if (entry.IsDirectory() == false)
173                 {
174                         // file
175                         Directory::Create(destFilePath, true);
176                         InstallerUtil::Copy(srcEntryDir, destEntryDir);
177                 }
178                 else
179                 {
180                         Directory::Create(destEntryDir, true);
181                         CopyDirectory(srcEntryDir, destEntryDir);
182                 }
183         }
184
185         AppLog("CopyDirectory(): src=[%ls], dest=[%ls]", srcFilePath.GetPointer(), destFilePath.GetPointer());
186         return true;
187 }
188
189 bool
190 InstallerUtil::IsSymlink(const Tizen::Base::String& filePath)
191 {
192         int err = -1;
193         struct stat fileinfo;
194
195         std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
196         TryReturn(pFilePath, false, "pFilePath is null");
197
198         err = lstat(pFilePath.get(), &fileinfo);
199         TryReturn(err >= 0, false, "lstat() failed(%s), filepath=[%s]", strerror(errno), pFilePath.get());
200
201         if (S_ISLNK(fileinfo.st_mode))
202         {
203                 return true;
204         }
205
206         return false;
207 }
208
209 bool
210 InstallerUtil::GetRealPath(const String& filePath, String& realPath)
211 {
212         char* pRealPath = null;
213
214         std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
215         TryReturn(pFilePath, false, "pFilePath is null");
216
217         char tmpPath[PATH_MAX] = {0};
218         pRealPath = realpath(pFilePath.get(), tmpPath);
219         TryReturn(pRealPath, false, "pRealPath is null");
220
221         realPath = tmpPath;
222
223         AppLog("GetRealPath(): path=[%ls], realPath=[%ls]", filePath.GetPointer(), realPath.GetPointer());
224
225         return true;
226 }
227
228 bool
229 InstallerUtil::CreateSymlink(const String& oldPath, const String& newPath)
230 {
231         int err = -1;
232         bool res = false;
233
234         res = File::IsFileExist(oldPath);
235         if (res == false)
236         {
237                 AppLog("CreateSymlink(): oldPath=[%ls] not found", oldPath.GetPointer());
238                 return true;
239         }
240
241         std::unique_ptr<char[]> pOldPath(_StringConverter::CopyToCharArrayN(oldPath));
242         TryReturn(pOldPath, false, "pOldPath is null");
243
244         std::unique_ptr<char[]> pNewPath(_StringConverter::CopyToCharArrayN(newPath));
245         TryReturn(pNewPath, false, "pNewPath is null");
246
247         err = symlink(pOldPath.get(), pNewPath.get());
248         TryReturn(err == 0, false, "symlink() is failed(%s), oldpath=[%s], newpath=[%s]", strerror(errno), pOldPath.get(), pNewPath.get());
249
250         SmackManager smackManager;
251         String label("_");
252         smackManager.AddLabelDir(label, newPath);
253
254         AppLog("CreateSymlink(): [%ls] -> [%ls]", newPath.GetPointer(), oldPath.GetPointer());
255
256         return true;
257 }
258
259 bool
260 InstallerUtil::ChangeMode(const String& filePath, int mode)
261 {
262         int err = -1;
263
264         std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
265         TryReturn(pFilePath, false, "pFilePath is null");
266
267         err = chmod(pFilePath.get(), mode);
268         TryReturn(err == 0, false, "chmod() is failed(%s), filepath=[%s], mode=[%o]", strerror(errno), pFilePath.get(), mode);
269
270         return true;
271 }
272
273 bool
274 InstallerUtil::ChangeOwner(const String& filePath)
275 {
276         int err = -1;
277
278         std::unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(filePath));
279         TryReturn(pFilePath, false, "pFilePath is null");
280
281         err = chown(pFilePath.get(), APP_OWNER_ID, APP_GROUP_ID);
282         TryReturn(err == 0, false, "chown() is failed(%s), filepath=[%s]", strerror(errno), pFilePath.get());
283
284         return true;
285 }
286
287 bool
288 InstallerUtil::ChangeDirectoryPermission(const String& filePath, int mode, bool appOwner)
289 {
290         result r = E_SUCCESS;
291         bool res = false;
292
293         res = File::IsFileExist(filePath);
294         if (res == false)
295         {
296                 AppLog("path=[%ls]: skip", filePath.GetPointer());
297                 return true;
298         }
299
300         std::unique_ptr<Directory> pDir(new (std::nothrow) Directory);
301         TryReturn(pDir, false, "pDir is null.");
302
303         r = pDir->Construct(filePath);
304         TryReturn(!IsFailed(r), false, "pDir->Construct() failed, filePath=[%ls]", filePath.GetPointer());
305
306         std::unique_ptr<DirEnumerator> pDirEnum(pDir->ReadN());
307         TryReturn(pDirEnum, false, "pDirEnum is null.");
308
309         while (pDirEnum->MoveNext() == E_SUCCESS)
310         {
311                 DirEntry entry = pDirEnum->GetCurrentDirEntry();
312                 String entryName = entry.GetName();
313                 if (entryName.IsEmpty() == true)
314                 {
315                         AppLog("entryName is empty.", entryName.GetPointer());
316                         continue;
317                 }
318
319                 String entryDir = filePath;
320                 entryDir += L"/";
321                 entryDir += entryName;
322
323                 if (entryName == L".")
324                 {
325                         if (appOwner == true)
326                         {
327                                 InstallerUtil::ChangeOwner(entryDir);
328                         }
329                         InstallerUtil::ChangeMode(entryDir, mode | PERM_EXECUTE);
330                         continue;
331                 }
332                 else if (entryName == L"..")
333                 {
334                         continue;
335                 }
336
337                 if (entry.IsDirectory() == false)
338                 {
339                         if (appOwner == true)
340                         {
341                                 InstallerUtil::ChangeOwner(entryDir);
342                         }
343                         InstallerUtil::ChangeMode(entryDir, mode);
344                 }
345                 else
346                 {
347                         ChangeDirectoryPermission(entryDir, mode, appOwner);
348                         if (appOwner == true)
349                         {
350                                 InstallerUtil::ChangeOwner(entryDir);
351                         }
352                         InstallerUtil::ChangeMode(entryDir, mode | PERM_EXECUTE);
353                 }
354         }
355
356         AppLog("path=[%ls], mode=[%04o], appOwner=[%s]",
357                         filePath.GetPointer(), mode, appOwner?"true":"false");
358
359         return true;
360 }
361
362 bool
363 InstallerUtil::IsDrmFile(const Tizen::Base::String& path)
364 {
365         bool res = true;
366         char* pFilePath = null;
367         result r = E_SUCCESS;
368         int isDrm = 0;
369
370         pFilePath = _StringConverter::CopyToCharArrayN(path);
371         TryCatch(pFilePath, r = GetLastResult(), "pFilePath is null");
372
373         isDrm = drm_oem_intel_isDrmFile(pFilePath);
374         if(isDrm == 1)
375         {
376                 AppLog("IsDrmFile() called, packagePath=[%ls] is a drm file", path.GetPointer());
377         }
378         else
379         {
380                 res = false;
381         }
382
383 CATCH:
384         delete [] pFilePath;
385         return res;
386 }
387
388 bool
389 InstallerUtil::DecryptPackage(const Tizen::Base::String& packagePath)
390 {
391             bool res = true;
392             char* pFilePath = null;
393             result r = E_SUCCESS;
394             int result = 0;
395
396             pFilePath = _StringConverter::CopyToCharArrayN(packagePath);
397             TryCatch(pFilePath, r = GetLastResult(), "pFilePath is null");
398
399             result = drm_oem_intel_decrypt_package(pFilePath, pFilePath);
400             if(result  == 1)
401             {
402                 AppLog("DecryptPackage() called, packagePath=%ls, decrpyt success", packagePath.GetPointer());
403             }
404             else
405             {
406                 AppLog("DecryptPackage() called, packagePath=%ls, decrypt failed", packagePath.GetPointer());
407                 res = false;
408             }
409
410 CATCH:
411             delete [] pFilePath;
412             return res;
413 }
414
415 String
416 InstallerUtil::GetCategory(int categoryType)
417 {
418         String category;
419
420         if (categoryType == CATEGORY_TYPE_IME)
421         {
422                 category = L"Ime";
423         }
424         else if (categoryType == CATEGORY_TYPE_HOME_SCREEN)
425         {
426                 category = L"home-screen";
427         }
428         else if (categoryType == CATEGORY_TYPE_LOCK_SCREEN)
429         {
430                 category = L"lock-screen";
431         }
432
433         return category;
434 }
435
436 int
437 InstallerUtil::GetCategoryType(char* pCategory)
438 {
439         CategoryType category = CATEGORY_TYPE_NONE;
440
441         if (strcasecmp(pCategory, "Ime") == 0)
442         {
443                 category = CATEGORY_TYPE_IME;
444         }
445         else if (strcasecmp(pCategory, "home-screen") == 0)
446         {
447                 category = CATEGORY_TYPE_HOME_SCREEN;
448         }
449         else if (strcasecmp(pCategory, "lock-screen") == 0)
450         {
451                 category = CATEGORY_TYPE_LOCK_SCREEN;
452         }
453
454         return category;
455 }
456
457 bool
458 InstallerUtil::CreateSymlinkForAppDirectory(const String& inPath, String& outPath)
459 {
460         String appId;
461
462         int length = inPath.GetLength();
463         inPath.SubString(length - PACKAGE_ID_LENGTH, PACKAGE_ID_LENGTH, appId);
464
465         String newPath;
466         newPath = PATH_OPT_APPS;
467         newPath += L"/";
468         newPath += appId;
469
470         if (inPath != newPath)
471         {
472                 InstallerUtil::CreateSymlink(inPath, newPath);
473         }
474
475         outPath = newPath;
476         AppLog("CreateSymlinkForAppDirectory(): output path=[%ls]", outPath.GetPointer());
477
478         return true;
479 }
480
481 bool
482 InstallerUtil::DumpLog(const char* pBuf)
483 {
484         char temp[4096] = {0};
485         TryReturn(pBuf, false, "pBuf is null");
486
487         int bufLen = strlen(pBuf);
488         strncpy(temp, pBuf, sizeof(temp));
489
490         char *pStart = &temp[0];
491
492         for (int i = 0; i < bufLen; i++)
493         {
494                 if (temp[i] == '\n')
495                 {
496                         temp[i] = 0;
497                         AppLog("%s", pStart);
498                         pStart = temp + i + 1;
499                 }
500         }
501
502         return true;
503 }
504
505 #define LOG_PRINT_LINE_MAX 20
506 #define LOG_BUFFER_COUNT_MAX 4096
507 bool
508 InstallerUtil::DumpLogData(char *pData, int dataLen)
509 {
510         const char      *szData = (const char*)pData;
511         char            ch = 0;
512         int                     i = 0, j = 0, idx = 0, idx2 = 0, high = 0, low = 0, temp = 0;
513
514         char            buf[LOG_PRINT_LINE_MAX + 2]                     = {0};
515         char            buf2[(LOG_PRINT_LINE_MAX + 2) * 3]      = {0};
516         char            buf_out[sizeof(buf) + sizeof(buf2) + 1] = {0};
517
518
519         if (dataLen > LOG_BUFFER_COUNT_MAX)
520         {
521                 dataLen = LOG_BUFFER_COUNT_MAX;
522         }
523
524         // 16 characters by 20 line are proper. // too many logs decrease performance.
525 //      if (dataLen > 16*20)
526 //              dataLen = 16*20;
527
528         AppLog("------------------------------------------");
529
530         while (i < (int)dataLen)
531         {
532                 ch      = szData[i];
533
534                 /* make ascii table */
535                 if (ch >= 32 && ch <= 128)
536                 {
537                         buf[idx++]      = ch;
538                 }
539                 else
540                         buf[idx++]      = '.';
541
542                 // make binary table
543                 high = (ch & 0xf0)>>4;
544                 low = ch & 0x0f;
545
546                 buf2[idx2++]    = LogChangeHexToStr(high);
547                 buf2[idx2++]    = LogChangeHexToStr(low);
548                 buf2[idx2++]    = ' ';
549
550                 if (idx >= LOG_PRINT_LINE_MAX)
551                 {
552                         memcpy(buf_out, buf2, idx2);
553
554                         buf_out[idx2++] = ' ';
555                         buf_out[idx2++] = ' ';
556
557                         memcpy(buf_out + idx2, buf, idx);
558                         buf_out[idx2+idx]       = '\0';
559
560                         idx             = 0;
561                         idx2    = 0;
562
563                         AppLog("%s\n", buf_out);
564                 }
565
566                 i++;
567         }
568
569         // last line
570         if (idx > 0)
571         {
572                 memcpy(buf_out, buf2, idx2);
573                 temp    = idx2;
574
575                 for (j = 0; j < (LOG_PRINT_LINE_MAX * 3) - temp; j++)
576                 {
577                         buf_out[idx2++] = ' ';
578                 }
579
580                 buf_out[idx2++] = ' ';
581                 buf_out[idx2++] = ' ';
582
583                 memcpy(buf_out+idx2, buf, idx);
584                 buf_out[idx2+idx]       = '\0';
585
586                 AppLog("%s\n", buf_out);
587         }
588
589         AppLog("------------------------------------------");
590
591         return TRUE;
592 }
593
594 char
595 InstallerUtil::LogChangeHexToStr(int hex)
596 {
597         char ch = '0';
598
599         const static char       hexValues[]     = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 0};
600
601
602         if (hex >= 0 && hex <= 0x0F)
603         {
604                 ch      = hexValues[hex];
605         }
606         else
607         {
608                 AppLog("LogChangeHexToStr: Error! [Hex Val: %d]\n", hex);
609         }
610
611         return ch;
612 }
613
614 bool
615 InstallerUtil::CreateLog(const String& logFile)
616 {
617         File file;
618
619         result r = file.Construct(logFile, "w");
620         if (IsFailed(r))
621         {
622                 return false;
623         }
624
625         return true;
626 }
627
628 bool
629 InstallerUtil::AppendLog(const char* pFunction, int lineNumber, bool fatal, const char* pFormat, ...)
630 {
631         File file;
632
633         InstallerManager *pManager = InstallerManager::GetInstance();
634         if (pManager == null)
635         {
636                 return false;
637         }
638
639         if (pManager->IsFileLogOn() == false)
640         {
641                 return true;
642         }
643
644         String logFile = pManager->GetLogFilePath();
645         result r = file.Construct(logFile, "a");
646         if (IsFailed(r))
647         {
648                 return false;
649         }
650
651         va_list args;
652         va_start(args, pFormat);
653         const int bufSize = 1024;
654         char logs[bufSize+1] = {0};
655         char logs2[bufSize+1] = {0};
656         if (fatal == false)
657         {
658                 snprintf(logs, bufSize, "     | %s (%d). > %s", (char*)pFunction, lineNumber, pFormat);
659         }
660         else
661         {
662                 snprintf(logs, bufSize, "[TRY]| %s (%d). > %s", (char*)pFunction, lineNumber, pFormat);
663         }
664
665         vsnprintf(logs2, bufSize, logs, args);
666         int length = strlen(logs2);
667         logs2[length] = '\n';
668
669         r = file.Write(logs2, length+1);
670         if (IsFailed(r))
671         {
672                 return false;
673         }
674         va_end(args);
675
676         return true;
677 }
678
679 bool
680 InstallerUtil::PrintLog(const String& logFile)
681 {
682         InstallerManager *pManager = InstallerManager::GetInstance();
683         if (pManager == null)
684         {
685                 return false;
686         }
687
688         if (pManager->IsFileLogOn() == false)
689         {
690                 return true;
691         }
692
693         File file;
694         FileAttributes attribute;
695
696         result r = File::GetAttributes(logFile, attribute);
697         if (IsFailed(r))
698         {
699                 return false;
700         }
701
702         int bufSize = 4096;
703         std::unique_ptr<char[]> pBuf(new (std::nothrow) char[bufSize]);
704         if (pBuf == null)
705         {
706                 return false;
707         }
708
709         r = file.Construct(logFile, "r");
710         if (IsFailed(r))
711         {
712                 return false;
713         }
714
715         int readBytes = 0;
716         do
717         {
718                 memset(pBuf.get(), 0, bufSize);
719                 readBytes = file.Read(pBuf.get(), bufSize);
720                 if (readBytes > 0)
721                 {
722                         fprintf(stderr, "%s", pBuf.get());
723                 }
724         }
725         while (readBytes > 0);
726
727         return true;
728 }