Modify the logic to support the virtual root
[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 {
63 }
64
65 CompatibilityManager::~CompatibilityManager(void)
66 {
67 }
68
69 bool
70 CompatibilityManager::PrepareDataCaging(const String& rootPath, const PackageId& packageId)
71 {
72         bool res = true;
73         int result = 0;
74         char* pCwd = null;
75
76         std::unique_ptr<char[]> pRootPath(_StringConverter::CopyToCharArrayN(rootPath));
77         TryCatch(pRootPath != null, res = false, "The memory is insufficient.");
78
79         res = CleanDirectories(rootPath, packageId);
80         TryCatch(res == true, , "CleanDirectories(%ls, %ls) failed.", rootPath.GetPointer(), packageId.GetPointer());
81
82         pCwd = get_current_dir_name();
83         TryCatch(pCwd != null, res = false, "get_current_dir_name() failed. [errno = %d(%s)]", errno, strerror(errno));
84
85         umask(0000);
86
87         result = chdir(pRootPath.get());
88         TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pRootPath.get(), errno, strerror(errno));
89
90         res = CreateOspInternalDirectories(rootPath, packageId);
91         TryCatch(res == true, , "CreateOspInternalDirectories(%ls, %ls) failed.", rootPath.GetPointer(), packageId.GetPointer());
92
93         res = CreateSlpDirectories();
94         TryCatch(res == true, , "CreateSlpDirectories() failed.");
95
96         res = CreateSymbolicLink();
97         TryCatch(res == true, , "CreateSymbolicLink() failed.");
98
99         result = chdir(pCwd);
100         TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pCwd, errno, strerror(errno));
101
102 CATCH:
103         if (pCwd)
104         {
105                 free(pCwd);
106         }
107
108         umask(0022);
109
110         AppLog("[Tizen::Io] result  = [%s]", res?"true":"false");
111
112         return res;
113 }
114
115 bool
116 CompatibilityManager::FinalizeDataCaging(const String& rootPath)
117 {
118         int res = 0;
119         unsigned int i = 0;
120
121         static const struct _PathInfo mountPath[] =
122         {
123                 { "./csa" },
124                 { "./dev/pts" },
125                 { "./dev/shm" },
126                 { "./dev" },
127                 { "./etc" },
128                 { "./lib" },
129                 { "./mnt" },
130                 { "./opt/usr" },
131                 { "./opt/var/kdb/db" },
132                 { "./opt/storage/sdcard" },
133                 { "./opt" },
134                 { "./proc" },
135                 { "./sbin" },
136                 { "./smack" },
137                 { "./srv" },
138                 { "./sys/kernel/debug" },
139                 { "./sys" },
140                 { "./tmp" },
141                 { "./usr" },
142                 { "./var/run" },
143                 { "./var" },
144                 { "./data/Share" },
145                 { "./data/Share2" },
146                 { "./Share" },
147                 { "./Share2" },
148                 { "./Media" },
149                 { "./Storagecard/Media" },
150                 { "./ShareExt" },
151                 { "./Share2Ext" },
152                 { "./HomeExt/Share" },
153                 { "./HomeExt/Share2" },
154                 { "./HomeExt" }
155         };
156
157         std::unique_ptr<char[]> pAppRootPath(_StringConverter::CopyToCharArrayN(rootPath));
158         TryReturn(pAppRootPath, false, "The memory is insufficient.");
159
160         res = chdir(pAppRootPath.get());
161         TryReturn(res == 0, false, "chdir() failed. (%d, %s), path = [%ls]", errno, strerror(errno), rootPath.GetPointer());
162
163         for (i = 0; i < sizeof(mountPath) / sizeof(struct _PathInfo); ++i)
164         {
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);
167         }
168
169         char* pPackageId = strrchr(pAppRootPath.get(), '/');
170         char mountFlag[PATH_MAX] = {0, };
171
172         sprintf(mountFlag, "/tmp/osp-compat/mount/internal/%s", ++pPackageId);
173         res = unlink(mountFlag);
174         if ((res == -1) && (errno != ENOENT))
175         {
176                 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
177                 return false;
178         }
179
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))
184         {
185                 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
186                 return false;
187         }
188
189         AppLog("[Tizen::Io] FinalizeDataCaging() succeeded, rootPath: %ls", rootPath.GetPointer());
190         return true;
191 }
192
193 bool
194 CompatibilityManager::CleanDirectories(const String& rootPath, const PackageId& packageId)
195 {
196         int ret = 0;
197         char removeCmd[PATH_MAX] = {0, };
198
199         String ospSharePkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
200         ospSharePkgIdPath.Append(L"share/");
201         ospSharePkgIdPath.Append(packageId);
202
203         String ospShare2PkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
204         ospShare2PkgIdPath.Append(L"share2/");
205         ospShare2PkgIdPath.Append(packageId);
206
207         sprintf(removeCmd, "rm -rf %ls", ospSharePkgIdPath.GetPointer());
208         AppLog("removeCmd  = [%s]", removeCmd);
209
210         ret = system(removeCmd);
211         TryReturn(ret != -1, false, "system(%s) failed.", removeCmd);
212
213         memset(removeCmd, 0, PATH_MAX);
214
215         sprintf(removeCmd, "rm -rf %ls", ospShare2PkgIdPath.GetPointer());
216         AppLog("removeCmd  = [%s]", removeCmd);
217
218         ret = system(removeCmd);
219         TryReturn(ret != -1, false, "system(%s) failed.", removeCmd);
220
221         AppLog("[Tizen::Io] CleanDirectories() succeeded, rootPath: %ls", rootPath.GetPointer());
222         return true;
223 }
224
225 bool
226 CompatibilityManager::LinkOspSharePath(const String& rootPath, const PackageId& packageId)
227 {
228         int ret = 0;
229         const char* pOspCompatSharedPath = "/opt/usr/share/.osp-compat/\0";
230
231         std::unique_ptr<char[]> pRootPath(_StringConverter::CopyToCharArrayN(rootPath));
232         TryReturn(pRootPath, false, "The memory is insufficient.");
233
234         std::unique_ptr<char[]> pPackageId(_StringConverter::CopyToCharArrayN(packageId));
235         TryReturn(pPackageId, false, "The memory is insufficient.");
236
237         char ospAppSharePath[PATH_MAX] = {0, };
238         char ospAppShare2Path[PATH_MAX] = {0, };
239         char ospSharePkgIdPath[PATH_MAX] = {0, };
240         char ospShare2PkgIdPath[PATH_MAX] = {0, };
241
242         strncpy(ospAppSharePath, pRootPath.get(), strlen(pRootPath.get()));
243         strncat(ospAppSharePath, "/shared/data", 12);
244
245         strncpy(ospSharePkgIdPath, pOspCompatSharedPath, strlen(pOspCompatSharedPath));
246         strncat(ospSharePkgIdPath, "share/", 6);
247         strncat(ospSharePkgIdPath, pPackageId.get(), strlen(pPackageId.get()));
248
249         strncpy(ospAppShare2Path, pRootPath.get(), strlen(pRootPath.get()));
250         strncat(ospAppShare2Path, "/shared/trusted", 15);
251
252         strncpy(ospShare2PkgIdPath, pOspCompatSharedPath, strlen(pOspCompatSharedPath));
253         strncat(ospShare2PkgIdPath, "share2/", 7);
254         strncat(ospShare2PkgIdPath, pPackageId.get(), strlen(pPackageId.get()));
255
256         unlink(ospSharePkgIdPath);
257         unlink(ospShare2PkgIdPath);
258
259         SmackManager smackManager;
260
261         ret = symlink(ospAppSharePath, ospSharePkgIdPath);
262         smackManager.AddLabelDir(L"_", ospSharePkgIdPath);
263
264         ret = symlink(ospAppShare2Path, ospShare2PkgIdPath);
265         smackManager.AddLabelDir(L"_", ospShare2PkgIdPath);
266
267         return true;
268 }
269
270 bool
271 CompatibilityManager::PrepareVirtualRoot(const Tizen::Base::String& rootPath, const Tizen::App::PackageId& packageId)
272 {
273         result r = E_SUCCESS;
274         bool res = true;
275         int result = 0;
276         char* pCwd = null;
277         String destPath = rootPath + DIR_VIRTUAL_ROOT;
278         SmackManager smackManager;
279
280         std::unique_ptr<char[]> pVirtualRootPath(_StringConverter::CopyToCharArrayN(destPath));
281         TryCatch(pVirtualRootPath != null, res = false, "The memory is insufficient.");
282
283         pCwd = get_current_dir_name();
284         TryCatch(pCwd != null, res = false, "get_current_dir_name() failed. [errno = %d(%s)]", errno, strerror(errno));
285
286         // appRoot/virtual-root
287         if (File::IsFileExist(destPath) == false)
288         {
289                 r = Directory::Create(destPath, false);
290                 TryCatch(!IsFailed(r), res = false, "Directory::Create() failed");
291         }
292
293         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
294
295         result = chdir(pVirtualRootPath.get());
296         TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pVirtualRootPath.get(), errno, strerror(errno));
297
298         res = CreateVirtualRootDirectories();
299         TryCatch(res == true, , "CreateVirtualRootDirectories() failed.");
300
301         smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
302
303         res = CreateSymbolicLink();
304         TryCatch(res == true, , "CreateSymbolicLink() failed.");
305
306         result = chdir(pCwd);
307         TryCatch(result == 0, res = false, "chdir(%s) failed. [errno = %d(%s)]", pCwd, errno, strerror(errno));
308
309 CATCH:
310         if (pCwd)
311         {
312                 free(pCwd);
313         }
314
315         AppLog("[Tizen::Io] result  = [%s]", res?"true":"false");
316
317         return res;
318 }
319
320 bool
321 CompatibilityManager::FinalizeVirtualRoot(const String& rootPath, const PackageId& packageId)
322 {
323         int res = 0;
324         unsigned int i = 0;
325         String destPath = rootPath + DIR_VIRTUAL_ROOT;
326         static const struct _PathInfo mountPath[] =
327         {
328                         { "./bin" },
329                         { "./cache" },
330                         { "./csa" },
331                         { "./data" },
332                         { "./dev/pts" },
333                         { "./dev/shm" },
334                         { "./dev" },
335                         { "./etc" },
336                         { "./lib/modules" },
337                         { "./lib" },
338                         { "./media" },
339                         { "./mnt" },
340                         { "./proc" },
341                         { "./run" },
342                         { "./sbin" },
343                         { "./smack" },
344                         { "./srv" },
345                         { "./sys/fs/cgroup/systemd" },
346                         { "./sys/fs/cgroup" },
347                         { "./sys" },
348                         { "./system" },
349                         { "./tmp" },
350                         { "./usr" },
351                         { "./var/run" },
352                         { "./var" },
353                         { "./opt/usr" },
354                         //{ "./opt/var/run" },
355                         { "./opt/storage/sdcard" },
356                         { "./opt" },
357         };
358
359         std::unique_ptr<char[]> pVirtualRootPath(_StringConverter::CopyToCharArrayN(destPath));
360         TryReturn(pVirtualRootPath, false, "The memory is insufficient.");
361
362         res = chdir(pVirtualRootPath.get());
363         TryReturn(res == 0, false, "chdir() failed. (%d, %s), path = [%ls]", errno, strerror(errno), destPath.GetPointer());
364
365         for (i = 0; i < sizeof(mountPath) / sizeof(struct _PathInfo); ++i)
366         {
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);
369         }
370
371         std::unique_ptr<char[]> pPackageId(_StringConverter::CopyToCharArrayN(packageId));
372         TryReturn(pPackageId, false, "The memory is insufficient.");
373
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))
378         {
379                 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
380                 return false;
381         }
382
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))
387         {
388                 AppLog("unlink(%s) failed, errno: %d (%s)", mountFlag, errno, strerror(errno));
389                 return false;
390         }
391
392         AppLog("[Tizen::Io] FinalizeVirtualRoot() succeeded, path: %ls", destPath.GetPointer());
393         return true;
394 }
395
396 bool
397 CompatibilityManager::CreateOspInternalDirectories(const String& rootPath, const PackageId& packageId)
398 {
399         result r = E_SUCCESS;
400         bool res = true;
401         int ret = 0;
402         unsigned int i = 0;
403         int uid = 5000;
404         struct _OspDir appSubDir[] =
405         {
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
414         };
415
416         String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
417         String ospShareAppIdPath(L"share/");
418         String ospShare2AppIdPath(L"share2/");
419
420         r = ospShareAppIdPath.Insert(ospCompatSharedPath, 0);
421         TryReturn(!IsFailed(r), false, "String::Insert() failed. [error: %s]", GetErrorMessage(r));
422
423         r = ospShare2AppIdPath.Insert(ospCompatSharedPath, 0);
424         TryReturn(!IsFailed(r), false, "String::Insert() failed. [error: %s]", GetErrorMessage(r));
425
426         for (i = 0; i < sizeof(appSubDir) / sizeof(struct _OspDir); i++)
427         {
428                 ret = mkdir(appSubDir[i].path, appSubDir[i].mode);
429                 if (ret == -1 && errno != 17) // EEXIST
430                 {
431                         AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), appSubDir[i].path, appSubDir[i].mode);
432                         return false;
433                 }
434
435                 if (appSubDir[i].appPrivilege)
436                 {
437                         ret = chown(appSubDir[i].path, uid, uid);
438                         if (ret == -1)
439                         {
440                                 AppLog("chown() failed (%s), path: %s, uid: %d", strerror(errno), appSubDir[i].path, uid);
441                                 return false;
442                         }
443                 }
444         }
445
446         SmackManager smackManager;
447         smackManager.SetupPath(packageId, L"./Storagecard", SMACK_DIR_TYPE_ANY_LABEL, L"_");
448
449         ospShareAppIdPath.Append(packageId);
450
451         std::unique_ptr<char[]> pOspShareAppIdPath(_StringConverter::CopyToCharArrayN(ospShareAppIdPath));
452         TryReturn(pOspShareAppIdPath, false, "The memory is insufficient.");
453
454         ret = mkdir(pOspShareAppIdPath.get(), 0705);
455         if (ret == -1 && errno != 17) // EEXIST
456         {
457                 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), pOspShareAppIdPath.get(), 0705);
458                 return false;
459         }
460
461         ret = chown(pOspShareAppIdPath.get(), uid, uid);
462         if (ret == -1)
463         {
464                 AppLog("chown() failed (%s), path: %s, uid: %d", strerror(errno), pOspShareAppIdPath.get(), uid);
465                 return false;
466         }
467
468         ospShare2AppIdPath.Append(packageId);
469
470         std::unique_ptr<char[]> pOspShare2AppIdPath(_StringConverter::CopyToCharArrayN(ospShare2AppIdPath));
471         TryReturn(pOspShare2AppIdPath, false, "The memory is insufficient.");
472
473         ret = mkdir(pOspShare2AppIdPath.get(), 0705);
474         if (ret == -1 && errno != 17) // EEXIST
475         {
476                 AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), pOspShare2AppIdPath.get(), 0705);
477                 return false;
478         }
479
480         ret = chown(pOspShare2AppIdPath.get(), uid, uid);
481         if (ret == -1)
482         {
483                 AppLog("chown() failed (%s), path: %s, uid: %d", strerror(errno), pOspShare2AppIdPath.get(), uid);
484                 return false;
485         }
486
487         String appSharedDataPath(rootPath);
488         appSharedDataPath.Append(L"/shared/data");
489
490         String appSharedTrustedPath(rootPath);
491         appSharedTrustedPath.Append(L"/shared/trusted");
492
493         r = Directory::Remove(appSharedDataPath, true);
494         TryReturn(r == E_SUCCESS, false, "Directory::Remove(%ls) failed.", appSharedDataPath.GetPointer());
495
496         r = Directory::Remove(appSharedTrustedPath, true);
497         TryReturn(r == E_SUCCESS, false, "Directory::Remove(%ls) failed.", appSharedTrustedPath.GetPointer());
498
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());
501
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());
504
505         AppLog("[Tizen::Io] CreateOspInternalDirectories() succeeded, rootPath: %ls", rootPath.GetPointer());
506         return true;
507 }
508
509 bool
510 CompatibilityManager::CreateSlpDirectories(void)
511 {
512         unsigned int i = 0;
513         int ret = 0;
514         struct _OspDir slpDir[] =
515         {
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 }
531         };
532
533         for (i = 0; i < sizeof(slpDir) / sizeof(struct _OspDir); i++)
534         {
535                 ret = mkdir(slpDir[i].path, slpDir[i].mode);
536                 if (ret == -1 && errno != 17) // EEXIST
537                 {
538                         AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), slpDir[i].path, slpDir[i].mode);
539                         return false;
540                 }
541         }
542
543         AppLog("[Tizen::Io] CreateSlpDirectories() succeeded.");
544         return true;
545 }
546
547 bool
548 CompatibilityManager::CreateSymbolicLink(void)
549 {
550         struct _LinkDir linkDirList[] =
551         {
552                 { "/opt/home", "./home" },
553                 { "/opt/home/root", "./root" },
554                 { "/mnt/mmc", "./sdcard" }
555         };
556
557         for (unsigned int i = 0; i < sizeof(linkDirList) / sizeof(struct _LinkDir); ++i)
558         {
559                 InstallerUtil::CreateSymlink(linkDirList[i].srcPath, linkDirList[i].destPath);
560         }
561
562         AppLog("[Tizen::Io] CreateSymbolicLink() succeeded.");
563         return true;
564 }
565
566 bool
567 CompatibilityManager::CreateVirtualRootDirectories(void)
568 {
569         unsigned int i = 0;
570         int ret = 0;
571         struct _OspDir virtualRootDir[] =
572         {
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 }
593         };
594
595         for (i = 0; i < sizeof(virtualRootDir) / sizeof(struct _OspDir); i++)
596         {
597                 ret = mkdir(virtualRootDir[i].path, virtualRootDir[i].mode);
598                 if (ret == -1 && errno != 17) // EEXIST
599                 {
600                         AppLog("mkdir() failed (%s), path: %s, mode: 0%o", strerror(errno), virtualRootDir[i].path, virtualRootDir[i].mode);
601                         return false;
602                 }
603         }
604
605         AppLog("[Tizen::Io] CreateVirtualRootDirectories() succeeded.");
606         return true;
607 }