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)
65 CompatibilityManager::~CompatibilityManager(void)
70 CompatibilityManager::PrepareDataCaging(const String& rootPath, const PackageId& packageId)
76 std::unique_ptr<char[]> pRootPath(_StringConverter::CopyToCharArrayN(rootPath));
77 TryCatch(pRootPath != null, res = false, "The memory is insufficient.");
79 res = CleanDirectories(rootPath, packageId);
80 TryCatch(res == true, , "CleanDirectories(%ls, %ls) failed.", rootPath.GetPointer(), packageId.GetPointer());
82 pCwd = get_current_dir_name();
83 TryCatch(pCwd != null, res = false, "get_current_dir_name() failed. [errno = %d(%s)]", errno, strerror(errno));
87 result = chdir(pRootPath.get());
88 TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pRootPath.get(), errno, strerror(errno));
90 res = CreateOspInternalDirectories(rootPath, packageId);
91 TryCatch(res == true, , "CreateOspInternalDirectories(%ls, %ls) failed.", rootPath.GetPointer(), packageId.GetPointer());
93 res = CreateSlpDirectories();
94 TryCatch(res == true, , "CreateSlpDirectories() failed.");
96 res = CreateSymbolicLink();
97 TryCatch(res == true, , "CreateSymbolicLink() failed.");
100 TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pCwd, errno, strerror(errno));
110 AppLog("[Tizen::Io] result = [%s]", res?"true":"false");
116 CompatibilityManager::FinalizeDataCaging(const String& rootPath)
121 static const struct _PathInfo mountPath[] =
131 { "./opt/var/kdb/db" },
132 { "./opt/storage/sdcard" },
138 { "./sys/kernel/debug" },
149 { "./Storagecard/Media" },
152 { "./HomeExt/Share" },
153 { "./HomeExt/Share2" },
157 std::unique_ptr<char[]> pAppRootPath(_StringConverter::CopyToCharArrayN(rootPath));
158 TryReturn(pAppRootPath, false, "The memory is insufficient.");
160 res = chdir(pAppRootPath.get());
161 TryReturn(res == 0, false, "chdir() failed. (%d, %s), path = [%ls]", errno, strerror(errno), rootPath.GetPointer());
163 for (i = 0; i < sizeof(mountPath) / sizeof(struct _PathInfo); ++i)
165 res = umount2(mountPath[i].destPath, MNT_DETACH);
166 TryReturn((res == 0) || (errno == EINVAL) || (errno == ENOENT), false, "umount2() failed. (%d, %s), path = [%s]", errno, strerror(errno), mountPath[i].destPath);
169 char* pPackageId = strrchr(pAppRootPath.get(), '/');
170 char mountFlag[PATH_MAX] = {0, };
172 sprintf(mountFlag, "/tmp/osp-compat/mount/internal/%s", ++pPackageId);
173 res = unlink(mountFlag);
174 if ((res == -1) && (errno != ENOENT))
176 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
180 memset(mountFlag, 0, PATH_MAX);
181 sprintf(mountFlag, "/tmp/osp-compat/mount/external/%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 AppLog("[Tizen::Io] FinalizeDataCaging() succeeded, rootPath: %ls", rootPath.GetPointer());
194 CompatibilityManager::CleanDirectories(const String& rootPath, const PackageId& packageId)
197 char removeCmd[PATH_MAX] = {0, };
199 String ospSharePkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
200 ospSharePkgIdPath.Append(L"share/");
201 ospSharePkgIdPath.Append(packageId);
203 String ospShare2PkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
204 ospShare2PkgIdPath.Append(L"share2/");
205 ospShare2PkgIdPath.Append(packageId);
207 sprintf(removeCmd, "rm -rf %ls", ospSharePkgIdPath.GetPointer());
208 AppLog("removeCmd = [%s]", removeCmd);
210 ret = system(removeCmd);
211 TryReturn(ret != -1, false, "system(%s) failed.", removeCmd);
213 memset(removeCmd, 0, PATH_MAX);
215 sprintf(removeCmd, "rm -rf %ls", ospShare2PkgIdPath.GetPointer());
216 AppLog("removeCmd = [%s]", removeCmd);
218 ret = system(removeCmd);
219 TryReturn(ret != -1, false, "system(%s) failed.", removeCmd);
221 AppLog("[Tizen::Io] CleanDirectories() succeeded, rootPath: %ls", rootPath.GetPointer());
226 CompatibilityManager::LinkOspSharePath(const String& rootPath, const PackageId& packageId)
229 const char* pOspCompatSharedPath = "/opt/usr/share/.osp-compat/\0";
231 std::unique_ptr<char[]> pRootPath(_StringConverter::CopyToCharArrayN(rootPath));
232 TryReturn(pRootPath, false, "The memory is insufficient.");
234 std::unique_ptr<char[]> pPackageId(_StringConverter::CopyToCharArrayN(packageId));
235 TryReturn(pPackageId, false, "The memory is insufficient.");
237 char ospAppSharePath[PATH_MAX] = {0, };
238 char ospAppShare2Path[PATH_MAX] = {0, };
239 char ospSharePkgIdPath[PATH_MAX] = {0, };
240 char ospShare2PkgIdPath[PATH_MAX] = {0, };
242 strncpy(ospAppSharePath, pRootPath.get(), strlen(pRootPath.get()));
243 strncat(ospAppSharePath, "/shared/data", 12);
245 strncpy(ospSharePkgIdPath, pOspCompatSharedPath, strlen(pOspCompatSharedPath));
246 strncat(ospSharePkgIdPath, "share/", 6);
247 strncat(ospSharePkgIdPath, pPackageId.get(), strlen(pPackageId.get()));
249 strncpy(ospAppShare2Path, pRootPath.get(), strlen(pRootPath.get()));
250 strncat(ospAppShare2Path, "/shared/trusted", 15);
252 strncpy(ospShare2PkgIdPath, pOspCompatSharedPath, strlen(pOspCompatSharedPath));
253 strncat(ospShare2PkgIdPath, "share2/", 7);
254 strncat(ospShare2PkgIdPath, pPackageId.get(), strlen(pPackageId.get()));
256 unlink(ospSharePkgIdPath);
257 unlink(ospShare2PkgIdPath);
259 SmackManager smackManager;
261 ret = symlink(ospAppSharePath, ospSharePkgIdPath);
262 smackManager.AddLabelDir(L"_", ospSharePkgIdPath);
264 ret = symlink(ospAppShare2Path, ospShare2PkgIdPath);
265 smackManager.AddLabelDir(L"_", ospShare2PkgIdPath);
271 CompatibilityManager::PrepareVirtualRoot(const Tizen::Base::String& rootPath, const Tizen::App::PackageId& packageId)
273 result r = E_SUCCESS;
277 String destPath = rootPath + DIR_VIRTUAL_ROOT;
278 SmackManager smackManager;
280 std::unique_ptr<char[]> pVirtualRootPath(_StringConverter::CopyToCharArrayN(destPath));
281 TryCatch(pVirtualRootPath != null, res = false, "The memory is insufficient.");
283 pCwd = get_current_dir_name();
284 TryCatch(pCwd != null, res = false, "get_current_dir_name() failed. [errno = %d(%s)]", errno, strerror(errno));
286 // appRoot/virtual-root
287 if (File::IsFileExist(destPath) == false)
289 r = Directory::Create(destPath, false);
290 TryCatch(!IsFailed(r), res = false, "Directory::Create() failed");
293 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
295 result = chdir(pVirtualRootPath.get());
296 TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pVirtualRootPath.get(), errno, strerror(errno));
298 res = CreateVirtualRootDirectories();
299 TryCatch(res == true, , "CreateVirtualRootDirectories() failed.");
301 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
303 res = CreateSymbolicLink();
304 TryCatch(res == true, , "CreateSymbolicLink() failed.");
306 result = chdir(pCwd);
307 TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pCwd, errno, strerror(errno));
315 AppLog("[Tizen::Io] result = [%s]", res?"true":"false");
321 CompatibilityManager::FinalizeVirtualRoot(const String& rootPath, const PackageId& packageId)
325 String destPath = rootPath + DIR_VIRTUAL_ROOT;
326 static const struct _PathInfo mountPath[] =
345 { "./sys/fs/cgroup/systemd" },
346 { "./sys/fs/cgroup" },
354 //{ "./opt/var/run" },
355 { "./opt/storage/sdcard" },
359 std::unique_ptr<char[]> pVirtualRootPath(_StringConverter::CopyToCharArrayN(destPath));
360 TryReturn(pVirtualRootPath, false, "The memory is insufficient.");
362 res = chdir(pVirtualRootPath.get());
363 TryReturn(res == 0, false, "chdir() failed. (%d, %s), path = [%ls]", errno, strerror(errno), destPath.GetPointer());
365 for (i = 0; i < sizeof(mountPath) / sizeof(struct _PathInfo); ++i)
367 res = umount2(mountPath[i].destPath, MNT_DETACH);
368 TryReturn((res == 0) || (errno == EINVAL) || (errno == ENOENT), false, "umount2() failed. (%d, %s), path = [%s]", errno, strerror(errno), mountPath[i].destPath);
371 std::unique_ptr<char[]> pPackageId(_StringConverter::CopyToCharArrayN(packageId));
372 TryReturn(pPackageId, false, "The memory is insufficient.");
374 char mountFlag[PATH_MAX] = {0, };
375 sprintf(mountFlag, "/tmp/osp-compat/mount/internal/%s", pPackageId.get());
376 res = unlink(mountFlag);
377 if ((res == -1) && (errno != ENOENT))
379 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
383 memset(mountFlag, 0, PATH_MAX);
384 sprintf(mountFlag, "/tmp/osp-compat/mount/external/%s", pPackageId.get());
385 res = unlink(mountFlag);
386 if ((res == -1) && (errno != ENOENT))
388 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
392 AppLog("[Tizen::Io] FinalizeVirtualRoot() succeeded, path: %ls", destPath.GetPointer());
397 CompatibilityManager::CreateOspInternalDirectories(const String& rootPath, const PackageId& packageId)
399 result r = E_SUCCESS;
404 struct _OspDir appSubDir[] =
406 { "./shared", 0755, false },
407 { "./data/Share", 0000, true }, // mount from /opt/usr/share/.osp-compat/share/{pkgId}
408 { "./data/Share2", 0000, true }, // mount from /opt/usr/share/.osp-compat/share2/{pkgId}
409 { "./Share", 0000, false }, // mount from /opt/usr/share/.osp-compat/share
410 { "./Share2", 0000, false }, // mount from /opt/usr/share/.osp-compat/share2
411 { "./Media", 0000, false }, // mount from /opt/usr/media
412 { "./Storagecard", 0705, false },
413 { "./Storagecard/Media", 0000, false }, // mount from /opt/storage/sdcard
416 String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
417 String ospShareAppIdPath(L"share/");
418 String ospShare2AppIdPath(L"share2/");
420 r = ospShareAppIdPath.Insert(ospCompatSharedPath, 0);
421 TryReturn(!IsFailed(r), false, "String::Insert() failed. [error: %s]", GetErrorMessage(r));
423 r = ospShare2AppIdPath.Insert(ospCompatSharedPath, 0);
424 TryReturn(!IsFailed(r), false, "String::Insert() failed. [error: %s]", GetErrorMessage(r));
426 for (i = 0; i < sizeof(appSubDir) / sizeof(struct _OspDir); i++)
428 ret = mkdir(appSubDir[i].path, appSubDir[i].mode);
429 if (ret == -1 && errno != 17) // EEXIST
431 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), appSubDir[i].path, appSubDir[i].mode);
435 if (appSubDir[i].appPrivilege)
437 ret = chown(appSubDir[i].path, uid, uid);
440 AppLog("chown() failed (%s), path: %s, uid: %d", strerror(errno), appSubDir[i].path, uid);
446 SmackManager smackManager;
447 smackManager.SetupPath(packageId, L"./Storagecard", SMACK_DIR_TYPE_ANY_LABEL, L"_");
449 ospShareAppIdPath.Append(packageId);
451 std::unique_ptr<char[]> pOspShareAppIdPath(_StringConverter::CopyToCharArrayN(ospShareAppIdPath));
452 TryReturn(pOspShareAppIdPath, false, "The memory is insufficient.");
454 ret = mkdir(pOspShareAppIdPath.get(), 0705);
455 if (ret == -1 && errno != 17) // EEXIST
457 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), pOspShareAppIdPath.get(), 0705);
461 ret = chown(pOspShareAppIdPath.get(), uid, uid);
464 AppLog("chown() failed (%s), path: %s, uid: %d", strerror(errno), pOspShareAppIdPath.get(), uid);
468 ospShare2AppIdPath.Append(packageId);
470 std::unique_ptr<char[]> pOspShare2AppIdPath(_StringConverter::CopyToCharArrayN(ospShare2AppIdPath));
471 TryReturn(pOspShare2AppIdPath, false, "The memory is insufficient.");
473 ret = mkdir(pOspShare2AppIdPath.get(), 0705);
474 if (ret == -1 && errno != 17) // EEXIST
476 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), pOspShare2AppIdPath.get(), 0705);
480 ret = chown(pOspShare2AppIdPath.get(), uid, uid);
483 AppLog("chown() failed (%s), path: %s, uid: %d", strerror(errno), pOspShare2AppIdPath.get(), uid);
487 String appSharedDataPath(rootPath);
488 appSharedDataPath.Append(L"/shared/data");
490 String appSharedTrustedPath(rootPath);
491 appSharedTrustedPath.Append(L"/shared/trusted");
493 r = Directory::Remove(appSharedDataPath, true);
494 TryReturn(r == E_SUCCESS, false, "Directory::Remove(%ls) failed.", appSharedDataPath.GetPointer());
496 r = Directory::Remove(appSharedTrustedPath, true);
497 TryReturn(r == E_SUCCESS, false, "Directory::Remove(%ls) failed.", appSharedTrustedPath.GetPointer());
499 res = InstallerUtil::CreateSymlink(ospShareAppIdPath, L"./shared/data");
500 TryReturn(res == true, false, "CreateSymlink() failed, errno: %d (%s), link: ./shared/data -> %s", errno, strerror(errno), pOspShareAppIdPath.get());
502 res = InstallerUtil::CreateSymlink(ospShare2AppIdPath, L"./shared/trusted");
503 TryReturn(res == true, false, " CreateSymlink() failed, errno: %d (%s), link: ./shared/trusted -> %s", errno, strerror(errno), pOspShare2AppIdPath.get());
505 AppLog("[Tizen::Io] CreateOspInternalDirectories() succeeded, rootPath: %ls", rootPath.GetPointer());
510 CompatibilityManager::CreateSlpDirectories(void)
514 struct _OspDir slpDir[] =
516 { "./csa", 0000, false },
517 { "./dev", 0000, false },
518 { "./etc", 0000, false },
519 { "./lib", 0000, false },
520 { "./media", 0000, false },
521 { "./mnt", 0000, false },
522 { "./opt", 0000, false },
523 { "./proc", 0000, false },
524 { "./sbin", 0000, false },
525 { "./smack", 0000, false },
526 { "./srv", 0000, false },
527 { "./sys", 0000, false },
528 { "./tmp", 0000, false },
529 { "./usr", 0000, false },
530 { "./var", 0000, false }
533 for (i = 0; i < sizeof(slpDir) / sizeof(struct _OspDir); i++)
535 ret = mkdir(slpDir[i].path, slpDir[i].mode);
536 if (ret == -1 && errno != 17) // EEXIST
538 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), slpDir[i].path, slpDir[i].mode);
543 AppLog("[Tizen::Io] CreateSlpDirectories() succeeded.");
548 CompatibilityManager::CreateSymbolicLink(void)
550 struct _LinkDir linkDirList[] =
552 { "/opt/home", "./home" },
553 { "/opt/home/root", "./root" },
554 { "/mnt/mmc", "./sdcard" }
557 for (unsigned int i = 0; i < sizeof(linkDirList) / sizeof(struct _LinkDir); ++i)
559 InstallerUtil::CreateSymlink(linkDirList[i].srcPath, linkDirList[i].destPath);
562 AppLog("[Tizen::Io] CreateSymbolicLink() succeeded.");
567 CompatibilityManager::CreateVirtualRootDirectories(void)
571 struct _OspDir virtualRootDir[] =
573 { "./bin", 0000, false },
574 { "./cache", 0000, false },
575 { "./csa", 0000, false },
576 { "./data", 0000, false },
577 { "./dev", 0000, false },
578 { "./etc", 0000, false },
579 { "./lib", 0000, false },
580 { "./media", 0000, false },
581 { "./mnt", 0000, false },
582 { "./opt", 0000, false },
583 { "./proc", 0000, false },
584 { "./run", 0000, false },
585 { "./sbin", 0000, false },
586 { "./smack", 0000, false },
587 { "./srv", 0000, false },
588 { "./sys", 0000, false },
589 { "./system", 0000, false },
590 { "./tmp", 0000, false },
591 { "./usr", 0000, false },
592 { "./var", 0000, false }
595 for (i = 0; i < sizeof(virtualRootDir) / sizeof(struct _OspDir); i++)
597 ret = mkdir(virtualRootDir[i].path, virtualRootDir[i].mode);
598 if (ret == -1 && errno != 17) // EEXIST
600 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), virtualRootDir[i].path, virtualRootDir[i].mode);
605 AppLog("[Tizen::Io] CreateVirtualRootDirectories() succeeded.");