acc470002a936acce26ea41c439d1247ca1235f8
[platform/framework/native/installer.git] / src / Manager / CompatibilityManager.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        CompatibilityManager.cpp
19  * @brief       This is the implementation file for %CompatibilityManager class.
20  */
21
22 #include <sys/stat.h>
23 #include <sys/mount.h>
24 #include <dirent.h>
25 #include <errno.h>
26 #include <unique_ptr.h>
27
28 #include <FIoFile.h>
29 #include <FIoDirectory.h>
30 #include <FBase_StringConverter.h>
31 #include <FSys_EnvironmentImpl.h>
32
33 #include "InstallerDefs.h"
34 #include "CompatibilityManager.h"
35 #include "SmackManager.h"
36
37 using namespace Tizen::App;
38 using namespace Tizen::Base;
39 using namespace Tizen::Io;
40 using namespace Tizen::System;
41
42 struct _OspDir
43 {
44         char path[PATH_MAX];
45         mode_t mode;
46         bool appPrivilege;
47 };
48
49 struct _LinkDir
50 {
51         char srcPath[PATH_MAX];
52         char destPath[PATH_MAX];
53 };
54
55 struct _PathInfo
56 {
57     char destPath[PATH_MAX];
58 };
59
60
61 CompatibilityManager::CompatibilityManager(void)
62 :__pContext(null)
63 {
64 }
65
66 CompatibilityManager::~CompatibilityManager(void)
67 {
68 }
69
70 bool
71 CompatibilityManager::Construct(InstallationContext* pContext)
72 {
73         __pContext = pContext;
74
75         return true;
76 }
77
78 bool
79 CompatibilityManager::PrepareDataCaging(const String& rootPath, const PackageId& packageId)
80 {
81         bool res = true;
82         int result = 0;
83         char* pCwd = null;
84
85         std::unique_ptr<char[]> pRootPath(_StringConverter::CopyToCharArrayN(rootPath));
86         TryCatch(pRootPath != null, res = false, "The memory is insufficient.");
87
88         res = CleanDirectories(rootPath, packageId);
89         TryCatch(res == true, , "CleanDirectories(%ls, %ls) failed.", rootPath.GetPointer(), packageId.GetPointer());
90
91         pCwd = get_current_dir_name();
92         TryCatch(pCwd != null, res = false, "get_current_dir_name() failed. [errno = %d(%s)]", errno, strerror(errno));
93
94         umask(0000);
95
96         result = chdir(pRootPath.get());
97         TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pRootPath.get(), errno, strerror(errno));
98
99         res = CreateOspInternalDirectories(rootPath, packageId);
100         TryCatch(res == true, , "CreateOspInternalDirectories(%ls, %ls) failed.", rootPath.GetPointer(), packageId.GetPointer());
101
102         res = CreateSlpDirectories();
103         TryCatch(res == true, , "CreateSlpDirectories() failed.");
104
105         res = CreateSymbolicLink();
106         TryCatch(res == true, , "CreateSymbolicLink() failed.");
107
108         result = chdir(pCwd);
109         TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pCwd, errno, strerror(errno));
110
111 CATCH:
112         if (pCwd)
113         {
114                 free(pCwd);
115         }
116
117         umask(0022);
118
119         AppLog("[Tizen::Io] result  = [%s]", res?"true":"false");
120
121         return res;
122 }
123
124 bool
125 CompatibilityManager::FinalizeDataCaging(const String& rootPath)
126 {
127         int res = 0;
128         unsigned int i = 0;
129
130         static const struct _PathInfo mountPath[] =
131         {
132                 { "./csa" },
133                 { "./dev/pts" },
134                 { "./dev/shm" },
135                 { "./dev" },
136                 { "./etc" },
137                 { "./lib" },
138                 { "./mnt" },
139                 { "./opt/usr" },
140                 { "./opt/var/kdb/db" },
141                 { "./opt/storage/sdcard" },
142                 { "./opt" },
143                 { "./proc" },
144                 { "./sbin" },
145                 { "./smack" },
146                 { "./srv" },
147                 { "./sys/kernel/debug" },
148                 { "./sys" },
149                 { "./tmp" },
150                 { "./usr" },
151                 { "./var/run" },
152                 { "./var" },
153                 { "./data/Share" },
154                 { "./data/Share2" },
155                 { "./Share" },
156                 { "./Share2" },
157                 { "./Media" },
158                 { "./Storagecard/Media" },
159                 { "./ShareExt" },
160                 { "./Share2Ext" },
161                 { "./HomeExt/Share" },
162                 { "./HomeExt/Share2" },
163                 { "./HomeExt" }
164         };
165
166         std::unique_ptr<char[]> pAppRootPath(_StringConverter::CopyToCharArrayN(rootPath));
167         TryReturn(pAppRootPath, false, "The memory is insufficient.");
168
169         res = chdir(pAppRootPath.get());
170         TryReturn(res == 0, false, "chdir() failed. (%d, %s), path = [%ls]", errno, strerror(errno), rootPath.GetPointer());
171
172         for (i = 0; i < sizeof(mountPath) / sizeof(struct _PathInfo); ++i)
173         {
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);
176         }
177
178         char* pPackageId = strrchr(pAppRootPath.get(), '/');
179         char mountFlag[PATH_MAX] = {0, };
180
181         sprintf(mountFlag, "/tmp/osp-compat/mount/internal/%s", ++pPackageId);
182         res = unlink(mountFlag);
183         if ((res == -1) && (errno != ENOENT))
184         {
185                 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
186                 return false;
187         }
188
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))
193         {
194                 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
195                 return false;
196         }
197
198         AppLog("[Tizen::Io] FinalizeDataCaging() succeeded, rootPath: %ls", rootPath.GetPointer());
199         return true;
200 }
201
202 bool
203 CompatibilityManager::CleanDirectories(const String& rootPath, const PackageId& packageId)
204 {
205         int ret = 0;
206         char removeCmd[PATH_MAX] = {0, };
207
208         String ospSharePkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
209         ospSharePkgIdPath.Append(L"share/");
210         ospSharePkgIdPath.Append(packageId);
211
212         String ospShare2PkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
213         ospShare2PkgIdPath.Append(L"share2/");
214         ospShare2PkgIdPath.Append(packageId);
215
216         sprintf(removeCmd, "rm -rf %ls", ospSharePkgIdPath.GetPointer());
217         AppLog("removeCmd  = [%s]", removeCmd);
218
219         ret = system(removeCmd);
220         TryReturn(ret != -1, false, "system(%s) failed.", removeCmd);
221
222         memset(removeCmd, 0, PATH_MAX);
223
224         sprintf(removeCmd, "rm -rf %ls", ospShare2PkgIdPath.GetPointer());
225         AppLog("removeCmd  = [%s]", removeCmd);
226
227         ret = system(removeCmd);
228         TryReturn(ret != -1, false, "system(%s) failed.", removeCmd);
229
230         AppLog("[Tizen::Io] CleanDirectories() succeeded, rootPath: %ls", rootPath.GetPointer());
231         return true;
232 }
233
234 bool
235 CompatibilityManager::LinkOspSharePath(const String& rootPath, const PackageId& packageId)
236 {
237         const char* pOspCompatSharedPath = "/opt/usr/share/.osp-compat/\0";
238
239         std::unique_ptr<char[]> pRootPath(_StringConverter::CopyToCharArrayN(rootPath));
240         TryReturn(pRootPath, false, "The memory is insufficient.");
241
242         std::unique_ptr<char[]> pPackageId(_StringConverter::CopyToCharArrayN(packageId));
243         TryReturn(pPackageId, false, "The memory is insufficient.");
244
245         char ospAppSharePath[PATH_MAX] = {0, };
246         char ospAppShare2Path[PATH_MAX] = {0, };
247         char ospSharePkgIdPath[PATH_MAX] = {0, };
248         char ospShare2PkgIdPath[PATH_MAX] = {0, };
249
250         strncpy(ospAppSharePath, pRootPath.get(), strlen(pRootPath.get()));
251         strncat(ospAppSharePath, "/shared/data", 12);
252
253         strncpy(ospSharePkgIdPath, pOspCompatSharedPath, strlen(pOspCompatSharedPath));
254         strncat(ospSharePkgIdPath, "share/", 6);
255         strncat(ospSharePkgIdPath, pPackageId.get(), strlen(pPackageId.get()));
256
257         strncpy(ospAppShare2Path, pRootPath.get(), strlen(pRootPath.get()));
258         strncat(ospAppShare2Path, "/shared/trusted", 15);
259
260         strncpy(ospShare2PkgIdPath, pOspCompatSharedPath, strlen(pOspCompatSharedPath));
261         strncat(ospShare2PkgIdPath, "share2/", 7);
262         strncat(ospShare2PkgIdPath, pPackageId.get(), strlen(pPackageId.get()));
263
264         unlink(ospSharePkgIdPath);
265         unlink(ospShare2PkgIdPath);
266
267         InstallerUtil::CreateSymlink(ospAppSharePath, ospSharePkgIdPath, false);
268         InstallerUtil::CreateSymlink(ospAppShare2Path, ospShare2PkgIdPath, false);
269
270         return true;
271 }
272
273 bool
274 CompatibilityManager::PrepareVirtualRoot(const Tizen::Base::String& rootPath, const Tizen::App::PackageId& packageId)
275 {
276         String virtualRoot = GetVirtualRootPath(rootPath);
277         TryReturn(virtualRoot.IsEmpty() == false, false, "GetVirtualRootPath(%ls) failed.", rootPath.GetPointer());
278
279         result r = E_SUCCESS;
280         bool res = true;
281         int result = 0;
282         char* pCwd = null;
283         String virtualRootPath = rootPath + DIR_DATA + L"/" + virtualRoot;
284
285         std::unique_ptr<char[]> pVirtualRootPath(_StringConverter::CopyToCharArrayN(virtualRootPath));
286         TryCatch(pVirtualRootPath != null, res = false, "The memory is insufficient.");
287
288         pCwd = get_current_dir_name();
289         TryCatch(pCwd != null, res = false, "get_current_dir_name() failed. [errno = %d(%s)]", errno, strerror(errno));
290
291         // appRoot/virtual-root
292         if (File::IsFileExist(virtualRootPath) == false)
293         {
294                 r = Directory::Create(virtualRootPath, true);
295                 TryCatch(!IsFailed(r), res = false, "Directory::Create() failed");
296         }
297
298         result = chdir(pVirtualRootPath.get());
299         TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pVirtualRootPath.get(), errno, strerror(errno));
300
301         res = CreateVirtualRootDirectories();
302         TryCatch(res == true, , "CreateVirtualRootDirectories() failed.");
303
304         res = CreateSymbolicLink();
305         TryCatch(res == true, , "CreateSymbolicLink() failed.");
306
307         result = chdir(pCwd);
308         TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pCwd, errno, strerror(errno));
309
310 CATCH:
311         if (pCwd)
312         {
313                 free(pCwd);
314         }
315
316         AppLog("[Tizen::Io] result  = [%s]", res?"true":"false");
317
318         return res;
319 }
320
321 bool
322 CompatibilityManager::FinalizeVirtualRoot(const String& rootPath, const PackageId& packageId)
323 {
324         String virtualRootPath = GetVirtualRootPath(rootPath);
325         TryReturn(virtualRootPath.IsEmpty() == false, false, "GetVirtualRootPath(%ls) failed.", rootPath.GetPointer());
326
327         int res = 0;
328         unsigned int i = 0;
329         String destPath = rootPath + DIR_DATA + L"/" + virtualRootPath;
330
331         static const struct _PathInfo mountPath[] =
332         {
333                         { "./bin" },
334                         { "./cache" },
335                         { "./csa" },
336                         { "./data" },
337                         { "./dev/pts" },
338                         { "./dev/shm" },
339                         { "./dev" },
340                         { "./etc" },
341                         { "./lib/modules" },
342                         { "./lib" },
343                         { "./media" },
344                         { "./mnt" },
345                         { "./proc" },
346                         { "./run" },
347                         { "./sbin" },
348                         { "./smack" },
349                         { "./srv" },
350                         { "./sys/fs/cgroup/systemd" },
351                         { "./sys/fs/cgroup" },
352                         { "./sys" },
353                         { "./system" },
354                         { "./tmp" },
355                         { "./usr" },
356                         { "./var/run" },
357                         { "./var" },
358                         { "./opt/usr" },
359                         //{ "./opt/var/run" },
360                         { "./opt/storage/sdcard" },
361                         { "./opt" },
362         };
363
364         std::unique_ptr<char[]> pVirtualRootPath(_StringConverter::CopyToCharArrayN(destPath));
365         TryReturn(pVirtualRootPath, false, "The memory is insufficient.");
366
367         res = chdir(pVirtualRootPath.get());
368         TryReturn(res == 0, false, "chdir() failed. (%d, %s), path = [%ls]", errno, strerror(errno), destPath.GetPointer());
369
370         for (i = 0; i < sizeof(mountPath) / sizeof(struct _PathInfo); ++i)
371         {
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);
374
375                 AppLog("umount2(%s) is succeeded.", mountPath[i].destPath);
376         }
377
378         std::unique_ptr<char[]> pPackageId(_StringConverter::CopyToCharArrayN(packageId));
379         TryReturn(pPackageId, false, "The memory is insufficient.");
380
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))
385         {
386                 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
387                 return false;
388         }
389
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))
394         {
395                 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
396                 return false;
397         }
398
399         AppLog("[Tizen::Io] FinalizeVirtualRoot() succeeded, path: %ls", destPath.GetPointer());
400         return true;
401 }
402
403 bool
404 CompatibilityManager::CreateOspInternalDirectories(const String& rootPath, const PackageId& packageId)
405 {
406         result r = E_SUCCESS;
407         bool res = true;
408         int ret = 0;
409         unsigned int i = 0;
410         int uid = 5000;
411         struct _OspDir appSubDir[] =
412         {
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
421         };
422
423         String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
424         String ospShareAppIdPath(L"share/");
425         String ospShare2AppIdPath(L"share2/");
426
427         r = ospShareAppIdPath.Insert(ospCompatSharedPath, 0);
428         TryReturn(!IsFailed(r), false, "String::Insert() failed. [error: %s]", GetErrorMessage(r));
429
430         r = ospShare2AppIdPath.Insert(ospCompatSharedPath, 0);
431         TryReturn(!IsFailed(r), false, "String::Insert() failed. [error: %s]", GetErrorMessage(r));
432
433         for (i = 0; i < sizeof(appSubDir) / sizeof(struct _OspDir); i++)
434         {
435                 ret = mkdir(appSubDir[i].path, appSubDir[i].mode);
436                 if (ret == -1 && errno != 17) // EEXIST
437                 {
438                         AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), appSubDir[i].path, appSubDir[i].mode);
439                         return false;
440                 }
441
442                 if (appSubDir[i].appPrivilege)
443                 {
444                         ret = chown(appSubDir[i].path, uid, uid);
445                         if (ret == -1)
446                         {
447                                 AppLog("chown() failed (%s), path: %s, uid: %d", strerror(errno), appSubDir[i].path, uid);
448                                 return false;
449                         }
450                 }
451         }
452
453         SmackManager smackManager;
454         smackManager.Construct(__pContext);
455         smackManager.SetupPath(packageId, L"./Storagecard", APP_PATH_ANY_LABEL, L"_");
456
457         ospShareAppIdPath.Append(packageId);
458
459         std::unique_ptr<char[]> pOspShareAppIdPath(_StringConverter::CopyToCharArrayN(ospShareAppIdPath));
460         TryReturn(pOspShareAppIdPath, false, "The memory is insufficient.");
461
462         ret = mkdir(pOspShareAppIdPath.get(), 0705);
463         if (ret == -1 && errno != 17) // EEXIST
464         {
465                 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), pOspShareAppIdPath.get(), 0705);
466                 return false;
467         }
468
469         ret = chown(pOspShareAppIdPath.get(), uid, uid);
470         if (ret == -1)
471         {
472                 AppLog("chown() failed (%s), path: %s, uid: %d", strerror(errno), pOspShareAppIdPath.get(), uid);
473                 return false;
474         }
475
476         ospShare2AppIdPath.Append(packageId);
477
478         std::unique_ptr<char[]> pOspShare2AppIdPath(_StringConverter::CopyToCharArrayN(ospShare2AppIdPath));
479         TryReturn(pOspShare2AppIdPath, false, "The memory is insufficient.");
480
481         ret = mkdir(pOspShare2AppIdPath.get(), 0705);
482         if (ret == -1 && errno != 17) // EEXIST
483         {
484                 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), pOspShare2AppIdPath.get(), 0705);
485                 return false;
486         }
487
488         ret = chown(pOspShare2AppIdPath.get(), uid, uid);
489         if (ret == -1)
490         {
491                 AppLog("chown() failed (%s), path: %s, uid: %d", strerror(errno), pOspShare2AppIdPath.get(), uid);
492                 return false;
493         }
494
495         String appSharedDataPath(rootPath);
496         appSharedDataPath.Append(L"/shared/data");
497
498         String appSharedTrustedPath(rootPath);
499         appSharedTrustedPath.Append(L"/shared/trusted");
500
501         r = Directory::Remove(appSharedDataPath, true);
502         TryReturn(r == E_SUCCESS, false, "Directory::Remove(%ls) failed.", appSharedDataPath.GetPointer());
503
504         r = Directory::Remove(appSharedTrustedPath, true);
505         TryReturn(r == E_SUCCESS, false, "Directory::Remove(%ls) failed.", appSharedTrustedPath.GetPointer());
506
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());
509
510         smackManager.SetupPath(packageId, ospShareAppIdPath, APP_PATH_PUBLIC_RO);
511
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());
514
515         smackManager.SetupPath(packageId, ospShare2AppIdPath, APP_PATH_GROUP_RW);
516
517         AppLog("[Tizen::Io] CreateOspInternalDirectories() succeeded, rootPath: %ls", rootPath.GetPointer());
518         return true;
519 }
520
521 bool
522 CompatibilityManager::CreateSlpDirectories(void)
523 {
524         unsigned int i = 0;
525         int ret = 0;
526         struct _OspDir slpDir[] =
527         {
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 }
542         };
543
544         for (i = 0; i < sizeof(slpDir) / sizeof(struct _OspDir); i++)
545         {
546                 ret = mkdir(slpDir[i].path, slpDir[i].mode);
547                 if (ret == -1 && errno != 17) // EEXIST
548                 {
549                         AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), slpDir[i].path, slpDir[i].mode);
550                         return false;
551                 }
552                 else
553                 {
554                         AppLog("Directory[%s, 0%o] is created.", slpDir[i].path, slpDir[i].mode);
555                 }
556         }
557
558         AppLog("[Tizen::Io] CreateSlpDirectories() succeeded.");
559         return true;
560 }
561
562 bool
563 CompatibilityManager::CreateSymbolicLink(void)
564 {
565         struct _LinkDir linkDirList[] =
566         {
567                 { "/opt/home", "./home" },
568                 { "/opt/home/root", "./root" },
569                 { "/mnt/mmc", "./sdcard" }
570         };
571
572         for (unsigned int i = 0; i < sizeof(linkDirList) / sizeof(struct _LinkDir); ++i)
573         {
574                 InstallerUtil::CreateSymlink(linkDirList[i].srcPath, linkDirList[i].destPath, false);
575         }
576
577         AppLog("[Tizen::Io] CreateSymbolicLink() succeeded.");
578         return true;
579 }
580
581 bool
582 CompatibilityManager::CreateVirtualRootDirectories(void)
583 {
584         unsigned int i = 0;
585         int ret = 0;
586         struct _OspDir virtualRootDir[] =
587         {
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 }
608         };
609
610         for (i = 0; i < sizeof(virtualRootDir) / sizeof(struct _OspDir); i++)
611         {
612                 ret = mkdir(virtualRootDir[i].path, virtualRootDir[i].mode);
613                 if (ret == -1 && errno != 17) // EEXIST
614                 {
615                         AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), virtualRootDir[i].path, virtualRootDir[i].mode);
616                         return false;
617                 }
618                 else
619                 {
620                         AppLog("Directory[%s, 0%o] is created.", virtualRootDir[i].path, virtualRootDir[i].mode);
621                 }
622         }
623
624         AppLog("[Tizen::Io] CreateVirtualRootDirectories() succeeded.");
625         return true;
626 }
627
628 String
629 CompatibilityManager::GetVirtualRootPath(const Tizen::Base::String& rootPath)
630 {
631         TryReturn(rootPath.IsEmpty() == false, L"", "rootPath is empty.");
632
633         String virtualRootInfoFile;
634         virtualRootInfoFile.Format(1024, L"%ls%ls", rootPath.GetPointer(), VIRTUAL_ROOT_INFO_FILE);
635
636         if (File::IsFileExist(virtualRootInfoFile) == false)
637         {
638                 AppLog("virtualRootInfoFile[%ls] is not existed.", virtualRootInfoFile.GetPointer());
639                 return L"";
640         }
641
642         result r = E_SUCCESS;
643         File file;
644         String virtualRootPath;
645
646         r = file.Construct(virtualRootInfoFile, L"r");
647         TryReturn(r == E_SUCCESS, L"", "file.Construct() is failed. [%ls]", virtualRootInfoFile.GetPointer());
648
649         r = file.Read(virtualRootPath);
650         TryReturn(r == E_SUCCESS, L"", "file.Read() is failed. [%ls]", virtualRootInfoFile.GetPointer());
651
652         AppLog("virtualRootPath = [%ls]", virtualRootPath.GetPointer());
653
654         return virtualRootPath;
655 }