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 CompatibilityManager.cpp
19 * @brief This is the implementation file for %CompatibilityManager class.
23 #include <sys/mount.h>
26 #include <unique_ptr.h>
29 #include <FIoDirectory.h>
30 #include <FBase_StringConverter.h>
31 #include <FSys_EnvironmentImpl.h>
33 #include "InstallerDefs.h"
34 #include "CompatibilityManager.h"
35 #include "SmackManager.h"
37 using namespace Tizen::App;
38 using namespace Tizen::Base;
39 using namespace Tizen::Io;
40 using namespace Tizen::System;
51 char srcPath[PATH_MAX];
52 char destPath[PATH_MAX];
57 char destPath[PATH_MAX];
61 CompatibilityManager::CompatibilityManager(void)
66 CompatibilityManager::~CompatibilityManager(void)
71 CompatibilityManager::Construct(InstallationContext* pContext)
73 __pContext = pContext;
79 CompatibilityManager::PrepareDataCaging(const String& rootPath, const PackageId& packageId)
85 std::unique_ptr<char[]> pRootPath(_StringConverter::CopyToCharArrayN(rootPath));
86 TryCatch(pRootPath != null, res = false, "The memory is insufficient.");
88 res = CleanDirectories(rootPath, packageId);
89 TryCatch(res == true, , "CleanDirectories(%ls, %ls) failed.", rootPath.GetPointer(), packageId.GetPointer());
91 pCwd = get_current_dir_name();
92 TryCatch(pCwd != null, res = false, "get_current_dir_name() failed. [errno = %d(%s)]", errno, strerror(errno));
96 result = chdir(pRootPath.get());
97 TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pRootPath.get(), errno, strerror(errno));
99 res = CreateOspInternalDirectories(rootPath, packageId);
100 TryCatch(res == true, , "CreateOspInternalDirectories(%ls, %ls) failed.", rootPath.GetPointer(), packageId.GetPointer());
102 res = CreateSlpDirectories();
103 TryCatch(res == true, , "CreateSlpDirectories() failed.");
105 res = CreateSymbolicLink();
106 TryCatch(res == true, , "CreateSymbolicLink() failed.");
108 result = chdir(pCwd);
109 TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pCwd, errno, strerror(errno));
119 AppLog("[Tizen::Io] result = [%s]", res?"true":"false");
125 CompatibilityManager::FinalizeDataCaging(const String& rootPath)
130 static const struct _PathInfo mountPath[] =
140 { "./opt/var/kdb/db" },
141 { "./opt/storage/sdcard" },
147 { "./sys/kernel/debug" },
158 { "./Storagecard/Media" },
161 { "./HomeExt/Share" },
162 { "./HomeExt/Share2" },
166 std::unique_ptr<char[]> pAppRootPath(_StringConverter::CopyToCharArrayN(rootPath));
167 TryReturn(pAppRootPath, false, "The memory is insufficient.");
169 res = chdir(pAppRootPath.get());
170 TryReturn(res == 0, false, "chdir() failed. (%d, %s), path = [%ls]", errno, strerror(errno), rootPath.GetPointer());
172 for (i = 0; i < sizeof(mountPath) / sizeof(struct _PathInfo); ++i)
174 res = umount2(mountPath[i].destPath, MNT_DETACH);
175 TryReturn((res == 0) || (errno == EINVAL) || (errno == ENOENT), false, "umount2() failed. (%d, %s), path = [%s]", errno, strerror(errno), mountPath[i].destPath);
178 char* pPackageId = strrchr(pAppRootPath.get(), '/');
179 char mountFlag[PATH_MAX] = {0, };
181 sprintf(mountFlag, "/tmp/osp-compat/mount/internal/%s", ++pPackageId);
182 res = unlink(mountFlag);
183 if ((res == -1) && (errno != ENOENT))
185 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
189 memset(mountFlag, 0, PATH_MAX);
190 sprintf(mountFlag, "/tmp/osp-compat/mount/external/%s", pPackageId);
191 res = unlink(mountFlag);
192 if ((res == -1) && (errno != ENOENT))
194 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
198 AppLog("[Tizen::Io] FinalizeDataCaging() succeeded, rootPath: %ls", rootPath.GetPointer());
203 CompatibilityManager::CleanDirectories(const String& rootPath, const PackageId& packageId)
206 char removeCmd[PATH_MAX] = {0, };
208 String ospSharePkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
209 ospSharePkgIdPath.Append(L"share/");
210 ospSharePkgIdPath.Append(packageId);
212 String ospShare2PkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
213 ospShare2PkgIdPath.Append(L"share2/");
214 ospShare2PkgIdPath.Append(packageId);
216 sprintf(removeCmd, "rm -rf %ls", ospSharePkgIdPath.GetPointer());
217 AppLog("removeCmd = [%s]", removeCmd);
219 ret = system(removeCmd);
220 TryReturn(ret != -1, false, "system(%s) failed.", removeCmd);
222 memset(removeCmd, 0, PATH_MAX);
224 sprintf(removeCmd, "rm -rf %ls", ospShare2PkgIdPath.GetPointer());
225 AppLog("removeCmd = [%s]", removeCmd);
227 ret = system(removeCmd);
228 TryReturn(ret != -1, false, "system(%s) failed.", removeCmd);
230 AppLog("[Tizen::Io] CleanDirectories() succeeded, rootPath: %ls", rootPath.GetPointer());
235 CompatibilityManager::LinkOspSharePath(const String& rootPath, const PackageId& packageId)
237 const char* pOspCompatSharedPath = "/opt/usr/share/.osp-compat/\0";
239 std::unique_ptr<char[]> pRootPath(_StringConverter::CopyToCharArrayN(rootPath));
240 TryReturn(pRootPath, false, "The memory is insufficient.");
242 std::unique_ptr<char[]> pPackageId(_StringConverter::CopyToCharArrayN(packageId));
243 TryReturn(pPackageId, false, "The memory is insufficient.");
245 char ospAppSharePath[PATH_MAX] = {0, };
246 char ospAppShare2Path[PATH_MAX] = {0, };
247 char ospSharePkgIdPath[PATH_MAX] = {0, };
248 char ospShare2PkgIdPath[PATH_MAX] = {0, };
250 strncpy(ospAppSharePath, pRootPath.get(), strlen(pRootPath.get()));
251 strncat(ospAppSharePath, "/shared/data", 12);
253 strncpy(ospSharePkgIdPath, pOspCompatSharedPath, strlen(pOspCompatSharedPath));
254 strncat(ospSharePkgIdPath, "share/", 6);
255 strncat(ospSharePkgIdPath, pPackageId.get(), strlen(pPackageId.get()));
257 strncpy(ospAppShare2Path, pRootPath.get(), strlen(pRootPath.get()));
258 strncat(ospAppShare2Path, "/shared/trusted", 15);
260 strncpy(ospShare2PkgIdPath, pOspCompatSharedPath, strlen(pOspCompatSharedPath));
261 strncat(ospShare2PkgIdPath, "share2/", 7);
262 strncat(ospShare2PkgIdPath, pPackageId.get(), strlen(pPackageId.get()));
264 unlink(ospSharePkgIdPath);
265 unlink(ospShare2PkgIdPath);
267 InstallerUtil::CreateSymlink(ospAppSharePath, ospSharePkgIdPath, false);
268 InstallerUtil::CreateSymlink(ospAppShare2Path, ospShare2PkgIdPath, false);
274 CompatibilityManager::PrepareVirtualRoot(const Tizen::Base::String& rootPath, const Tizen::App::PackageId& packageId)
276 String virtualRoot = GetVirtualRootPath(rootPath);
277 TryReturn(virtualRoot.IsEmpty() == false, false, "GetVirtualRootPath(%ls) failed.", rootPath.GetPointer());
279 result r = E_SUCCESS;
283 String virtualRootPath = rootPath + DIR_DATA + L"/" + virtualRoot;
285 std::unique_ptr<char[]> pVirtualRootPath(_StringConverter::CopyToCharArrayN(virtualRootPath));
286 TryCatch(pVirtualRootPath != null, res = false, "The memory is insufficient.");
288 pCwd = get_current_dir_name();
289 TryCatch(pCwd != null, res = false, "get_current_dir_name() failed. [errno = %d(%s)]", errno, strerror(errno));
291 // appRoot/virtual-root
292 if (File::IsFileExist(virtualRootPath) == false)
294 r = Directory::Create(virtualRootPath, true);
295 TryCatch(!IsFailed(r), res = false, "Directory::Create() failed");
298 result = chdir(pVirtualRootPath.get());
299 TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pVirtualRootPath.get(), errno, strerror(errno));
301 res = CreateVirtualRootDirectories();
302 TryCatch(res == true, , "CreateVirtualRootDirectories() failed.");
304 res = CreateSymbolicLink();
305 TryCatch(res == true, , "CreateSymbolicLink() failed.");
307 result = chdir(pCwd);
308 TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pCwd, errno, strerror(errno));
316 AppLog("[Tizen::Io] result = [%s]", res?"true":"false");
322 CompatibilityManager::FinalizeVirtualRoot(const String& rootPath, const PackageId& packageId)
324 String virtualRootPath = GetVirtualRootPath(rootPath);
325 TryReturn(virtualRootPath.IsEmpty() == false, false, "GetVirtualRootPath(%ls) failed.", rootPath.GetPointer());
329 String destPath = rootPath + DIR_DATA + L"/" + virtualRootPath;
331 static const struct _PathInfo mountPath[] =
350 { "./sys/fs/cgroup/systemd" },
351 { "./sys/fs/cgroup" },
359 //{ "./opt/var/run" },
360 { "./opt/storage/sdcard" },
364 std::unique_ptr<char[]> pVirtualRootPath(_StringConverter::CopyToCharArrayN(destPath));
365 TryReturn(pVirtualRootPath, false, "The memory is insufficient.");
367 res = chdir(pVirtualRootPath.get());
368 TryReturn(res == 0, false, "chdir() failed. (%d, %s), path = [%ls]", errno, strerror(errno), destPath.GetPointer());
370 for (i = 0; i < sizeof(mountPath) / sizeof(struct _PathInfo); ++i)
372 res = umount2(mountPath[i].destPath, MNT_DETACH);
373 TryReturn((res == 0) || (errno == EINVAL) || (errno == ENOENT), false, "umount2() failed. (%d, %s), path = [%s]", errno, strerror(errno), mountPath[i].destPath);
375 AppLog("umount2(%s) is succeeded.", mountPath[i].destPath);
378 std::unique_ptr<char[]> pPackageId(_StringConverter::CopyToCharArrayN(packageId));
379 TryReturn(pPackageId, false, "The memory is insufficient.");
381 char mountFlag[PATH_MAX] = {0, };
382 sprintf(mountFlag, "/tmp/osp-compat/mount/internal/%s", pPackageId.get());
383 res = unlink(mountFlag);
384 if ((res == -1) && (errno != ENOENT))
386 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
390 memset(mountFlag, 0, PATH_MAX);
391 sprintf(mountFlag, "/tmp/osp-compat/mount/external/%s", pPackageId.get());
392 res = unlink(mountFlag);
393 if ((res == -1) && (errno != ENOENT))
395 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
399 AppLog("[Tizen::Io] FinalizeVirtualRoot() succeeded, path: %ls", destPath.GetPointer());
404 CompatibilityManager::CreateOspInternalDirectories(const String& rootPath, const PackageId& packageId)
406 result r = E_SUCCESS;
411 struct _OspDir appSubDir[] =
413 { "./shared", 0755, false },
414 { "./data/Share", 0000, true }, // mount from /opt/usr/share/.osp-compat/share/{pkgId}
415 { "./data/Share2", 0000, true }, // mount from /opt/usr/share/.osp-compat/share2/{pkgId}
416 { "./Share", 0000, false }, // mount from /opt/usr/share/.osp-compat/share
417 { "./Share2", 0000, false }, // mount from /opt/usr/share/.osp-compat/share2
418 { "./Media", 0000, false }, // mount from /opt/usr/media
419 { "./Storagecard", 0705, false },
420 { "./Storagecard/Media", 0000, false }, // mount from /opt/storage/sdcard
423 String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
424 String ospShareAppIdPath(L"share/");
425 String ospShare2AppIdPath(L"share2/");
427 r = ospShareAppIdPath.Insert(ospCompatSharedPath, 0);
428 TryReturn(!IsFailed(r), false, "String::Insert() failed. [error: %s]", GetErrorMessage(r));
430 r = ospShare2AppIdPath.Insert(ospCompatSharedPath, 0);
431 TryReturn(!IsFailed(r), false, "String::Insert() failed. [error: %s]", GetErrorMessage(r));
433 for (i = 0; i < sizeof(appSubDir) / sizeof(struct _OspDir); i++)
435 ret = mkdir(appSubDir[i].path, appSubDir[i].mode);
436 if (ret == -1 && errno != 17) // EEXIST
438 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), appSubDir[i].path, appSubDir[i].mode);
442 if (appSubDir[i].appPrivilege)
444 ret = chown(appSubDir[i].path, uid, uid);
447 AppLog("chown() failed (%s), path: %s, uid: %d", strerror(errno), appSubDir[i].path, uid);
453 SmackManager smackManager;
454 smackManager.Construct(__pContext);
455 smackManager.SetupPath(packageId, L"./Storagecard", APP_PATH_ANY_LABEL, L"_");
457 ospShareAppIdPath.Append(packageId);
459 std::unique_ptr<char[]> pOspShareAppIdPath(_StringConverter::CopyToCharArrayN(ospShareAppIdPath));
460 TryReturn(pOspShareAppIdPath, false, "The memory is insufficient.");
462 ret = mkdir(pOspShareAppIdPath.get(), 0705);
463 if (ret == -1 && errno != 17) // EEXIST
465 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), pOspShareAppIdPath.get(), 0705);
469 ret = chown(pOspShareAppIdPath.get(), uid, uid);
472 AppLog("chown() failed (%s), path: %s, uid: %d", strerror(errno), pOspShareAppIdPath.get(), uid);
476 ospShare2AppIdPath.Append(packageId);
478 std::unique_ptr<char[]> pOspShare2AppIdPath(_StringConverter::CopyToCharArrayN(ospShare2AppIdPath));
479 TryReturn(pOspShare2AppIdPath, false, "The memory is insufficient.");
481 ret = mkdir(pOspShare2AppIdPath.get(), 0705);
482 if (ret == -1 && errno != 17) // EEXIST
484 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), pOspShare2AppIdPath.get(), 0705);
488 ret = chown(pOspShare2AppIdPath.get(), uid, uid);
491 AppLog("chown() failed (%s), path: %s, uid: %d", strerror(errno), pOspShare2AppIdPath.get(), uid);
495 String appSharedDataPath(rootPath);
496 appSharedDataPath.Append(L"/shared/data");
498 String appSharedTrustedPath(rootPath);
499 appSharedTrustedPath.Append(L"/shared/trusted");
501 r = Directory::Remove(appSharedDataPath, true);
502 TryReturn(r == E_SUCCESS, false, "Directory::Remove(%ls) failed.", appSharedDataPath.GetPointer());
504 r = Directory::Remove(appSharedTrustedPath, true);
505 TryReturn(r == E_SUCCESS, false, "Directory::Remove(%ls) failed.", appSharedTrustedPath.GetPointer());
507 res = InstallerUtil::CreateSymlink(ospShareAppIdPath, L"./shared/data", false);
508 TryReturn(res == true, false, "CreateSymlink() failed, errno: %d (%s), link: ./shared/data -> %s", errno, strerror(errno), pOspShareAppIdPath.get());
510 smackManager.SetupPath(packageId, ospShareAppIdPath, APP_PATH_PUBLIC_RO);
512 res = InstallerUtil::CreateSymlink(ospShare2AppIdPath, L"./shared/trusted", false);
513 TryReturn(res == true, false, " CreateSymlink() failed, errno: %d (%s), link: ./shared/trusted -> %s", errno, strerror(errno), pOspShare2AppIdPath.get());
515 smackManager.SetupPath(packageId, ospShare2AppIdPath, APP_PATH_GROUP_RW);
517 AppLog("[Tizen::Io] CreateOspInternalDirectories() succeeded, rootPath: %ls", rootPath.GetPointer());
522 CompatibilityManager::CreateSlpDirectories(void)
526 struct _OspDir slpDir[] =
528 { "./csa", 0000, false },
529 { "./dev", 0000, false },
530 { "./etc", 0000, false },
531 { "./lib", 0000, false },
532 { "./mnt", 0000, false },
533 { "./opt", 0000, false },
534 { "./proc", 0000, false },
535 { "./sbin", 0000, false },
536 { "./smack", 0000, false },
537 { "./srv", 0000, false },
538 { "./sys", 0000, false },
539 { "./tmp", 0000, false },
540 { "./usr", 0000, false },
541 { "./var", 0000, false }
544 for (i = 0; i < sizeof(slpDir) / sizeof(struct _OspDir); i++)
546 ret = mkdir(slpDir[i].path, slpDir[i].mode);
547 if (ret == -1 && errno != 17) // EEXIST
549 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), slpDir[i].path, slpDir[i].mode);
554 AppLog("Directory[%s, 0%o] is created.", slpDir[i].path, slpDir[i].mode);
558 AppLog("[Tizen::Io] CreateSlpDirectories() succeeded.");
563 CompatibilityManager::CreateSymbolicLink(void)
565 struct _LinkDir linkDirList[] =
567 { "/opt/home", "./home" },
568 { "/opt/home/root", "./root" },
569 { "/mnt/mmc", "./sdcard" }
572 for (unsigned int i = 0; i < sizeof(linkDirList) / sizeof(struct _LinkDir); ++i)
574 InstallerUtil::CreateSymlink(linkDirList[i].srcPath, linkDirList[i].destPath, false);
577 AppLog("[Tizen::Io] CreateSymbolicLink() succeeded.");
582 CompatibilityManager::CreateVirtualRootDirectories(void)
586 struct _OspDir virtualRootDir[] =
588 { "./bin", 0000, false },
589 { "./cache", 0000, false },
590 { "./csa", 0000, false },
591 { "./data", 0000, false },
592 { "./dev", 0000, false },
593 { "./etc", 0000, false },
594 { "./lib", 0000, false },
595 { "./media", 0000, false },
596 { "./mnt", 0000, false },
597 { "./opt", 0000, false },
598 { "./proc", 0000, false },
599 { "./run", 0000, false },
600 { "./sbin", 0000, false },
601 { "./smack", 0000, false },
602 { "./srv", 0000, false },
603 { "./sys", 0000, false },
604 { "./system", 0000, false },
605 { "./tmp", 0000, false },
606 { "./usr", 0000, false },
607 { "./var", 0000, false }
610 for (i = 0; i < sizeof(virtualRootDir) / sizeof(struct _OspDir); i++)
612 ret = mkdir(virtualRootDir[i].path, virtualRootDir[i].mode);
613 if (ret == -1 && errno != 17) // EEXIST
615 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), virtualRootDir[i].path, virtualRootDir[i].mode);
620 AppLog("Directory[%s, 0%o] is created.", virtualRootDir[i].path, virtualRootDir[i].mode);
624 AppLog("[Tizen::Io] CreateVirtualRootDirectories() succeeded.");
629 CompatibilityManager::GetVirtualRootPath(const Tizen::Base::String& rootPath)
631 TryReturn(rootPath.IsEmpty() == false, L"", "rootPath is empty.");
633 String virtualRootInfoFile;
634 virtualRootInfoFile.Format(1024, L"%ls%ls", rootPath.GetPointer(), VIRTUAL_ROOT_INFO_FILE);
636 if (File::IsFileExist(virtualRootInfoFile) == false)
638 AppLog("virtualRootInfoFile[%ls] is not existed.", virtualRootInfoFile.GetPointer());
642 result r = E_SUCCESS;
644 String virtualRootPath;
646 r = file.Construct(virtualRootInfoFile, L"r");
647 TryReturn(r == E_SUCCESS, L"", "file.Construct() is failed. [%ls]", virtualRootInfoFile.GetPointer());
649 r = file.Read(virtualRootPath);
650 TryReturn(r == E_SUCCESS, L"", "file.Read() is failed. [%ls]", virtualRootInfoFile.GetPointer());
652 AppLog("virtualRootPath = [%ls]", virtualRootPath.GetPointer());
654 return virtualRootPath;