Fixed typo in launcher_TC
[platform/core/dotnet/launcher.git] / NativeLauncher / util / utils.cc
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <dirent.h>
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <limits.h>
22 #include <strings.h>
23 #include <pkgmgr_installer_info.h>
24 #include <sys/smack.h>
25 #include <sys/prctl.h>
26 #include <openssl/sha.h>
27
28 #include <cstdlib>
29 #include <cstring>
30 #include <algorithm>
31 #include <unordered_map>
32 #include <vector>
33 #include <iterator>
34 #include <fstream>
35 #include <sstream>
36 #include <map>
37 #include <iomanip>
38
39 #include "log.h"
40 #include "utils.h"
41 #include "path_manager.h"
42
43 static bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffset, int length)
44 {
45         return static_cast<int>(a.length()) - length >= aOffset &&
46                 static_cast<int>(b.length()) - length >= bOffset &&
47                 std::equal(b.begin() + bOffset, b.begin() + bOffset + length, a.begin() + aOffset,
48                         [](unsigned char a, unsigned char b)
49                         { return std::tolower(a) == std::tolower(b); });
50 }
51
52 bool isManagedAssembly(const std::string& fileName)
53 {
54         return (iCompare(fileName, fileName.size()-4, ".dll", 0, 4) ||
55                         iCompare(fileName, fileName.size()-4, ".exe", 0, 4)) &&
56                         !isNativeImage(fileName);
57 }
58
59 bool isNativeImage(const std::string& fileName)
60 {
61         return iCompare(fileName, fileName.size()-7, ".ni", 0, 3);
62 }
63
64 std::string concatPath(const std::string& path1, const std::string& path2)
65 {
66         std::string path(path1);
67         if (path.back() == PATH_SEPARATOR) {
68                 path.append(path2);
69         } else {
70                 path += PATH_SEPARATOR;
71                 path.append(path2);
72         }
73
74         return path;
75 }
76
77 void splitPath(const std::string& path, std::vector<std::string>& out)
78 {
79         std::istringstream ss(path);
80         std::string token;
81
82         while (std::getline(ss, token, ':')) {
83                 out.push_back(token);
84         }
85 }
86
87 std::string getAbsolutePath(const std::string& path)
88 {
89         std::string absPath;
90         char *realPath = realpath(path.c_str(), NULL);
91         if (realPath) {
92                 absPath.assign(realPath);
93                 free(realPath);
94         }
95
96         return absPath;
97 }
98
99 std::string getRootPath(const std::string& pkgId)
100 {
101         int ret = 0;
102         char *path = 0;
103         std::string rootPath;
104
105         pkgmgrinfo_pkginfo_h pkg_handle;
106         ret = pkgmgrGetPkgInfo(pkgId, &pkg_handle);
107         if (ret != 0) {
108                 return rootPath;
109         }
110
111         ret = pkgmgrinfo_pkginfo_get_root_path(pkg_handle, &path);
112         if (ret != PMINFO_R_OK) {
113                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
114                 return rootPath;
115         }
116         rootPath = path;
117         pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
118
119         return rootPath;
120 }
121
122 std::string getExecName(const std::string& pkgId)
123 {
124         char *exec = NULL;
125         char *appId = 0;
126         std::string execName;
127
128         pkgmgrinfo_pkginfo_h pkg_handle;
129         int ret = pkgmgrGetPkgInfo(pkgId, &pkg_handle);
130         if (ret != 0) {
131                 return execName;
132         }
133
134         ret = pkgmgrinfo_pkginfo_get_mainappid(pkg_handle, &appId);
135         if (ret != PMINFO_R_OK) {
136                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
137                 return execName;
138         }
139
140         pkgmgrinfo_appinfo_h app_handle;
141         ret = pkgmgrGetAppInfo(appId, &app_handle);
142         if (ret != 0) {
143                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
144                 return execName;
145         }
146
147         ret = pkgmgrinfo_appinfo_get_exec(app_handle, &exec);
148         if (ret != PMINFO_R_OK) {
149                 pkgmgrinfo_appinfo_destroy_appinfo(app_handle);
150                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
151                 return execName;
152         }
153         execName = std::string(exec).substr(std::string(exec).rfind('/') + 1);
154
155         pkgmgrinfo_appinfo_destroy_appinfo(app_handle);
156         pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
157
158         return execName;
159 }
160
161 std::string getAppType(const std::string& pkgId)
162 {
163         char *appId = 0;
164         char *type = 0;
165         std::string appType;
166
167         pkgmgrinfo_pkginfo_h pkg_handle;
168         int ret = pkgmgrGetPkgInfo(pkgId, &pkg_handle);
169         if (ret != 0) {
170                 return appType;
171         }
172
173         ret = pkgmgrinfo_pkginfo_get_mainappid(pkg_handle, &appId);
174         if (ret != PMINFO_R_OK) {
175                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
176                 return appType;
177         }
178
179         pkgmgrinfo_appinfo_h app_handle;
180         ret = pkgmgrGetAppInfo(appId, &app_handle);
181         if (ret != 0) {
182                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
183                 return appType;
184         }
185
186         ret = pkgmgrinfo_appinfo_get_apptype(app_handle, &type);
187         if (ret != PMINFO_R_OK) {
188                 pkgmgrinfo_appinfo_destroy_appinfo(app_handle);
189                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
190                 return appType;
191         }
192         appType = type;
193
194         pkgmgrinfo_appinfo_destroy_appinfo(app_handle);
195         pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
196
197         return appType;
198 }
199
200 std::string getMetadataValue(const std::string& pkgId, const std::string& key)
201 {
202         char *value = NULL;
203         char *appId = 0;
204         std::string metadataValue;
205
206         pkgmgrinfo_pkginfo_h pkg_handle;
207         int ret = pkgmgrGetPkgInfo(pkgId, &pkg_handle);
208         if (ret != 0) {
209                 return metadataValue;
210         }
211
212         ret = pkgmgrinfo_pkginfo_get_mainappid(pkg_handle, &appId);
213         if (ret != PMINFO_R_OK) {
214                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
215                 return metadataValue;
216         }
217
218         pkgmgrinfo_appinfo_h app_handle;
219         ret = pkgmgrGetAppInfo(appId, &app_handle);
220         if (ret != 0) {
221                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
222                 return metadataValue;
223         }
224
225         ret = pkgmgrinfo_appinfo_get_metadata_value(app_handle, key.c_str(), &value);
226         if (ret != PMINFO_R_OK) {
227                 pkgmgrinfo_appinfo_destroy_appinfo(app_handle);
228                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
229                 return metadataValue;
230         }
231         metadataValue = std::string(value);
232
233         pkgmgrinfo_appinfo_destroy_appinfo(app_handle);
234         pkgmgrinfo_pkginfo_destroy_pkginfo(pkg_handle);
235
236         return metadataValue;
237 }
238
239 bool isReadOnlyApp(const std::string& pkgId)
240 {
241         bool readOnly = false;
242         int ret = 0;
243         uid_t uid = 0;
244
245         if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
246                 _ERR("Failed to get UID");
247                 return readOnly;
248         }
249
250         pkgmgrinfo_pkginfo_h handle;
251         if (uid == 0) {
252                 ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId.c_str(), &handle);
253         } else {
254                 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, &handle);
255         }
256
257         if (ret != PMINFO_R_OK) {
258                 return readOnly;
259         }
260
261         ret = pkgmgrinfo_pkginfo_is_readonly(handle, &readOnly);
262         if (ret != PMINFO_R_OK) {
263                 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
264                 return readOnly;
265         }
266
267         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
268
269         return readOnly;
270 }
271
272 std::string getBaseName(const std::string& path)
273 {
274         auto pos = path.find_last_of(PATH_SEPARATOR);
275         if (pos != std::string::npos)
276                 return path.substr(0, pos);
277         else
278                 return std::string(".");
279         return path;
280 }
281
282 std::string replaceAll(const std::string& str, const std::string& pattern, const std::string& replace)
283 {
284         std::string result = str;
285         std::string::size_type pos = 0;
286         std::string::size_type offset = 0;
287
288         while ((pos = result.find(pattern, offset)) != std::string::npos) {
289                 result.replace(result.begin() + pos, result.begin() + pos + pattern.size(), replace);
290                 offset = pos + replace.size();
291         }
292
293         return result;
294 }
295
296 bool isFile(const std::string& path)
297 {
298         struct stat sb;
299         return lstat(path.c_str(), &sb) == 0;
300 }
301
302 bool isDirectory(const std::string& path)
303 {
304         struct stat sb;
305         if (stat(path.c_str(), &sb) != 0) {
306                 return false;
307         }
308         if (sb.st_mode & S_IFDIR) {
309                 return true;
310         } else {
311                 return false;
312         }
313 }
314
315 std::string getAssemblyNameFromPath(const std::string& path)
316 {
317         std::string ret(getFileName(path));
318
319         if (ret.find_last_of(".") == std::string::npos)
320                 return ret;
321         ret.erase(ret.find_last_of("."));
322
323         if (ret.size() > 3 && std::equal(ret.begin() + ret.size() - 3, ret.end(), ".ni"))
324                 ret.erase(ret.size() - 3);
325
326         return ret;
327 }
328
329 void addAssembliesFromDirectories(const std::vector<std::string>& directories, std::string& list)
330 {
331         std::vector<std::string> assems;
332         std::unordered_map<std::string, std::string> assemPaths;
333
334         auto reader = [&assems, &assemPaths](const std::string& path, const std::string& filename) {
335                 if (isManagedAssembly(filename) || isNativeImage(filename)) {
336                         std::string assem = getAssemblyNameFromPath(filename);
337
338                         if (assemPaths.count(assem) == 0) {
339                                 assems.push_back(assem);
340                                 assemPaths[assem] = path;
341                         } else if (isManagedAssembly(assemPaths[assem]) && isNativeImage(filename)) {
342                                 // Update only if a native image is found in the same directory.
343                                 // For example, if we have two directories = { X, Y } where X contains A.dll and
344                                 // Y contains both A.dll and A.ni.dll, always A.dll in X will be used.
345                                 if (getBaseName(assemPaths[assem]).compare(getBaseName(path)) == 0)
346                                         assemPaths[assem] = path;
347                         }
348                 }
349         };
350         for (auto& directory : directories)
351                 scanFilesInDirectory(directory, reader, 0);
352
353         if (!list.empty() && list.back() != ':')
354                 list.push_back(':');
355
356         for (auto& assem : assems)
357                 list += assemPaths[assem] + ":";
358
359         if (list.back() == ':')
360                 list.pop_back();
361 }
362
363 void scanFilesInDirectory(const std::string& directory, FileReader reader, unsigned int depth)
364 {
365         DIR *dir;
366         struct dirent* entry;
367         bool isDir;
368
369         dir = opendir(directory.c_str());
370
371         if (dir == nullptr)
372                 return;
373
374         std::vector<std::string> innerDirectories;
375
376         while ((entry = readdir(dir)) != nullptr) {
377                 isDir = false;
378                 std::string path = concatPath(directory, entry->d_name);
379                 switch (entry->d_type) {
380                         case DT_REG: break;
381                         case DT_DIR:
382                                 isDir = true;
383                                 break;
384                         // symlink is added to the list even if there is no original file.
385                         // It used to remove broken symlinks related to TAC
386                         case DT_LNK:
387                                 break;
388                         case DT_UNKNOWN:
389                                 continue;
390                         default:
391                                 continue;
392                 }
393                 if (!isDir)
394                         reader(path, entry->d_name);
395                 else if (depth > 0 && strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
396                         innerDirectories.push_back(path);
397         }
398
399         if (depth > 0)
400                 for (auto& d : innerDirectories)
401                         scanFilesInDirectory(d, reader, depth - 1);
402
403         closedir(dir);
404 }
405
406 void copySmackAndOwnership(const std::string& fromPath, const std::string& toPath, bool isSymlink)
407 {
408         char* label = NULL;
409         struct stat info;
410
411         if (isSymlink) {
412                 // change smack label for symbolic link.
413                 if (smack_lgetlabel(fromPath.c_str(), &label, SMACK_LABEL_ACCESS) == 0) {
414                         if (smack_lsetlabel(toPath.c_str(), label, SMACK_LABEL_ACCESS) < 0) {
415                                 fprintf(stderr, "Fail to set smack label\n");
416                         }
417                         free(label);
418                 }
419
420                 // change owner and groups for symbolic link.
421                 if (!lstat(fromPath.c_str(), &info)) {
422                         if (lchown(toPath.c_str(), info.st_uid, info.st_gid) == -1)
423                                 fprintf(stderr, "Failed to change owner and group name\n");
424                 }
425         } else {
426                 // change smack label
427                 if (smack_getlabel(fromPath.c_str(), &label, SMACK_LABEL_ACCESS) == 0) {
428                         if (smack_setlabel(toPath.c_str(), label, SMACK_LABEL_ACCESS) < 0) {
429                                 fprintf(stderr, "Fail to set smack label\n");
430                         }
431                         free(label);
432                 }
433
434                 // change owner and groups for generated ni file.
435                 if (!stat(fromPath.c_str(), &info)) {
436                         if (chown(toPath.c_str(), info.st_uid, info.st_gid) == -1)
437                                 fprintf(stderr, "Failed to change owner and group name\n");
438                 }
439         }
440 }
441
442 static bool setOwnership(const bf::path& path, uid_t uid, gid_t gid)
443 {
444         int fd = open(path.c_str(), O_RDONLY);
445         if (fd < 0) {
446                 _ERR("Can't open directory: %s", path.c_str());
447                 return false;
448         }
449         int ret = fchown(fd, uid, gid);
450         close(fd);
451         if (ret != 0) {
452                 _ERR("Failed to change owner of: %s", path.c_str());
453                 return false;
454         }
455         return true;
456 }
457
458 static bool setDirPermissions(const bf::path& path, bf::perms permissions)
459 {
460         bs::error_code error;
461         bf::permissions(path, permissions, error);
462         if (error) {
463                 _ERR("Failed to set permissions for directory: %s, %s", path.c_str(), error.message().c_str());
464                 return false;
465         }
466         return true;
467 }
468
469 static bool setDirOwnershipAndPermissions(const bf::path& path, bf::perms permissions, uid_t uid, gid_t gid)
470 {
471         if (!setOwnership(path, uid, gid)) {
472                 _ERR("Failed to change owner: %s, (uid: %d, gid: %d)", path.c_str(), uid, gid);
473                 return false;
474         }
475         if (!setDirPermissions(path, permissions)) {
476                 _ERR("Failed to change permission: %s, (%d)", path.c_str(), permissions);
477                 return false;
478         }
479         return true;
480 }
481
482 static bool copyOwnershipAndPermissions(const bf::path& path, const bf::path& path2)
483 {
484         if (!exist(path)) {
485                 _ERR("Failed to copy ownership and permissions from %s to %s", path.c_str(), path2.c_str());
486                 return false;
487         }
488         bf::perms permissions = bf::status(path).permissions();
489         struct stat stats;
490         if (stat(path.c_str(), &stats) != 0) {
491                 return false;
492         }
493         if (!setDirOwnershipAndPermissions(path2, permissions, stats.st_uid, stats.st_gid)) {
494                 _ERR("Failed to copy ownership and permissions from %s to %s", path.c_str(), path2.c_str());
495                 return false;
496         }
497         return true;
498 }
499
500 bool exist(const bf::path& path)
501 {
502         bs::error_code error;
503         int ret = bf::exists(path, error);
504         if (error) {
505                 if ((error.value() != bs::errc::success) && (error.value() != bs::errc::no_such_file_or_directory)) {
506                         _ERR("Failed to check %s exists : %s", path.c_str(), error.message().c_str());
507                 }
508         }
509         return ret;
510 }
511
512 bool createDir(const bf::path& path)
513 {
514         if (exist(path)) {
515                 return true;
516         }
517         bs::error_code error;
518         bf::create_directories(path, error);
519         if (error) {
520                 _ERR("Failed to create directory: %s", error.message().c_str());
521                 return false;
522         }
523         return true;
524 }
525
526 bool copyDir(const bf::path& path1, const bf::path& path2, FSFlag flags)
527 {
528         try {
529                 // Check whether the function call is valid
530                 if (!exist(path1) || !bf::is_directory(path1)) {
531                         _ERR("Source directory %s does not exist or is not a directory", path1.c_str());
532                         return false;
533                 }
534                 if (!exist(path2)) {
535                         // Create the destination directory
536                         if (!createDir(path2)) {
537                                 _ERR("Unable to create destination directory %s", path2.c_str());
538                                 return false;
539                         }
540                         if (flags & FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS) {
541                                 copyOwnershipAndPermissions(path1, path2);
542                         }
543                 } else {
544                         if (!(flags & (FS_MERGE_SKIP | FS_MERGE_OVERWRITE))) {
545                                 _ERR("Destination directory %s already exists", path2.c_str());
546                                 return false;
547                         }
548                         if (flags & (FS_MERGE_OVERWRITE | FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS)) {
549                                 copyOwnershipAndPermissions(path1, path2);
550                         }
551                 }
552         } catch (const bf::filesystem_error& error) {
553                 _ERR("Failed to copy directory: %s", error.what());
554                 return false;
555         }
556
557         // Iterate through the source directory
558         for (bf::directory_iterator file(path1); file != bf::directory_iterator(); ++file) {
559                 try {
560                         bf::path current(file->path());
561                         bf::path target = path2 / current.filename();
562                         if (bf::is_symlink(symlink_status(current))) {
563                                 if ((flags & (FS_MERGE_SKIP | FS_MERGE_OVERWRITE)) && exist(target)) {
564                                         continue;
565                                 }
566                                 bs::error_code error;
567                                 bf::copy_symlink(current, target, error);
568                                 if (error) {
569                                         _ERR("Failed to copy symlink: %s, %s", current.c_str(), error.message().c_str());
570                                         return false;
571                                 }
572                         } else if (bf::is_directory(current)) {
573                                 // Found directory: Recursion
574                                 if (!copyDir(current, target, flags)) {
575                                         return false;
576                                 }
577                         } else {
578                                 if ((flags & FS_MERGE_SKIP) && exist(target)) {
579                                         continue;
580                                 }
581                                 bf::path destination = target;
582                                 if (flags & FS_COMMIT_COPY_FILE) {
583                                         destination = bf::unique_path(target.parent_path() / "%%%%-%%%%-%%%%-%%%%");
584                                 }
585                                 if (flags & FS_MERGE_OVERWRITE) {
586                                         bf::copy_file(current, destination, bf::copy_option::overwrite_if_exists);
587                                 } else {
588                                         bf::copy_file(current, destination);
589                                 }
590                                 if (flags & FS_PRESERVE_OWNERSHIP_AND_PERMISSIONS) {
591                                         copyOwnershipAndPermissions(current, destination);
592                                 }
593                                 if (flags & FS_COMMIT_COPY_FILE) {
594                                         if (flags & FS_MERGE_OVERWRITE) {
595                                                 bf::remove(target);
596                                         }
597                                         bf::rename(destination, target);
598                                 }
599                         }
600                 } catch (const bf::filesystem_error& error) {
601                         _ERR("Failed to copy directory: %s", error.what());
602                         return false;
603                 }
604         }
605         return true;
606 }
607
608 bool copyFile(const bf::path& path1, const bf::path& path2)
609 {
610         bs::error_code error;
611         if (!exist(path1)) {
612                 return false;
613         }
614         bf::copy_file(path1, path2, bf::copy_option::overwrite_if_exists, error);
615         if (error) {
616                 _ERR("copy file %s due to error [%s]", path1.c_str(), error.message().c_str());
617                 return false;
618         }
619         return true;
620 }
621
622 bool moveFile(const bf::path& path1, const bf::path& path2)
623 {
624         if (!exist(path1) || exist(path2)) {
625                 return false;
626         }
627         bs::error_code error;
628         bf::rename(path1, path2, error);
629         if (error) {
630                 _ERR("Cannot move file: %s. Will copy/remove... with error [%s]", path1.c_str(), error.message().c_str());
631                 bf::copy_file(path1, path2, bf::copy_option::overwrite_if_exists, error);
632                 if (error) {
633                         _ERR("Cannot copy file %s due to error [%s]", path1.c_str(), error.message().c_str());
634                         return false;
635                 }
636                 bf::remove_all(path1, error);
637                 if (error) {
638                         _ERR("Cannot remove old file when coping: %s with error [%s]", path1.c_str(), error.message().c_str());
639                         return false;
640                 }
641         }
642         return true;
643 }
644
645 bool removeFile(const bf::path& path)
646 {
647         if (!exist(path)) {
648                 return true;
649         }
650         bs::error_code error;
651         bf::remove(path, error);
652         if (error) {
653                 _ERR("Cannot remove: %s, %s", path.c_str(), error.message().c_str());
654                 return false;
655         }
656         return true;
657 }
658
659 bool removeAll(const bf::path& path)
660 {
661         if (!exist(path)) {
662                 return true;
663         }
664         bs::error_code error;
665         bf::remove_all(path, error);
666         if (error) {
667                 _ERR("Cannot remove: %s, %s", path.c_str(), error.message().c_str());
668                 return false;
669         }
670         return true;
671 }
672
673 void setCmdName(const std::string& name)
674 {
675         #define PRC_NAME_LENGTH         16
676
677         char processName[PRC_NAME_LENGTH] = {0, };
678
679         if (name.empty())
680                 return;
681
682         memset(processName, '\0', PRC_NAME_LENGTH);
683         snprintf(processName, PRC_NAME_LENGTH, "%s", name.c_str());
684         prctl(PR_SET_NAME, processName);
685 }
686
687 std::string getFileName(const std::string& path)
688 {
689         std::string ret(path);
690         size_t index = ret.find_last_of(PATH_SEPARATOR);
691         return index == std::string::npos ? ret : ret.substr(index + 1);
692 }
693
694 std::string SHA256(const std::string& path)
695 {
696         std::string output = "";
697         FILE *file = fopen(path.c_str(), "rb");
698         if (!file) {
699                 return output;
700         }
701
702         unsigned char hash[SHA256_DIGEST_LENGTH];
703         SHA256_CTX sha256;
704         SHA256_Init(&sha256);
705         int bytesRead = 0;
706         const int bufSize = 32768;
707         char *buffer = (char*)malloc(bufSize);
708         if (!buffer) {
709                 fclose(file);
710                 return output;
711         }
712
713         while ((bytesRead = fread(buffer, 1, bufSize, file))) {
714                 SHA256_Update(&sha256, buffer, bytesRead);
715         }
716         SHA256_Final(hash, &sha256);
717
718         std::stringstream ss;
719         for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
720                 ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
721         }
722         output = ss.str();
723
724         fclose(file);
725         free(buffer);
726
727         return output;
728 }
729
730 int pkgmgrGetPkgInfo(const std::string& pkgId, pkgmgrinfo_pkginfo_h* handle)
731 {
732         uid_t uid = 0;
733         int ret = 0;
734
735         if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
736                 _ERR("Failed to get UID");
737                 return -1;
738         }
739
740         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, handle);
741         if (ret != PMINFO_R_OK) {
742                 _ERR("Failed to get pkginfo (%d)", ret);
743                 return -1;
744         }
745
746         return 0;
747 }
748
749 int pkgmgrGetAppInfo(const std::string& appId, pkgmgrinfo_appinfo_h* handle)
750 {
751         uid_t uid = 0;
752         int ret = 0;
753
754         if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
755                 _ERR("Failed to get UID");
756                 return -1;
757         }
758
759         ret = pkgmgrinfo_appinfo_get_usr_appinfo(appId.c_str(), uid, handle);
760         if (ret != PMINFO_R_OK) {
761                 _ERR("Failed to get appinfo (%d)", ret);
762                 return -1;
763         }
764
765         return 0;
766 }
767
768 int pkgmgrMDFilterForeach(pkgmgrinfo_appinfo_metadata_filter_h handle,
769                                          pkgmgrinfo_app_list_cb app_cb,
770                                          void *user_data)
771 {
772         uid_t uid = 0;
773         int ret = 0;
774
775         if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
776                 _ERR("Failed to get UID");
777                 return -1;
778         }
779
780
781         ret = pkgmgrinfo_appinfo_usr_metadata_filter_foreach(handle, app_cb, user_data, uid);
782         if (ret != PMINFO_R_OK) {
783                 _ERR("Failed to execute the metadata filter query (%d)", ret);
784                 return -1;
785         }
786
787         return 0;
788 }
789