sync with tizen_2.0
[platform/framework/native/appfw.git] / src / io / FIo_FileImpl.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 /**
19  * @file        FIo_FileImpl.cpp
20  * @brief       This is the implementation file for %_FileImpl class.
21  */
22
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <sys/mount.h>
29 #include <limits.h>
30 #include <errno.h>
31 #include <new>
32 #include <unique_ptr.h>
33
34 #include <FBaseSysLog.h>
35 #include <FAppPkgPackageInfo.h>
36 #include <FIoDirectory.h>
37 #include <FIoFile.h>
38 #include <FAppApp.h>
39 #include <FSysEnvironment.h>
40
41 #include <FBase_StringConverter.h>
42 #include <FApp_AppInfo.h>
43 #include <FAppPkg_PackageInfoImpl.h>
44 #include <FSys_EnvironmentImpl.h>
45
46 #include "FIo_FileImpl.h"
47 #include "FIo_NormalFile.h"
48 #include "FIo_DirectoryImpl.h"
49 #include "FIo_SecureFile.h"
50 #include "FIo_SecureIoUtil.h"
51 #include "FIo_IFileCore.h"
52 #include "FIo_FileUtil.h"
53
54 using namespace std;
55 using namespace Tizen::Base;
56 using namespace Tizen::App;
57 using namespace Tizen::System;
58
59 namespace Tizen { namespace Io
60 {
61
62 static const int _MAX_PATH_LENGTH = 128;
63 static const int _APP_UID = 5000;
64 static const size_t _MAX_FILE_OPENMODE_LENGTH = 3;
65 static const char _INTERNAL_MOUNT_FLAG[] = "/tmp/osp-compat/mount/internal";
66 static const char _EXTERNAL_MOUNT_FLAG[] = "/tmp/osp-compat/mount/external";
67
68 struct _OspDir
69 {
70         char path[_MAX_PATH_LENGTH];
71         mode_t mode;
72         bool appPrivilege; // false: root privilege
73 };
74
75 struct _LinkDir
76 {
77         char srcPath[_MAX_PATH_LENGTH];
78         char destPath[_MAX_PATH_LENGTH];
79 };
80
81 struct _PathInfo
82 {
83     char destPath[_MAX_PATH_LENGTH];
84 };
85
86 _FileImpl::_FileImpl(void)
87         : __pCore(null)
88         , __read(false)
89         , __write(false)
90         , __truncate(false)
91         , __append(false)
92 {
93 }
94
95 _FileImpl::~_FileImpl(void)
96 {
97         delete __pCore;
98 }
99
100 _FileImpl::_FileImpl(const _FileImpl& fileImpl)
101         : __pCore(null)
102         , __read(false)
103         , __write(false)
104         , __truncate(false)
105         , __append(false)
106 {
107         SysAssertf(false, "_FileImpl class does not support copy constructor.\n");
108 }
109
110 _FileImpl&
111 _FileImpl::operator =(const _FileImpl& fileImpl)
112 {
113         SysAssertf(false, "_FileImpl class does not support '=' operator.\n");
114
115         if (&fileImpl == this)
116         {
117                 return *this;
118         }
119
120         return *this;
121 }
122
123 bool
124 _FileImpl::VerifyFileOpenMode(const char* pOpenMode)
125 {
126         if (pOpenMode == null)
127         {
128                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode is null.");
129                 return false;
130         }
131
132         if (strlen(pOpenMode) > _MAX_FILE_OPENMODE_LENGTH)
133         {
134                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
135                 return false;
136         }
137
138         switch (pOpenMode[0])
139         {
140         case 'r':
141                 __read = true;
142                 break;
143         case 'w':
144                 __write = true;
145                 __truncate = true;
146                 break;
147         case 'a':
148                 __write = true;
149                 __append = true;
150                 break;
151         default:
152                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
153                 return false;
154         }
155
156         switch (pOpenMode[1])
157         {
158         case '\0':
159                 break;
160         case '+':
161                 if (pOpenMode[2] == '\0' || pOpenMode[2] == 'b')
162                 {
163                         __read = true;
164                         __write = true;
165                         break;
166                 }
167                 else
168                 {
169                         SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
170                         return false;
171                 }
172         case 'b':
173                 if (pOpenMode[2] == '\0')
174                 {
175                         break;
176                 }
177                 else if (pOpenMode[2] == '+')
178                 {
179                         __read = true;
180                         __write = true;
181                         break;
182                 }
183                 else
184                 {
185                         SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
186                         return false;
187                 }
188         default:
189                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
190                 return false;
191         }
192
193         return true;
194 }
195
196 result
197 _FileImpl::Construct(const String& filePath, const String& openMode, bool createParentDirsToo, const ByteBuffer* pSecretKey)
198 {
199         SysAssertf(__pCore == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
200         result r = E_SUCCESS;
201
202         if (openMode.Contains(L'r') == true)
203         {
204                 SysTryReturnResult(NID_IO, !createParentDirsToo, E_INVALID_ARG,
205                                 "The specified createParentDirsToo cannot be used without file creation mode.");
206         }
207
208         if (createParentDirsToo == true)
209         {
210                 String dirPath;
211                 int position = 0;
212
213                 r = filePath.LastIndexOf(L'/', filePath.GetLength() - 1, position);
214                 SysTryReturnResult(NID_IO, r != E_OBJ_NOT_FOUND, E_INVALID_ARG, "The specified filePath is invalid.");
215                 SysTryReturnResult(NID_IO, !(position == 0), E_INVALID_ARG, "The specified filePath is invalid.");
216
217                 r = filePath.SubString(0, position, dirPath);
218                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Failed to extract dir path.", GetErrorMessage(r));
219
220                 r = Directory::Create(dirPath, true);
221                 if (IsFailed(r))
222                 {
223                         if (r == E_FILE_ALREADY_EXIST)
224                         {
225                                 r = E_SUCCESS;
226                         }
227                         else
228                         {
229                                 SysPropagate(NID_IO, r);
230                                 return r;
231                         }
232                 }
233         }
234
235         unique_ptr<char[]> pOpenMode(_StringConverter::CopyToCharArrayN(openMode));
236         SysTryReturnResult(NID_IO, pOpenMode != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
237
238         return Construct(filePath, pOpenMode.get(), pSecretKey);
239 }
240
241 result
242 _FileImpl::Construct(const String& filePath, const char* pOpenMode, const ByteBuffer* pSecretKey)
243 {
244         SysAssertf(__pCore == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class\n");
245         result r = E_SUCCESS;
246
247         bool isValidOpenMode = VerifyFileOpenMode(pOpenMode);
248         SysTryReturnResult(NID_IO, isValidOpenMode == true, E_INVALID_ARG, "The specified openMode is invalid. (%s)", pOpenMode);
249
250         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
251                         E_INVALID_ARG, " [%ls] is not compatible.", filePath.GetPointer());
252
253         if (!__truncate && IsFileExist(filePath))
254         {
255                 r = _SecureIoUtil::CheckSecureFileHeader(filePath, pSecretKey);
256                 if (r == E_END_OF_FILE)
257                 {
258                         r = E_IO; //for security error
259                 }
260                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
261         }
262
263         if (pSecretKey == null)
264         {
265                 unique_ptr<_NormalFile> pNormalFile(new (std::nothrow) _NormalFile());
266                 SysTryReturnResult(NID_IO, pNormalFile, E_OUT_OF_MEMORY, "The memory is insufficient.");
267
268                 r = pNormalFile->Construct(filePath, pOpenMode);
269                 SysTryReturn(NID_IO, !IsFailed(r), r , r, "[%s] Propagated.", GetErrorMessage(r));
270                 __pCore = pNormalFile.release();
271         }
272         else
273         {
274                 unique_ptr<_SecureFile> pSecureFile(new (std::nothrow) _SecureFile(__read, __write, __truncate, __append));
275                 SysTryReturnResult(NID_IO, pSecureFile, E_OUT_OF_MEMORY, "The memory is insufficient.");
276
277                 r = pSecureFile->Construct(filePath, pOpenMode, pSecretKey);
278                 SysTryReturn(NID_IO, !IsFailed(r), r , r, "[%s] Propagated.", GetErrorMessage(r));
279                 __pCore = pSecureFile.release();
280         }
281
282         return E_SUCCESS;
283 }
284
285 result
286 _FileImpl::ReadN(char** buffer, int& length)
287 {
288         result r = E_SUCCESS;
289         if (__pCore != null)
290         {
291                 _NormalFile* pNormalFile = dynamic_cast< _NormalFile* > (__pCore);
292                 if (pNormalFile != null)
293                 {
294                         r = pNormalFile->ReadN(buffer, length);
295                 }
296         }
297         else
298         {
299                 r = E_INVALID_OPERATION;
300         }
301
302         return r;
303 }
304
305 result
306 _FileImpl::Read(ByteBuffer& buffer)
307 {
308         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
309         SysTryReturnResult(NID_IO, __read == true, E_ILLEGAL_ACCESS, "File is not opened for reading.");
310         return __pCore->Read(buffer);
311 }
312
313 int
314 _FileImpl::Read(void* buffer, int length)
315 {
316         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
317         SysTryReturn(NID_IO, __read == true, 0, E_ILLEGAL_ACCESS, "[E_ILLEGAL_ACCESS] File is not opened for reading.");
318         return __pCore->Read(buffer, length);
319 }
320
321 result
322 _FileImpl::Read(String& buffer)
323 {
324         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
325         SysTryReturnResult(NID_IO, __read == true, E_ILLEGAL_ACCESS, "File is not opened for reading.");
326         return __pCore->Read(buffer);
327 }
328
329 result
330 _FileImpl::Write(const ByteBuffer& buffer)
331 {
332         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
333         SysTryReturnResult(NID_IO, __write == true, E_ILLEGAL_ACCESS, "File is not opened for writing.");
334         return __pCore->Write(buffer);
335 }
336
337 result
338 _FileImpl::Write(const void* buffer, int length)
339 {
340         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
341         SysTryReturnResult(NID_IO, __write == true, E_ILLEGAL_ACCESS, "File is not opened for writing.");
342         return __pCore->Write(buffer, length);
343 }
344
345 result
346 _FileImpl::Write(const String& buffer)
347 {
348         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
349         SysTryReturnResult(NID_IO, __write == true, E_ILLEGAL_ACCESS, "File is not opened for writing.");
350         return __pCore->Write(buffer);
351 }
352
353 result
354 _FileImpl::Flush(void)
355 {
356         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
357         return __pCore->Flush();
358 }
359
360 int
361 _FileImpl::Tell(void) const
362 {
363         SysTryReturnResult(NID_IO, __pCore != null, -1, "File is not constructed! Construct destined file first! ");
364         return __pCore->Tell();
365 }
366
367 result
368 _FileImpl::Seek(FileSeekPosition position, long offset)
369 {
370         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
371         return __pCore->Seek(position, offset);
372 }
373
374 result
375 _FileImpl::Truncate(int length)
376 {
377         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
378         SysTryReturnResult(NID_IO, __write == true, E_ILLEGAL_ACCESS, "File is not opened for writing.");
379         return __pCore->Truncate(length);
380 }
381
382 String
383 _FileImpl::GetName(void) const
384 {
385         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
386         return __pCore->GetName();
387 }
388
389 FILE*
390 _FileImpl::GetFilePointer(void) const
391 {
392         SysAssertf(__pCore != null, "Not yet constructed. Construct() should be called before use.\n");
393         return __pCore->GetFilePointer();
394 }
395
396 result
397 _FileImpl::Remove(const String& filePath)
398 {
399         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
400                                           E_INVALID_ARG, " [%ls] is not compatible.", filePath.GetPointer());
401         return _FileUtil::Remove(filePath);
402 }
403
404 result
405 _FileImpl::Move(const String& oldFilePath, const String& newFilePath)
406 {
407         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(oldFilePath, _AppInfo::IsOspCompat()) == true,
408                                           E_INVALID_ARG, " [%ls] is not compatible.", oldFilePath.GetPointer());
409
410         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(newFilePath, _AppInfo::IsOspCompat()) == true,
411                                           E_INVALID_ARG, " [%ls] is not compatible.", newFilePath.GetPointer());
412         return _FileUtil::Move(oldFilePath, newFilePath);
413 }
414
415 result
416 _FileImpl::Copy(const String& srcFilePath, const String& destFilePath, bool failIfExist)
417 {
418         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(srcFilePath, _AppInfo::IsOspCompat()) == true,
419                                           E_INVALID_ARG, " [%ls] is not compatible.", srcFilePath.GetPointer());
420
421         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(destFilePath, _AppInfo::IsOspCompat()) == true,
422                                           E_INVALID_ARG, " [%ls] is not compatible.", destFilePath.GetPointer());
423         return _FileUtil::Copy(srcFilePath, destFilePath, failIfExist);
424 }
425
426 result
427 _FileImpl::GetAttributes(const String& filePath, FileAttributes& attribute)
428 {
429         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
430                                           E_INVALID_ARG, " [%ls] is not compatible.", filePath.GetPointer());
431         return _FileUtil::GetAttributes(filePath, attribute);
432 }
433
434 String
435 _FileImpl::GetFileName(const String& filePath)
436 {
437         String fileName;
438         SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true, fileName, E_INVALID_ARG,
439                         "[E_INVALID_ARG] The length of the specified filePath (%ls) is zero or exceeds system limitations.",
440                         filePath.GetPointer());
441
442         return _FileUtil::GetFileName(filePath);
443 }
444
445 String
446 _FileImpl::GetFileExtension(const String& filePath)
447 {
448         String extName;
449         SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true, extName, E_INVALID_ARG,
450                         "[E_INVALID_ARG] The length of the specified filePath (%ls) is zero or exceeds system limitations.",
451                         filePath.GetPointer());
452
453         return _FileUtil::GetFileExtension(filePath);
454 }
455
456 bool
457 _FileImpl::IsFileExist(const String& filePath)
458 {
459         SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
460                         false, E_INVALID_ARG, "[E_INVALID_ARG] The specified filePath (%ls) is invalid.", filePath.GetPointer());
461
462         return _FileUtil::IsFileExist(filePath);
463 }
464
465 result
466 _FileImpl::ConvertToSecureFile(const String& plainFilePath, const String& secureFilePath,
467                                                            const ByteBuffer& key)
468 {
469         return _FileUtil::ConvertToSecureFile(plainFilePath, secureFilePath, &key);
470 }
471
472 bool
473 _FileImpl::IsAppPath(const String& filePath)
474 {
475         SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
476                         false, E_INVALID_ARG, "[E_INVALID_ARG] The specified filePath (%ls) is invalid.", filePath.GetPointer());
477
478         return _FileUtil::IsAppPath(filePath);
479 }
480
481 bool
482 _FileImpl::IsMediaPath(const String& filePath)
483 {
484         SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
485                         false, E_INVALID_ARG, "[E_INVALID_ARG] The specified filePath (%ls) is invalid.", filePath.GetPointer());
486
487         return _FileUtil::IsMediaPath(filePath);
488 }
489
490 bool
491 _FileImpl::IsSystemPath(const String& filePath)
492 {
493         SysTryReturn(NID_IO, VerifyFilePathCompatibility(filePath, _AppInfo::IsOspCompat()) == true,
494                         false, E_INVALID_ARG, "[E_INVALID_ARG] The specified filePath (%ls) is invalid.", filePath.GetPointer());
495
496         return _FileUtil::IsSystemPath(filePath);
497 }
498
499 bool
500 _FileImpl::VerifyFilePath(const String& filePath, _FilePathType pathType)
501 {
502         return _FileUtil::VerifyFilePath(filePath, pathType);
503 }
504
505 bool
506 _FileImpl::CleanDirectories(const String& appRootPath, const String& pkgId)
507 {
508         char removeCmd[PATH_MAX] = {0, };
509         int ret = 0;
510
511         String ospSharePkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
512         ospSharePkgIdPath.Append(L"share/");
513         ospSharePkgIdPath.Append(pkgId);
514
515         String ospShare2PkgIdPath = _EnvironmentImpl::GetOspCompatSharedPath();
516         ospShare2PkgIdPath.Append(L"share2/");
517         ospShare2PkgIdPath.Append(pkgId);
518
519 #if 0
520         r = Directory::Remove(ospSharePkgIdPath, true);
521         SysTryReturn(NID_IO, !IsFailed(r), false, E_SYSTEM, "[%s] Failed to remove directory (%ls)",
522                         GetErrorMessage(r), ospSharePkgIdPath.GetPointer());
523
524         r = Directory::Remove(ospShare2PkgIdPath, true);
525         SysTryReturn(NID_IO, !IsFailed(r), false, E_SYSTEM, "[%s] Failed to remove directory (%ls)",
526                         GetErrorMessage(r), ospShare2PkgIdPath.GetPointer());
527 #else
528         sprintf(removeCmd, "rm -rf %ls", ospSharePkgIdPath.GetPointer());
529         ret = system(removeCmd);
530         SysTryReturn(NID_IO, ret != -1, false, E_SYSTEM, "Failed to remove directory (%ls)",
531                         ospSharePkgIdPath.GetPointer());
532
533         memset(removeCmd, 0, PATH_MAX);
534
535         sprintf(removeCmd, "rm -rf %ls", ospShare2PkgIdPath.GetPointer());
536         ret = system(removeCmd);
537         SysTryReturn(NID_IO, ret != -1, false, E_SYSTEM, "Failed to remove directory (%ls)",
538                         ospShare2PkgIdPath.GetPointer());
539 #endif
540
541         return true;
542 }
543
544 // This method is called by package installer backend.
545 bool
546 _FileImpl::PrepareDataCaging(const String& appRootPath, const String& pkgId)
547 {
548         int index = 0;
549         char* pCwd = null;
550         bool internalInstalled = true;
551         result r = E_SUCCESS;
552
553         SysLog(NID_IO, "[data_caging] PrepareDataCaging() was called by installer backend, appRootPath: %ls, packageId: %ls",
554                         appRootPath.GetPointer(), pkgId.GetPointer());
555
556         if (CleanDirectories(appRootPath, pkgId) == false)
557         {
558                 SysLog(NID_IO, "CleanDirectories() failed.");
559                 return false;
560         }
561
562         pCwd = get_current_dir_name();
563         SysTryCatch(NID_IO, pCwd != null, r = E_SYSTEM, E_SYSTEM,
564                            "[E_SYSTEM] get_current_dir_name() was failed, errno: %d (%s).", errno, strerror(errno));
565
566         // Check whether package is installed on internal storage or not
567         r = appRootPath.IndexOf("/opt/storage/sdcard", 0, index);
568         if (r == E_SUCCESS)
569         {
570                 internalInstalled = false;
571         }
572         else
573         {
574                 internalInstalled = true;
575         }
576
577         umask(0000);
578
579         if (internalInstalled == true)
580         {
581                 unique_ptr<char[]> pAppRootPath(_StringConverter::CopyToCharArrayN(appRootPath));
582                 SysTryCatch(NID_IO, pAppRootPath != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The memory is insufficient.");
583
584                 SysTryCatch(NID_IO, chdir(pAppRootPath.get()) == 0, r = E_SYSTEM, E_SYSTEM,
585                                 "[E_SYSTEM] chdir() was failed (%s), path: %s", strerror(errno), pAppRootPath.get());
586
587                 SysTryCatch(NID_IO, CreateOspInternalDirectories(pkgId) == true, r = E_SYSTEM, E_SYSTEM,
588                                 "[E_SYSTEM] fail to create OSP Internal directories");
589         }
590         else
591         {
592                 String appExRootPath(appRootPath);
593
594                 int ret = 0;
595
596                 appExRootPath.Append(pkgId);
597                 unique_ptr<char[]> pAppExRootPath(_StringConverter::CopyToCharArrayN(appExRootPath));
598                 SysTryCatch(NID_IO, pAppExRootPath != null, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The memory is insufficient.");
599
600                 ret = mkdir(pAppExRootPath.get(), 0705);
601                 if (ret == -1 && errno != 17) // EEXIST
602                 {
603                         SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
604                                                 strerror(errno), pAppExRootPath.get(), 0705);
605                         goto CATCH;
606                 }
607
608                 SysTryCatch(NID_IO, chdir(pAppExRootPath.get()) == 0, r = E_SYSTEM, E_SYSTEM,
609                                 "[E_SYSTEM] chdir() was failed (%s), path: %s", strerror(errno), pAppExRootPath.get());
610                 SysTryCatch(NID_IO, CreateOspExternalDirectories(pkgId) == true, r = E_SYSTEM, E_SYSTEM,
611                                 "[E_SYSTEM] fail to create OSP External directories");
612         }
613
614         SysTryCatch(NID_IO, CreateSlpDirectories() == true, r = E_SYSTEM, E_SYSTEM,
615                         "[E_SYSTEM] fail to create SLP directories");
616         SysTryCatch(NID_IO, CreateSymbolicLink() == true, r = E_SYSTEM, E_SYSTEM,
617                         "[E_SYSTEM] Fail to create symbolic link.");
618         SysTryCatch(NID_IO, chdir(pCwd) == 0, r = E_SYSTEM, E_SYSTEM,
619                         "[E_SYSTEM] chdir() was failed (%s), path: %s", strerror(errno), pCwd);
620
621         r = E_SUCCESS;
622         SysLog(NID_IO, "[data_caging] PrepareDataCaging() succeeded.");
623
624         // fall thru
625 CATCH:
626         if (pCwd != null)
627         {
628                 free(pCwd);
629         }
630
631         umask(0022);
632
633         if (IsFailed(r))
634         {
635                 SysLog(NID_IO, "[data_caging] PrepareDataCaging() failed.");
636                 return false;
637         }
638
639         return true;
640 }
641
642 bool
643 _FileImpl::FinalizeDataCaging(const String& appRootPath) // for 2.0 app
644 {
645         static const struct _PathInfo mountPath[] =
646         {
647                 //{ "./bin" },
648                 //{ "./boot" },
649                 //{ "./cache" },
650                 { "./csa" },
651                 { "./dev/pts" },
652                 { "./dev/shm" },
653                 { "./dev" },
654                 { "./etc" },
655                 { "./lib" },
656                 //{ "./lost+found" },
657                 { "./media" },
658                 { "./mnt" },
659                 { "./opt/usr" },
660                 { "./opt/var/kdb/db" },
661                 { "./opt/storage/sdcard" },
662                 { "./opt" },
663                 //{ "./packaging" },
664                 { "./proc" },
665                 { "./sbin" },
666                 { "./srv" },
667                 { "./sys/kernel/debug" },
668                 { "./sys" },
669                 { "./tmp" },
670                 { "./usr" },
671                 { "./var/run" },
672                 { "./var" },
673
674                 { "./data/Share" },
675                 { "./data/Share2" },
676                 { "./Share" },
677                 { "./Share2" },
678                 //{ "./Clipboard" },
679                 //{ "./NPKI" },
680                 //{ "./System" },
681                 //{ "./Tmp" },
682                 { "./Media" },
683
684                 { "./Storagecard/Media" },
685         { "./ShareExt" },
686         { "./Share2Ext" },
687         { "./HomeExt/Share" },
688         { "./HomeExt/Share2" },
689         { "./HomeExt" }
690         };
691
692         unique_ptr< char[] > pAppRootPath(_StringConverter::CopyToCharArrayN(appRootPath));
693         SysTryReturn(NID_IO, pAppRootPath != null, false, E_OUT_OF_MEMORY,
694                         "[E_OUT_OF_MEMORY] The memory is insufficient.");
695
696         SysTryReturn(NID_IO, chdir(pAppRootPath.get()) == 0, false, E_SYSTEM,
697                         "[E_SYSTEM] chdir() failed (%d, %s), path: %ls", errno, strerror(errno), appRootPath.GetPointer());
698
699         for (int i = 0; i < sizeof(mountPath) / sizeof(struct _PathInfo); ++i)
700         {
701                 int ret = umount2(mountPath[i].destPath, MNT_DETACH);
702                 SysTryLog(NID_IO, ret == 0, "umount2() errno: %d (%s)", errno, strerror(errno));
703                 SysTryReturn(NID_IO, ret == 0 || errno == EINVAL || errno == ENOENT, false, E_SYSTEM,
704                                 "[E_SYSTEM] umount2() failed (%d, %s), path: %s", errno, strerror(errno), mountPath[i].destPath);
705         }
706
707         char* pkgId = strrchr(pAppRootPath.get(), '/');
708         char mountFlag[_MAX_PATH_LENGTH] = { 0, };
709         sprintf(mountFlag, "%s/%s", _INTERNAL_MOUNT_FLAG, ++pkgId);
710         int res = unlink(mountFlag);
711         if (res == -1 && errno != ENOENT)
712         {
713                 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to remove mount flag (%s), errno: %d (%s)",
714                                 mountFlag, errno, strerror(errno));
715                 return false;
716         }
717
718         memset(mountFlag, 0, _MAX_PATH_LENGTH);
719         sprintf(mountFlag, "%s/%s", _EXTERNAL_MOUNT_FLAG, pkgId);
720         res = unlink(mountFlag);
721         if (res == -1 && errno != ENOENT)
722         {
723                 SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to remove mount flag (%s), errno: %d (%s)",
724                                 mountFlag, errno, strerror(errno));
725                 return false;
726         }
727
728         SysLog(NID_IO, "[data_caging] FinalizeDataCaging() succeeded, appRootPath: %ls", appRootPath.GetPointer());
729         return true;
730 }
731
732 int
733 _FileImpl::GetAvailableUid(void)
734 {
735         return _APP_UID;
736 }
737
738 bool
739 _FileImpl::CreateOspApplicationDirectories(const String& appRootPath, const String& pkgId) // for 2.1 app
740 {
741         struct _OspDir appSubDir[] =
742         {
743                 { "./shared\0",                 0755, false },
744                 //{ "./shared/data\0",  0755, true },
745                 { "./shared/res\0",             0755, false },
746                 { "./shared/trusted\0", 0755, true },
747                 //{ "./cache\0", 0700, true }
748         };
749         int uid = -1;
750         int ret = 0;
751         unsigned int i = 0;
752         result r = E_SUCCESS;
753
754         SysTryReturn(NID_IO, CleanDirectories(appRootPath, pkgId) == true, false, E_SYSTEM,
755                         "[E_SYSTEM] Failed to clean directories for 2.0 application compatibility.");
756
757         unique_ptr<char[]> pAppRootPath(_StringConverter::CopyToCharArrayN(appRootPath));
758         SysTryReturn(NID_IO, pAppRootPath != null, false, E_SYSTEM, "[E_SYSTEM] The memory is insufficient.");
759
760         SysTryReturn(NID_IO, chdir(pAppRootPath.get()) == 0, false, E_SYSTEM,
761                         "[E_SYSTEM] chdir() failed (%d, %s), path: %s", errno, strerror(errno), pAppRootPath.get());
762
763         uid = GetAvailableUid();
764
765         umask(0000);
766
767         for (i = 0; i < sizeof(appSubDir) / sizeof(struct _OspDir); ++i)
768         {
769                 ret = mkdir(appSubDir[i].path, appSubDir[i].mode);
770                 if (ret == -1 && errno != 17) // EEXIST
771                 {
772                         SysLog(NID_IO, "[E_SYSTEM] mkdir() failed (%d, %s), path: %s, mode: 0%o",
773                                         errno, strerror(errno), appSubDir[i].path, appSubDir[i].mode);
774                         goto CATCH;
775                 }
776
777                 if (appSubDir[i].appPrivilege)
778                 {
779                         ret = chown(appSubDir[i].path, uid, uid);
780                         SysTryCatch(NID_IO, ret == 0, , E_SYSTEM,
781                                         "[E_SYSTEM] chown() failed (%d, %s), path: %s, uid: %d",
782                                         errno, strerror(errno), appSubDir[i].path, uid);
783                 }
784         }
785
786         if (access("./shared/data", F_OK) == 0)
787         {
788                 SysTryCatch(NID_IO, system("chown -R 5000:5000 ./shared/data") != -1, , E_SYSTEM,
789                                 "[E_SYSTEM] chown() failed");
790         }
791         // XXX: Temp code for supporting old share directory.
792         else if (access("./share", F_OK) == 0)
793         {
794                 SysTryCatch(NID_IO, system("rm -rf ./shared/data") != -1, , E_SYSTEM,
795                                 "[E_SYSTEM] Failed to remove ./shared/data directory");
796                 
797                 SysTryCatch(NID_IO, rename("./share", "./shared/data") == 0, , E_SYSTEM,
798                                 "[E_SYSTEM] Failed to rename share directory (%d, %s)", errno, strerror(errno));
799
800                 SysTryCatch(NID_IO, system("chown -R 5000:5000 ./shared/data") != -1, , E_SYSTEM,
801                                 "[E_SYSTEM] chown() failed");
802
803                 SysTryCatch(NID_IO, chmod("./shared/data", 0755) == 0, , E_SYSTEM, "[E_SYSTEM] chmod() failed");
804         }
805         // XXX-end
806
807         umask(0022);
808
809         SysLog(NID_IO, "_FileImpl::CreateOspApplicationDirectories() succeeded.");
810         return true;
811
812 CATCH:
813         umask(0022);
814
815         return false;
816 }
817
818 bool
819 _FileImpl::CreateOspInternalDirectories(const String& pkgId) // for 2.0 app
820 {
821         unsigned int i = 0;
822         int ret = 0;
823         int uid = -1;
824         struct _OspDir appSubDir[] =
825         {
826 //              { "./data",                     0700, true },   // It is created by installer.
827                 { "./shared",           0755, false },
828                 { "./data/Share",       0000, true },   // mount from /opt/usr/share/.osp-compat/share/{pkgId}
829                 { "./data/Share2",      0000, true },   // mount from /opt/usr/share/.osp-compat/share2/{pkgId}
830                 { "./Share",            0000, false },  // mount from /opt/usr/share/.osp-compat/share
831                 { "./Share2",           0000, false },  // mount from /opt/usr/share/.osp-compat/share2
832 //              { "./Clipboard",        0000, false },
833 //              { "./NPKI",                     0000, false },
834 //              { "./System",           0000, false },
835 //              { "./Tmp",                      0000, false },
836                 { "./Media",            0000, false },  // mount from /opt/usr/media
837                 { "./Storagecard",      0705, false },
838                 { "./Storagecard/Media", 0000, false }, // mount from /opt/storage/sdcard
839         };
840 #if 1
841         struct _OspDir mediaDir[] =
842         {
843                 { "/opt/usr/media/Images", 0777, false },
844                 { "/opt/usr/media/Sounds", 0777, false },
845                 { "/opt/usr/media/Videos", 0777, false },
846                 //{ "/opt/usr/media/Themes", 0777, false },
847                 { "/opt/usr/media/Others", 0777, false }
848         };
849 #endif
850         String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
851         String ospShareAppIdPath(L"share/");
852         String ospShare2AppIdPath(L"share2/");
853         result r = E_SUCCESS;
854
855         r = ospShareAppIdPath.Insert(ospCompatSharedPath, 0);
856         SysTryReturn(NID_IO, !IsFailed(r), false, E_SYSTEM,
857                         "[E_SYSTEM] String::Insert() failed. (error: %s)", GetErrorMessage(r));
858
859         r = ospShare2AppIdPath.Insert(ospCompatSharedPath, 0);
860         SysTryReturn(NID_IO, !IsFailed(r), false, E_SYSTEM,
861                         "[E_SYSTEM] String::Insert() failed. (error: %s)", GetErrorMessage(r));
862
863         uid = GetAvailableUid();
864
865         for (i = 0; i < sizeof(appSubDir) / sizeof(struct _OspDir); i++)
866         {
867                 ret = mkdir(appSubDir[i].path, appSubDir[i].mode);
868                 if (ret == -1 && errno != 17) // EEXIST
869                 {
870                         SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
871                                                 strerror(errno), appSubDir[i].path, appSubDir[i].mode);
872                         return false;
873                 }
874                 if (appSubDir[i].appPrivilege)
875                 {
876                         ret = chown(appSubDir[i].path, uid, uid);
877                         if (ret == -1)
878                         {
879                                 SysLog(NID_IO, "chown() failed (%s), path: %s, uid: %d",
880                                                         strerror(errno), appSubDir[i].path, uid);
881                                 return false;
882                         }
883                 }
884         }
885
886         ospShareAppIdPath.Append(pkgId);
887         unique_ptr<char[]> pOspShareAppIdPath(_StringConverter::CopyToCharArrayN(ospShareAppIdPath));
888         SysTryReturn(NID_IO, pOspShareAppIdPath != null, false, E_SYSTEM, "[E_SYSTEM] The memory is insufficient.");
889         ret = mkdir(pOspShareAppIdPath.get(), 0705);
890         if (ret == -1 && errno != 17) // EEXIST
891         {
892                 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
893                                         strerror(errno), pOspShareAppIdPath.get(), 0705);
894                 return false;
895         }
896         ret = chown(pOspShareAppIdPath.get(), uid, uid);
897         if (ret == -1)
898         {
899                 SysLog(NID_IO, "chown() failed (%s), path: %s, uid: %d",
900                                         strerror(errno), pOspShareAppIdPath.get(), uid);
901                 return false;
902         }
903
904         ospShare2AppIdPath.Append(pkgId);
905         unique_ptr<char[]> pOspShare2AppIdPath(_StringConverter::CopyToCharArrayN(ospShare2AppIdPath));
906         SysTryReturn(NID_IO, pOspShare2AppIdPath != null, false, E_SYSTEM, "[E_SYSTEM] The memory is insufficient.");
907         ret = mkdir(pOspShare2AppIdPath.get(), 0705);    // TODO: change to 0770
908         if (ret == -1 && errno != 17) // EEXIST
909         {
910                 SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
911                                         strerror(errno), pOspShare2AppIdPath.get(), 0705);
912                 return false;
913         }
914         ret = chown(pOspShare2AppIdPath.get(), uid, uid);
915         if (ret == -1)
916         {
917                 SysLog(NID_IO, "chown() failed (%s), path: %s, uid: %d",
918                                         strerror(errno), pOspShare2AppIdPath.get(), uid);
919                 return false;
920         }
921
922 #if 1
923         for (i = 0; i < sizeof(mediaDir) / sizeof(struct _OspDir); ++i)
924         {
925                 ret = mkdir(mediaDir[i].path, mediaDir[i].mode);
926                 if (ret == -1 && errno != 17) // EEXIST
927                 {
928                         SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
929                                         strerror(errno), mediaDir[i].path, mediaDir[i].mode);
930                         return false;
931                 }
932                 ret = chown(mediaDir[i].path, 5000, 5000);
933                 SysTryReturn(NID_IO, ret == 0, false, E_SYSTEM,
934                                 "[E_SYSTEM] chown() failed (%d, %s), path: %s, uid: 5000, gid: 5000",
935                                 errno, strerror(errno), mediaDir[i].path);
936         }
937 #endif
938
939         // XXX: shared directory is not supported for 2.0 applications
940 #if 0
941         if (access("./shared/data", F_OK) == 0)
942         {
943                 char copyCmd[256] = { 0, };
944                 sprintf(copyCmd, "cp -rf ./shared/data/* /opt/usr/share/.osp-compat/share/%ls/", pkgId.GetPointer());
945                 ret = system(copyCmd);
946                 SysTryReturn(NID_IO, ret != -1, false, E_SYSTEM, "Failed to copy command (%s)", copyCmd);
947
948                 SysTryReturn(NID_IO, system("rm -rf ./shared/data") != -1, false, E_SYSTEM,
949                         "[E_SYSTEM] rmdir() failed, path: ./shared/data");
950
951                 char chownCmd[256] = { 0, };
952                 sprintf(chownCmd, "chown -R 5000:5000 /opt/usr/share/.osp-compat/share/%ls/", pkgId.GetPointer());
953                 SysTryReturn(NID_IO, system(chownCmd) != -1, false, E_SYSTEM, "[E_SYSTEM] chown() failed");
954
955                 char symlinkCmd[256] = { 0, };
956                 sprintf(symlinkCmd, "ln -s %s ./shared/data", pOspShareAppIdPath.get());
957                 SysTryReturn(NID_IO, system(symlinkCmd) != -1, false, E_SYSTEM, "[E_SYSTEM] symlink() failed");
958         }
959 #endif
960         char symlinkCmd[256] = { 0, };
961         sprintf(symlinkCmd, "ln -s %s ./shared/data", pOspShareAppIdPath.get());
962         SysTryReturn(NID_IO, system(symlinkCmd) != -1, false, E_SYSTEM, "[E_SYSTEM] symlink() failed");
963
964         return true;
965 }
966
967 // TODO: Need to test this method.
968 bool
969 _FileImpl::CreateOspExternalDirectories(const String& pkgId)
970 {
971         unsigned int i = 0;
972         int ret = 0;
973         int uid = -1;
974         struct _OspDir appSubDir[] = { // virtual path
975 //              { "./data", 0700, true },
976                 { "./System", 0000, false },                // mount from /opt/apps/com.samsung.osp/system
977                 { "./Storagecard", 0705, false },
978                 { "./Storagecard/Media", 0000, false }          // mount from /opt/storage/sdcard
979         };
980 #if 0
981         struct _OspDir mediaDir[] = { // physical path
982                 { "/opt/usr/media/Images", 0777, false },
983                 { "/opt/usr/media/Sounds", 0777, false },
984                 { "/opt/usr/media/Videos", 0777, false },
985                 //{ "/opt/usr/media/Themes", 0777, false },
986                 { "/opt/usr/media/Others", 0777, false }
987         };
988 #endif
989
990         for (i = 0; i < sizeof(appSubDir) / sizeof(struct _OspDir); i++)
991         {
992                 ret = mkdir(appSubDir[i].path, appSubDir[i].mode);
993                 if (ret == -1 && errno != 17) // EEXIST
994                 {
995                         SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
996                                                 strerror(errno), appSubDir[i].path, appSubDir[i].mode);
997                         return false;
998                 }
999                 if (appSubDir[i].appPrivilege)
1000                 {
1001                         ret = chown(appSubDir[i].path, uid, uid);
1002                         if (ret == -1)
1003                         {
1004                                 SysLog(NID_IO, "chown() failed (%s), path: %s, uid: %d",
1005                                                         strerror(errno), appSubDir[i].path, uid);
1006                                 return false;
1007                         }
1008                 }
1009         }
1010
1011 #if 0
1012         for (i = 0; i < sizeof(mediaDir) / sizeof(struct _OspDir); i++)
1013         {
1014                 ret = mkdir(mediaDir[i].path, mediaDir[i].mode);
1015                 if (ret == -1 && errno != 17) // EEXIST
1016                 {
1017                         SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1018                                                 strerror(errno), mediaDir[i].path, mediaDir[i].mode);
1019                         return false;
1020                 }
1021         }
1022 #endif
1023
1024         return true;
1025 }
1026
1027 bool
1028 _FileImpl::CreateSlpDirectories(void)
1029 {
1030         unsigned int i = 0;
1031         int ret = 0;
1032         struct _OspDir slpDir[] = { // virtual path
1033                 //{ "./bin", 0000, false },     // mount from /bin
1034                 //{ "./boot", 0000,     false },
1035                 //{ "./cache", 0000, false },
1036                 { "./csa", 0000, false },
1037                 { "./dev", 0000, false },
1038                 { "./etc", 0000, false },
1039                 { "./lib", 0000, false },
1040                 //{ "./lost+found",     0000, false },
1041                 { "./media", 0000, false },
1042                 { "./mnt", 0000, false },
1043                 { "./opt", 0000, false },
1044                 //{ "./packaging", 0000, false },
1045                 { "./proc", 0000, false },
1046                 { "./sbin", 0000, false },
1047                 { "./srv", 0000, false },
1048                 { "./sys", 0000, false },
1049                 { "./tmp", 0000, false },
1050                 { "./usr", 0000, false },
1051                 { "./var", 0000, false }
1052         };
1053
1054         for (i = 0; i < sizeof(slpDir) / sizeof(struct _OspDir); i++)
1055         {
1056                 ret = mkdir(slpDir[i].path, slpDir[i].mode);
1057                 if (ret == -1 && errno != 17) // EEXIST
1058                 {
1059                         SysLog(NID_IO, "mkdir() failed (%s), path: %s, mode: 0%o",
1060                                                 strerror(errno), slpDir[i].path, slpDir[i].mode);
1061                         return false;
1062                 }
1063         }
1064
1065         return true;
1066 }
1067
1068 bool
1069 _FileImpl::CreateSymbolicLink(void)
1070 {
1071         struct _LinkDir linkDirList[] = {
1072                 { "/opt/home",          "./home" },
1073                 { "/opt/home/root",     "./root" },
1074                 { "/mnt/mmc",           "./sdcard" }
1075         };
1076
1077         for (unsigned int i = 0; i < sizeof(linkDirList) / sizeof(struct _LinkDir); ++i)
1078         {
1079                 int ret = symlink(linkDirList[i].srcPath, linkDirList[i].destPath);
1080                 if (ret == -1 && errno != 17) // EEXIST
1081                 {
1082                         SysLog(NID_IO, "Failed to create symbolic link, errno: %d (%s), src path: %s, dest path: %s",
1083                                         strerror(errno), linkDirList[i].srcPath, linkDirList[i].destPath);
1084                         return false;
1085                 }
1086         }
1087
1088         return true;
1089 }
1090
1091 bool
1092 _FileImpl::VerifyFilePathCompatibility(const String& filePath, bool ospCompat)
1093 {
1094         if (ospCompat == true)
1095         {
1096                 if (filePath[0] != L'/')
1097                 {
1098                         return false;
1099                 }
1100         }
1101         int length = filePath.GetLength();
1102         if (length > 0)
1103         {
1104                 return true;
1105         }
1106         return false;
1107 }
1108
1109 _FileImpl*
1110 _FileImpl::GetInstance(File& file)
1111 {
1112         return file.__pFileImpl;
1113 }
1114
1115 const _FileImpl*
1116 _FileImpl::GetInstance(const File& file)
1117 {
1118         return file.__pFileImpl;
1119 }
1120
1121 result
1122 _FileImpl::ConvertVirtualToPhysicalPath(const String& virtualPath, String& physicalPath) // for 2.0 app
1123 {
1124         SysTryReturnResult(NID_IO, VerifyFilePathCompatibility(virtualPath, _AppInfo::IsOspCompat()) == true,
1125                         E_INVALID_ARG, "[E_INVALID_ARG] %ls is not compatible.", virtualPath.GetPointer());
1126
1127         const wchar_t* virtualPathPrefix[] =
1128         {
1129                 L"/Home/Share2",
1130                 L"/Home/Share",
1131                 L"/Home",
1132                 L"/Res",
1133                 L"/Share2",
1134                 L"/Share/AppControl",
1135                 L"/Share",
1136                 //L"/HomeExt",
1137                 //L"/ShareExt",
1138                 //L"/Share2Ext",
1139                 //L"/NPKI",
1140                 L"/Media",
1141                 L"/Storagecard/Media",
1142                 //L"/Storagecard/NPKI",
1143         };
1144         result r = E_SUCCESS;
1145         int count = sizeof(virtualPathPrefix)/sizeof(wchar_t*);
1146         int i = 0;
1147
1148         for (i = 0; i < count; i++)
1149         {
1150                 SysLog(NID_IO, "[V2P] i: %d, path: %ls", i, virtualPathPrefix[i]);
1151                 if (virtualPath.StartsWith(virtualPathPrefix[i], 0) == true)
1152                 {
1153                         break;
1154                 }
1155         }
1156         SysTryReturnResult(NID_IO, i != count, E_INVALID_ARG, "The path (%ls) is not matched.",
1157                         virtualPath.GetPointer());
1158
1159         int prefixLen = String(virtualPathPrefix[i]).GetLength();
1160         if (virtualPath.GetLength() > prefixLen)
1161         {
1162                 wchar_t ch = '\0';
1163
1164                 r = virtualPath.GetCharAt(prefixLen, ch);
1165                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] The path (%ls) is not matched.",
1166                                 GetErrorMessage(r), virtualPath.GetPointer());
1167
1168                 if (ch != L'/')
1169                 {
1170                         physicalPath.Clear();
1171                         SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
1172                                         virtualPath.GetPointer());
1173
1174                         return E_INVALID_ARG;
1175                 }
1176         }
1177
1178         String subPath;
1179         virtualPath.SubString(wcslen(virtualPathPrefix[i]), subPath);
1180
1181         Tizen::App::App* pApp = Tizen::App::App::GetInstance();
1182         SysTryReturnResult(NID_IO, pApp != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1183         String homePath = pApp->GetAppRootPath();
1184         String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
1185
1186         switch (i)
1187         {
1188         case 0:
1189                 physicalPath = homePath + L"data/Share2";
1190                 break;
1191         case 1:
1192                 physicalPath = homePath + L"data/Share";
1193                 break;
1194         case 2:
1195                 physicalPath = homePath + L"data";
1196                 break;
1197         case 3:
1198                 physicalPath = homePath + L"res";
1199                 break;
1200         case 4:
1201                 physicalPath = ospCompatSharedPath + L"share2";
1202                 break;
1203         case 5:
1204                 physicalPath = ospCompatSharedPath + L"share/AppControl";
1205                 break;
1206         case 6:
1207                 physicalPath = ospCompatSharedPath + L"share";
1208                 break;
1209         case 7:
1210                 physicalPath = Tizen::System::Environment::GetMediaPath();
1211                 break;
1212         case 8:
1213                 physicalPath = Tizen::System::Environment::GetExternalStoragePath() + L"Media";
1214                 break;
1215         default:
1216                 SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
1217                                 virtualPath.GetPointer());
1218                 return E_INVALID_ARG;
1219         }
1220
1221         if (subPath.IsEmpty() == false)
1222         {
1223                 physicalPath.Append(subPath);
1224         }
1225
1226         return r;
1227 }
1228
1229 result
1230 _FileImpl::ConvertPhysicalToVirtualPath(const String& physicalPath, String& virtualPath) // for 2.0 app
1231 {
1232         result r = E_SUCCESS;
1233         const wchar_t* homeSubDir[] = {
1234                 L"/data/Share2",
1235                 L"/data/Share",
1236                 L"/data",
1237                 L"/res",
1238         };
1239         const wchar_t* ospHomeSubDir[] = {
1240                 L"/share2",
1241                 L"/share/AppControl",
1242                 L"/share",
1243         };
1244         String subPath;
1245         int homeSubDirCount = sizeof(homeSubDir)/sizeof(wchar_t*);
1246         int ospHomeSubDirCount = sizeof(ospHomeSubDir)/sizeof(wchar_t*);
1247         int baseDirLen = 0;
1248         int i = 0;
1249
1250         SysLog(NID_IO, "[P2V] physicalPath: %ls", physicalPath.GetPointer());
1251
1252         Tizen::App::App* pApp = Tizen::App::App::GetInstance();
1253         SysTryReturnResult(NID_IO, pApp != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1254         String homePath = pApp->GetAppRootPath();
1255         homePath.SetLength(homePath.GetLength() - 1);
1256
1257         String ospCompatSharedPath = _EnvironmentImpl::GetOspCompatSharedPath();
1258         ospCompatSharedPath.SetLength(ospCompatSharedPath.GetLength() - 1);
1259
1260         String mediaPath = Tizen::System::Environment::GetMediaPath();
1261         mediaPath.SetLength(mediaPath.GetLength() - 1);
1262
1263         String externalPath = Tizen::System::Environment::GetExternalStoragePath();
1264         externalPath.SetLength(externalPath.GetLength() - 1);
1265
1266         if (physicalPath.StartsWith(homePath, 0) == true)
1267         {
1268                 physicalPath.SubString(homePath.GetLength(), subPath);
1269
1270                 for (i = 0; i < homeSubDirCount; i++)
1271                 {
1272                         SysLog(NID_IO, "[P2V] i: %d, path: %ls", i, homeSubDir[i]);
1273                         if (subPath.StartsWith(homeSubDir[i], 0) == true)
1274                         {
1275                                 break;
1276                         }
1277                 }
1278                 SysTryReturnResult(NID_IO, i != homeSubDirCount, E_INVALID_ARG, "The path (%ls) is not matched.",
1279                                 physicalPath.GetPointer());
1280
1281                 baseDirLen = homePath.GetLength() + String(homeSubDir[i]).GetLength();
1282
1283                 switch (i)
1284                 {
1285                 case 0:
1286                         virtualPath = L"/Home/Share2";
1287                         break;
1288                 case 1:
1289                         virtualPath = L"/Home/Share";
1290                         break;
1291                 case 2:
1292                         virtualPath = L"/Home";
1293                         break;
1294                 case 3:
1295                         virtualPath = L"/Res";
1296                         break;
1297                 default:
1298                         break;
1299                 }
1300
1301         }
1302         else if (physicalPath.StartsWith(ospCompatSharedPath, 0) == true)
1303         {
1304                 physicalPath.SubString(ospCompatSharedPath.GetLength(), subPath);
1305
1306                 for (i = 0; i < ospHomeSubDirCount; i++)
1307                 {
1308                         SysLog(NID_IO, "[P2V] i: %d, path: %ls", i, ospHomeSubDir[i]);
1309                         if (subPath.StartsWith(ospHomeSubDir[i], 0) == true)
1310                         {
1311                                 break;
1312                         }
1313                 }
1314                 SysTryReturnResult(NID_IO, i != ospHomeSubDirCount, E_INVALID_ARG, "The path (%ls) is not matched.",
1315                                 physicalPath.GetPointer());
1316
1317                 baseDirLen = ospCompatSharedPath.GetLength() + String(ospHomeSubDir[i]).GetLength();
1318
1319                 switch (i)
1320                 {
1321                 case 0:
1322                         virtualPath = L"/Share2";
1323                         break;
1324                 case 1:
1325                         virtualPath = L"/Share/AppControl";
1326                         break;
1327                 case 2:
1328                         virtualPath = L"/Share";
1329                         break;
1330                 default:
1331                         break;
1332                 }
1333         }
1334         else if (physicalPath.StartsWith(mediaPath, 0) == true)
1335         {
1336                 SysLog(NID_IO, "[P2V] media");
1337                 virtualPath = L"/Media";
1338                 baseDirLen = mediaPath.GetLength();
1339         }
1340         else if (physicalPath.StartsWith(externalPath, 0) == true)
1341         {
1342                 SysLog(NID_IO, "[P2V] external media");
1343                 virtualPath = L"/Storagecard/Media";
1344                 baseDirLen = externalPath.GetLength();
1345         }
1346         else
1347         {
1348                 SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
1349                                 physicalPath.GetPointer());
1350
1351                 return E_INVALID_ARG;
1352         }
1353
1354         if (physicalPath.GetLength() > baseDirLen)
1355         {
1356                 wchar_t ch = '\0';
1357
1358                 r = physicalPath.GetCharAt(baseDirLen, ch);
1359                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] The path (%ls) is not matched.",
1360                                 GetErrorMessage(r), physicalPath.GetPointer());
1361
1362                 if (ch != L'/')
1363                 {
1364                         virtualPath.Clear();
1365                         SysLog(NID_IO, "[E_INVALID_ARG] The path (%ls) is not matched.",
1366                                         physicalPath.GetPointer());
1367
1368                         return E_INVALID_ARG;
1369                 }
1370         }
1371
1372         subPath.Clear();
1373         physicalPath.SubString(baseDirLen, subPath);
1374
1375         if (subPath.IsEmpty() == false)
1376         {
1377                 virtualPath.Append(subPath);
1378         }
1379
1380         return r;
1381 }
1382
1383 }} // Tizen::Io